Merge branch 'linux-2.6'
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index e9a3cb1..ee0209a 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -711,13 +711,14 @@
 like address space bits, you'll have to add a bus translator to the
 prom_parse.c file of the recent kernels for your bus type.
 
-The "reg" property only defines addresses and sizes (if #size-cells
-is non-0) within a given bus. In order to translate addresses upward
+The "reg" property only defines addresses and sizes (if #size-cells is
+non-0) within a given bus. In order to translate addresses upward
 (that is into parent bus addresses, and possibly into CPU physical
 addresses), all busses must contain a "ranges" property. If the
 "ranges" property is missing at a given level, it's assumed that
-translation isn't possible. The format of the "ranges" property for a
-bus is a list of:
+translation isn't possible, i.e., the registers are not visible on the
+parent bus.  The format of the "ranges" property for a bus is a list
+of:
 
 	bus address, parent bus address, size
 
@@ -735,6 +736,10 @@
 1/1 format, unless the processor supports physical addresses greater
 than 32-bits, in which case a 2/1 format is recommended.
 
+Alternatively, the "ranges" property may be empty, indicating that the
+registers are visible on the parent bus using an identity mapping
+translation.  In other words, the parent bus address space is the same
+as the child bus address space.
 
 2) Note about "compatible" properties
 -------------------------------------
@@ -1218,16 +1223,14 @@
 
   Required properties:
     - reg : Offset and length of the register set for the device
-    - device_type : Should be "mdio"
     - compatible : Should define the compatible device type for the
-      mdio.  Currently, this is most likely to be "gianfar"
+      mdio.  Currently, this is most likely to be "fsl,gianfar-mdio"
 
   Example:
 
 	mdio@24520 {
 		reg = <24520 20>;
-		device_type = "mdio"; 
-		compatible = "gianfar";
+		compatible = "fsl,gianfar-mdio";
 
 		ethernet-phy@0 {
 			......
@@ -1626,6 +1629,19 @@
    - interrupt-parent : the phandle for the interrupt controller that
      services interrupts for this device.
    - pio-handle : The phandle for the Parallel I/O port configuration.
+   - rx-clock-name: the UCC receive clock source
+     "none": clock source is disabled
+     "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+     "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+   - tx-clock-name: the UCC transmit clock source
+     "none": clock source is disabled
+     "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+     "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+   The following two properties are deprecated.  rx-clock has been replaced
+   with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
+   Drivers that currently use the deprecated properties should continue to
+   do so, in order to support older device trees, but they should be updated
+   to check for the new properties first.
    - rx-clock : represents the UCC receive clock source.
      0x00 : clock source is disabled;
      0x1~0x10 : clock source is BRG1~BRG16 respectively;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 232c298..d40844f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -160,6 +160,7 @@
 
 config PPC_OF_PLATFORM_PCI
 	bool
+	depends on PCI
 	depends on PPC64 # not supported on 32 bits yet
 	default n
 
@@ -417,7 +418,7 @@
 
 config ISA_DMA_API
 	bool
-	default y
+	default !PPC_ISERIES || PCI
 
 menu "Bus options"
 
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 6a79fe4..d20ccf5 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -151,6 +151,13 @@
 
 config PPC_EARLY_DEBUG
 	bool "Early debugging (dangerous)"
+	help
+	  Say Y to enable some early debugging facilities that may be available
+	  for your processor/board combination. Those facilities are hacks
+	  intended to debug problems early during boot, this should not be
+	  enabled in a production kernel.
+	  Note that enabling this will also cause the kernel default log level
+	  to be pushed to max automatically very early during boot
 
 choice
 	prompt "Early debugging console"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index bd87626..f70df9b 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -167,6 +167,9 @@
 $(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
+bootwrapper_install:
+	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+
 define archhelp
   @echo '* zImage          - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)'
   @echo '  install         - Install kernel using'
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c
index ebf9e21..3d0e4f9 100644
--- a/arch/powerpc/boot/4xx.c
+++ b/arch/powerpc/boot/4xx.c
@@ -122,7 +122,7 @@
 	else
 		dpath = 4; /* 32 bits */
 
-	/* get adress pins (rows) */
+	/* get address pins (rows) */
 	val = mfdcr_sdram0(DDR0_42);
 
 	row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 18e3271..9149bb8 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -33,7 +33,7 @@
 BOOTCFLAGS	+= -fno-stack-protector
 endif
 
-BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj)
+BOOTCFLAGS	+= -I$(obj) -I$(srctree)/$(obj) -I$(srctree)/$(src)/libfdt
 
 $(obj)/4xx.o: BOOTCFLAGS += -mcpu=440
 $(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
@@ -46,7 +46,9 @@
 $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
 	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
-src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
+src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+src-wlib := string.S crt0.S stdio.c main.c \
+		$(addprefix libfdt/,$(src-libfdt)) libfdt-wrapper.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S \
 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
@@ -101,24 +103,61 @@
       cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
 
 $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
+	$(Q)mkdir -p $(dir $@)
 	$(call if_changed_dep,bootcc)
 $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE
+	$(Q)mkdir -p $(dir $@)
 	$(call if_changed_dep,bootas)
 
 $(obj)/wrapper.a: $(obj-wlib) FORCE
 	$(call if_changed,bootar)
 
-hostprogs-y	:= addnote addRamDisk hack-coff mktree
+hostprogs-y	:= addnote addRamDisk hack-coff mktree dtc
 
 targets		+= $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y		:= $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
 		   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper		:=$(srctree)/$(src)/wrapper
-wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
+wrapperbits	:= $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
 			$(wrapper) FORCE
 
 #############
+# Bits for building dtc
+# DTC_GENPARSER      := 1    # Uncomment to rebuild flex/bison output
+
+dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o
+dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+dtc-objs := $(addprefix dtc-src/, $(dtc-objs))
+
+# prerequisites on generated files needs to be explicit
+$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h
+$(obj)/dtc-src/dtc-lexer.lex.o:  $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h
+
+HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/
+
+targets += dtc-src/dtc-parser.tab.c
+targets += dtc-src/dtc-lexer.lex.c
+
+ifdef DTC_GENPARSER
+BISON = bison
+FLEX = flex
+
+quiet_cmd_bison = BISON   $@
+      cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
+quiet_cmd_flex = FLEX    $@
+      cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
+
+$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
+     $(call if_changed,bison)
+
+$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
+
+$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
+     $(call if_changed,flex)
+endif
+
+#############
 # Bits for building various flavours of zImage
 
 ifneq ($(CROSS32_COMPILE),)
@@ -243,3 +282,51 @@
 clean-kernel += $(addsuffix .gz,$(clean-kernel))
 # If not absolute clean-files are relative to $(obj).
 clean-files += $(addprefix $(objtree)/, $(clean-kernel))
+
+WRAPPER_OBJDIR := /usr/lib/kernel-wrapper
+WRAPPER_DTSDIR := /usr/lib/kernel-wrapper/dts
+WRAPPER_BINDIR := /usr/sbin
+INSTALL := install
+
+extra-installed		:= $(patsubst $(obj)/%, $(DESTDIR)$(WRAPPER_OBJDIR)/%, $(extra-y))
+hostprogs-installed	:= $(patsubst %, $(DESTDIR)$(WRAPPER_BINDIR)/%, $(hostprogs-y))
+wrapper-installed	:= $(DESTDIR)$(WRAPPER_BINDIR)/wrapper
+dts-installed		:= $(patsubst $(obj)/dts/%, $(DESTDIR)$(WRAPPER_DTSDIR)/%, $(wildcard $(obj)/dts/*.dts))
+
+all-installed		:= $(extra-installed) $(hostprogs-installed) $(wrapper-installed) $(dts-installed)
+
+quiet_cmd_mkdir           = MKDIR   $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
+      cmd_mkdir           = mkdir -p $@
+
+quiet_cmd_install	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_OBJDIR)/%,%,$@)
+      cmd_install	  = $(INSTALL)  -m0644 $(patsubst $(DESTDIR)$(WRAPPER_OBJDIR)/%,$(obj)/%,$@) $@
+
+quiet_cmd_install_dts	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_DTSDIR)/%,dts/%,$@)
+      cmd_install_dts	  = $(INSTALL)  -m0644 $(patsubst $(DESTDIR)$(WRAPPER_DTSDIR)/%,$(srctree)/$(obj)/dts/%,$@) $@
+
+quiet_cmd_install_exe	  = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,%,$@)
+      cmd_install_exe	  = $(INSTALL)  -m0755 $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,$(obj)/%,$@) $@
+
+quiet_cmd_install_wrapper = INSTALL $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,%,$@)
+      cmd_install_wrapper = $(INSTALL)  -m0755 $(patsubst $(DESTDIR)$(WRAPPER_BINDIR)/%,$(srctree)/$(obj)/%,$@) $@ ;\
+				sed -i $@ -e 's%^object=.*%object=$(WRAPPER_OBJDIR)%' \
+					  -e 's%^objbin=.*%objbin=$(WRAPPER_BINDIR)%' \
+
+
+$(DESTDIR)$(WRAPPER_OBJDIR) $(DESTDIR)$(WRAPPER_DTSDIR) $(DESTDIR)$(WRAPPER_BINDIR):
+	$(call cmd,mkdir)
+
+$(extra-installed)	: $(DESTDIR)$(WRAPPER_OBJDIR)/% : $(obj)/% | $(DESTDIR)$(WRAPPER_OBJDIR)
+	$(call cmd,install)
+
+$(hostprogs-installed)  : $(DESTDIR)$(WRAPPER_BINDIR)/% : $(obj)/% | $(DESTDIR)$(WRAPPER_BINDIR)
+	$(call cmd,install_exe)
+
+$(dts-installed)	: $(DESTDIR)$(WRAPPER_DTSDIR)/% : $(srctree)/$(obj)/dts/% | $(DESTDIR)$(WRAPPER_DTSDIR)
+	$(call cmd,install_dts)
+
+$(wrapper-installed): $(DESTDIR)$(WRAPPER_BINDIR) $(srctree)/$(obj)/wrapper | $(DESTDIR)$(WRAPPER_BINDIR)
+	$(call cmd,install_wrapper)
+
+$(obj)/bootwrapper_install: $(all-installed)
+
diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c
index f61fcda..e634359 100644
--- a/arch/powerpc/boot/bamboo.c
+++ b/arch/powerpc/boot/bamboo.c
@@ -42,6 +42,6 @@
 	platform_ops.exit = ibm44x_dbcr_reset;
 	bamboo_mac0 = mac0;
 	bamboo_mac1 = mac1;
-	ft_init(_dtb_start, 0, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
diff --git a/arch/powerpc/boot/cuboot-52xx.c b/arch/powerpc/boot/cuboot-52xx.c
index 9256a26..a861154 100644
--- a/arch/powerpc/boot/cuboot-52xx.c
+++ b/arch/powerpc/boot/cuboot-52xx.c
@@ -53,7 +53,7 @@
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c
index a050550..acd860e 100644
--- a/arch/powerpc/boot/cuboot-83xx.c
+++ b/arch/powerpc/boot/cuboot-83xx.c
@@ -52,7 +52,7 @@
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c
index 345dcbe..943779e 100644
--- a/arch/powerpc/boot/cuboot-85xx.c
+++ b/arch/powerpc/boot/cuboot-85xx.c
@@ -53,7 +53,7 @@
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-8xx.c b/arch/powerpc/boot/cuboot-8xx.c
index 0e82015..c202c88 100644
--- a/arch/powerpc/boot/cuboot-8xx.c
+++ b/arch/powerpc/boot/cuboot-8xx.c
@@ -41,7 +41,7 @@
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-hpc2.c b/arch/powerpc/boot/cuboot-hpc2.c
index d333898..1b89532 100644
--- a/arch/powerpc/boot/cuboot-hpc2.c
+++ b/arch/powerpc/boot/cuboot-hpc2.c
@@ -42,7 +42,7 @@
 		unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-pq2.c b/arch/powerpc/boot/cuboot-pq2.c
index 61574f3..f56ac6c 100644
--- a/arch/powerpc/boot/cuboot-pq2.c
+++ b/arch/powerpc/boot/cuboot-pq2.c
@@ -255,7 +255,7 @@
                    unsigned long r6, unsigned long r7)
 {
 	CUBOOT_INIT();
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 	platform_ops.fixups = pq2_platform_fixups;
 }
diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c
index ec635e0..cf78260 100644
--- a/arch/powerpc/boot/cuboot-sequoia.c
+++ b/arch/powerpc/boot/cuboot-sequoia.c
@@ -51,6 +51,6 @@
 	CUBOOT_INIT();
 	platform_ops.fixups = sequoia_fixups;
 	platform_ops.exit = ibm44x_dbcr_reset;
-	ft_init(_dtb_start, 0, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
diff --git a/arch/powerpc/boot/dtc-src/Makefile.dtc b/arch/powerpc/boot/dtc-src/Makefile.dtc
new file mode 100644
index 0000000..d607fdb
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/Makefile.dtc
@@ -0,0 +1,25 @@
+# Makefile.dtc
+#
+# This is not a complete Makefile of itself.  Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
+	checks.c
+DTC_EXTRA = dtc.h srcpos.h
+DTC_LEXFILES = dtc-lexer.l
+DTC_BISONFILES = dtc-parser.y
+
+DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c)
+DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c)
+DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h)
+
+DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS)
+DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES)
+DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
+
+DTC_CLEANFILES = $(DTC_GEN_ALL)
+
+# We assume the containing Makefile system can do auto-dependencies for most
+# things, but we supply the dependencies on generated header files explicitly
+
+$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES))
diff --git a/arch/powerpc/boot/dtc-src/checks.c b/arch/powerpc/boot/dtc-src/checks.c
new file mode 100644
index 0000000..2ce961c
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/checks.c
@@ -0,0 +1,750 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2007.
+ *
+ *
+ * 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 "dtc.h"
+
+#ifdef TRACE_CHECKS
+#define TRACE(c, ...) \
+	do { \
+		fprintf(stderr, "=== %s: ", (c)->name); \
+		fprintf(stderr, __VA_ARGS__); \
+		fprintf(stderr, "\n"); \
+	} while (0)
+#else
+#define TRACE(c, fmt, ...)	do { } while (0)
+#endif
+
+enum checklevel {
+	IGNORE = 0,
+	WARN = 1,
+	ERROR = 2,
+};
+
+enum checkstatus {
+	UNCHECKED = 0,
+	PREREQ,
+	PASSED,
+	FAILED,
+};
+
+struct check;
+
+typedef void (*tree_check_fn)(struct check *c, struct node *dt);
+typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*prop_check_fn)(struct check *c, struct node *dt,
+			      struct node *node, struct property *prop);
+
+struct check {
+	const char *name;
+	tree_check_fn tree_fn;
+	node_check_fn node_fn;
+	prop_check_fn prop_fn;
+	void *data;
+	enum checklevel level;
+	enum checkstatus status;
+	int inprogress;
+	int num_prereqs;
+	struct check **prereq;
+};
+
+#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
+	static struct check nm = { \
+		.name = #nm, \
+		.tree_fn = (tfn), \
+		.node_fn = (nfn), \
+		.prop_fn = (pfn), \
+		.data = (d), \
+		.level = (lvl), \
+		.status = UNCHECKED, \
+		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
+		.prereq = nm##_prereqs, \
+	};
+
+#define TREE_CHECK(nm, d, lvl, ...) \
+	CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
+#define NODE_CHECK(nm, d, lvl, ...) \
+	CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
+#define PROP_CHECK(nm, d, lvl, ...) \
+	CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
+#define BATCH_CHECK(nm, lvl, ...) \
+	CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+
+#ifdef __GNUC__
+static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
+#endif
+static inline void check_msg(struct check *c, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+
+	if ((c->level < WARN) || (c->level <= quiet))
+		return; /* Suppress message */
+
+	fprintf(stderr, "%s (%s): ",
+		(c->level == ERROR) ? "ERROR" : "Warning", c->name);
+	vfprintf(stderr, fmt, ap);
+	fprintf(stderr, "\n");
+}
+
+#define FAIL(c, ...) \
+	do { \
+		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+		(c)->status = FAILED; \
+		check_msg((c), __VA_ARGS__); \
+	} while (0)
+
+static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+{
+	struct node *child;
+	struct property *prop;
+
+	TRACE(c, "%s", node->fullpath);
+	if (c->node_fn)
+		c->node_fn(c, dt, node);
+
+	if (c->prop_fn)
+		for_each_property(node, prop) {
+			TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
+			c->prop_fn(c, dt, node, prop);
+		}
+
+	for_each_child(node, child)
+		check_nodes_props(c, dt, child);
+}
+
+static int run_check(struct check *c, struct node *dt)
+{
+	int error = 0;
+	int i;
+
+	assert(!c->inprogress);
+
+	if (c->status != UNCHECKED)
+		goto out;
+
+	c->inprogress = 1;
+
+	for (i = 0; i < c->num_prereqs; i++) {
+		struct check *prq = c->prereq[i];
+		error |= run_check(prq, dt);
+		if (prq->status != PASSED) {
+			c->status = PREREQ;
+			check_msg(c, "Failed prerequisite '%s'",
+				  c->prereq[i]->name);
+		}
+	}
+
+	if (c->status != UNCHECKED)
+		goto out;
+
+	if (c->node_fn || c->prop_fn)
+		check_nodes_props(c, dt, dt);
+
+	if (c->tree_fn)
+		c->tree_fn(c, dt);
+	if (c->status == UNCHECKED)
+		c->status = PASSED;
+
+	TRACE(c, "\tCompleted, status %d", c->status);
+
+out:
+	c->inprogress = 0;
+	if ((c->status != PASSED) && (c->level == ERROR))
+		error = 1;
+	return error;
+}
+
+/*
+ * Utility check functions
+ */
+
+static void check_is_string(struct check *c, struct node *root,
+			    struct node *node)
+{
+	struct property *prop;
+	char *propname = c->data;
+
+	prop = get_property(node, propname);
+	if (!prop)
+		return; /* Not present, assumed ok */
+
+	if (!data_is_one_string(prop->val))
+		FAIL(c, "\"%s\" property in %s is not a string",
+		     propname, node->fullpath);
+}
+#define CHECK_IS_STRING(nm, propname, lvl) \
+	CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+
+static void check_is_cell(struct check *c, struct node *root,
+			  struct node *node)
+{
+	struct property *prop;
+	char *propname = c->data;
+
+	prop = get_property(node, propname);
+	if (!prop)
+		return; /* Not present, assumed ok */
+
+	if (prop->val.len != sizeof(cell_t))
+		FAIL(c, "\"%s\" property in %s is not a single cell",
+		     propname, node->fullpath);
+}
+#define CHECK_IS_CELL(nm, propname, lvl) \
+	CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+
+/*
+ * Structural check functions
+ */
+
+static void check_duplicate_node_names(struct check *c, struct node *dt,
+				       struct node *node)
+{
+	struct node *child, *child2;
+
+	for_each_child(node, child)
+		for (child2 = child->next_sibling;
+		     child2;
+		     child2 = child2->next_sibling)
+			if (streq(child->name, child2->name))
+				FAIL(c, "Duplicate node name %s",
+				     child->fullpath);
+}
+NODE_CHECK(duplicate_node_names, NULL, ERROR);
+
+static void check_duplicate_property_names(struct check *c, struct node *dt,
+					   struct node *node)
+{
+	struct property *prop, *prop2;
+
+	for_each_property(node, prop)
+		for (prop2 = prop->next; prop2; prop2 = prop2->next)
+			if (streq(prop->name, prop2->name))
+				FAIL(c, "Duplicate property name %s in %s",
+				     prop->name, node->fullpath);
+}
+NODE_CHECK(duplicate_property_names, NULL, ERROR);
+
+static void check_explicit_phandles(struct check *c, struct node *root,
+					  struct node *node)
+{
+	struct property *prop;
+	struct node *other;
+	cell_t phandle;
+
+	prop = get_property(node, "linux,phandle");
+	if (! prop)
+		return; /* No phandle, that's fine */
+
+	if (prop->val.len != sizeof(cell_t)) {
+		FAIL(c, "%s has bad length (%d) linux,phandle property",
+		     node->fullpath, prop->val.len);
+		return;
+	}
+
+	phandle = propval_cell(prop);
+	if ((phandle == 0) || (phandle == -1)) {
+		FAIL(c, "%s has invalid linux,phandle value 0x%x",
+		     node->fullpath, phandle);
+		return;
+	}
+
+	other = get_node_by_phandle(root, phandle);
+	if (other) {
+		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+		     node->fullpath, phandle, other->fullpath);
+		return;
+	}
+
+	node->phandle = phandle;
+}
+NODE_CHECK(explicit_phandles, NULL, ERROR);
+
+static void check_name_properties(struct check *c, struct node *root,
+				  struct node *node)
+{
+	struct property *prop;
+
+	prop = get_property(node, "name");
+	if (!prop)
+		return; /* No name property, that's fine */
+
+	if ((prop->val.len != node->basenamelen+1)
+	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0))
+		FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
+		     " of base node name)", node->fullpath, prop->val.val);
+}
+CHECK_IS_STRING(name_is_string, "name", ERROR);
+NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+
+/*
+ * Reference fixup functions
+ */
+
+static void fixup_phandle_references(struct check *c, struct node *dt,
+				     struct node *node, struct property *prop)
+{
+      struct marker *m = prop->val.markers;
+      struct node *refnode;
+      cell_t phandle;
+
+      for_each_marker_of_type(m, REF_PHANDLE) {
+	      assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+	      refnode = get_node_by_ref(dt, m->ref);
+	      if (! refnode) {
+		      FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+			   m->ref);
+		      continue;
+	      }
+
+	      phandle = get_node_phandle(dt, refnode);
+	      *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle);
+      }
+}
+CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+      &duplicate_node_names, &explicit_phandles);
+
+static void fixup_path_references(struct check *c, struct node *dt,
+				  struct node *node, struct property *prop)
+{
+	struct marker *m = prop->val.markers;
+	struct node *refnode;
+	char *path;
+
+	for_each_marker_of_type(m, REF_PATH) {
+		assert(m->offset <= prop->val.len);
+
+		refnode = get_node_by_ref(dt, m->ref);
+		if (!refnode) {
+			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+			     m->ref);
+			continue;
+		}
+
+		path = refnode->fullpath;
+		prop->val = data_insert_at_marker(prop->val, m, path,
+						  strlen(path) + 1);
+	}
+}
+CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+      &duplicate_node_names);
+
+/*
+ * Semantic checks
+ */
+CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
+CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
+CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+
+CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
+CHECK_IS_STRING(model_is_string, "model", WARN);
+CHECK_IS_STRING(status_is_string, "status", WARN);
+
+static void fixup_addr_size_cells(struct check *c, struct node *dt,
+				  struct node *node)
+{
+	struct property *prop;
+
+	node->addr_cells = -1;
+	node->size_cells = -1;
+
+	prop = get_property(node, "#address-cells");
+	if (prop)
+		node->addr_cells = propval_cell(prop);
+
+	prop = get_property(node, "#size-cells");
+	if (prop)
+		node->size_cells = propval_cell(prop);
+}
+CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
+      &address_cells_is_cell, &size_cells_is_cell);
+
+#define node_addr_cells(n) \
+	(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
+#define node_size_cells(n) \
+	(((n)->size_cells == -1) ? 1 : (n)->size_cells)
+
+static void check_reg_format(struct check *c, struct node *dt,
+			     struct node *node)
+{
+	struct property *prop;
+	int addr_cells, size_cells, entrylen;
+
+	prop = get_property(node, "reg");
+	if (!prop)
+		return; /* No "reg", that's fine */
+
+	if (!node->parent) {
+		FAIL(c, "Root node has a \"reg\" property");
+		return;
+	}
+
+	if (prop->val.len == 0)
+		FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
+
+	addr_cells = node_addr_cells(node->parent);
+	size_cells = node_size_cells(node->parent);
+	entrylen = (addr_cells + size_cells) * sizeof(cell_t);
+
+	if ((prop->val.len % entrylen) != 0)
+		FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
+		     "(#address-cells == %d, #size-cells == %d)",
+		     node->fullpath, prop->val.len, addr_cells, size_cells);
+}
+NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+
+static void check_ranges_format(struct check *c, struct node *dt,
+				struct node *node)
+{
+	struct property *prop;
+	int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
+
+	prop = get_property(node, "ranges");
+	if (!prop)
+		return;
+
+	if (!node->parent) {
+		FAIL(c, "Root node has a \"ranges\" property");
+		return;
+	}
+
+	p_addr_cells = node_addr_cells(node->parent);
+	p_size_cells = node_size_cells(node->parent);
+	c_addr_cells = node_addr_cells(node);
+	c_size_cells = node_size_cells(node);
+	entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
+
+	if (prop->val.len == 0) {
+		if (p_addr_cells != c_addr_cells)
+			FAIL(c, "%s has empty \"ranges\" property but its "
+			     "#address-cells (%d) differs from %s (%d)",
+			     node->fullpath, c_addr_cells, node->parent->fullpath,
+			     p_addr_cells);
+		if (p_size_cells != c_size_cells)
+			FAIL(c, "%s has empty \"ranges\" property but its "
+			     "#size-cells (%d) differs from %s (%d)",
+			     node->fullpath, c_size_cells, node->parent->fullpath,
+			     p_size_cells);
+	} else if ((prop->val.len % entrylen) != 0) {
+		FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
+		     "(parent #address-cells == %d, child #address-cells == %d, "
+		     "#size-cells == %d)", node->fullpath, prop->val.len,
+		     p_addr_cells, c_addr_cells, c_size_cells);
+	}
+}
+NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+
+/*
+ * Style checks
+ */
+static void check_avoid_default_addr_size(struct check *c, struct node *dt,
+					  struct node *node)
+{
+	struct property *reg, *ranges;
+
+	if (!node->parent)
+		return; /* Ignore root node */
+
+	reg = get_property(node, "reg");
+	ranges = get_property(node, "ranges");
+
+	if (!reg && !ranges)
+		return;
+
+	if ((node->parent->addr_cells == -1))
+		FAIL(c, "Relying on default #address-cells value for %s",
+		     node->fullpath);
+
+	if ((node->parent->size_cells == -1))
+		FAIL(c, "Relying on default #size-cells value for %s",
+		     node->fullpath);
+}
+NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+
+static void check_obsolete_chosen_interrupt_controller(struct check *c,
+						       struct node *dt)
+{
+	struct node *chosen;
+	struct property *prop;
+
+	chosen = get_node_by_path(dt, "/chosen");
+	if (!chosen)
+		return;
+
+	prop = get_property(chosen, "interrupt-controller");
+	if (prop)
+		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
+		     "property");
+}
+TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+
+static struct check *check_table[] = {
+	&duplicate_node_names, &duplicate_property_names,
+	&name_is_string, &name_properties,
+	&explicit_phandles,
+	&phandle_references, &path_references,
+
+	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+	&device_type_is_string, &model_is_string, &status_is_string,
+
+	&addr_size_cells, &reg_format, &ranges_format,
+
+	&avoid_default_addr_size,
+	&obsolete_chosen_interrupt_controller,
+};
+
+int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
+
+void process_checks(int force, struct boot_info *bi,
+		    int checkflag, int outversion, int boot_cpuid_phys)
+{
+	struct node *dt = bi->dt;
+	int i;
+	int error = 0;
+
+	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+		struct check *c = check_table[i];
+
+		if (c->level != IGNORE)
+			error = error || run_check(c, dt);
+	}
+
+	if (error) {
+		if (!force) {
+			fprintf(stderr, "ERROR: Input tree has errors, aborting "
+				"(use -f to force output)\n");
+			exit(2);
+		} else if (quiet < 3) {
+			fprintf(stderr, "Warning: Input tree has errors, "
+				"output forced\n");
+		}
+	}
+
+	if (checkflag) {
+		if (error) {
+			fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
+		} else {
+			if (!check_semantics(bi->dt, outversion,
+					     boot_cpuid_phys))
+				fprintf(stderr, "Warning: Input tree has semantic errors\n");
+		}
+	}
+}
+
+/*
+ * Semantic check functions
+ */
+
+#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
+#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
+
+#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
+
+#define CHECK_HAVE(node, propname) \
+	do { \
+		if (! (prop = get_property((node), (propname)))) \
+			DO_ERR("Missing \"%s\" property in %s\n", (propname), \
+				(node)->fullpath); \
+	} while (0);
+
+#define CHECK_HAVE_WARN(node, propname) \
+	do { \
+		if (! (prop  = get_property((node), (propname)))) \
+			WARNMSG("%s has no \"%s\" property\n", \
+				(node)->fullpath, (propname)); \
+	} while (0)
+
+#define CHECK_HAVE_STRING(node, propname) \
+	do { \
+		CHECK_HAVE((node), (propname)); \
+		if (prop && !data_is_one_string(prop->val)) \
+			DO_ERR("\"%s\" property in %s is not a string\n", \
+				(propname), (node)->fullpath); \
+	} while (0)
+
+#define CHECK_HAVE_STREQ(node, propname, value) \
+	do { \
+		CHECK_HAVE_STRING((node), (propname)); \
+		if (prop && !streq(prop->val.val, (value))) \
+			DO_ERR("%s has wrong %s, %s (should be %s\n", \
+				(node)->fullpath, (propname), \
+				prop->val.val, (value)); \
+	} while (0)
+
+#define CHECK_HAVE_ONECELL(node, propname) \
+	do { \
+		CHECK_HAVE((node), (propname)); \
+		if (prop && (prop->val.len != sizeof(cell_t))) \
+			DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
+	} while (0)
+
+#define CHECK_HAVE_WARN_ONECELL(node, propname) \
+	do { \
+		CHECK_HAVE_WARN((node), (propname)); \
+		if (prop && (prop->val.len != sizeof(cell_t))) \
+			DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
+	} while (0)
+
+#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
+	do { \
+		struct node *ref; \
+		CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
+		if (prop) {\
+			cell_t phandle = propval_cell(prop); \
+			if ((phandle == 0) || (phandle == -1)) { \
+				DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
+			} else { \
+				ref = get_node_by_phandle((root), propval_cell(prop)); \
+				if (! ref) \
+					DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
+			} \
+		} \
+	} while (0)
+
+#define CHECK_HAVE_WARN_STRING(node, propname) \
+	do { \
+		CHECK_HAVE_WARN((node), (propname)); \
+		if (prop && !data_is_one_string(prop->val)) \
+			DO_ERR("\"%s\" property in %s is not a string\n", \
+				(propname), (node)->fullpath); \
+	} while (0)
+
+static int check_root(struct node *root)
+{
+	struct property *prop;
+	int ok = 1;
+
+	CHECK_HAVE_STRING(root, "model");
+	CHECK_HAVE_WARN(root, "compatible");
+
+	return ok;
+}
+
+static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
+{
+	struct node *cpus, *cpu;
+	struct property *prop;
+	struct node *bootcpu = NULL;
+	int ok = 1;
+
+	cpus = get_subnode(root, "cpus");
+	if (! cpus) {
+		ERRMSG("Missing /cpus node\n");
+		return 0;
+	}
+
+	if (cpus->addr_cells != 1)
+		DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
+		       cpus->fullpath, cpus->addr_cells);
+	if (cpus->size_cells != 0)
+		DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
+		       cpus->fullpath, cpus->size_cells);
+
+	for_each_child(cpus, cpu) {
+		CHECK_HAVE_STREQ(cpu, "device_type", "cpu");
+
+		CHECK_HAVE_ONECELL(cpu, "reg");
+		if (prop) {
+			cell_t unitnum;
+			char *eptr;
+
+			unitnum = strtol(get_unitname(cpu), &eptr, 16);
+			if (*eptr) {
+				WARNMSG("%s has bad format unit name %s (should be CPU number\n",
+					cpu->fullpath, get_unitname(cpu));
+			} else if (unitnum != propval_cell(prop)) {
+				WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
+				       cpu->fullpath, get_unitname(cpu),
+				       propval_cell(prop));
+			}
+		}
+
+/* 		CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
+/* 		CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
+		CHECK_HAVE_ONECELL(cpu, "d-cache-size");
+		CHECK_HAVE_ONECELL(cpu, "i-cache-size");
+
+		CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
+		CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");
+
+		prop = get_property(cpu, "linux,boot-cpu");
+		if (prop) {
+			if (prop->val.len)
+				WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
+					cpu->fullpath);
+			if (bootcpu)
+				DO_ERR("Multiple boot cpus (%s and %s)\n",
+				       bootcpu->fullpath, cpu->fullpath);
+			else
+				bootcpu = cpu;
+		}
+	}
+
+	if (outversion < 2) {
+		if (! bootcpu)
+			WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
+	} else {
+		if (bootcpu)
+			WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
+		if (boot_cpuid_phys == 0xfeedbeef)
+			WARNMSG("physical boot CPU not set.  Use -b option to set\n");
+	}
+
+	return ok;
+}
+
+static int check_memory(struct node *root)
+{
+	struct node *mem;
+	struct property *prop;
+	int nnodes = 0;
+	int ok = 1;
+
+	for_each_child(root, mem) {
+		if (! strneq(mem->name, "memory", mem->basenamelen))
+			continue;
+
+		nnodes++;
+
+		CHECK_HAVE_STREQ(mem, "device_type", "memory");
+		CHECK_HAVE(mem, "reg");
+	}
+
+	if (nnodes == 0) {
+		ERRMSG("No memory nodes\n");
+		return 0;
+	}
+
+	return ok;
+}
+
+int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
+{
+	int ok = 1;
+
+	ok = ok && check_root(dt);
+	ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
+	ok = ok && check_memory(dt);
+	if (! ok)
+		return 0;
+
+	return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/data.c b/arch/powerpc/boot/dtc-src/data.c
new file mode 100644
index 0000000..a94718c
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/data.c
@@ -0,0 +1,321 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+
+void data_free(struct data d)
+{
+	struct marker *m, *nm;
+
+	m = d.markers;
+	while (m) {
+		nm = m->next;
+		free(m->ref);
+		free(m);
+		m = nm;
+	}
+
+	assert(!d.val || d.asize);
+
+	if (d.val)
+		free(d.val);
+}
+
+struct data data_grow_for(struct data d, int xlen)
+{
+	struct data nd;
+	int newsize;
+
+	/* we must start with an allocated datum */
+	assert(!d.val || d.asize);
+
+	if (xlen == 0)
+		return d;
+
+	nd = d;
+
+	newsize = xlen;
+
+	while ((d.len + xlen) > newsize)
+		newsize *= 2;
+
+	nd.asize = newsize;
+	nd.val = xrealloc(d.val, newsize);
+
+	assert(nd.asize >= (d.len + xlen));
+
+	return nd;
+}
+
+struct data data_copy_mem(const char *mem, int len)
+{
+	struct data d;
+
+	d = data_grow_for(empty_data, len);
+
+	d.len = len;
+	memcpy(d.val, mem, len);
+
+	return d;
+}
+
+static char get_oct_char(const char *s, int *i)
+{
+	char x[4];
+	char *endx;
+	long val;
+
+	x[3] = '\0';
+	x[0] = s[(*i)];
+	if (x[0]) {
+		x[1] = s[(*i)+1];
+		if (x[1])
+			x[2] = s[(*i)+2];
+	}
+
+	val = strtol(x, &endx, 8);
+	if ((endx - x) == 0)
+		fprintf(stderr, "Empty \\nnn escape\n");
+
+	(*i) += endx - x;
+	return val;
+}
+
+static char get_hex_char(const char *s, int *i)
+{
+	char x[3];
+	char *endx;
+	long val;
+
+	x[2] = '\0';
+	x[0] = s[(*i)];
+	if (x[0])
+		x[1] = s[(*i)+1];
+
+	val = strtol(x, &endx, 16);
+	if ((endx - x) == 0)
+		fprintf(stderr, "Empty \\x escape\n");
+
+	(*i) += endx - x;
+	return val;
+}
+
+struct data data_copy_escape_string(const char *s, int len)
+{
+	int i = 0;
+	struct data d;
+	char *q;
+
+	d = data_grow_for(empty_data, strlen(s)+1);
+
+	q = d.val;
+	while (i < len) {
+		char c = s[i++];
+
+		if (c != '\\') {
+			q[d.len++] = c;
+			continue;
+		}
+
+		c = s[i++];
+		assert(c);
+		switch (c) {
+		case 'a':
+			q[d.len++] = '\a';
+			break;
+		case 'b':
+			q[d.len++] = '\b';
+			break;
+		case 't':
+			q[d.len++] = '\t';
+			break;
+		case 'n':
+			q[d.len++] = '\n';
+			break;
+		case 'v':
+			q[d.len++] = '\v';
+			break;
+		case 'f':
+			q[d.len++] = '\f';
+			break;
+		case 'r':
+			q[d.len++] = '\r';
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+			i--; /* need to re-read the first digit as
+			      * part of the octal value */
+			q[d.len++] = get_oct_char(s, &i);
+			break;
+		case 'x':
+			q[d.len++] = get_hex_char(s, &i);
+			break;
+		default:
+			q[d.len++] = c;
+		}
+	}
+
+	q[d.len++] = '\0';
+	return d;
+}
+
+struct data data_copy_file(FILE *f, size_t len)
+{
+	struct data d;
+
+	d = data_grow_for(empty_data, len);
+
+	d.len = len;
+	fread(d.val, len, 1, f);
+
+	return d;
+}
+
+struct data data_append_data(struct data d, const void *p, int len)
+{
+	d = data_grow_for(d, len);
+	memcpy(d.val + d.len, p, len);
+	d.len += len;
+	return d;
+}
+
+struct data data_insert_at_marker(struct data d, struct marker *m,
+				  const void *p, int len)
+{
+	d = data_grow_for(d, len);
+	memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
+	memcpy(d.val + m->offset, p, len);
+	d.len += len;
+
+	/* Adjust all markers after the one we're inserting at */
+	m = m->next;
+	for_each_marker(m)
+		m->offset += len;
+	return d;
+}
+
+struct data data_append_markers(struct data d, struct marker *m)
+{
+	struct marker **mp = &d.markers;
+
+	/* Find the end of the markerlist */
+	while (*mp)
+		mp = &((*mp)->next);
+	*mp = m;
+	return d;
+}
+
+struct data data_merge(struct data d1, struct data d2)
+{
+	struct data d;
+	struct marker *m2 = d2.markers;
+
+	d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
+
+	/* Adjust for the length of d1 */
+	for_each_marker(m2)
+		m2->offset += d1.len;
+
+	d2.markers = NULL; /* So data_free() doesn't clobber them */
+	data_free(d2);
+
+	return d;
+}
+
+struct data data_append_cell(struct data d, cell_t word)
+{
+	cell_t beword = cpu_to_be32(word);
+
+	return data_append_data(d, &beword, sizeof(beword));
+}
+
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+{
+	struct fdt_reserve_entry bere;
+
+	bere.address = cpu_to_be64(re->address);
+	bere.size = cpu_to_be64(re->size);
+
+	return data_append_data(d, &bere, sizeof(bere));
+}
+
+struct data data_append_addr(struct data d, u64 addr)
+{
+	u64 beaddr = cpu_to_be64(addr);
+
+	return data_append_data(d, &beaddr, sizeof(beaddr));
+}
+
+struct data data_append_byte(struct data d, uint8_t byte)
+{
+	return data_append_data(d, &byte, 1);
+}
+
+struct data data_append_zeroes(struct data d, int len)
+{
+	d = data_grow_for(d, len);
+
+	memset(d.val + d.len, 0, len);
+	d.len += len;
+	return d;
+}
+
+struct data data_append_align(struct data d, int align)
+{
+	int newlen = ALIGN(d.len, align);
+	return data_append_zeroes(d, newlen - d.len);
+}
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref)
+{
+	struct marker *m;
+
+	m = xmalloc(sizeof(*m));
+	m->offset = d.len;
+	m->type = type;
+	m->ref = ref;
+	m->next = NULL;
+
+	return data_append_markers(d, m);
+}
+
+int data_is_one_string(struct data d)
+{
+	int i;
+	int len = d.len;
+
+	if (len == 0)
+		return 0;
+
+	for (i = 0; i < len-1; i++)
+		if (d.val[i] == '\0')
+			return 0;
+
+	if (d.val[len-1] != '\0')
+		return 0;
+
+	return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.l b/arch/powerpc/boot/dtc-src/dtc-lexer.l
new file mode 100644
index 0000000..c811b22
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc-lexer.l
@@ -0,0 +1,328 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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
+ */
+
+%option noyywrap nounput yylineno
+
+%x INCLUDE
+%x BYTESTRING
+%x PROPNODENAME
+%s V1
+
+PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
+PATHCHAR	({PROPNODECHAR}|[/])
+LABEL		[a-zA-Z_][a-zA-Z0-9_]*
+
+%{
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG	1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...)	do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT()	if (dts_version == 0) { \
+				DPRINT("<INITIAL>\n"); \
+				BEGIN(INITIAL); \
+			} else { \
+				DPRINT("<V1>\n"); \
+				BEGIN(V1); \
+			}
+%}
+
+%%
+<*>"/include/"		BEGIN(INCLUDE);
+
+<INCLUDE>\"[^"\n]*\"	{
+			yytext[strlen(yytext) - 1] = 0;
+			if (!push_input_file(yytext + 1)) {
+				/* Some unrecoverable error.*/
+				exit(1);
+			}
+			BEGIN_DEFAULT();
+		}
+
+
+<*><<EOF>>		{
+			if (!pop_input_file()) {
+				yyterminate();
+			}
+		}
+
+<*>\"([^\\"]|\\.)*\"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("String: %s\n", yytext);
+			yylval.data = data_copy_escape_string(yytext+1,
+					yyleng-2);
+			yylloc.first_line = yylineno;
+			return DT_STRING;
+		}
+
+<*>"/dts-v1/"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Keyword: /dts-v1/\n");
+			dts_version = 1;
+			BEGIN_DEFAULT();
+			return DT_V1;
+		}
+
+<*>"/memreserve/"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Keyword: /memreserve/\n");
+			BEGIN_DEFAULT();
+			return DT_MEMRESERVE;
+		}
+
+<*>{LABEL}:	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Label: %s\n", yytext);
+			yylval.labelref = strdup(yytext);
+			yylval.labelref[yyleng-1] = '\0';
+			return DT_LABEL;
+		}
+
+<INITIAL>[bodh]# {
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			if (*yytext == 'b')
+				yylval.cbase = 2;
+			else if (*yytext == 'o')
+				yylval.cbase = 8;
+			else if (*yytext == 'd')
+				yylval.cbase = 10;
+			else
+				yylval.cbase = 16;
+			DPRINT("Base: %d\n", yylval.cbase);
+			return DT_BASE;
+		}
+
+<INITIAL>[0-9a-fA-F]+	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LEGACYLITERAL;
+		}
+
+<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LITERAL;
+		}
+
+\&{LABEL}	{	/* label reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Ref: %s\n", yytext+1);
+			yylval.labelref = strdup(yytext+1);
+			return DT_REF;
+		}
+
+"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yytext[yyleng-1] = '\0';
+			DPRINT("Ref: %s\n", yytext+2);
+			yylval.labelref = strdup(yytext+2);
+			return DT_REF;
+		}
+
+<INITIAL>"&/"{PATHCHAR}+ {	/* old-style path reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Ref: %s\n", yytext+1);
+			yylval.labelref = strdup(yytext+1);
+			return DT_REF;
+		}
+
+<BYTESTRING>[0-9a-fA-F]{2} {
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.byte = strtol(yytext, NULL, 16);
+			DPRINT("Byte: %02x\n", (int)yylval.byte);
+			return DT_BYTE;
+		}
+
+<BYTESTRING>"]"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("/BYTESTRING\n");
+			BEGIN_DEFAULT();
+			return ']';
+		}
+
+<PROPNODENAME>{PROPNODECHAR}+ {
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("PropNodeName: %s\n", yytext);
+			yylval.propnodename = strdup(yytext);
+			BEGIN_DEFAULT();
+			return DT_PROPNODENAME;
+		}
+
+
+<*>[[:space:]]+	/* eat whitespace */
+
+<*>"/*"([^*]|\*+[^*/])*\*+"/"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Comment: %s\n", yytext);
+			/* eat comments */
+		}
+
+<*>"//".*\n	/* eat line comments */
+
+<*>.		{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+				(unsigned)yytext[0]);
+			if (yytext[0] == '[') {
+				DPRINT("<BYTESTRING>\n");
+				BEGIN(BYTESTRING);
+			}
+			if ((yytext[0] == '{')
+			    || (yytext[0] == ';')) {
+				DPRINT("<PROPNODENAME>\n");
+				BEGIN(PROPNODENAME);
+			}
+			return yytext[0];
+		}
+
+%%
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+	int filenum;
+	FILE *file;
+	YY_BUFFER_STATE yy_prev_buf;
+	int yy_prev_lineno;
+	struct incl_file *prev;
+};
+
+struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH	(100)
+
+static int incl_depth = 0;
+
+
+int push_input_file(const char *filename)
+{
+	FILE *f;
+	struct incl_file *incl_file;
+
+	if (!filename) {
+		yyerror("No include file name given.");
+		return 0;
+	}
+
+	if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
+		yyerror("Includes nested too deeply");
+		return 0;
+	}
+
+	f = dtc_open_file(filename);
+
+	incl_file = malloc(sizeof(struct incl_file));
+	if (!incl_file) {
+		yyerror("Can not allocate include file space.");
+		return 0;
+	}
+
+	/*
+	 * Save current context.
+	 */
+	incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+	incl_file->yy_prev_lineno = yylineno;
+	incl_file->filenum = srcpos_filenum;
+	incl_file->file = yyin;
+	incl_file->prev = incl_file_stack;
+
+	incl_file_stack = incl_file;
+
+	/*
+	 * Establish new context.
+	 */
+	srcpos_filenum = lookup_file_name(filename, 0);
+	yylineno = 1;
+	yyin = f;
+	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+
+	return 1;
+}
+
+
+int pop_input_file(void)
+{
+	struct incl_file *incl_file;
+
+	if (incl_file_stack == 0)
+		return 0;
+
+	fclose(yyin);
+
+	/*
+	 * Pop.
+	 */
+	--incl_depth;
+	incl_file = incl_file_stack;
+	incl_file_stack = incl_file->prev;
+
+	/*
+	 * Recover old context.
+	 */
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	yy_switch_to_buffer(incl_file->yy_prev_buf);
+	yylineno = incl_file->yy_prev_lineno;
+	srcpos_filenum = incl_file->filenum;
+	yyin = incl_file->file;
+
+	/*
+	 * Free old state.
+	 */
+	free(incl_file);
+
+	if (YY_CURRENT_BUFFER == 0)
+		return 0;
+
+	return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped b/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped
new file mode 100644
index 0000000..d0f7424
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped
@@ -0,0 +1,2174 @@
+#line 2 "dtc-lexer.lex.c"
+
+#line 4 "dtc-lexer.lex.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = (yy_hold_char); \
+		YY_RESTORE_YY_MORE_OFFSET \
+		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	(yytext_ptr) = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	(yy_hold_char) = *yy_cp; \
+	*yy_cp = '\0'; \
+	(yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 20
+#define YY_END_OF_BUFFER 21
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[94] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       21,   19,   16,   16,   19,   19,   19,    8,    8,   19,
+        8,   19,   19,   19,   19,   14,   15,   15,   19,    9,
+        9,   16,    0,    3,    0,    0,   10,    0,    0,    0,
+        0,    0,    0,    8,    8,    6,    0,    7,    0,    2,
+        0,   13,   13,   15,   15,    9,    0,   12,   10,    0,
+        0,    0,    0,   18,    0,    0,    0,    2,    9,    0,
+       17,    0,    0,    0,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    4,    0,    0,    1,    0,    0,
+        0,    5,    0
+
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    6,    1,    1,
+        1,    7,    8,    8,    9,    8,   10,   11,   12,   13,
+       13,   13,   13,   13,   13,   13,   13,   14,    1,    1,
+        1,    1,    8,    8,   15,   15,   15,   15,   15,   15,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   17,   16,   16,
+        1,   18,   19,    1,   16,    1,   15,   20,   21,   22,
+
+       23,   15,   16,   24,   25,   16,   16,   26,   27,   28,
+       24,   16,   16,   29,   30,   31,   32,   33,   16,   17,
+       16,   16,   34,    1,   35,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[36] =
+    {   0,
+        1,    1,    1,    1,    2,    1,    2,    2,    2,    3,
+        4,    4,    4,    5,    6,    7,    7,    1,    1,    6,
+        6,    6,    6,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    8,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[107] =
+    {   0,
+        0,    0,   32,    0,   53,    0,   76,    0,  108,  111,
+      280,  288,   37,   39,   33,   36,  106,    0,  123,  146,
+      255,  251,   45,    0,  159,  288,    0,   53,  108,  172,
+      114,  127,  158,  288,  245,    0,    0,  234,  235,  236,
+      197,  195,  199,    0,    0,  288,    0,  288,  160,  288,
+      183,  288,    0,    0,  183,  182,    0,    0,    0,    0,
+      204,  189,  207,  288,  179,  187,  180,  194,    0,  171,
+      288,  196,  178,  174,  288,  169,  169,  177,  165,  153,
+      143,  155,  137,  118,  288,  122,   42,  288,   36,   36,
+       40,  288,  288,  212,  218,  223,  229,  234,  239,  245,
+
+      251,  255,  262,  270,  275,  280
+    } ;
+
+static yyconst flex_int16_t yy_def[107] =
+    {   0,
+       93,    1,    1,    3,    3,    5,   93,    7,    3,    3,
+       93,   93,   93,   93,   94,   95,   93,   96,   93,   19,
+       19,   20,   97,   98,   20,   93,   99,  100,   95,   93,
+       93,   93,   94,   93,   94,  101,  102,   93,  103,  104,
+       93,   93,   93,   96,   19,   93,   20,   93,   97,   93,
+       97,   93,   20,   99,  100,   93,  105,  101,  102,  106,
+      103,  103,  104,   93,   93,   93,   93,   94,  105,  106,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,    0,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93
+    } ;
+
+static yyconst flex_int16_t yy_nxt[324] =
+    {   0,
+       12,   13,   14,   15,   12,   16,   12,   12,   12,   17,
+       18,   18,   18,   12,   19,   20,   20,   12,   12,   21,
+       19,   21,   19,   22,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   12,   12,   23,   34,   12,   32,   32,
+       32,   32,   12,   12,   12,   36,   20,   33,   50,   92,
+       35,   20,   20,   20,   20,   20,   15,   54,   91,   54,
+       54,   54,   51,   24,   24,   24,   46,   25,   90,   38,
+       89,   26,   25,   25,   25,   25,   12,   13,   14,   15,
+       27,   12,   27,   27,   27,   17,   27,   27,   27,   12,
+       28,   28,   28,   12,   12,   28,   28,   28,   28,   28,
+
+       28,   28,   28,   28,   28,   28,   28,   28,   28,   12,
+       12,   15,   39,   29,   15,   40,   29,   93,   30,   31,
+       31,   30,   31,   31,   56,   56,   56,   41,   32,   32,
+       42,   88,   43,   45,   45,   45,   46,   45,   47,   47,
+       87,   38,   45,   45,   45,   45,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   86,
+       47,   34,   33,   50,   85,   47,   47,   47,   47,   53,
+       53,   53,   84,   53,   83,   35,   82,   51,   53,   53,
+       53,   53,   56,   56,   56,   93,   68,   54,   57,   54,
+       54,   54,   56,   56,   56,   62,   46,   34,   71,   81,
+
+       80,   79,   78,   77,   76,   75,   74,   73,   72,   64,
+       62,   35,   33,   33,   33,   33,   33,   33,   33,   33,
+       37,   67,   66,   37,   37,   37,   44,   65,   44,   49,
+       49,   49,   49,   49,   49,   49,   49,   52,   64,   52,
+       54,   62,   54,   60,   54,   54,   55,   93,   55,   55,
+       55,   55,   58,   58,   58,   48,   58,   58,   59,   48,
+       59,   59,   61,   61,   61,   61,   61,   61,   61,   61,
+       63,   63,   63,   63,   63,   63,   63,   63,   69,   93,
+       69,   70,   70,   70,   93,   70,   70,   11,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93
+    } ;
+
+static yyconst flex_int16_t yy_chk[324] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    3,   15,    3,   13,   13,
+       14,   14,    3,    3,    3,   16,    3,   23,   23,   91,
+       15,    3,    3,    3,    3,    3,    5,   28,   90,   28,
+       28,   28,   23,    5,    5,    5,   28,    5,   89,   16,
+       87,    5,    5,    5,    5,    5,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    9,   17,    9,   10,   17,   10,   29,    9,    9,
+        9,   10,   10,   10,   31,   31,   31,   17,   32,   32,
+       17,   86,   17,   19,   19,   19,   19,   19,   19,   19,
+       84,   29,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   20,   20,   20,   83,
+       20,   33,   49,   49,   82,   20,   20,   20,   20,   25,
+       25,   25,   81,   25,   80,   33,   79,   49,   25,   25,
+       25,   25,   30,   30,   30,   51,   51,   55,   30,   55,
+       55,   55,   56,   56,   56,   62,   55,   68,   62,   78,
+
+       77,   76,   74,   73,   72,   70,   67,   66,   65,   63,
+       61,   68,   94,   94,   94,   94,   94,   94,   94,   94,
+       95,   43,   42,   95,   95,   95,   96,   41,   96,   97,
+       97,   97,   97,   97,   97,   97,   97,   98,   40,   98,
+       99,   39,   99,   38,   99,   99,  100,   35,  100,  100,
+      100,  100,  101,  101,  101,   22,  101,  101,  102,   21,
+      102,  102,  103,  103,  103,  103,  103,  103,  103,  103,
+      104,  104,  104,  104,  104,  104,  104,  104,  105,   11,
+      105,  106,  106,  106,    0,  106,  106,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[21] =
+    {   0,
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 
+    0,     };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "dtc-lexer.l"
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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
+ */
+
+
+
+
+#line 33 "dtc-lexer.l"
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG	1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...)	do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT()	if (dts_version == 0) { \
+				DPRINT("<INITIAL>\n"); \
+				BEGIN(INITIAL); \
+			} else { \
+				DPRINT("<V1>\n"); \
+				BEGIN(V1); \
+			}
+#line 627 "dtc-lexer.lex.c"
+
+#define INITIAL 0
+#define INCLUDE 1
+#define BYTESTRING 2
+#define PROPNODENAME 3
+#define V1 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    
+#line 57 "dtc-lexer.l"
+
+#line 784 "dtc-lexer.lex.c"
+
+	if ( !(yy_init) )
+		{
+		(yy_init) = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! (yy_start) )
+			(yy_start) = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			yyensure_buffer_stack ();
+			YY_CURRENT_BUFFER_LVALUE =
+				yy_create_buffer(yyin,YY_BUF_SIZE );
+		}
+
+		yy_load_buffer_state( );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = (yy_c_buf_p);
+
+		/* Support of yytext. */
+		*yy_cp = (yy_hold_char);
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = (yy_start);
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				(yy_last_accepting_state) = yy_current_state;
+				(yy_last_accepting_cpos) = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 94 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 288 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    yylineno++;
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = (yy_hold_char);
+			yy_cp = (yy_last_accepting_cpos);
+			yy_current_state = (yy_last_accepting_state);
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 58 "dtc-lexer.l"
+BEGIN(INCLUDE);
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 60 "dtc-lexer.l"
+{
+			yytext[strlen(yytext) - 1] = 0;
+			if (!push_input_file(yytext + 1)) {
+				/* Some unrecoverable error.*/
+				exit(1);
+			}
+			BEGIN_DEFAULT();
+		}
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(INCLUDE):
+case YY_STATE_EOF(BYTESTRING):
+case YY_STATE_EOF(PROPNODENAME):
+case YY_STATE_EOF(V1):
+#line 70 "dtc-lexer.l"
+{
+			if (!pop_input_file()) {
+				yyterminate();
+			}
+		}
+	YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 76 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("String: %s\n", yytext);
+			yylval.data = data_copy_escape_string(yytext+1,
+					yyleng-2);
+			yylloc.first_line = yylineno;
+			return DT_STRING;
+		}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 86 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Keyword: /dts-v1/\n");
+			dts_version = 1;
+			BEGIN_DEFAULT();
+			return DT_V1;
+		}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 95 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Keyword: /memreserve/\n");
+			BEGIN_DEFAULT();
+			return DT_MEMRESERVE;
+		}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 103 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Label: %s\n", yytext);
+			yylval.labelref = strdup(yytext);
+			yylval.labelref[yyleng-1] = '\0';
+			return DT_LABEL;
+		}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 112 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			if (*yytext == 'b')
+				yylval.cbase = 2;
+			else if (*yytext == 'o')
+				yylval.cbase = 8;
+			else if (*yytext == 'd')
+				yylval.cbase = 10;
+			else
+				yylval.cbase = 16;
+			DPRINT("Base: %d\n", yylval.cbase);
+			return DT_BASE;
+		}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LEGACYLITERAL;
+		}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 135 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LITERAL;
+		}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 143 "dtc-lexer.l"
+{	/* label reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Ref: %s\n", yytext+1);
+			yylval.labelref = strdup(yytext+1);
+			return DT_REF;
+		}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 151 "dtc-lexer.l"
+{	/* new-style path reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yytext[yyleng-1] = '\0';
+			DPRINT("Ref: %s\n", yytext+2);
+			yylval.labelref = strdup(yytext+2);
+			return DT_REF;
+		}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 160 "dtc-lexer.l"
+{	/* old-style path reference */
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Ref: %s\n", yytext+1);
+			yylval.labelref = strdup(yytext+1);
+			return DT_REF;
+		}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 168 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.byte = strtol(yytext, NULL, 16);
+			DPRINT("Byte: %02x\n", (int)yylval.byte);
+			return DT_BYTE;
+		}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 176 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("/BYTESTRING\n");
+			BEGIN_DEFAULT();
+			return ']';
+		}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 184 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("PropNodeName: %s\n", yytext);
+			yylval.propnodename = strdup(yytext);
+			BEGIN_DEFAULT();
+			return DT_PROPNODENAME;
+		}
+	YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
+/* eat whitespace */
+	YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 196 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Comment: %s\n", yytext);
+			/* eat comments */
+		}
+	YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+/* eat line comments */
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+				(unsigned)yytext[0]);
+			if (yytext[0] == '[') {
+				DPRINT("<BYTESTRING>\n");
+				BEGIN(BYTESTRING);
+			}
+			if ((yytext[0] == '{')
+			    || (yytext[0] == ';')) {
+				DPRINT("<PROPNODENAME>\n");
+				BEGIN(PROPNODENAME);
+			}
+			return yytext[0];
+		}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 222 "dtc-lexer.l"
+ECHO;
+	YY_BREAK
+#line 1111 "dtc-lexer.lex.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = (yy_hold_char);
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state(  );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++(yy_c_buf_p);
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = (yy_c_buf_p);
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer(  ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				(yy_did_buffer_switch_on_eof) = 0;
+
+				if ( yywrap( ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				(yy_c_buf_p) =
+					(yytext_ptr) + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				(yy_c_buf_p) =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+				yy_current_state = yy_get_previous_state(  );
+
+				yy_cp = (yy_c_buf_p);
+				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = (yytext_ptr);
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			(yy_n_chars), (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	if ( (yy_n_chars) == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart(yyin  );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	(yy_n_chars) += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    
+	yy_current_state = (yy_start);
+
+	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			(yy_last_accepting_state) = yy_current_state;
+			(yy_last_accepting_cpos) = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 94 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+	register int yy_is_jam;
+    	register char *yy_cp = (yy_c_buf_p);
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		(yy_last_accepting_state) = yy_current_state;
+		(yy_last_accepting_cpos) = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 94 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 93);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+	int c;
+    
+	*(yy_c_buf_p) = (yy_hold_char);
+
+	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+			/* This was really a NUL. */
+			*(yy_c_buf_p) = '\0';
+
+		else
+			{ /* need more input */
+			int offset = (yy_c_buf_p) - (yytext_ptr);
+			++(yy_c_buf_p);
+
+			switch ( yy_get_next_buffer(  ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart(yyin );
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap( ) )
+						return EOF;
+
+					if ( ! (yy_did_buffer_switch_on_eof) )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					(yy_c_buf_p) = (yytext_ptr) + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+	(yy_hold_char) = *++(yy_c_buf_p);
+
+	if ( c == '\n' )
+		   
+    yylineno++;
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+	if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+		YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+	}
+
+	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+	yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		yypop_buffer_state();
+	 *		yypush_buffer_state(new_buffer);
+     */
+	yyensure_buffer_stack ();
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	yy_load_buffer_state( );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	(yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer(b,file );
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yyfree((void *) b->yy_ch_buf  );
+
+	yyfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+	int oerrno = errno;
+    
+	yy_flush_buffer(b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+    	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+    	if (new_buffer == NULL)
+		return;
+
+	yyensure_buffer_stack();
+
+	/* This block is copied from yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*(yy_c_buf_p) = (yy_hold_char);
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		(yy_buffer_stack_top)++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from yy_switch_to_buffer. */
+	yy_load_buffer_state( );
+	(yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+    	if (!YY_CURRENT_BUFFER)
+		return;
+
+	yy_delete_buffer(YY_CURRENT_BUFFER );
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if ((yy_buffer_stack_top) > 0)
+		--(yy_buffer_stack_top);
+
+	if (YY_CURRENT_BUFFER) {
+		yy_load_buffer_state( );
+		(yy_did_buffer_switch_on_eof) = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+	int num_to_alloc;
+    
+	if (!(yy_buffer_stack)) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+		
+		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		(yy_buffer_stack_max) = num_to_alloc;
+		(yy_buffer_stack_top) = 0;
+		return;
+	}
+
+	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+								((yy_buffer_stack),
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								);
+
+		/* zero only the new slots.*/
+		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+		(yy_buffer_stack_max) = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer(b  );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+	return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) yyalloc(n  );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer(buf,n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = (yy_hold_char); \
+		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+		(yy_hold_char) = *(yy_c_buf_p); \
+		*(yy_c_buf_p) = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    /* We do not touch yylineno unless the option is enabled. */
+    yylineno =  1;
+    
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		yy_delete_buffer(YY_CURRENT_BUFFER  );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		yypop_buffer_state();
+	}
+
+	/* Destroy the stack itself. */
+	yyfree((yy_buffer_stack) );
+	(yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+	return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 222 "dtc-lexer.l"
+
+
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+	int filenum;
+	FILE *file;
+	YY_BUFFER_STATE yy_prev_buf;
+	int yy_prev_lineno;
+	struct incl_file *prev;
+};
+
+struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH	(100)
+
+static int incl_depth = 0;
+
+
+int push_input_file(const char *filename)
+{
+	FILE *f;
+	struct incl_file *incl_file;
+
+	if (!filename) {
+		yyerror("No include file name given.");
+		return 0;
+	}
+
+	if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
+		yyerror("Includes nested too deeply");
+		return 0;
+	}
+
+	f = dtc_open_file(filename);
+
+	incl_file = malloc(sizeof(struct incl_file));
+	if (!incl_file) {
+		yyerror("Can not allocate include file space.");
+		return 0;
+	}
+
+	/*
+	 * Save current context.
+	 */
+	incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+	incl_file->yy_prev_lineno = yylineno;
+	incl_file->filenum = srcpos_filenum;
+	incl_file->file = yyin;
+	incl_file->prev = incl_file_stack;
+
+	incl_file_stack = incl_file;
+
+	/*
+	 * Establish new context.
+	 */
+	srcpos_filenum = lookup_file_name(filename, 0);
+	yylineno = 1;
+	yyin = f;
+	yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+
+	return 1;
+}
+
+
+int pop_input_file(void)
+{
+	struct incl_file *incl_file;
+
+	if (incl_file_stack == 0)
+		return 0;
+
+	fclose(yyin);
+
+	/*
+	 * Pop.
+	 */
+	--incl_depth;
+	incl_file = incl_file_stack;
+	incl_file_stack = incl_file->prev;
+
+	/*
+	 * Recover old context.
+	 */
+	yy_delete_buffer(YY_CURRENT_BUFFER);
+	yy_switch_to_buffer(incl_file->yy_prev_buf);
+	yylineno = incl_file->yy_prev_lineno;
+	srcpos_filenum = incl_file->filenum;
+	yyin = incl_file->file;
+
+	/*
+	 * Free old state.
+	 */
+	free(incl_file);
+
+	if (YY_CURRENT_BUFFER == 0)
+		return 0;
+
+	return 1;
+}
+
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped b/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped
new file mode 100644
index 0000000..28e6ec02
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped
@@ -0,0 +1,1983 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, 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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 1
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DT_V1 = 258,
+     DT_MEMRESERVE = 259,
+     DT_PROPNODENAME = 260,
+     DT_LITERAL = 261,
+     DT_LEGACYLITERAL = 262,
+     DT_BASE = 263,
+     DT_BYTE = 264,
+     DT_STRING = 265,
+     DT_LABEL = 266,
+     DT_REF = 267
+   };
+#endif
+/* Tokens.  */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 23 "dtc-parser.y"
+
+#include "dtc.h"
+#include "srcpos.h"
+
+int yylex(void);
+unsigned long long eval_literal(const char *s, int base, int bits);
+
+extern struct boot_info *the_boot_info;
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 34 "dtc-parser.y"
+{
+	char *propnodename;
+	char *literal;
+	char *labelref;
+	unsigned int cbase;
+	u8 byte;
+	struct data data;
+
+	u64 addr;
+	cell_t cell;
+	struct property *prop;
+	struct property *proplist;
+	struct node *node;
+	struct node *nodelist;
+	struct reserve_info *re;
+}
+/* Line 187 of yacc.c.  */
+#line 148 "dtc-parser.tab.c"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 173 "dtc-parser.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+	     && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+    YYLTYPE yyls;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)					\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack, Stack, yysize);				\
+	Stack = &yyptr->Stack;						\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  9
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   60
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  24
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  20
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  43
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  67
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   267
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    23,    14,     2,    15,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
+      19,    18,    20,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    21,     2,    22,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    16,     2,    17,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint8 yyprhs[] =
+{
+       0,     0,     3,     8,    11,    12,    15,    21,    22,    25,
+      27,    34,    36,    38,    41,    47,    48,    51,    57,    61,
+      64,    69,    74,    77,    80,    81,    84,    87,    88,    91,
+      94,    97,    98,   100,   102,   105,   106,   109,   112,   113,
+     116,   119,   123,   124
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      25,     0,    -1,     3,    13,    26,    31,    -1,    28,    31,
+      -1,    -1,    27,    26,    -1,    43,     4,    30,    30,    13,
+      -1,    -1,    29,    28,    -1,    27,    -1,    43,     4,    30,
+      14,    30,    13,    -1,     6,    -1,     7,    -1,    15,    32,
+      -1,    16,    33,    41,    17,    13,    -1,    -1,    33,    34,
+      -1,    43,     5,    18,    35,    13,    -1,    43,     5,    13,
+      -1,    36,    10,    -1,    36,    19,    37,    20,    -1,    36,
+      21,    40,    22,    -1,    36,    12,    -1,    35,    11,    -1,
+      -1,    35,    23,    -1,    36,    11,    -1,    -1,    37,    39,
+      -1,    37,    12,    -1,    37,    11,    -1,    -1,     8,    -1,
+       6,    -1,    38,     7,    -1,    -1,    40,     9,    -1,    40,
+      11,    -1,    -1,    42,    41,    -1,    42,    34,    -1,    43,
+       5,    32,    -1,    -1,    11,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    85,    85,    89,    97,   100,   107,   115,   118,   125,
+     129,   136,   140,   147,   154,   162,   165,   172,   176,   183,
+     187,   191,   195,   199,   207,   210,   214,   222,   225,   229,
+     234,   242,   245,   249,   253,   261,   264,   268,   276,   279,
+     283,   291,   299,   302
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
+  "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
+  "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "';'", "'-'", "'/'", "'{'",
+  "'}'", "'='", "'<'", "'>'", "'['", "']'", "','", "$accept", "sourcefile",
+  "memreserves", "memreserve", "v0_memreserves", "v0_memreserve", "addr",
+  "devicetree", "nodedef", "proplist", "propdef", "propdata",
+  "propdataprefix", "celllist", "cellbase", "cellval", "bytestring",
+  "subnodes", "subnode", "label", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,    59,    45,    47,   123,   125,    61,    60,
+      62,    91,    93,    44
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    24,    25,    25,    26,    26,    27,    28,    28,    29,
+      29,    30,    30,    31,    32,    33,    33,    34,    34,    35,
+      35,    35,    35,    35,    36,    36,    36,    37,    37,    37,
+      37,    38,    38,    39,    39,    40,    40,    40,    41,    41,
+      41,    42,    43,    43
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     4,     2,     0,     2,     5,     0,     2,     1,
+       6,     1,     1,     2,     5,     0,     2,     5,     3,     2,
+       4,     4,     2,     2,     0,     2,     2,     0,     2,     2,
+       2,     0,     1,     1,     2,     0,     2,     2,     0,     2,
+       2,     3,     0,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       7,     0,    43,     0,     9,     0,     7,     0,     4,     1,
+       0,     3,     8,     0,     0,     4,     0,    15,    13,    11,
+      12,     0,     2,     5,     0,    38,     0,     0,     0,    16,
+       0,    38,     0,     0,     6,     0,    40,    39,     0,    10,
+      14,    18,    24,    41,     0,     0,    23,    17,    25,    19,
+      26,    22,    27,    35,    31,     0,    33,    32,    30,    29,
+      20,     0,    28,    36,    37,    21,    34
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     3,    14,     4,     5,     6,    27,    11,    18,    25,
+      29,    44,    45,    54,    61,    62,    55,    30,    31,     7
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -13
+static const yytype_int8 yypact[] =
+{
+      23,    11,   -13,    37,   -13,    -4,    18,    39,    18,   -13,
+      28,   -13,   -13,    34,    -4,    18,    41,   -13,   -13,   -13,
+     -13,    25,   -13,   -13,    34,    -3,    34,    33,    34,   -13,
+      30,    -3,    43,    36,   -13,    38,   -13,   -13,    20,   -13,
+     -13,   -13,   -13,   -13,     2,     9,   -13,   -13,   -13,   -13,
+     -13,   -13,   -13,   -13,    -2,    -6,   -13,   -13,   -13,   -13,
+     -13,    45,   -13,   -13,   -13,   -13,   -13
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -13,   -13,    35,    27,    47,   -13,   -12,    40,    17,   -13,
+      26,   -13,   -13,   -13,   -13,   -13,   -13,    29,   -13,    -8
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -43
+static const yytype_int8 yytable[] =
+{
+      16,    21,   -42,    63,    56,    64,    57,    16,     2,    58,
+      59,    10,    28,    46,    33,    47,    65,    32,    60,    49,
+      50,    51,   -42,    32,     8,    48,     1,   -42,    52,     2,
+      53,    19,    20,    41,     2,    15,    17,     9,    42,    26,
+      19,    20,    15,    13,    17,    24,    34,    35,    38,    39,
+      23,    40,    66,    12,    22,    43,     0,    36,     0,     0,
+      37
+};
+
+static const yytype_int8 yycheck[] =
+{
+       8,    13,     5,     9,     6,    11,     8,    15,    11,    11,
+      12,    15,    24,    11,    26,    13,    22,    25,    20,    10,
+      11,    12,     4,    31,    13,    23,     3,     4,    19,    11,
+      21,     6,     7,    13,    11,     8,    16,     0,    18,    14,
+       6,     7,    15,     4,    16,     4,    13,    17,     5,    13,
+      15,    13,     7,     6,    14,    38,    -1,    31,    -1,    -1,
+      31
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,    11,    25,    27,    28,    29,    43,    13,     0,
+      15,    31,    28,     4,    26,    27,    43,    16,    32,     6,
+       7,    30,    31,    26,     4,    33,    14,    30,    30,    34,
+      41,    42,    43,    30,    13,    17,    34,    41,     5,    13,
+      13,    13,    18,    32,    35,    36,    11,    13,    23,    10,
+      11,    12,    19,    21,    37,    40,     6,     8,    11,    12,
+      20,    38,    39,     9,    11,    22,     7
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value, Location); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (yylocationp);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule)
+    YYSTYPE *yyvsp;
+    YYLTYPE *yylsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       , &(yylsp[(yyi + 1) - (yynrhs)])		       );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, yylsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    YYLTYPE *yylocationp;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+/* Location data for the look-ahead symbol.  */
+YYLTYPE yylloc;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+  /* The locations where the error started and ended.  */
+  YYLTYPE yyerror_range[2];
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;		/* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+  yylsp = yyls;
+#if YYLTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 0;
+#endif
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+	YYLTYPE *yyls1 = yyls;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yyls1, yysize * sizeof (*yylsp),
+		    &yystacksize);
+	yyls = yyls1;
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss);
+	YYSTACK_RELOCATE (yyvs);
+	YYSTACK_RELOCATE (yyls);
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 86 "dtc-parser.y"
+    {
+			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node));
+		;}
+    break;
+
+  case 3:
+#line 90 "dtc-parser.y"
+    {
+			the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node));
+		;}
+    break;
+
+  case 4:
+#line 97 "dtc-parser.y"
+    {
+			(yyval.re) = NULL;
+		;}
+    break;
+
+  case 5:
+#line 101 "dtc-parser.y"
+    {
+			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+		;}
+    break;
+
+  case 6:
+#line 108 "dtc-parser.y"
+    {
+			(yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
+		;}
+    break;
+
+  case 7:
+#line 115 "dtc-parser.y"
+    {
+			(yyval.re) = NULL;
+		;}
+    break;
+
+  case 8:
+#line 119 "dtc-parser.y"
+    {
+			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+		;}
+    break;
+
+  case 9:
+#line 126 "dtc-parser.y"
+    {
+			(yyval.re) = (yyvsp[(1) - (1)].re);
+		;}
+    break;
+
+  case 10:
+#line 130 "dtc-parser.y"
+    {
+			(yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
+		;}
+    break;
+
+  case 11:
+#line 137 "dtc-parser.y"
+    {
+			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+		;}
+    break;
+
+  case 12:
+#line 141 "dtc-parser.y"
+    {
+			(yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
+		;}
+    break;
+
+  case 13:
+#line 148 "dtc-parser.y"
+    {
+			(yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
+		;}
+    break;
+
+  case 14:
+#line 155 "dtc-parser.y"
+    {
+			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
+		;}
+    break;
+
+  case 15:
+#line 162 "dtc-parser.y"
+    {
+			(yyval.proplist) = NULL;
+		;}
+    break;
+
+  case 16:
+#line 166 "dtc-parser.y"
+    {
+			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
+		;}
+    break;
+
+  case 17:
+#line 173 "dtc-parser.y"
+    {
+			(yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
+		;}
+    break;
+
+  case 18:
+#line 177 "dtc-parser.y"
+    {
+			(yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
+		;}
+    break;
+
+  case 19:
+#line 184 "dtc-parser.y"
+    {
+			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+		;}
+    break;
+
+  case 20:
+#line 188 "dtc-parser.y"
+    {
+			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+		;}
+    break;
+
+  case 21:
+#line 192 "dtc-parser.y"
+    {
+			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+		;}
+    break;
+
+  case 22:
+#line 196 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 23:
+#line 200 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 24:
+#line 207 "dtc-parser.y"
+    {
+			(yyval.data) = empty_data;
+		;}
+    break;
+
+  case 25:
+#line 211 "dtc-parser.y"
+    {
+			(yyval.data) = (yyvsp[(1) - (2)].data);
+		;}
+    break;
+
+  case 26:
+#line 215 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 27:
+#line 222 "dtc-parser.y"
+    {
+			(yyval.data) = empty_data;
+		;}
+    break;
+
+  case 28:
+#line 226 "dtc-parser.y"
+    {
+			(yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+		;}
+    break;
+
+  case 29:
+#line 230 "dtc-parser.y"
+    {
+			(yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
+							      (yyvsp[(2) - (2)].labelref)), -1);
+		;}
+    break;
+
+  case 30:
+#line 235 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 31:
+#line 242 "dtc-parser.y"
+    {
+			(yyval.cbase) = 16;
+		;}
+    break;
+
+  case 33:
+#line 250 "dtc-parser.y"
+    {
+			(yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+		;}
+    break;
+
+  case 34:
+#line 254 "dtc-parser.y"
+    {
+			(yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
+		;}
+    break;
+
+  case 35:
+#line 261 "dtc-parser.y"
+    {
+			(yyval.data) = empty_data;
+		;}
+    break;
+
+  case 36:
+#line 265 "dtc-parser.y"
+    {
+			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+		;}
+    break;
+
+  case 37:
+#line 269 "dtc-parser.y"
+    {
+			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+		;}
+    break;
+
+  case 38:
+#line 276 "dtc-parser.y"
+    {
+			(yyval.nodelist) = NULL;
+		;}
+    break;
+
+  case 39:
+#line 280 "dtc-parser.y"
+    {
+			(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
+		;}
+    break;
+
+  case 40:
+#line 284 "dtc-parser.y"
+    {
+			yyerror("syntax error: properties must precede subnodes\n");
+			YYERROR;
+		;}
+    break;
+
+  case 41:
+#line 292 "dtc-parser.y"
+    {
+			(yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
+		;}
+    break;
+
+  case 42:
+#line 299 "dtc-parser.y"
+    {
+			(yyval.labelref) = NULL;
+		;}
+    break;
+
+  case 43:
+#line 303 "dtc-parser.y"
+    {
+			(yyval.labelref) = (yyvsp[(1) - (1)].labelref);
+		;}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 1734 "dtc-parser.tab.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (yymsg);
+	  }
+	else
+	  {
+	    yyerror (YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+  yyerror_range[0] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval, &yylloc);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[0] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+      yyerror_range[0] = *yylsp;
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp, yylsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+  yyerror_range[1] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the look-ahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval, &yylloc);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp, yylsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 308 "dtc-parser.y"
+
+
+void yyerror (char const *s)
+{
+	const char *fname = srcpos_filename_for_num(yylloc.filenum);
+
+	if (strcmp(fname, "-") == 0)
+		fname = "stdin";
+
+	fprintf(stderr, "%s:%d %s\n",
+		fname, yylloc.first_line, s);
+}
+
+unsigned long long eval_literal(const char *s, int base, int bits)
+{
+	unsigned long long val;
+	char *e;
+
+	errno = 0;
+	val = strtoull(s, &e, base);
+	if (*e)
+		yyerror("bad characters in literal");
+	else if ((errno == ERANGE)
+		 || ((bits < 64) && (val >= (1ULL << bits))))
+		yyerror("literal out of range");
+	else if (errno != 0)
+		yyerror("bad literal");
+	return val;
+}
+
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped b/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped
new file mode 100644
index 0000000..4707b02
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped
@@ -0,0 +1,111 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   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, 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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DT_V1 = 258,
+     DT_MEMRESERVE = 259,
+     DT_PROPNODENAME = 260,
+     DT_LITERAL = 261,
+     DT_LEGACYLITERAL = 262,
+     DT_BASE = 263,
+     DT_BYTE = 264,
+     DT_STRING = 265,
+     DT_LABEL = 266,
+     DT_REF = 267
+   };
+#endif
+/* Tokens.  */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 34 "dtc-parser.y"
+{
+	char *propnodename;
+	char *literal;
+	char *labelref;
+	unsigned int cbase;
+	u8 byte;
+	struct data data;
+
+	u64 addr;
+	cell_t cell;
+	struct property *prop;
+	struct property *proplist;
+	struct node *node;
+	struct node *nodelist;
+	struct reserve_info *re;
+}
+/* Line 1489 of yacc.c.  */
+#line 90 "dtc-parser.tab.h"
+	YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYLTYPE yylloc;
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.y b/arch/powerpc/boot/dtc-src/dtc-parser.y
new file mode 100644
index 0000000..002ea7f
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc-parser.y
@@ -0,0 +1,336 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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
+ */
+
+%locations
+
+%{
+#include "dtc.h"
+#include "srcpos.h"
+
+int yylex(void);
+unsigned long long eval_literal(const char *s, int base, int bits);
+
+extern struct boot_info *the_boot_info;
+
+%}
+
+%union {
+	char *propnodename;
+	char *literal;
+	char *labelref;
+	unsigned int cbase;
+	u8 byte;
+	struct data data;
+
+	u64 addr;
+	cell_t cell;
+	struct property *prop;
+	struct property *proplist;
+	struct node *node;
+	struct node *nodelist;
+	struct reserve_info *re;
+}
+
+%token DT_V1
+%token DT_MEMRESERVE
+%token <propnodename> DT_PROPNODENAME
+%token <literal> DT_LITERAL
+%token <literal> DT_LEGACYLITERAL
+%token <cbase> DT_BASE
+%token <byte> DT_BYTE
+%token <data> DT_STRING
+%token <labelref> DT_LABEL
+%token <labelref> DT_REF
+
+%type <data> propdata
+%type <data> propdataprefix
+%type <re> memreserve
+%type <re> memreserves
+%type <re> v0_memreserve
+%type <re> v0_memreserves
+%type <addr> addr
+%type <data> celllist
+%type <cbase> cellbase
+%type <cell> cellval
+%type <data> bytestring
+%type <prop> propdef
+%type <proplist> proplist
+
+%type <node> devicetree
+%type <node> nodedef
+%type <node> subnode
+%type <nodelist> subnodes
+%type <labelref> label
+
+%%
+
+sourcefile:
+	  DT_V1 ';' memreserves devicetree
+		{
+			the_boot_info = build_boot_info($3, $4);
+		}
+	| v0_memreserves devicetree
+		{
+			the_boot_info = build_boot_info($1, $2);
+		}
+	;
+
+memreserves:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	| memreserve memreserves
+		{
+			$$ = chain_reserve_entry($1, $2);
+		}
+	;
+
+memreserve:
+	  label DT_MEMRESERVE addr addr ';'
+		{
+			$$ = build_reserve_entry($3, $4, $1);
+		}
+	;
+
+v0_memreserves:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	| v0_memreserve v0_memreserves
+		{
+			$$ = chain_reserve_entry($1, $2);
+		};
+	;
+
+v0_memreserve:
+	  memreserve
+		{
+			$$ = $1;
+		}
+	| label DT_MEMRESERVE addr '-' addr ';'
+		{
+			$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
+		}
+	;
+
+addr:
+	  DT_LITERAL
+		{
+			$$ = eval_literal($1, 0, 64);
+		}
+	| DT_LEGACYLITERAL
+		{
+			$$ = eval_literal($1, 16, 64);
+		}
+	  ;
+
+devicetree:
+	  '/' nodedef
+		{
+			$$ = name_node($2, "", NULL);
+		}
+	;
+
+nodedef:
+	  '{' proplist subnodes '}' ';'
+		{
+			$$ = build_node($2, $3);
+		}
+	;
+
+proplist:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	| proplist propdef
+		{
+			$$ = chain_property($2, $1);
+		}
+	;
+
+propdef:
+	  label DT_PROPNODENAME '=' propdata ';'
+		{
+			$$ = build_property($2, $4, $1);
+		}
+	| label DT_PROPNODENAME ';'
+		{
+			$$ = build_property($2, empty_data, $1);
+		}
+	;
+
+propdata:
+	  propdataprefix DT_STRING
+		{
+			$$ = data_merge($1, $2);
+		}
+	| propdataprefix '<' celllist '>'
+		{
+			$$ = data_merge($1, $3);
+		}
+	| propdataprefix '[' bytestring ']'
+		{
+			$$ = data_merge($1, $3);
+		}
+	| propdataprefix DT_REF
+		{
+			$$ = data_add_marker($1, REF_PATH, $2);
+		}
+	| propdata DT_LABEL
+		{
+			$$ = data_add_marker($1, LABEL, $2);
+		}
+	;
+
+propdataprefix:
+	  /* empty */
+		{
+			$$ = empty_data;
+		}
+	| propdata ','
+		{
+			$$ = $1;
+		}
+	| propdataprefix DT_LABEL
+		{
+			$$ = data_add_marker($1, LABEL, $2);
+		}
+	;
+
+celllist:
+	  /* empty */
+		{
+			$$ = empty_data;
+		}
+	| celllist cellval
+		{
+			$$ = data_append_cell($1, $2);
+		}
+	| celllist DT_REF
+		{
+			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
+							      $2), -1);
+		}
+	| celllist DT_LABEL
+		{
+			$$ = data_add_marker($1, LABEL, $2);
+		}
+	;
+
+cellbase:
+	  /* empty */
+		{
+			$$ = 16;
+		}
+	| DT_BASE
+	;
+
+cellval:
+	  DT_LITERAL
+		{
+			$$ = eval_literal($1, 0, 32);
+		}
+	| cellbase DT_LEGACYLITERAL
+		{
+			$$ = eval_literal($2, $1, 32);
+		}
+	;
+
+bytestring:
+	  /* empty */
+		{
+			$$ = empty_data;
+		}
+	| bytestring DT_BYTE
+		{
+			$$ = data_append_byte($1, $2);
+		}
+	| bytestring DT_LABEL
+		{
+			$$ = data_add_marker($1, LABEL, $2);
+		}
+	;
+
+subnodes:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	|  subnode subnodes
+		{
+			$$ = chain_node($1, $2);
+		}
+	| subnode propdef
+		{
+			yyerror("syntax error: properties must precede subnodes\n");
+			YYERROR;
+		}
+	;
+
+subnode:
+	  label DT_PROPNODENAME nodedef
+		{
+			$$ = name_node($3, $2, $1);
+		}
+	;
+
+label:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	| DT_LABEL
+		{
+			$$ = $1;
+		}
+	;
+
+%%
+
+void yyerror (char const *s)
+{
+	const char *fname = srcpos_filename_for_num(yylloc.filenum);
+
+	if (strcmp(fname, "-") == 0)
+		fname = "stdin";
+
+	fprintf(stderr, "%s:%d %s\n",
+		fname, yylloc.first_line, s);
+}
+
+unsigned long long eval_literal(const char *s, int base, int bits)
+{
+	unsigned long long val;
+	char *e;
+
+	errno = 0;
+	val = strtoull(s, &e, base);
+	if (*e)
+		yyerror("bad characters in literal");
+	else if ((errno == ERANGE)
+		 || ((bits < 64) && (val >= (1ULL << bits))))
+		yyerror("literal out of range");
+	else if (errno != 0)
+		yyerror("bad literal");
+	return val;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc.c b/arch/powerpc/boot/dtc-src/dtc.c
new file mode 100644
index 0000000..01131d7
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc.c
@@ -0,0 +1,231 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+#include "version_gen.h"
+
+/*
+ * Command line options
+ */
+int quiet;		/* Level of quietness */
+int reservenum;		/* Number of memory reservation slots */
+int minsize;		/* Minimum blob size */
+int padsize;		/* Additional padding to blob */
+
+char *join_path(const char *path, const char *name)
+{
+	int lenp = strlen(path);
+	int lenn = strlen(name);
+	int len;
+	int needslash = 1;
+	char *str;
+
+	len = lenp + lenn + 2;
+	if ((lenp > 0) && (path[lenp-1] == '/')) {
+		needslash = 0;
+		len--;
+	}
+
+	str = xmalloc(len);
+	memcpy(str, path, lenp);
+	if (needslash) {
+		str[lenp] = '/';
+		lenp++;
+	}
+	memcpy(str+lenp, name, lenn+1);
+	return str;
+}
+
+void fill_fullpaths(struct node *tree, const char *prefix)
+{
+	struct node *child;
+	const char *unit;
+
+	tree->fullpath = join_path(prefix, tree->name);
+
+	unit = strchr(tree->name, '@');
+	if (unit)
+		tree->basenamelen = unit - tree->name;
+	else
+		tree->basenamelen = strlen(tree->name);
+
+	for_each_child(tree, child)
+		fill_fullpaths(child, tree->fullpath);
+}
+
+static void  __attribute__ ((noreturn)) usage(void)
+{
+	fprintf(stderr, "Usage:\n");
+	fprintf(stderr, "\tdtc [options] <input file>\n");
+	fprintf(stderr, "\nOptions:\n");
+	fprintf(stderr, "\t-h\n");
+	fprintf(stderr, "\t\tThis help text\n");
+	fprintf(stderr, "\t-q\n");
+	fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
+	fprintf(stderr, "\t-I <input format>\n");
+	fprintf(stderr, "\t\tInput formats are:\n");
+	fprintf(stderr, "\t\t\tdts - device tree source text\n");
+	fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+	fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
+	fprintf(stderr, "\t-o <output file>\n");
+	fprintf(stderr, "\t-O <output format>\n");
+	fprintf(stderr, "\t\tOutput formats are:\n");
+	fprintf(stderr, "\t\t\tdts - device tree source text\n");
+	fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+	fprintf(stderr, "\t\t\tasm - assembler source\n");
+	fprintf(stderr, "\t-V <output version>\n");
+	fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
+	fprintf(stderr, "\t-R <number>\n");
+	fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
+	fprintf(stderr, "\t-S <bytes>\n");
+	fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
+	fprintf(stderr, "\t-p <bytes>\n");
+	fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
+	fprintf(stderr, "\t-b <number>\n");
+	fprintf(stderr, "\t\tSet the physical boot cpu\n");
+	fprintf(stderr, "\t-f\n");
+	fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+	fprintf(stderr, "\t-v\n");
+	fprintf(stderr, "\t\tPrint DTC version and exit\n");
+	exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+	struct boot_info *bi;
+	const char *inform = "dts";
+	const char *outform = "dts";
+	const char *outname = "-";
+	int force = 0, check = 0;
+	const char *arg;
+	int opt;
+	FILE *inf = NULL;
+	FILE *outf = NULL;
+	int outversion = DEFAULT_FDT_VERSION;
+	int boot_cpuid_phys = 0xfeedbeef;
+
+	quiet      = 0;
+	reservenum = 0;
+	minsize    = 0;
+	padsize    = 0;
+
+	while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
+		switch (opt) {
+		case 'I':
+			inform = optarg;
+			break;
+		case 'O':
+			outform = optarg;
+			break;
+		case 'o':
+			outname = optarg;
+			break;
+		case 'V':
+			outversion = strtol(optarg, NULL, 0);
+			break;
+		case 'R':
+			reservenum = strtol(optarg, NULL, 0);
+			break;
+		case 'S':
+			minsize = strtol(optarg, NULL, 0);
+			break;
+		case 'p':
+			padsize = strtol(optarg, NULL, 0);
+			break;
+		case 'f':
+			force = 1;
+			break;
+		case 'c':
+			check = 1;
+			break;
+		case 'q':
+			quiet++;
+			break;
+		case 'b':
+			boot_cpuid_phys = strtol(optarg, NULL, 0);
+			break;
+		case 'v':
+		    printf("Version: %s\n", DTC_VERSION);
+		    exit(0);
+		case 'h':
+		default:
+			usage();
+		}
+	}
+
+	if (argc > (optind+1))
+		usage();
+	else if (argc < (optind+1))
+		arg = "-";
+	else
+		arg = argv[optind];
+
+	/* minsize and padsize are mutually exclusive */
+	if ((minsize) && (padsize)) {
+		die("Can't set both -p and -S\n");
+	}
+
+	fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
+		inform, outform, arg);
+
+	if (streq(inform, "dts")) {
+		bi = dt_from_source(arg);
+	} else if (streq(inform, "fs")) {
+		bi = dt_from_fs(arg);
+	} else if(streq(inform, "dtb")) {
+		inf = dtc_open_file(arg);
+		bi = dt_from_blob(inf);
+	} else {
+		die("Unknown input format \"%s\"\n", inform);
+	}
+
+	if (inf && (inf != stdin))
+		fclose(inf);
+
+	if (! bi || ! bi->dt)
+		die("Couldn't read input tree\n");
+
+	process_checks(force, bi, check, outversion, boot_cpuid_phys);
+
+	if (streq(outname, "-")) {
+		outf = stdout;
+	} else {
+		outf = fopen(outname, "w");
+		if (! outf)
+			die("Couldn't open output file %s: %s\n",
+			    outname, strerror(errno));
+	}
+
+	if (streq(outform, "dts")) {
+		dt_to_source(outf, bi);
+	} else if (streq(outform, "dtb")) {
+		dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
+	} else if (streq(outform, "asm")) {
+		dt_to_asm(outf, bi, outversion, boot_cpuid_phys);
+	} else if (streq(outform, "null")) {
+		/* do nothing */
+	} else {
+		die("Unknown output format \"%s\"\n", outform);
+	}
+
+	exit(0);
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc.h b/arch/powerpc/boot/dtc-src/dtc.h
new file mode 100644
index 0000000..65281777
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/dtc.h
@@ -0,0 +1,269 @@
+#ifndef _DTC_H
+#define _DTC_H
+
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#include <fdt.h>
+
+#define DEFAULT_FDT_VERSION	17
+/*
+ * Command line options
+ */
+extern int quiet;		/* Level of quietness */
+extern int reservenum;		/* Number of memory reservation slots */
+extern int minsize;		/* Minimum blob size */
+extern int padsize;		/* Additional padding to blob */
+
+static inline void __attribute__((noreturn)) die(char * str, ...)
+{
+	va_list ap;
+
+	va_start(ap, str);
+	fprintf(stderr, "FATAL ERROR: ");
+	vfprintf(stderr, str, ap);
+	exit(1);
+}
+
+static inline void *xmalloc(size_t len)
+{
+	void *new = malloc(len);
+
+	if (! new)
+		die("malloc() failed\n");
+
+	return new;
+}
+
+static inline void *xrealloc(void *p, size_t len)
+{
+	void *new = realloc(p, len);
+
+	if (! new)
+		die("realloc() failed (len=%d)\n", len);
+
+	return new;
+}
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef u32 cell_t;
+
+#define cpu_to_be16(x)	htons(x)
+#define be16_to_cpu(x)	ntohs(x)
+
+#define cpu_to_be32(x)	htonl(x)
+#define be32_to_cpu(x)	ntohl(x)
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_be64(x)	(x)
+#define be64_to_cpu(x)	(x)
+#else
+#define cpu_to_be64(x)	bswap_64(x)
+#define be64_to_cpu(x)	bswap_64(x)
+#endif
+
+#define streq(a, b)	(strcmp((a), (b)) == 0)
+#define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0)
+
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Data blobs */
+enum markertype {
+	REF_PHANDLE,
+	REF_PATH,
+	LABEL,
+};
+
+struct  marker {
+	enum markertype type;
+	int offset;
+	char *ref;
+	struct marker *next;
+};
+
+struct data {
+	int len;
+	char *val;
+	int asize;
+	struct marker *markers;
+};
+
+
+#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
+
+#define for_each_marker(m) \
+	for (; (m); (m) = (m)->next)
+#define for_each_marker_of_type(m, t) \
+	for_each_marker(m) \
+		if ((m)->type == (t))
+
+void data_free(struct data d);
+
+struct data data_grow_for(struct data d, int xlen);
+
+struct data data_copy_mem(const char *mem, int len);
+struct data data_copy_escape_string(const char *s, int len);
+struct data data_copy_file(FILE *f, size_t len);
+
+struct data data_append_data(struct data d, const void *p, int len);
+struct data data_insert_at_marker(struct data d, struct marker *m,
+				  const void *p, int len);
+struct data data_merge(struct data d1, struct data d2);
+struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
+struct data data_append_addr(struct data d, u64 addr);
+struct data data_append_byte(struct data d, uint8_t byte);
+struct data data_append_zeroes(struct data d, int len);
+struct data data_append_align(struct data d, int align);
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref);
+
+int data_is_one_string(struct data d);
+
+/* DT constraints */
+
+#define MAX_PROPNAME_LEN	31
+#define MAX_NODENAME_LEN	31
+
+/* Live trees */
+struct property {
+	char *name;
+	struct data val;
+
+	struct property *next;
+
+	char *label;
+};
+
+struct node {
+	char *name;
+	struct property *proplist;
+	struct node *children;
+
+	struct node *parent;
+	struct node *next_sibling;
+
+	char *fullpath;
+	int basenamelen;
+
+	cell_t phandle;
+	int addr_cells, size_cells;
+
+	char *label;
+};
+
+#define for_each_property(n, p) \
+	for ((p) = (n)->proplist; (p); (p) = (p)->next)
+
+#define for_each_child(n, c)	\
+	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+
+struct property *build_property(char *name, struct data val, char *label);
+struct property *chain_property(struct property *first, struct property *list);
+struct property *reverse_properties(struct property *first);
+
+struct node *build_node(struct property *proplist, struct node *children);
+struct node *name_node(struct node *node, char *name, char *label);
+struct node *chain_node(struct node *first, struct node *list);
+
+void add_property(struct node *node, struct property *prop);
+void add_child(struct node *parent, struct node *child);
+
+const char *get_unitname(struct node *node);
+struct property *get_property(struct node *node, const char *propname);
+cell_t propval_cell(struct property *prop);
+struct node *get_subnode(struct node *node, const char *nodename);
+struct node *get_node_by_path(struct node *tree, const char *path);
+struct node *get_node_by_label(struct node *tree, const char *label);
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
+struct node *get_node_by_ref(struct node *tree, const char *ref);
+cell_t get_node_phandle(struct node *root, struct node *node);
+
+/* Boot info (tree plus memreserve information */
+
+struct reserve_info {
+	struct fdt_reserve_entry re;
+
+	struct reserve_info *next;
+
+	char *label;
+};
+
+struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label);
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+					 struct reserve_info *list);
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+				       struct reserve_info *new);
+
+
+struct boot_info {
+	struct reserve_info *reservelist;
+	struct node *dt;		/* the device tree */
+};
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+				  struct node *tree);
+
+/* Checks */
+
+void process_checks(int force, struct boot_info *bi,
+		    int checkflag, int outversion, int boot_cpuid_phys);
+
+/* Flattened trees */
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version,
+		int boot_cpuid_phys);
+void dt_to_asm(FILE *f, struct boot_info *bi, int version,
+	       int boot_cpuid_phys);
+
+struct boot_info *dt_from_blob(FILE *f);
+
+/* Tree source */
+
+void dt_to_source(FILE *f, struct boot_info *bi);
+struct boot_info *dt_from_source(const char *f);
+
+/* FS trees */
+
+struct boot_info *dt_from_fs(const char *dirname);
+
+/* misc */
+
+char *join_path(const char *path, const char *name);
+void fill_fullpaths(struct node *tree, const char *prefix);
+
+#endif /* _DTC_H */
diff --git a/arch/powerpc/boot/dtc-src/flattree.c b/arch/powerpc/boot/dtc-src/flattree.c
new file mode 100644
index 0000000..a7cfb84
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/flattree.c
@@ -0,0 +1,968 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+
+#define FTF_FULLPATH	0x1
+#define FTF_VARALIGN	0x2
+#define FTF_NAMEPROPS	0x4
+#define FTF_BOOTCPUID	0x8
+#define FTF_STRTABSIZE	0x10
+#define FTF_STRUCTSIZE	0x20
+#define FTF_NOPS	0x40
+
+static struct version_info {
+	int version;
+	int last_comp_version;
+	int hdr_size;
+	int flags;
+} version_table[] = {
+	{1, 1, FDT_V1_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
+	{2, 1, FDT_V2_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
+	{3, 1, FDT_V3_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
+	{16, 16, FDT_V3_SIZE,
+	 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
+	{17, 16, FDT_V17_SIZE,
+	 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
+};
+
+struct emitter {
+	void (*cell)(void *, cell_t);
+	void (*string)(void *, char *, int);
+	void (*align)(void *, int);
+	void (*data)(void *, struct data);
+	void (*beginnode)(void *, const char *);
+	void (*endnode)(void *, const char *);
+	void (*property)(void *, const char *);
+};
+
+static void bin_emit_cell(void *e, cell_t val)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_cell(*dtbuf, val);
+}
+
+static void bin_emit_string(void *e, char *str, int len)
+{
+	struct data *dtbuf = e;
+
+	if (len == 0)
+		len = strlen(str);
+
+	*dtbuf = data_append_data(*dtbuf, str, len);
+	*dtbuf = data_append_byte(*dtbuf, '\0');
+}
+
+static void bin_emit_align(void *e, int a)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_align(*dtbuf, a);
+}
+
+static void bin_emit_data(void *e, struct data d)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_data(*dtbuf, d.val, d.len);
+}
+
+static void bin_emit_beginnode(void *e, const char *label)
+{
+	bin_emit_cell(e, FDT_BEGIN_NODE);
+}
+
+static void bin_emit_endnode(void *e, const char *label)
+{
+	bin_emit_cell(e, FDT_END_NODE);
+}
+
+static void bin_emit_property(void *e, const char *label)
+{
+	bin_emit_cell(e, FDT_PROP);
+}
+
+static struct emitter bin_emitter = {
+	.cell = bin_emit_cell,
+	.string = bin_emit_string,
+	.align = bin_emit_align,
+	.data = bin_emit_data,
+	.beginnode = bin_emit_beginnode,
+	.endnode = bin_emit_endnode,
+	.property = bin_emit_property,
+};
+
+static void emit_label(FILE *f, const char *prefix, const char *label)
+{
+	fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
+	fprintf(f, "%s_%s:\n", prefix, label);
+	fprintf(f, "_%s_%s:\n", prefix, label);
+}
+
+static void emit_offset_label(FILE *f, const char *label, int offset)
+{
+	fprintf(f, "\t.globl\t%s\n", label);
+	fprintf(f, "%s\t= . + %d\n", label, offset);
+}
+
+static void asm_emit_cell(void *e, cell_t val)
+{
+	FILE *f = e;
+
+	fprintf(f, "\t.long\t0x%x\n", val);
+}
+
+static void asm_emit_string(void *e, char *str, int len)
+{
+	FILE *f = e;
+	char c = 0;
+
+	if (len != 0) {
+		/* XXX: ewww */
+		c = str[len];
+		str[len] = '\0';
+	}
+
+	fprintf(f, "\t.string\t\"%s\"\n", str);
+
+	if (len != 0) {
+		str[len] = c;
+	}
+}
+
+static void asm_emit_align(void *e, int a)
+{
+	FILE *f = e;
+
+	fprintf(f, "\t.balign\t%d\n", a);
+}
+
+static void asm_emit_data(void *e, struct data d)
+{
+	FILE *f = e;
+	int off = 0;
+	struct marker *m;
+
+	m = d.markers;
+	while (m) {
+		if (m->type == LABEL)
+			emit_offset_label(f, m->ref, m->offset);
+		m = m->next;
+	}
+
+	while ((d.len - off) >= sizeof(u32)) {
+		fprintf(f, "\t.long\t0x%x\n",
+			be32_to_cpu(*((u32 *)(d.val+off))));
+		off += sizeof(u32);
+	}
+
+	if ((d.len - off) >= sizeof(u16)) {
+		fprintf(f, "\t.short\t0x%hx\n",
+			be16_to_cpu(*((u16 *)(d.val+off))));
+		off += sizeof(u16);
+	}
+
+	if ((d.len - off) >= 1) {
+		fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
+		off += 1;
+	}
+
+	assert(off == d.len);
+}
+
+static void asm_emit_beginnode(void *e, const char *label)
+{
+	FILE *f = e;
+
+	if (label) {
+		fprintf(f, "\t.globl\t%s\n", label);
+		fprintf(f, "%s:\n", label);
+	}
+	fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
+}
+
+static void asm_emit_endnode(void *e, const char *label)
+{
+	FILE *f = e;
+
+	fprintf(f, "\t.long\tFDT_END_NODE\n");
+	if (label) {
+		fprintf(f, "\t.globl\t%s_end\n", label);
+		fprintf(f, "%s_end:\n", label);
+	}
+}
+
+static void asm_emit_property(void *e, const char *label)
+{
+	FILE *f = e;
+
+	if (label) {
+		fprintf(f, "\t.globl\t%s\n", label);
+		fprintf(f, "%s:\n", label);
+	}
+	fprintf(f, "\t.long\tFDT_PROP\n");
+}
+
+static struct emitter asm_emitter = {
+	.cell = asm_emit_cell,
+	.string = asm_emit_string,
+	.align = asm_emit_align,
+	.data = asm_emit_data,
+	.beginnode = asm_emit_beginnode,
+	.endnode = asm_emit_endnode,
+	.property = asm_emit_property,
+};
+
+static int stringtable_insert(struct data *d, const char *str)
+{
+	int i;
+
+	/* FIXME: do this more efficiently? */
+
+	for (i = 0; i < d->len; i++) {
+		if (streq(str, d->val + i))
+			return i;
+	}
+
+	*d = data_append_data(*d, str, strlen(str)+1);
+	return i;
+}
+
+static void flatten_tree(struct node *tree, struct emitter *emit,
+			 void *etarget, struct data *strbuf,
+			 struct version_info *vi)
+{
+	struct property *prop;
+	struct node *child;
+	int seen_name_prop = 0;
+
+	emit->beginnode(etarget, tree->label);
+
+	if (vi->flags & FTF_FULLPATH)
+		emit->string(etarget, tree->fullpath, 0);
+	else
+		emit->string(etarget, tree->name, 0);
+
+	emit->align(etarget, sizeof(cell_t));
+
+	for_each_property(tree, prop) {
+		int nameoff;
+
+		if (streq(prop->name, "name"))
+			seen_name_prop = 1;
+
+		nameoff = stringtable_insert(strbuf, prop->name);
+
+		emit->property(etarget, prop->label);
+		emit->cell(etarget, prop->val.len);
+		emit->cell(etarget, nameoff);
+
+		if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
+			emit->align(etarget, 8);
+
+		emit->data(etarget, prop->val);
+		emit->align(etarget, sizeof(cell_t));
+	}
+
+	if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
+		emit->property(etarget, NULL);
+		emit->cell(etarget, tree->basenamelen+1);
+		emit->cell(etarget, stringtable_insert(strbuf, "name"));
+
+		if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
+			emit->align(etarget, 8);
+
+		emit->string(etarget, tree->name, tree->basenamelen);
+		emit->align(etarget, sizeof(cell_t));
+	}
+
+	for_each_child(tree, child) {
+		flatten_tree(child, emit, etarget, strbuf, vi);
+	}
+
+	emit->endnode(etarget, tree->label);
+}
+
+static struct data flatten_reserve_list(struct reserve_info *reservelist,
+				 struct version_info *vi)
+{
+	struct reserve_info *re;
+	struct data d = empty_data;
+	static struct fdt_reserve_entry null_re = {0,0};
+	int    j;
+
+	for (re = reservelist; re; re = re->next) {
+		d = data_append_re(d, &re->re);
+	}
+	/*
+	 * Add additional reserved slots if the user asked for them.
+	 */
+	for (j = 0; j < reservenum; j++) {
+		d = data_append_re(d, &null_re);
+	}
+
+	return d;
+}
+
+static void make_fdt_header(struct fdt_header *fdt,
+			    struct version_info *vi,
+			    int reservesize, int dtsize, int strsize,
+			    int boot_cpuid_phys)
+{
+	int reserve_off;
+
+	reservesize += sizeof(struct fdt_reserve_entry);
+
+	memset(fdt, 0xff, sizeof(*fdt));
+
+	fdt->magic = cpu_to_be32(FDT_MAGIC);
+	fdt->version = cpu_to_be32(vi->version);
+	fdt->last_comp_version = cpu_to_be32(vi->last_comp_version);
+
+	/* Reserve map should be doubleword aligned */
+	reserve_off = ALIGN(vi->hdr_size, 8);
+
+	fdt->off_mem_rsvmap = cpu_to_be32(reserve_off);
+	fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize);
+	fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize
+					  + dtsize);
+	fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize);
+
+	if (vi->flags & FTF_BOOTCPUID)
+		fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys);
+	if (vi->flags & FTF_STRTABSIZE)
+		fdt->size_dt_strings = cpu_to_be32(strsize);
+	if (vi->flags & FTF_STRUCTSIZE)
+		fdt->size_dt_struct = cpu_to_be32(dtsize);
+}
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version,
+		int boot_cpuid_phys)
+{
+	struct version_info *vi = NULL;
+	int i;
+	struct data blob       = empty_data;
+	struct data reservebuf = empty_data;
+	struct data dtbuf      = empty_data;
+	struct data strbuf     = empty_data;
+	struct fdt_header fdt;
+	int padlen = 0;
+
+	for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+		if (version_table[i].version == version)
+			vi = &version_table[i];
+	}
+	if (!vi)
+		die("Unknown device tree blob version %d\n", version);
+
+	flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
+	bin_emit_cell(&dtbuf, FDT_END);
+
+	reservebuf = flatten_reserve_list(bi->reservelist, vi);
+
+	/* Make header */
+	make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+			boot_cpuid_phys);
+
+	/*
+	 * If the user asked for more space than is used, adjust the totalsize.
+	 */
+	if (minsize > 0) {
+		padlen = minsize - be32_to_cpu(fdt.totalsize);
+		if ((padlen < 0) && (quiet < 1))
+			fprintf(stderr,
+				"Warning: blob size %d >= minimum size %d\n",
+				be32_to_cpu(fdt.totalsize), minsize);
+	}
+
+	if (padsize > 0)
+		padlen = padsize;
+
+	if (padlen > 0) {
+		int tsize = be32_to_cpu(fdt.totalsize);
+		tsize += padlen;
+		fdt.totalsize = cpu_to_be32(tsize);
+	}
+
+	/*
+	 * Assemble the blob: start with the header, add with alignment
+	 * the reserve buffer, add the reserve map terminating zeroes,
+	 * the device tree itself, and finally the strings.
+	 */
+	blob = data_append_data(blob, &fdt, sizeof(fdt));
+	blob = data_append_align(blob, 8);
+	blob = data_merge(blob, reservebuf);
+	blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
+	blob = data_merge(blob, dtbuf);
+	blob = data_merge(blob, strbuf);
+
+	/*
+	 * If the user asked for more space than is used, pad out the blob.
+	 */
+	if (padlen > 0)
+		blob = data_append_zeroes(blob, padlen);
+
+	fwrite(blob.val, blob.len, 1, f);
+
+	if (ferror(f))
+		die("Error writing device tree blob: %s\n", strerror(errno));
+
+	/*
+	 * data_merge() frees the right-hand element so only the blob
+	 * remains to be freed.
+	 */
+	data_free(blob);
+}
+
+static void dump_stringtable_asm(FILE *f, struct data strbuf)
+{
+	const char *p;
+	int len;
+
+	p = strbuf.val;
+
+	while (p < (strbuf.val + strbuf.len)) {
+		len = strlen(p);
+		fprintf(f, "\t.string \"%s\"\n", p);
+		p += len+1;
+	}
+}
+
+void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
+{
+	struct version_info *vi = NULL;
+	int i;
+	struct data strbuf = empty_data;
+	struct reserve_info *re;
+	const char *symprefix = "dt";
+
+	for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+		if (version_table[i].version == version)
+			vi = &version_table[i];
+	}
+	if (!vi)
+		die("Unknown device tree blob version %d\n", version);
+
+	fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
+	fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
+	fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
+	fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
+	fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
+	fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
+	fprintf(f, "\n");
+
+	emit_label(f, symprefix, "blob_start");
+	emit_label(f, symprefix, "header");
+	fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
+	fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
+		symprefix, symprefix);
+	fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
+		symprefix, symprefix);
+	fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
+		symprefix, symprefix);
+	fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
+		symprefix, symprefix);
+	fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
+	fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
+		vi->last_comp_version);
+
+	if (vi->flags & FTF_BOOTCPUID)
+		fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
+			boot_cpuid_phys);
+
+	if (vi->flags & FTF_STRTABSIZE)
+		fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
+			symprefix, symprefix);
+
+	if (vi->flags & FTF_STRUCTSIZE)
+		fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
+			symprefix, symprefix);
+
+	/*
+	 * Reserve map entries.
+	 * Align the reserve map to a doubleword boundary.
+	 * Each entry is an (address, size) pair of u64 values.
+	 * Always supply a zero-sized temination entry.
+	 */
+	asm_emit_align(f, 8);
+	emit_label(f, symprefix, "reserve_map");
+
+	fprintf(f, "/* Memory reserve map from source file */\n");
+
+	/*
+	 * Use .long on high and low halfs of u64s to avoid .quad
+	 * as it appears .quad isn't available in some assemblers.
+	 */
+	for (re = bi->reservelist; re; re = re->next) {
+		if (re->label) {
+			fprintf(f, "\t.globl\t%s\n", re->label);
+			fprintf(f, "%s:\n", re->label);
+		}
+		fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+			(unsigned int)(re->re.address >> 32),
+			(unsigned int)(re->re.address & 0xffffffff));
+		fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+			(unsigned int)(re->re.size >> 32),
+			(unsigned int)(re->re.size & 0xffffffff));
+	}
+	for (i = 0; i < reservenum; i++) {
+		fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+	}
+
+	fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+
+	emit_label(f, symprefix, "struct_start");
+	flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
+	fprintf(f, "\t.long\tFDT_END\n");
+	emit_label(f, symprefix, "struct_end");
+
+	emit_label(f, symprefix, "strings_start");
+	dump_stringtable_asm(f, strbuf);
+	emit_label(f, symprefix, "strings_end");
+
+	emit_label(f, symprefix, "blob_end");
+
+	/*
+	 * If the user asked for more space than is used, pad it out.
+	 */
+	if (minsize > 0) {
+		fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
+			minsize, symprefix, symprefix);
+	}
+	if (padsize > 0) {
+		fprintf(f, "\t.space\t%d, 0\n", padsize);
+	}
+	emit_label(f, symprefix, "blob_abs_end");
+
+	data_free(strbuf);
+}
+
+struct inbuf {
+	char *base, *limit, *ptr;
+};
+
+static void inbuf_init(struct inbuf *inb, void *base, void *limit)
+{
+	inb->base = base;
+	inb->limit = limit;
+	inb->ptr = inb->base;
+}
+
+static void flat_read_chunk(struct inbuf *inb, void *p, int len)
+{
+	if ((inb->ptr + len) > inb->limit)
+		die("Premature end of data parsing flat device tree\n");
+
+	memcpy(p, inb->ptr, len);
+
+	inb->ptr += len;
+}
+
+static u32 flat_read_word(struct inbuf *inb)
+{
+	u32 val;
+
+	assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
+
+	flat_read_chunk(inb, &val, sizeof(val));
+
+	return be32_to_cpu(val);
+}
+
+static void flat_realign(struct inbuf *inb, int align)
+{
+	int off = inb->ptr - inb->base;
+
+	inb->ptr = inb->base + ALIGN(off, align);
+	if (inb->ptr > inb->limit)
+		die("Premature end of data parsing flat device tree\n");
+}
+
+static char *flat_read_string(struct inbuf *inb)
+{
+	int len = 0;
+	const char *p = inb->ptr;
+	char *str;
+
+	do {
+		if (p >= inb->limit)
+			die("Premature end of data parsing flat device tree\n");
+		len++;
+	} while ((*p++) != '\0');
+
+	str = strdup(inb->ptr);
+
+	inb->ptr += len;
+
+	flat_realign(inb, sizeof(u32));
+
+	return str;
+}
+
+static struct data flat_read_data(struct inbuf *inb, int len)
+{
+	struct data d = empty_data;
+
+	if (len == 0)
+		return empty_data;
+
+	d = data_grow_for(d, len);
+	d.len = len;
+
+	flat_read_chunk(inb, d.val, len);
+
+	flat_realign(inb, sizeof(u32));
+
+	return d;
+}
+
+static char *flat_read_stringtable(struct inbuf *inb, int offset)
+{
+	const char *p;
+
+	p = inb->base + offset;
+	while (1) {
+		if (p >= inb->limit || p < inb->base)
+			die("String offset %d overruns string table\n",
+			    offset);
+
+		if (*p == '\0')
+			break;
+
+		p++;
+	}
+
+	return strdup(inb->base + offset);
+}
+
+static struct property *flat_read_property(struct inbuf *dtbuf,
+					   struct inbuf *strbuf, int flags)
+{
+	u32 proplen, stroff;
+	char *name;
+	struct data val;
+
+	proplen = flat_read_word(dtbuf);
+	stroff = flat_read_word(dtbuf);
+
+	name = flat_read_stringtable(strbuf, stroff);
+
+	if ((flags & FTF_VARALIGN) && (proplen >= 8))
+		flat_realign(dtbuf, 8);
+
+	val = flat_read_data(dtbuf, proplen);
+
+	return build_property(name, val, NULL);
+}
+
+
+static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
+{
+	struct reserve_info *reservelist = NULL;
+	struct reserve_info *new;
+	const char *p;
+	struct fdt_reserve_entry re;
+
+	/*
+	 * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
+	 * List terminates at an entry with size equal to zero.
+	 *
+	 * First pass, count entries.
+	 */
+	p = inb->ptr;
+	while (1) {
+		flat_read_chunk(inb, &re, sizeof(re));
+		re.address  = be64_to_cpu(re.address);
+		re.size = be64_to_cpu(re.size);
+		if (re.size == 0)
+			break;
+
+		new = build_reserve_entry(re.address, re.size, NULL);
+		reservelist = add_reserve_entry(reservelist, new);
+	}
+
+	return reservelist;
+}
+
+
+static char *nodename_from_path(const char *ppath, const char *cpath)
+{
+	const char *lslash;
+	int plen;
+
+	lslash = strrchr(cpath, '/');
+	if (! lslash)
+		return NULL;
+
+	plen = lslash - cpath;
+
+	if (streq(cpath, "/") && streq(ppath, ""))
+		return "";
+
+	if ((plen == 0) && streq(ppath, "/"))
+		return strdup(lslash+1);
+
+	if (! strneq(ppath, cpath, plen))
+		return NULL;
+
+	return strdup(lslash+1);
+}
+
+static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-";
+static const char UNITCHAR[] = "0123456789abcdef,";
+
+static int check_node_name(const char *name)
+{
+	const char *atpos;
+	int basenamelen;
+
+	atpos = strrchr(name, '@');
+
+	if (atpos)
+		basenamelen = atpos - name;
+	else
+		basenamelen = strlen(name);
+
+	if (strspn(name, PROPCHAR) < basenamelen)
+		return -1;
+
+	if (atpos
+	    && ((basenamelen + 1 + strspn(atpos+1, UNITCHAR)) < strlen(name)))
+		return -1;
+
+	return basenamelen;
+}
+
+static struct node *unflatten_tree(struct inbuf *dtbuf,
+				   struct inbuf *strbuf,
+				   const char *parent_path, int flags)
+{
+	struct node *node;
+	u32 val;
+
+	node = build_node(NULL, NULL);
+
+	if (flags & FTF_FULLPATH) {
+		node->fullpath = flat_read_string(dtbuf);
+		node->name = nodename_from_path(parent_path, node->fullpath);
+
+		if (! node->name)
+			die("Path \"%s\" is not valid as a child of \"%s\"\n",
+			    node->fullpath, parent_path);
+	} else {
+		node->name = flat_read_string(dtbuf);
+		node->fullpath = join_path(parent_path, node->name);
+	}
+
+	node->basenamelen = check_node_name(node->name);
+	if (node->basenamelen < 0) {
+		fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name);
+	}
+
+	do {
+		struct property *prop;
+		struct node *child;
+
+		val = flat_read_word(dtbuf);
+		switch (val) {
+		case FDT_PROP:
+			if (node->children)
+				fprintf(stderr, "Warning: Flat tree input has "
+					"subnodes preceding a property.\n");
+			prop = flat_read_property(dtbuf, strbuf, flags);
+			add_property(node, prop);
+			break;
+
+		case FDT_BEGIN_NODE:
+			child = unflatten_tree(dtbuf,strbuf, node->fullpath,
+					       flags);
+			add_child(node, child);
+			break;
+
+		case FDT_END_NODE:
+			break;
+
+		case FDT_END:
+			die("Premature FDT_END in device tree blob\n");
+			break;
+
+		case FDT_NOP:
+			if (!(flags & FTF_NOPS))
+				fprintf(stderr, "Warning: NOP tag found in flat tree"
+					" version <16\n");
+
+			/* Ignore */
+			break;
+
+		default:
+			die("Invalid opcode word %08x in device tree blob\n",
+			    val);
+		}
+	} while (val != FDT_END_NODE);
+
+	return node;
+}
+
+
+struct boot_info *dt_from_blob(FILE *f)
+{
+	u32 magic, totalsize, version, size_str, size_dt;
+	u32 off_dt, off_str, off_mem_rsvmap;
+	int rc;
+	char *blob;
+	struct fdt_header *fdt;
+	char *p;
+	struct inbuf dtbuf, strbuf;
+	struct inbuf memresvbuf;
+	int sizeleft;
+	struct reserve_info *reservelist;
+	struct node *tree;
+	u32 val;
+	int flags = 0;
+
+	rc = fread(&magic, sizeof(magic), 1, f);
+	if (ferror(f))
+		die("Error reading DT blob magic number: %s\n",
+		    strerror(errno));
+	if (rc < 1) {
+		if (feof(f))
+			die("EOF reading DT blob magic number\n");
+		else
+			die("Mysterious short read reading magic number\n");
+	}
+
+	magic = be32_to_cpu(magic);
+	if (magic != FDT_MAGIC)
+		die("Blob has incorrect magic number\n");
+
+	rc = fread(&totalsize, sizeof(totalsize), 1, f);
+	if (ferror(f))
+		die("Error reading DT blob size: %s\n", strerror(errno));
+	if (rc < 1) {
+		if (feof(f))
+			die("EOF reading DT blob size\n");
+		else
+			die("Mysterious short read reading blob size\n");
+	}
+
+	totalsize = be32_to_cpu(totalsize);
+	if (totalsize < FDT_V1_SIZE)
+		die("DT blob size (%d) is too small\n", totalsize);
+
+	blob = xmalloc(totalsize);
+
+	fdt = (struct fdt_header *)blob;
+	fdt->magic = cpu_to_be32(magic);
+	fdt->totalsize = cpu_to_be32(totalsize);
+
+	sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
+	p = blob + sizeof(magic)  + sizeof(totalsize);
+
+	while (sizeleft) {
+		if (feof(f))
+			die("EOF before reading %d bytes of DT blob\n",
+			    totalsize);
+
+		rc = fread(p, 1, sizeleft, f);
+		if (ferror(f))
+			die("Error reading DT blob: %s\n",
+			    strerror(errno));
+
+		sizeleft -= rc;
+		p += rc;
+	}
+
+	off_dt = be32_to_cpu(fdt->off_dt_struct);
+	off_str = be32_to_cpu(fdt->off_dt_strings);
+	off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap);
+	version = be32_to_cpu(fdt->version);
+
+	fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
+	fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
+	fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
+	fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
+	fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap);
+	fprintf(stderr, "\tversion:\t\t0x%x\n", version );
+	fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
+		be32_to_cpu(fdt->last_comp_version));
+
+	if (off_mem_rsvmap >= totalsize)
+		die("Mem Reserve structure offset exceeds total size\n");
+
+	if (off_dt >= totalsize)
+		die("DT structure offset exceeds total size\n");
+
+	if (off_str > totalsize)
+		die("String table offset exceeds total size\n");
+
+	if (version >= 2)
+		fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n",
+			be32_to_cpu(fdt->boot_cpuid_phys));
+
+	size_str = -1;
+	if (version >= 3) {
+		size_str = be32_to_cpu(fdt->size_dt_strings);
+		fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str);
+		if (off_str+size_str > totalsize)
+			die("String table extends past total size\n");
+	}
+
+	if (version >= 17) {
+		size_dt = be32_to_cpu(fdt->size_dt_struct);
+		fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt);
+		if (off_dt+size_dt > totalsize)
+			die("Structure block extends past total size\n");
+	}
+
+	if (version < 16) {
+		flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
+	} else {
+		flags |= FTF_NOPS;
+	}
+
+	inbuf_init(&memresvbuf,
+		   blob + off_mem_rsvmap, blob + totalsize);
+	inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
+	if (size_str >= 0)
+		inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
+	else
+		inbuf_init(&strbuf, blob + off_str, blob + totalsize);
+
+	reservelist = flat_read_mem_reserve(&memresvbuf);
+
+	val = flat_read_word(&dtbuf);
+
+	if (val != FDT_BEGIN_NODE)
+		die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
+
+	tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
+
+	val = flat_read_word(&dtbuf);
+	if (val != FDT_END)
+		die("Device tree blob doesn't end with FDT_END\n");
+
+	free(blob);
+
+	return build_boot_info(reservelist, tree);
+}
diff --git a/arch/powerpc/boot/dtc-src/fstree.c b/arch/powerpc/boot/dtc-src/fstree.c
new file mode 100644
index 0000000..2a160a4
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/fstree.c
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+static struct node *read_fstree(const char *dirname)
+{
+	DIR *d;
+	struct dirent *de;
+	struct stat st;
+	struct node *tree;
+
+	d = opendir(dirname);
+	if (! d)
+		die("opendir(): %s\n", strerror(errno));
+
+	tree = build_node(NULL, NULL);
+
+	while ((de = readdir(d)) != NULL) {
+		char *tmpnam;
+
+		if (streq(de->d_name, ".")
+		    || streq(de->d_name, ".."))
+			continue;
+
+		tmpnam = join_path(dirname, de->d_name);
+
+		if (lstat(tmpnam, &st) < 0)
+			die("stat(%s): %s\n", tmpnam, strerror(errno));
+
+		if (S_ISREG(st.st_mode)) {
+			struct property *prop;
+			FILE *pfile;
+
+			pfile = fopen(tmpnam, "r");
+			if (! pfile) {
+				fprintf(stderr,
+					"WARNING: Cannot open %s: %s\n",
+					tmpnam, strerror(errno));
+			} else {
+				prop = build_property(strdup(de->d_name),
+						      data_copy_file(pfile,
+								     st.st_size),
+						      NULL);
+				add_property(tree, prop);
+				fclose(pfile);
+			}
+		} else if (S_ISDIR(st.st_mode)) {
+			struct node *newchild;
+
+			newchild = read_fstree(tmpnam);
+			newchild = name_node(newchild, strdup(de->d_name),
+					     NULL);
+			add_child(tree, newchild);
+		}
+
+		free(tmpnam);
+	}
+
+	return tree;
+}
+
+struct boot_info *dt_from_fs(const char *dirname)
+{
+	struct node *tree;
+
+	tree = read_fstree(dirname);
+	tree = name_node(tree, "", NULL);
+
+	fill_fullpaths(tree, "");
+
+	return build_boot_info(NULL, tree);
+}
+
diff --git a/arch/powerpc/boot/dtc-src/livetree.c b/arch/powerpc/boot/dtc-src/livetree.c
new file mode 100644
index 0000000..6ba0846
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/livetree.c
@@ -0,0 +1,305 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+
+/*
+ * Tree building functions
+ */
+
+struct property *build_property(char *name, struct data val, char *label)
+{
+	struct property *new = xmalloc(sizeof(*new));
+
+	new->name = name;
+	new->val = val;
+
+	new->next = NULL;
+
+	new->label = label;
+
+	return new;
+}
+
+struct property *chain_property(struct property *first, struct property *list)
+{
+	assert(first->next == NULL);
+
+	first->next = list;
+	return first;
+}
+
+struct property *reverse_properties(struct property *first)
+{
+	struct property *p = first;
+	struct property *head = NULL;
+	struct property *next;
+
+	while (p) {
+		next = p->next;
+		p->next = head;
+		head = p;
+		p = next;
+	}
+	return head;
+}
+
+struct node *build_node(struct property *proplist, struct node *children)
+{
+	struct node *new = xmalloc(sizeof(*new));
+	struct node *child;
+
+	memset(new, 0, sizeof(*new));
+
+	new->proplist = reverse_properties(proplist);
+	new->children = children;
+
+	for_each_child(new, child) {
+		child->parent = new;
+	}
+
+	return new;
+}
+
+struct node *name_node(struct node *node, char *name, char * label)
+{
+	assert(node->name == NULL);
+
+	node->name = name;
+
+	node->label = label;
+
+	return node;
+}
+
+struct node *chain_node(struct node *first, struct node *list)
+{
+	assert(first->next_sibling == NULL);
+
+	first->next_sibling = list;
+	return first;
+}
+
+void add_property(struct node *node, struct property *prop)
+{
+	struct property **p;
+
+	prop->next = NULL;
+
+	p = &node->proplist;
+	while (*p)
+		p = &((*p)->next);
+
+	*p = prop;
+}
+
+void add_child(struct node *parent, struct node *child)
+{
+	struct node **p;
+
+	child->next_sibling = NULL;
+
+	p = &parent->children;
+	while (*p)
+		p = &((*p)->next_sibling);
+
+	*p = child;
+}
+
+struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label)
+{
+	struct reserve_info *new = xmalloc(sizeof(*new));
+
+	new->re.address = address;
+	new->re.size = size;
+
+	new->next = NULL;
+
+	new->label = label;
+
+	return new;
+}
+
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+					struct reserve_info *list)
+{
+	assert(first->next == NULL);
+
+	first->next = list;
+	return first;
+}
+
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+				      struct reserve_info *new)
+{
+	struct reserve_info *last;
+
+	new->next = NULL;
+
+	if (! list)
+		return new;
+
+	for (last = list; last->next; last = last->next)
+		;
+
+	last->next = new;
+
+	return list;
+}
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+				  struct node *tree)
+{
+	struct boot_info *bi;
+
+	bi = xmalloc(sizeof(*bi));
+	bi->reservelist = reservelist;
+	bi->dt = tree;
+
+	return bi;
+}
+
+/*
+ * Tree accessor functions
+ */
+
+const char *get_unitname(struct node *node)
+{
+	if (node->name[node->basenamelen] == '\0')
+		return "";
+	else
+		return node->name + node->basenamelen + 1;
+}
+
+struct property *get_property(struct node *node, const char *propname)
+{
+	struct property *prop;
+
+	for_each_property(node, prop)
+		if (streq(prop->name, propname))
+			return prop;
+
+	return NULL;
+}
+
+cell_t propval_cell(struct property *prop)
+{
+	assert(prop->val.len == sizeof(cell_t));
+	return be32_to_cpu(*((cell_t *)prop->val.val));
+}
+
+struct node *get_subnode(struct node *node, const char *nodename)
+{
+	struct node *child;
+
+	for_each_child(node, child)
+		if (streq(child->name, nodename))
+			return child;
+
+	return NULL;
+}
+
+struct node *get_node_by_path(struct node *tree, const char *path)
+{
+	const char *p;
+	struct node *child;
+
+	if (!path || ! (*path))
+		return tree;
+
+	while (path[0] == '/')
+		path++;
+
+	p = strchr(path, '/');
+
+	for_each_child(tree, child) {
+		if (p && strneq(path, child->name, p-path))
+			return get_node_by_path(child, p+1);
+		else if (!p && streq(path, child->name))
+			return child;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_label(struct node *tree, const char *label)
+{
+	struct node *child, *node;
+
+	assert(label && (strlen(label) > 0));
+
+	if (tree->label && streq(tree->label, label))
+		return tree;
+
+	for_each_child(tree, child) {
+		node = get_node_by_label(child, label);
+		if (node)
+			return node;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
+{
+	struct node *child, *node;
+
+	assert((phandle != 0) && (phandle != -1));
+
+	if (tree->phandle == phandle)
+		return tree;
+
+	for_each_child(tree, child) {
+		node = get_node_by_phandle(child, phandle);
+		if (node)
+			return node;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_ref(struct node *tree, const char *ref)
+{
+	if (ref[0] == '/')
+		return get_node_by_path(tree, ref);
+	else
+		return get_node_by_label(tree, ref);
+}
+
+cell_t get_node_phandle(struct node *root, struct node *node)
+{
+	static cell_t phandle = 1; /* FIXME: ick, static local */
+
+	if ((node->phandle != 0) && (node->phandle != -1))
+		return node->phandle;
+
+	assert(! get_property(node, "linux,phandle"));
+
+	while (get_node_by_phandle(root, phandle))
+		phandle++;
+
+	node->phandle = phandle;
+	add_property(node,
+		     build_property("linux,phandle",
+				    data_append_cell(empty_data, phandle),
+				    NULL));
+
+	return node->phandle;
+}
diff --git a/arch/powerpc/boot/dtc-src/srcpos.c b/arch/powerpc/boot/dtc-src/srcpos.c
new file mode 100644
index 0000000..352b0fe
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/srcpos.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+
+/*
+ * Record the complete unique set of opened file names.
+ * Primarily used to cache source position file names.
+ */
+#define MAX_N_FILE_NAMES	(100)
+
+const char *file_names[MAX_N_FILE_NAMES];
+static int n_file_names = 0;
+
+/*
+ * Like yylineno, this is the current open file pos.
+ */
+
+int srcpos_filenum = -1;
+
+
+
+FILE *dtc_open_file(const char *fname)
+{
+	FILE *f;
+
+	if (lookup_file_name(fname, 1) < 0)
+		die("Too many files opened\n");
+
+	if (streq(fname, "-"))
+		f = stdin;
+	else
+		f = fopen(fname, "r");
+
+	if (! f)
+		die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+
+	return f;
+}
+
+
+
+/*
+ * Locate and optionally add filename fname in the file_names[] array.
+ *
+ * If the filename is currently not in the array and the boolean
+ * add_it is non-zero, an attempt to add the filename will be made.
+ *
+ * Returns;
+ *    Index [0..MAX_N_FILE_NAMES) where the filename is kept
+ *    -1 if the name can not be recorded
+ */
+
+int lookup_file_name(const char *fname, int add_it)
+{
+	int i;
+
+	for (i = 0; i < n_file_names; i++) {
+		if (strcmp(file_names[i], fname) == 0)
+			return i;
+	}
+
+	if (add_it) {
+		if (n_file_names < MAX_N_FILE_NAMES) {
+			file_names[n_file_names] = strdup(fname);
+			return n_file_names++;
+		}
+	}
+
+	return -1;
+}
+
+
+const char *srcpos_filename_for_num(int filenum)
+{
+	if (0 <= filenum && filenum < n_file_names) {
+		return file_names[filenum];
+	}
+
+	return 0;
+}
+
+
+const char *srcpos_get_filename(void)
+{
+	return srcpos_filename_for_num(srcpos_filenum);
+}
diff --git a/arch/powerpc/boot/dtc-src/srcpos.h b/arch/powerpc/boot/dtc-src/srcpos.h
new file mode 100644
index 0000000..ce7ab5b
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/srcpos.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+/*
+ * Augment the standard YYLTYPE with a filenum index into an
+ * array of all opened filenames.
+ */
+
+#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
+typedef struct YYLTYPE {
+    int first_line;
+    int first_column;
+    int last_line;
+    int last_column;
+    int filenum;
+} YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED	1
+#define YYLTYPE_IS_TRIVIAL	1
+#endif
+
+/* Cater to old parser templates. */
+#ifndef YYID
+#define YYID(n)	(n)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)					\
+    do									\
+      if (YYID (N))							\
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	  (Current).filenum      = YYRHSLOC (Rhs, N).filenum;		\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	  (Current).filenum      = YYRHSLOC (Rhs, 0).filenum;		\
+	}								\
+    while (YYID (0))
+
+
+
+extern void yyerror(char const *);
+
+extern int srcpos_filenum;
+
+extern int push_input_file(const char *filename);
+extern int pop_input_file(void);
+
+extern FILE *dtc_open_file(const char *fname);
+extern int lookup_file_name(const char *fname, int add_it);
+extern const char *srcpos_filename_for_num(int filenum);
+const char *srcpos_get_filename(void);
diff --git a/arch/powerpc/boot/dtc-src/treesource.c b/arch/powerpc/boot/dtc-src/treesource.c
new file mode 100644
index 0000000..a6a7767
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/treesource.c
@@ -0,0 +1,275 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+extern FILE *yyin;
+extern int yyparse(void);
+extern void yyerror(char const *);
+
+struct boot_info *the_boot_info;
+
+struct boot_info *dt_from_source(const char *fname)
+{
+	the_boot_info = NULL;
+
+	push_input_file(fname);
+
+	if (yyparse() != 0)
+		return NULL;
+
+	fill_fullpaths(the_boot_info->dt, "");
+
+	return the_boot_info;
+}
+
+static void write_prefix(FILE *f, int level)
+{
+	int i;
+
+	for (i = 0; i < level; i++)
+		fputc('\t', f);
+}
+
+int isstring(char c)
+{
+	return (isprint(c)
+		|| (c == '\0')
+		|| strchr("\a\b\t\n\v\f\r", c));
+}
+
+static void write_propval_string(FILE *f, struct data val)
+{
+	const char *str = val.val;
+	int i;
+	int newchunk = 1;
+	struct marker *m = val.markers;
+
+	assert(str[val.len-1] == '\0');
+
+	for (i = 0; i < (val.len-1); i++) {
+		char c = str[i];
+
+		if (newchunk) {
+			while (m && (m->offset <= i)) {
+				if (m->type == LABEL) {
+					assert(m->offset == i);
+					fprintf(f, "%s: ", m->ref);
+				}
+				m = m->next;
+			}
+			fprintf(f, "\"");
+			newchunk = 0;
+		}
+
+		switch (c) {
+		case '\a':
+			fprintf(f, "\\a");
+			break;
+		case '\b':
+			fprintf(f, "\\b");
+			break;
+		case '\t':
+			fprintf(f, "\\t");
+			break;
+		case '\n':
+			fprintf(f, "\\n");
+			break;
+		case '\v':
+			fprintf(f, "\\v");
+			break;
+		case '\f':
+			fprintf(f, "\\f");
+			break;
+		case '\r':
+			fprintf(f, "\\r");
+			break;
+		case '\\':
+			fprintf(f, "\\\\");
+			break;
+		case '\"':
+			fprintf(f, "\\\"");
+			break;
+		case '\0':
+			fprintf(f, "\", ");
+			newchunk = 1;
+			break;
+		default:
+			if (isprint(c))
+				fprintf(f, "%c", c);
+			else
+				fprintf(f, "\\x%02hhx", c);
+		}
+	}
+	fprintf(f, "\"");
+
+	/* Wrap up any labels at the end of the value */
+	for_each_marker_of_type(m, LABEL) {
+		assert (m->offset == val.len);
+		fprintf(f, " %s:", m->ref);
+	}
+}
+
+static void write_propval_cells(FILE *f, struct data val)
+{
+	void *propend = val.val + val.len;
+	cell_t *cp = (cell_t *)val.val;
+	struct marker *m = val.markers;
+
+	fprintf(f, "<");
+	for (;;) {
+		while (m && (m->offset <= ((char *)cp - val.val))) {
+			if (m->type == LABEL) {
+				assert(m->offset == ((char *)cp - val.val));
+				fprintf(f, "%s: ", m->ref);
+			}
+			m = m->next;
+		}
+
+		fprintf(f, "0x%x", be32_to_cpu(*cp++));
+		if ((void *)cp >= propend)
+			break;
+		fprintf(f, " ");
+	}
+
+	/* Wrap up any labels at the end of the value */
+	for_each_marker_of_type(m, LABEL) {
+		assert (m->offset == val.len);
+		fprintf(f, " %s:", m->ref);
+	}
+	fprintf(f, ">");
+}
+
+static void write_propval_bytes(FILE *f, struct data val)
+{
+	void *propend = val.val + val.len;
+	const char *bp = val.val;
+	struct marker *m = val.markers;
+
+	fprintf(f, "[");
+	for (;;) {
+		while (m && (m->offset == (bp-val.val))) {
+			if (m->type == LABEL)
+				fprintf(f, "%s: ", m->ref);
+			m = m->next;
+		}
+
+		fprintf(f, "%02hhx", *bp++);
+		if ((void *)bp >= propend)
+			break;
+		fprintf(f, " ");
+	}
+
+	/* Wrap up any labels at the end of the value */
+	for_each_marker_of_type(m, LABEL) {
+		assert (m->offset == val.len);
+		fprintf(f, " %s:", m->ref);
+	}
+	fprintf(f, "]");
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+	int len = prop->val.len;
+	const char *p = prop->val.val;
+	struct marker *m = prop->val.markers;
+	int nnotstring = 0, nnul = 0;
+	int nnotstringlbl = 0, nnotcelllbl = 0;
+	int i;
+
+	if (len == 0) {
+		fprintf(f, ";\n");
+		return;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (! isstring(p[i]))
+			nnotstring++;
+		if (p[i] == '\0')
+			nnul++;
+	}
+
+	for_each_marker_of_type(m, LABEL) {
+		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
+			nnotstringlbl++;
+		if ((m->offset % sizeof(cell_t)) != 0)
+			nnotcelllbl++;
+	}
+
+	fprintf(f, " = ");
+	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+	    && (nnotstringlbl == 0)) {
+		write_propval_string(f, prop->val);
+	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
+		write_propval_cells(f, prop->val);
+	} else {
+		write_propval_bytes(f, prop->val);
+	}
+
+	fprintf(f, ";\n");
+}
+
+static void write_tree_source_node(FILE *f, struct node *tree, int level)
+{
+	struct property *prop;
+	struct node *child;
+
+	write_prefix(f, level);
+	if (tree->label)
+		fprintf(f, "%s: ", tree->label);
+	if (tree->name && (*tree->name))
+		fprintf(f, "%s {\n", tree->name);
+	else
+		fprintf(f, "/ {\n");
+
+	for_each_property(tree, prop) {
+		write_prefix(f, level+1);
+		if (prop->label)
+			fprintf(f, "%s: ", prop->label);
+		fprintf(f, "%s", prop->name);
+		write_propval(f, prop);
+	}
+	for_each_child(tree, child) {
+		fprintf(f, "\n");
+		write_tree_source_node(f, child, level+1);
+	}
+	write_prefix(f, level);
+	fprintf(f, "};\n");
+}
+
+
+void dt_to_source(FILE *f, struct boot_info *bi)
+{
+	struct reserve_info *re;
+
+	fprintf(f, "/dts-v1/;\n\n");
+
+	for (re = bi->reservelist; re; re = re->next) {
+		if (re->label)
+			fprintf(f, "%s: ", re->label);
+		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
+			(unsigned long long)re->re.address,
+			(unsigned long long)re->re.size);
+	}
+
+	write_tree_source_node(f, bi->dt, 0);
+}
+
diff --git a/arch/powerpc/boot/dtc-src/version_gen.h b/arch/powerpc/boot/dtc-src/version_gen.h
new file mode 100644
index 0000000..6c34303
--- /dev/null
+++ b/arch/powerpc/boot/dtc-src/version_gen.h
@@ -0,0 +1 @@
+#define DTC_VERSION "DTC 1.0.0-gd6f9b62f"
diff --git a/arch/powerpc/boot/dts/kuroboxHD.dts b/arch/powerpc/boot/dts/kuroboxHD.dts
index ec71ab8..4469588 100644
--- a/arch/powerpc/boot/dts/kuroboxHD.dts
+++ b/arch/powerpc/boot/dts/kuroboxHD.dts
@@ -23,6 +23,12 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -60,7 +66,7 @@
 		i2c@80003000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <80003000 1000>;
 			interrupts = <5 2>;
@@ -73,7 +79,8 @@
 			};
 		};
 
-		serial@80004500 {
+		serial0: serial@80004500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <80004500 8>;
@@ -83,7 +90,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@80004600 {
+		serial1: serial@80004600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <80004600 8>;
@@ -102,7 +110,7 @@
 			reg = <80040000 40000>;
 		};
 
-		pci@fec00000 {
+		pci0: pci@fec00000 {
 			#address-cells = <3>;
 			#size-cells = <2>;
 			#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/kuroboxHG.dts b/arch/powerpc/boot/dts/kuroboxHG.dts
index 32ecd23..8443c85 100644
--- a/arch/powerpc/boot/dts/kuroboxHG.dts
+++ b/arch/powerpc/boot/dts/kuroboxHG.dts
@@ -23,6 +23,12 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -60,7 +66,7 @@
 		i2c@80003000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <80003000 1000>;
 			interrupts = <5 2>;
@@ -73,7 +79,8 @@
 			};
 		};
 
-		serial@80004500 {
+		serial0: serial@80004500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <80004500 8>;
@@ -83,7 +90,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@80004600 {
+		serial1: serial@80004600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <80004600 8>;
@@ -102,7 +110,7 @@
 			reg = <80040000 40000>;
 		};
 
-		pci@fec00000 {
+		pci0: pci@fec00000 {
 			#address-cells = <3>;
 			#size-cells = <2>;
 			#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/lite5200.dts b/arch/powerpc/boot/dts/lite5200.dts
index 6731763..23eeeb1 100644
--- a/arch/powerpc/boot/dts/lite5200.dts
+++ b/arch/powerpc/boot/dts/lite5200.dts
@@ -284,7 +284,8 @@
 		};
 
 		i2c@3d00 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "mpc5200-i2c","fsl-i2c";
 			cell-index = <0>;
 			reg = <3d00 40>;
@@ -294,7 +295,8 @@
 		};
 
 		i2c@3d40 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "mpc5200-i2c","fsl-i2c";
 			cell-index = <1>;
 			reg = <3d40 40>;
diff --git a/arch/powerpc/boot/dts/lite5200b.dts b/arch/powerpc/boot/dts/lite5200b.dts
index b540388..f94e073 100644
--- a/arch/powerpc/boot/dts/lite5200b.dts
+++ b/arch/powerpc/boot/dts/lite5200b.dts
@@ -300,7 +300,8 @@
 		};
 
 		i2c@3d00 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "mpc5200b-i2c","mpc5200-i2c","fsl-i2c";
 			cell-index = <0>;
 			reg = <3d00 40>;
@@ -310,7 +311,8 @@
 		};
 
 		i2c@3d40 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
 			compatible = "mpc5200b-i2c","mpc5200-i2c","fsl-i2c";
 			cell-index = <1>;
 			reg = <3d40 40>;
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 9e7eba9..c5b6665 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -15,6 +15,14 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -52,7 +60,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -61,7 +71,9 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
@@ -91,11 +103,10 @@
 		};
 
 		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <24520 20>;
 			phy1: ethernet-phy@1 {
 				interrupt-parent = < &ipic >;
 				interrupts = <13 8>;
@@ -110,7 +121,8 @@
 			};
 		};
 
-		ethernet@24000 {
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -121,7 +133,8 @@
 			phy-handle = < &phy1 >;
 		};
 
-		ethernet@25000 {
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -132,7 +145,8 @@
 			phy-handle = < &phy4 >;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -141,7 +155,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -179,7 +194,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index c64f303..26ac467 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -15,6 +15,14 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -59,7 +67,7 @@
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -72,7 +80,8 @@
 			};
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -81,7 +90,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -208,44 +218,34 @@
 			mode = "slave";
 		};
 
-		ucc@2200 {
+		enet0: ucc@2200 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <3>;
 			device-id = <3>;
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = < &qeic >;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <19>;
-			tx-clock = <1a>;
+			rx-clock-name = "clk9";
+			tx-clock-name = "clk10";
 			phy-handle = < &phy3 >;
 			pio-handle = < &pio3 >;
 		};
 
-		ucc@3200 {
+		enet1: ucc@3200 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <4>;
 			device-id = <4>;
 			reg = <3200 200>;
 			interrupts = <23>;
 			interrupt-parent = < &qeic >;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <17>;
-			tx-clock = <18>;
+			rx-clock-name = "clk7";
+			tx-clock-name = "clk8";
 			phy-handle = < &phy4 >;
 			pio-handle = < &pio4 >;
 		};
@@ -283,7 +283,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x11 AD17 */
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts
index 388c8a7..10ff7aa 100644
--- a/arch/powerpc/boot/dts/mpc832x_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts
@@ -15,6 +15,14 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -52,7 +60,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -60,7 +70,8 @@
 			dfsrr;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -69,7 +80,8 @@
 			interrupt-parent = <&pic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -187,44 +199,34 @@
 			mode = "cpu";
 		};
 
-		ucc@3000 {
+		enet0: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <2>;
 			device-id = <2>;
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <20>;
-			tx-clock = <13>;
+			rx-clock-name = "clk16";
+			tx-clock-name = "clk3";
 			phy-handle = <&phy00>;
 			pio-handle = <&ucc2pio>;
 		};
 
-		ucc@2200 {
+		enet1: ucc@2200 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <3>;
 			device-id = <3>;
 			reg = <2200 200>;
 			interrupts = <22>;
 			interrupt-parent = <&qeic>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <19>;
-			tx-clock = <1a>;
+			rx-clock-name = "clk9";
+			tx-clock-name = "clk10";
 			phy-handle = <&phy04>;
 			pio-handle = <&ucc3pio>;
 		};
@@ -262,7 +264,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x10 AD16 (USB) */
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 5072f6d..e354f26 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -14,6 +14,15 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -51,7 +60,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -60,7 +71,9 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
@@ -102,11 +115,10 @@
 		};
 
 		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <24520 20>;
 
 			/* Vitesse 8201 */
 			phy1c: ethernet-phy@1c {
@@ -125,17 +137,12 @@
 			};
 		};
 
-		ethernet@24000 {
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
 			interrupt-parent = < &ipic >;
@@ -143,19 +150,12 @@
 			linux,network-index = <0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
 			interrupt-parent = < &ipic >;
@@ -163,7 +163,8 @@
 			linux,network-index = <1>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -172,7 +173,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -203,7 +205,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x10 - SATA */
@@ -224,7 +227,8 @@
 		device_type = "pci";
 	};
 
-	pci@e0008600 {
+	pci1: pci@e0008600 {
+		cell-index = <2>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x0E - MiniPCI Slot */
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
index 074f7a2..ebdf0b7 100644
--- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts
@@ -14,6 +14,13 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -51,7 +58,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -60,7 +69,9 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
@@ -90,11 +101,10 @@
 		};
 
 		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <24520 20>;
 
 			/* Vitesse 8201 */
 			phy1c: ethernet-phy@1c {
@@ -105,7 +115,8 @@
 			};
 		};
 
-		ethernet@24000 {
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -117,7 +128,8 @@
 			linux,network-index = <0>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -126,7 +138,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -157,7 +170,8 @@
 		};
 	};
 
-	pci@e0008600 {
+	pci0: pci@e0008600 {
+		cell-index = <2>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 				/* IDSEL 0x0F - PCI Slot */
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index 49363f8..0ba13eb 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -15,6 +15,15 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -59,7 +68,7 @@
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -75,7 +84,7 @@
 		i2c@3100 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
@@ -119,11 +128,11 @@
 		};
 
 		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = < &ipic >;
 				interrupts = <11 8>;
@@ -138,17 +147,12 @@
 			};
 		};
 
-		ethernet@24000 {
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <20 8 21 8 22 8>;
 			interrupt-parent = < &ipic >;
@@ -156,19 +160,12 @@
 			linux,network-index = <0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 8 24 8 25 8>;
 			interrupt-parent = < &ipic >;
@@ -176,7 +173,8 @@
 			linux,network-index = <1>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -185,7 +183,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -225,7 +224,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
@@ -285,7 +285,8 @@
 		device_type = "pci";
 	};
 
-	pci@e0008600 {
+	pci1: pci@e0008600 {
+		cell-index = <2>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 0b2d2b5..fd841b2 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -20,6 +20,14 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -64,7 +72,7 @@
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <e 8>;
@@ -80,7 +88,7 @@
 		i2c@3100 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <f 8>;
@@ -88,7 +96,8 @@
 			dfsrr;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -97,7 +106,8 @@
 			interrupt-parent = < &ipic >;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -239,45 +249,35 @@
 			mode = "slave";
 		};
 
-		ucc@2000 {
+		enet0: ucc@2000 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <1>;
 			device-id = <1>;
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = < &qeic >;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <0>;
-			tx-clock = <19>;
+			rx-clock-name = "none";
+			tx-clock-name = "clk9";
 			phy-handle = < &phy0 >;
 			phy-connection-type = "rgmii-id";
 			pio-handle = < &pio1 >;
 		};
 
-		ucc@3000 {
+		enet1: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <2>;
 			device-id = <2>;
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = < &qeic >;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <0>;
-			tx-clock = <14>;
+			rx-clock-name = "none";
+			tx-clock-name = "clk4";
 			phy-handle = < &phy1 >;
 			phy-connection-type = "rgmii-id";
 			pio-handle = < &pio2 >;
@@ -316,7 +316,8 @@
 		};
 	};
 
-	pci@e0008500 {
+	pci0: pci@e0008500 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index 6442a71..9752484 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -16,6 +16,15 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -63,7 +72,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -74,9 +85,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <5 1>;
@@ -97,64 +108,44 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy1>;
 		};
 
-		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet2: ethernet@26000 {
+			cell-index = <2>;
 			device_type = "network";
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <29 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
@@ -163,7 +154,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
@@ -183,7 +175,8 @@
 		};
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index f3f4d79..fa8d9aa 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -16,6 +16,15 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -63,7 +72,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -74,9 +85,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <5 1>;
@@ -91,9 +102,8 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -104,9 +114,8 @@
 			phy-handle = <&phy0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -117,7 +126,8 @@
 			phy-handle = <&phy1>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
@@ -126,7 +136,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
@@ -183,7 +194,8 @@
 		};
 	};
 
-	pci1: pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		interrupt-map-mask = <1f800 0 0 7>;
 		interrupt-map = <
 
@@ -250,11 +262,12 @@
 			#interrupt-cells = <2>;
 			compatible = "chrp,iic";
 			interrupts = <1>;
-			interrupt-parent = <&pci1>;
+			interrupt-parent = <&pci0>;
 		};
 	};
 
-	pci@e0009000 {
+	pci1: pci@e0009000 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index 6c608de..54b3bdf 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -15,6 +15,17 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		pci3 = &pci3;
+	};
+
 	cpus {
 		#cpus = <1>;
 		#address-cells = <1>;
@@ -64,7 +75,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -72,12 +85,23 @@
 			dfsrr;
 		};
 
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <2b 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <a 1>;
@@ -92,9 +116,8 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -106,9 +129,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@26000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -120,7 +142,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -129,7 +152,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -156,7 +180,8 @@
 		};
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		compatible = "fsl,mpc8540-pci";
 		device_type = "pci";
 		interrupt-map-mask = <f800 0 0 7>;
@@ -187,7 +212,8 @@
 		reg = <e0008000 1000>;
 	};
 
-	pcie@e0009000 {
+	pci1: pcie@e0009000 {
+		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -223,7 +249,8 @@
 		};
 	};
 
-	pcie@e000a000 {
+	pci2: pcie@e000a000 {
+		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -259,7 +286,8 @@
 		};
 	};
 
-	pcie@e000b000 {
+	pci3: pcie@e000b000 {
+		cell-index = <3>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -369,6 +397,5 @@
 				};
 			};
 		};
-
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
index 69ca502..1f470c6 100644
--- a/arch/powerpc/boot/dts/mpc8548cds.dts
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -16,6 +16,20 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+/*
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+*/
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -63,7 +77,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -71,12 +87,23 @@
 			dfsrr;
 		};
 
+		i2c@3100 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <2b 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <5 1>;
@@ -103,9 +130,8 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -116,9 +142,8 @@
 			phy-handle = <&phy0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -130,9 +155,8 @@
 		};
 
 /* eTSEC 3/4 are currently broken
-		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet2: ethernet@26000 {
+			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -143,9 +167,8 @@
 			phy-handle = <&phy2>;
 		};
 
-		ethernet@27000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet3: ethernet@27000 {
+			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -157,7 +180,8 @@
 		};
  */
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;	// reg base, size
@@ -166,7 +190,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
@@ -193,7 +218,8 @@
 		};
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 			/* IDSEL 0x4 (PCIX Slot 2) */
@@ -342,7 +368,8 @@
 		};
 	};
 
-	pci@e0009000 {
+	pci1: pci@e0009000 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
@@ -366,7 +393,8 @@
 		device_type = "pci";
 	};
 
-	pcie@e000a000 {
+	pci2: pcie@e000a000 {
+		cell-index = <2>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index 57029cc..4538f3c 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -16,6 +16,15 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -63,7 +72,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -74,9 +85,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <5 1>;
@@ -91,9 +102,8 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -104,9 +114,8 @@
 			phy-handle = <&phy0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
@@ -117,7 +126,8 @@
 			phy-handle = <&phy1>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>; 	// reg base, size
@@ -126,7 +136,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;	// reg base, size
@@ -183,7 +194,8 @@
 		};
 	};
 
-	pci1: pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		interrupt-map-mask = <1f800 0 0 7>;
 		interrupt-map = <
 
@@ -250,11 +262,12 @@
 			#interrupt-cells = <2>;
 			compatible = "chrp,iic";
 			interrupts = <1>;
-			interrupt-parent = <&pci1>;
+			interrupt-parent = <&pci0>;
 		};
 	};
 
-	pci@e0009000 {
+	pci1: pci@e0009000 {
+		cell-index = <1>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 6b362f8..639ce8a 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -16,6 +16,16 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -63,11 +73,11 @@
 		};
 
 		mdio@24520 {
-			device_type = "mdio";
-			compatible = "gianfar";
-			reg = <24520 20>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			compatible = "fsl,gianfar-mdio";
+			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <5 1>;
@@ -94,36 +104,24 @@
 			};
 		};
 
-		ethernet@24000 {
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy0>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
@@ -174,7 +172,7 @@
 				compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
 			};
 
-			serial@91a00 {
+			serial0: serial@91a00 {
 				device_type = "serial";
 				compatible = "fsl,mpc8560-scc-uart",
 				             "fsl,cpm2-scc-uart";
@@ -186,7 +184,7 @@
 				interrupt-parent = <&cpmpic>;
 			};
 
-			serial@91a20 {
+			serial1: serial@91a20 {
 				device_type = "serial";
 				compatible = "fsl,mpc8560-scc-uart",
 				             "fsl,cpm2-scc-uart";
@@ -198,17 +196,11 @@
 				interrupt-parent = <&cpmpic>;
 			};
 
-			ethernet@91320 {
+			enet2: ethernet@91320 {
 				device_type = "network";
 				compatible = "fsl,mpc8560-fcc-enet",
 				             "fsl,cpm2-fcc-enet";
 				reg = <91320 20 88500 100 913b0 1>;
-				/*
-				 * mac-address is deprecated and will be removed
-				 * in 2.6.25.  Only recent versions of
-				 * U-Boot support local-mac-address, however.
-				 */
-				mac-address = [ 00 00 00 00 00 00 ];
 				local-mac-address = [ 00 00 00 00 00 00 ];
 				fsl,cpm-command = <16200300>;
 				interrupts = <21 8>;
@@ -216,17 +208,11 @@
 				phy-handle = <&phy2>;
 			};
 
-			ethernet@91340 {
+			enet3: ethernet@91340 {
 				device_type = "network";
 				compatible = "fsl,mpc8560-fcc-enet",
 				             "fsl,cpm2-fcc-enet";
 				reg = <91340 20 88600 100 913d0 1>;
-				/*
-				 * mac-address is deprecated and will be removed
-				 * in 2.6.25.  Only recent versions of
-				 * U-Boot support local-mac-address, however.
-				 */
-				mac-address = [ 00 00 00 00 00 00 ];
 				local-mac-address = [ 00 00 00 00 00 00 ];
 				fsl,cpm-command = <1a400300>;
 				interrupts = <22 8>;
@@ -236,7 +222,8 @@
 		};
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts
index 5439437..5818a7c 100644
--- a/arch/powerpc/boot/dts/mpc8568mds.dts
+++ b/arch/powerpc/boot/dts/mpc8568mds.dts
@@ -20,6 +20,17 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -74,7 +85,7 @@
 		i2c@3000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -90,7 +101,7 @@
 		i2c@3100 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "i2c";
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <2b 2>;
@@ -101,9 +112,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@7 {
 				interrupt-parent = <&mpic>;
 				interrupts = <1 1>;
@@ -130,45 +141,32 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
  			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy2>;
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
  			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -183,7 +181,8 @@
 			fsl,has-rstcr;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -318,45 +317,35 @@
 			mode = "cpu";
 		};
 
-		ucc@2000 {
+		enet2: ucc@2000 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <1>;
 			device-id = <1>;
 			reg = <2000 200>;
 			interrupts = <20>;
 			interrupt-parent = <&qeic>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <0>;
-			tx-clock = <20>;
+			rx-clock-name = "none";
+			tx-clock-name = "clk16";
 			pio-handle = <&pio1>;
 			phy-handle = <&phy0>;
 			phy-connection-type = "rgmii-id";
 		};
 
-		ucc@3000 {
+		enet3: ucc@3000 {
 			device_type = "network";
 			compatible = "ucc_geth";
 			model = "UCC";
+			cell-index = <2>;
 			device-id = <2>;
 			reg = <3000 200>;
 			interrupts = <21>;
 			interrupt-parent = <&qeic>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
-			rx-clock = <0>;
-			tx-clock = <20>;
+			rx-clock-name = "none";
+			tx-clock-name = "clk16";
 			pio-handle = <&pio2>;
 			phy-handle = <&phy1>;
 			phy-connection-type = "rgmii-id";
@@ -366,7 +355,6 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2120 18>;
-			device_type = "mdio";
 			compatible = "ucc_geth_phy";
 
 			/* These are the same PHYs as on
@@ -410,7 +398,8 @@
 
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 			/* IDSEL 0x12 AD18 */
@@ -440,7 +429,8 @@
 	};
 
 	/* PCI Express */
-	pcie@e000a000 {
+	pci1: pcie@e000a000 {
+		cell-index = <2>;
 		interrupt-map-mask = <f800 0 0 7>;
 		interrupt-map = <
 
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index 0eb44fb..233e0d5 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -15,6 +15,18 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -69,7 +81,9 @@
 		};
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -78,7 +92,9 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <2b 2>;
@@ -89,9 +105,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <a 1>;
@@ -114,9 +130,8 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -128,9 +143,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -142,9 +156,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet2: ethernet@26000 {
+			cell-index = <2>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -156,9 +169,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@27000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet3: ethernet@27000 {
+			cell-index = <3>;
 			device_type = "network";
 			model = "eTSEC";
 			compatible = "gianfar";
@@ -170,7 +182,8 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -179,7 +192,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -206,7 +220,8 @@
 		};
 	};
 
-	pcie@ffe08000 {
+	pci0: pcie@ffe08000 {
+		cell-index = <0>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -415,7 +430,8 @@
 
 	};
 
-	pcie@ffe09000 {
+	pci1: pcie@ffe09000 {
+		cell-index = <1>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -451,7 +467,8 @@
 		};
 	};
 
-	pcie@ffe0a000 {
+	pci2: pcie@ffe0a000 {
+		cell-index = <2>;
 		compatible = "fsl,mpc8548-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 966edf1..01040a75 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -15,6 +15,13 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -47,10 +54,10 @@
 		bus-frequency = <0>;
 
 		i2c@3000 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
@@ -58,17 +65,18 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
-			compatible = "fsl-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			cell-index = <1>;
+			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <2b 2>;
 			interrupt-parent = <&mpic>;
 			dfsrr;
 		};
 
-		serial@4500 {
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -77,7 +85,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -86,7 +95,6 @@
 			interrupt-parent = <&mpic>;
 		};
 
-
 		mpic: interrupt-controller@40000 {
 			clock-frequency = <0>;
 			interrupt-controller;
@@ -105,7 +113,8 @@
 		};
 	};
 
-	pci@e0008000 {
+	pci0: pci@e0008000 {
+		cell-index = <0>;
 		compatible = "fsl,mpc8610-pci";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -134,7 +143,8 @@
 			>;
 	};
 
-	pcie@e000a000 {
+	pci1: pcie@e000a000 {
+		cell-index = <1>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index abb26dc..86fc228 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -16,6 +16,17 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		ethernet3 = &enet3;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -58,7 +69,9 @@
 		bus-frequency = <0>;
 
 		i2c@3000 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
 			compatible = "fsl-i2c";
 			reg = <3000 100>;
 			interrupts = <2b 2>;
@@ -67,7 +80,9 @@
 		};
 
 		i2c@3100 {
-			device_type = "i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
 			compatible = "fsl-i2c";
 			reg = <3100 100>;
 			interrupts = <2b 2>;
@@ -78,9 +93,9 @@
 		mdio@24520 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			device_type = "mdio";
-			compatible = "gianfar";
+			compatible = "fsl,gianfar-mdio";
 			reg = <24520 20>;
+
 			phy0: ethernet-phy@0 {
 				interrupt-parent = <&mpic>;
 				interrupts = <a 1>;
@@ -107,19 +122,12 @@
 			};
 		};
 
-		ethernet@24000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet0: ethernet@24000 {
+			cell-index = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1d 2 1e 2 22 2>;
 			interrupt-parent = <&mpic>;
@@ -127,19 +135,12 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet1: ethernet@25000 {
+			cell-index = <1>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <23 2 24 2 28 2>;
 			interrupt-parent = <&mpic>;
@@ -147,19 +148,12 @@
 			phy-connection-type = "rgmii-id";
 		};
 		
-		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet2: ethernet@26000 {
+			cell-index = <2>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <1F 2 20 2 21 2>;
 			interrupt-parent = <&mpic>;
@@ -167,26 +161,21 @@
 			phy-connection-type = "rgmii-id";
 		};
 
-		ethernet@27000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
+		enet3: ethernet@27000 {
+			cell-index = <3>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <27000 1000>;
-			/*
-			 * mac-address is deprecated and will be removed
-			 * in 2.6.25.  Only recent versions of
-			 * U-Boot support local-mac-address, however.
-			 */
-			mac-address = [ 00 00 00 00 00 00 ];
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <25 2 26 2 27 2>;
 			interrupt-parent = <&mpic>;
 			phy-handle = <&phy3>;
 			phy-connection-type = "rgmii-id";
 		};
-		serial@4500 {
+
+		serial0: serial@4500 {
+			cell-index = <0>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4500 100>;
@@ -195,7 +184,8 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@4600 {
+		serial1: serial@4600 {
+			cell-index = <1>;
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <4600 100>;
@@ -222,7 +212,8 @@
 		};
 	};
 
-	pcie@f8008000 {
+	pci0: pcie@f8008000 {
+		cell-index = <0>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
@@ -430,7 +421,8 @@
 
 	};
 
-	pcie@f8009000 {
+	pci1: pcie@f8009000 {
+		cell-index = <1>;
 		compatible = "fsl,mpc8641-pcie";
 		device_type = "pci";
 		#interrupt-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts
index 90f2293..daf9433 100644
--- a/arch/powerpc/boot/dts/mpc866ads.dts
+++ b/arch/powerpc/boot/dts/mpc866ads.dts
@@ -12,7 +12,7 @@
 
 / {
 	model = "MPC866ADS";
-	compatible = "mpc8xx";
+	compatible = "fsl,mpc866ads";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -23,15 +23,15 @@
 		PowerPC,866@0 {
 			device_type = "cpu";
 			reg = <0>;
-			d-cache-line-size = <20>;	// 32 bytes
-			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-line-size = <10>;	// 16 bytes
+			i-cache-line-size = <10>;	// 16 bytes
 			d-cache-size = <2000>;		// L1, 8K
 			i-cache-size = <4000>;		// L1, 16K
 			timebase-frequency = <0>;
 			bus-frequency = <0>;
 			clock-frequency = <0>;
 			interrupts = <f 2>;	// decrementer interrupt
-			interrupt-parent = <&Mpc8xx_pic>;
+			interrupt-parent = <&PIC>;
 		};
 	};
 
@@ -40,107 +40,139 @@
 		reg = <00000000 800000>;
 	};
 
-	soc866@ff000000 {
+	localbus@ff000100 {
+		compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <ff000100 40>;
+
+		ranges = <
+			1 0 ff080000 00008000
+			5 0 ff0a0000 00008000
+		>;
+
+		board-control@1,0 {
+			reg = <1 0 20 5 300 4>;
+			compatible = "fsl,mpc866ads-bcsr";
+		};
+	};
+
+	soc@ff000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		device_type = "soc";
 		ranges = <0 ff000000 00100000>;
 		reg = <ff000000 00000200>;
 		bus-frequency = <0>;
-		mdio@e80 {
-			device_type = "mdio";
-			compatible = "fs_enet";
-			reg = <e80 8>;
+
+		mdio@e00 {
+			compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
+			reg = <e00 188>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			phy: ethernet-phy@f {
+			PHY: ethernet-phy@f {
 				reg = <f>;
 				device_type = "ethernet-phy";
 			};
 		};
 
-		fec@e00 {
+		ethernet@e00 {
 			device_type = "network";
-			compatible = "fs_enet";
-			model = "FEC";
-			device-id = <1>;
+			compatible = "fsl,mpc866-fec-enet",
+			             "fsl,pq1-fec-enet";
 			reg = <e00 188>;
-			mac-address = [ 00 00 0C 00 01 FD ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <3 1>;
-			interrupt-parent = <&Mpc8xx_pic>;
-			phy-handle = <&Phy>;
+			interrupt-parent = <&PIC>;
+			phy-handle = <&PHY>;
+			linux,network-index = <0>;
 		};
 
-		mpc8xx_pic: pic@ff000000 {
+		PIC: pic@0 {
 			interrupt-controller;
-			#address-cells = <0>;
 			#interrupt-cells = <2>;
 			reg = <0 24>;
-			device_type = "mpc8xx-pic";
-			compatible = "CPM";
+			compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
 		};
 
-		cpm@ff000000 {
+		cpm@9c0 {
 			#address-cells = <1>;
 			#size-cells = <1>;
-			device_type = "cpm";
-			model = "CPM";
-			ranges = <0 0 4000>;
-			reg = <860 f0>;
-			command-proc = <9c0>;
+			compatible = "fsl,mpc866-cpm", "fsl,cpm1";
+			ranges;
+			reg = <9c0 40>;
 			brg-frequency = <0>;
 			interrupts = <0 2>;	// cpm error interrupt
-			interrupt-parent = <&Cpm_pic>;
+			interrupt-parent = <&CPM_PIC>;
 
-			cpm_pic: pic@930 {
+			muram@2000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 2000 2000>;
+
+				data@0 {
+					compatible = "fsl,cpm-muram-data";
+					reg = <0 1c00>;
+				};
+			};
+
+			brg@9f0 {
+				compatible = "fsl,mpc866-brg",
+					     "fsl,cpm1-brg",
+					     "fsl,cpm-brg";
+				reg = <9f0 10>;
+				clock-frequency = <0>;
+			};
+
+			CPM_PIC: pic@930 {
 				interrupt-controller;
 				#address-cells = <0>;
-				#interrupt-cells = <2>;
+				#interrupt-cells = <1>;
 				interrupts = <5 2 0 2>;
-				interrupt-parent = <&Mpc8xx_pic>;
+				interrupt-parent = <&PIC>;
 				reg = <930 20>;
-				device_type = "cpm-pic";
-				compatible = "CPM";
+				compatible = "fsl,mpc866-cpm-pic",
+				             "fsl,cpm1-pic";
 			};
 
-			smc@a80 {
+
+			serial@a80 {
 				device_type = "serial";
-				compatible = "cpm_uart";
-				model = "SMC";
-				device-id = <1>;
+				compatible = "fsl,mpc866-smc-uart",
+				             "fsl,cpm1-smc-uart";
 				reg = <a80 10 3e80 40>;
-				clock-setup = <00ffffff 0>;
-				rx-clock = <1>;
-				tx-clock = <1>;
-				current-speed = <0>;
-				interrupts = <4 3>;
-				interrupt-parent = <&Cpm_pic>;
+				interrupts = <4>;
+				interrupt-parent = <&CPM_PIC>;
+				fsl,cpm-brg = <1>;
+				fsl,cpm-command = <0090>;
 			};
 
-			smc@a90 {
+			serial@a90 {
 				device_type = "serial";
-				compatible = "cpm_uart";
-				model = "SMC";
-				device-id = <2>;
-				reg = <a90 20 3f80 40>;
-				clock-setup = <ff00ffff 90000>;
-				rx-clock = <2>;
-				tx-clock = <2>;
-				current-speed = <0>;
-				interrupts = <3 3>;
-				interrupt-parent = <&Cpm_pic>;
+				compatible = "fsl,mpc866-smc-uart",
+				             "fsl,cpm1-smc-uart";
+				reg = <a90 10 3f80 40>;
+				interrupts = <3>;
+				interrupt-parent = <&CPM_PIC>;
+				fsl,cpm-brg = <2>;
+				fsl,cpm-command = <00d0>;
 			};
 
-			scc@a00 {
+			ethernet@a00 {
 				device_type = "network";
-				compatible = "fs_enet";
-				model = "SCC";
-				device-id = <1>;
-				reg = <a00 18 3c00 80>;
-				mac-address = [ 00 00 0C 00 03 FD ];
-				interrupts = <1e 3>;
-				interrupt-parent = <&Cpm_pic>;
+				compatible = "fsl,mpc866-scc-enet",
+				             "fsl,cpm1-scc-enet";
+				reg = <a00 18 3c00 100>;
+				local-mac-address = [ 00 00 00 00 00 00 ];
+				interrupts = <1e>;
+				interrupt-parent = <&CPM_PIC>;
+				fsl,cpm-command = <0000>;
+				linux,network-index = <1>;
 			};
 		};
 	};
+
+	chosen {
+		linux,stdout-path = "/soc/cpm/serial@a80";
+	};
 };
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c
index 86c0f5d..ee31be5 100644
--- a/arch/powerpc/boot/ebony.c
+++ b/arch/powerpc/boot/ebony.c
@@ -146,6 +146,6 @@
 	platform_ops.exit = ibm44x_dbcr_reset;
 	ebony_mac0 = mac0;
 	ebony_mac1 = mac1;
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
diff --git a/arch/powerpc/boot/ep88xc.c b/arch/powerpc/boot/ep88xc.c
index 6b87cdc..a400f54 100644
--- a/arch/powerpc/boot/ep88xc.c
+++ b/arch/powerpc/boot/ep88xc.c
@@ -45,7 +45,7 @@
 	mem_size *= 1024 * 1024;
 	simple_alloc_init(_end, mem_size - (unsigned long)_end, 32, 64);
 
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 
 	planetcore_set_stdout_path(table);
 
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
deleted file mode 100644
index cf30675..0000000
--- a/arch/powerpc/boot/flatdevtree.c
+++ /dev/null
@@ -1,1036 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Copyright Pantelis Antoniou 2006
- * Copyright (C) IBM Corporation 2006
- *
- * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
- *	    Hollis Blanchard <hollisb@us.ibm.com>
- *	    Mark A. Greer <mgreer@mvista.com>
- *	    Paul Mackerras <paulus@samba.org>
- */
-
-#include <string.h>
-#include <stddef.h>
-#include "flatdevtree.h"
-#include "flatdevtree_env.h"
-
-#define _ALIGN(x, al)	(((x) + (al) - 1) & ~((al) - 1))
-
-static char *ft_root_node(struct ft_cxt *cxt)
-{
-	return cxt->rgn[FT_STRUCT].start;
-}
-
-/* Routines for keeping node ptrs returned by ft_find_device current */
-/* First entry not used b/c it would return 0 and be taken as NULL/error */
-static void *ft_get_phandle(struct ft_cxt *cxt, char *node)
-{
-	unsigned int i;
-
-	if (!node)
-		return NULL;
-
-	for (i = 1; i < cxt->nodes_used; i++)	/* already there? */
-		if (cxt->node_tbl[i] == node)
-			return (void *)i;
-
-	if (cxt->nodes_used < cxt->node_max) {
-		cxt->node_tbl[cxt->nodes_used] = node;
-		return (void *)cxt->nodes_used++;
-	}
-
-	return NULL;
-}
-
-static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
-{
-	unsigned int i = (unsigned int)phandle;
-
-	if (i < cxt->nodes_used)
-		return cxt->node_tbl[i];
-	return NULL;
-}
-
-static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
-{
-	unsigned int i;
-
-	if (shift == 0)
-		return;
-
-	for (i = 1; i < cxt->nodes_used; i++)
-		if (cxt->node_tbl[i] < addr)
-			cxt->node_tbl[i] += shift;
-}
-
-static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
-{
-	unsigned int i;
-
-	if (shift == 0)
-		return;
-
-	for (i = 1; i < cxt->nodes_used; i++)
-		if (cxt->node_tbl[i] >= addr)
-			cxt->node_tbl[i] += shift;
-}
-
-/* Struct used to return info from ft_next() */
-struct ft_atom {
-	u32 tag;
-	const char *name;
-	void *data;
-	u32 size;
-};
-
-/* Set ptrs to current one's info; return addr of next one */
-static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
-{
-	u32 sz;
-
-	if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
-		return NULL;
-
-	ret->tag = be32_to_cpu(*(u32 *) p);
-	p += 4;
-
-	switch (ret->tag) {	/* Tag */
-	case OF_DT_BEGIN_NODE:
-		ret->name = p;
-		ret->data = (void *)(p - 4);	/* start of node */
-		p += _ALIGN(strlen(p) + 1, 4);
-		break;
-	case OF_DT_PROP:
-		ret->size = sz = be32_to_cpu(*(u32 *) p);
-		ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
-		ret->data = (void *)(p + 8);
-		p += 8 + _ALIGN(sz, 4);
-		break;
-	case OF_DT_END_NODE:
-	case OF_DT_NOP:
-		break;
-	case OF_DT_END:
-	default:
-		p = NULL;
-		break;
-	}
-
-	return p;
-}
-
-#define HDR_SIZE	_ALIGN(sizeof(struct boot_param_header), 8)
-#define EXPAND_INCR	1024	/* alloc this much extra when expanding */
-
-/* Copy the tree to a newly-allocated region and put things in order */
-static int ft_reorder(struct ft_cxt *cxt, int nextra)
-{
-	unsigned long tot;
-	enum ft_rgn_id r;
-	char *p, *pend;
-	int stroff;
-
-	tot = HDR_SIZE + EXPAND_INCR;
-	for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
-		tot += cxt->rgn[r].size;
-	if (nextra > 0)
-		tot += nextra;
-	tot = _ALIGN(tot, 8);
-
-	if (!cxt->realloc)
-		return 0;
-	p = cxt->realloc(NULL, tot);
-	if (!p)
-		return 0;
-
-	memcpy(p, cxt->bph, sizeof(struct boot_param_header));
-	/* offsets get fixed up later */
-
-	cxt->bph = (struct boot_param_header *)p;
-	cxt->max_size = tot;
-	pend = p + tot;
-	p += HDR_SIZE;
-
-	memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
-	cxt->rgn[FT_RSVMAP].start = p;
-	p += cxt->rgn[FT_RSVMAP].size;
-
-	memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
-	ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
-			p - cxt->rgn[FT_STRUCT].start);
-	cxt->p += p - cxt->rgn[FT_STRUCT].start;
-	cxt->rgn[FT_STRUCT].start = p;
-
-	p = pend - cxt->rgn[FT_STRINGS].size;
-	memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
-	stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
-	cxt->rgn[FT_STRINGS].start = p;
-	cxt->str_anchor = p + stroff;
-
-	cxt->isordered = 1;
-	return 1;
-}
-
-static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
-{
-	if (r > FT_RSVMAP)
-		return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
-	return (char *)cxt->bph + HDR_SIZE;
-}
-
-static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
-{
-	if (r < FT_STRINGS)
-		return cxt->rgn[r + 1].start;
-	return (char *)cxt->bph + cxt->max_size;
-}
-
-/*
- * See if we can expand region rgn by nextra bytes by using up
- * free space after or before the region.
- */
-static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
-		int nextra)
-{
-	char *p = *pp;
-	char *rgn_start, *rgn_end;
-
-	rgn_start = cxt->rgn[rgn].start;
-	rgn_end = rgn_start + cxt->rgn[rgn].size;
-	if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
-		/* move following stuff */
-		if (p < rgn_end) {
-			if (nextra < 0)
-				memmove(p, p - nextra, rgn_end - p + nextra);
-			else
-				memmove(p + nextra, p, rgn_end - p);
-			if (rgn == FT_STRUCT)
-				ft_node_update_after(cxt, p, nextra);
-		}
-		cxt->rgn[rgn].size += nextra;
-		if (rgn == FT_STRINGS)
-			/* assumes strings only added at beginning */
-			cxt->str_anchor += nextra;
-		return 1;
-	}
-	if (prev_end(cxt, rgn) <= rgn_start - nextra) {
-		/* move preceding stuff */
-		if (p > rgn_start) {
-			memmove(rgn_start - nextra, rgn_start, p - rgn_start);
-			if (rgn == FT_STRUCT)
-				ft_node_update_before(cxt, p, -nextra);
-		}
-		*pp -= nextra;
-		cxt->rgn[rgn].start -= nextra;
-		cxt->rgn[rgn].size += nextra;
-		return 1;
-	}
-	return 0;
-}
-
-static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
-			 int nextra)
-{
-	unsigned long size, ssize, tot;
-	char *str, *next;
-	enum ft_rgn_id r;
-
-	if (!cxt->isordered) {
-		unsigned long rgn_off = *pp - cxt->rgn[rgn].start;
-
-		if (!ft_reorder(cxt, nextra))
-			return 0;
-
-		*pp = cxt->rgn[rgn].start + rgn_off;
-	}
-	if (ft_shuffle(cxt, pp, rgn, nextra))
-		return 1;
-
-	/* See if there is space after the strings section */
-	ssize = cxt->rgn[FT_STRINGS].size;
-	if (cxt->rgn[FT_STRINGS].start + ssize
-			< (char *)cxt->bph + cxt->max_size) {
-		/* move strings up as far as possible */
-		str = (char *)cxt->bph + cxt->max_size - ssize;
-		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
-		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
-		cxt->rgn[FT_STRINGS].start = str;
-		/* enough space now? */
-		if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
-			return 1;
-	}
-
-	/* how much total free space is there following this region? */
-	tot = 0;
-	for (r = rgn; r < FT_STRINGS; ++r) {
-		char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
-		tot += next_start(cxt, rgn) - r_end;
-	}
-
-	/* cast is to shut gcc up; we know nextra >= 0 */
-	if (tot < (unsigned int)nextra) {
-		/* have to reallocate */
-		char *newp, *new_start;
-		int shift;
-
-		if (!cxt->realloc)
-			return 0;
-		size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
-		newp = cxt->realloc(cxt->bph, size);
-		if (!newp)
-			return 0;
-		cxt->max_size = size;
-		shift = newp - (char *)cxt->bph;
-
-		if (shift) { /* realloc can return same addr */
-			cxt->bph = (struct boot_param_header *)newp;
-			ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
-					shift);
-			for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
-				new_start = cxt->rgn[r].start + shift;
-				cxt->rgn[r].start = new_start;
-			}
-			*pp += shift;
-			cxt->str_anchor += shift;
-		}
-
-		/* move strings up to the end */
-		str = newp + size - ssize;
-		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
-		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
-		cxt->rgn[FT_STRINGS].start = str;
-
-		if (ft_shuffle(cxt, pp, rgn, nextra))
-			return 1;
-	}
-
-	/* must be FT_RSVMAP and we need to move FT_STRUCT up */
-	if (rgn == FT_RSVMAP) {
-		next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
-			+ nextra;
-		ssize = cxt->rgn[FT_STRUCT].size;
-		if (next + ssize >= cxt->rgn[FT_STRINGS].start)
-			return 0;	/* "can't happen" */
-		memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
-		ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
-		cxt->rgn[FT_STRUCT].start = next;
-
-		if (ft_shuffle(cxt, pp, rgn, nextra))
-			return 1;
-	}
-
-	return 0;		/* "can't happen" */
-}
-
-static void ft_put_word(struct ft_cxt *cxt, u32 v)
-{
-	*(u32 *) cxt->p = cpu_to_be32(v);
-	cxt->p += 4;
-}
-
-static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
-{
-	unsigned long sza = _ALIGN(sz, 4);
-
-	/* zero out the alignment gap if necessary */
-	if (sz < sza)
-		*(u32 *) (cxt->p + sza - 4) = 0;
-
-	/* copy in the data */
-	memcpy(cxt->p, data, sz);
-
-	cxt->p += sza;
-}
-
-char *ft_begin_node(struct ft_cxt *cxt, const char *name)
-{
-	unsigned long nlen = strlen(name) + 1;
-	unsigned long len = 8 + _ALIGN(nlen, 4);
-	char *ret;
-
-	if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
-		return NULL;
-
-	ret = cxt->p;
-
-	ft_put_word(cxt, OF_DT_BEGIN_NODE);
-	ft_put_bin(cxt, name, strlen(name) + 1);
-
-	return ret;
-}
-
-void ft_end_node(struct ft_cxt *cxt)
-{
-	ft_put_word(cxt, OF_DT_END_NODE);
-}
-
-void ft_nop(struct ft_cxt *cxt)
-{
-	if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
-		ft_put_word(cxt, OF_DT_NOP);
-}
-
-#define NO_STRING	0x7fffffff
-
-static int lookup_string(struct ft_cxt *cxt, const char *name)
-{
-	char *p, *end;
-
-	p = cxt->rgn[FT_STRINGS].start;
-	end = p + cxt->rgn[FT_STRINGS].size;
-	while (p < end) {
-		if (strcmp(p, (char *)name) == 0)
-			return p - cxt->str_anchor;
-		p += strlen(p) + 1;
-	}
-
-	return NO_STRING;
-}
-
-/* lookup string and insert if not found */
-static int map_string(struct ft_cxt *cxt, const char *name)
-{
-	int off;
-	char *p;
-
-	off = lookup_string(cxt, name);
-	if (off != NO_STRING)
-		return off;
-	p = cxt->rgn[FT_STRINGS].start;
-	if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
-		return NO_STRING;
-	strcpy(p, name);
-	return p - cxt->str_anchor;
-}
-
-int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
-		unsigned int sz)
-{
-	int off, len;
-
-	off = map_string(cxt, name);
-	if (off == NO_STRING)
-		return -1;
-
-	len = 12 + _ALIGN(sz, 4);
-	if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
-		return -1;
-
-	ft_put_word(cxt, OF_DT_PROP);
-	ft_put_word(cxt, sz);
-	ft_put_word(cxt, off);
-	ft_put_bin(cxt, data, sz);
-	return 0;
-}
-
-int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
-{
-	return ft_prop(cxt, name, str, strlen(str) + 1);
-}
-
-int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
-{
-	u32 v = cpu_to_be32((u32) val);
-
-	return ft_prop(cxt, name, &v, 4);
-}
-
-/* Calculate the size of the reserved map */
-static unsigned long rsvmap_size(struct ft_cxt *cxt)
-{
-	struct ft_reserve *res;
-
-	res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
-	while (res->start || res->len)
-		++res;
-	return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
-}
-
-/* Calculate the size of the struct region by stepping through it */
-static unsigned long struct_size(struct ft_cxt *cxt)
-{
-	char *p = cxt->rgn[FT_STRUCT].start;
-	char *next;
-	struct ft_atom atom;
-
-	/* make check in ft_next happy */
-	if (cxt->rgn[FT_STRUCT].size == 0)
-		cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL)
-		p = next;
-	return p + 4 - cxt->rgn[FT_STRUCT].start;
-}
-
-/* add `adj' on to all string offset values in the struct area */
-static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
-{
-	char *p = cxt->rgn[FT_STRUCT].start;
-	char *next;
-	struct ft_atom atom;
-	int off;
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		if (atom.tag == OF_DT_PROP) {
-			off = be32_to_cpu(*(u32 *) (p + 8));
-			*(u32 *) (p + 8) = cpu_to_be32(off + adj);
-		}
-		p = next;
-	}
-}
-
-/* start construction of the flat OF tree from scratch */
-void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
-		void *(*realloc_fn) (void *, unsigned long))
-{
-	struct boot_param_header *bph = blob;
-	char *p;
-	struct ft_reserve *pres;
-
-	/* clear the cxt */
-	memset(cxt, 0, sizeof(*cxt));
-
-	cxt->bph = bph;
-	cxt->max_size = max_size;
-	cxt->realloc = realloc_fn;
-	cxt->isordered = 1;
-
-	/* zero everything in the header area */
-	memset(bph, 0, sizeof(*bph));
-
-	bph->magic = cpu_to_be32(OF_DT_HEADER);
-	bph->version = cpu_to_be32(0x10);
-	bph->last_comp_version = cpu_to_be32(0x10);
-
-	/* start pointers */
-	cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
-	cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
-	pres = (struct ft_reserve *)p;
-	cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
-	cxt->rgn[FT_STRUCT].size = 4;
-	cxt->rgn[FT_STRINGS].start = blob + max_size;
-	cxt->rgn[FT_STRINGS].size = 0;
-
-	/* init rsvmap and struct */
-	pres->start = 0;
-	pres->len = 0;
-	*(u32 *) p = cpu_to_be32(OF_DT_END);
-
-	cxt->str_anchor = blob;
-}
-
-/* open up an existing blob to be examined or modified */
-int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
-		unsigned int max_find_device,
-		void *(*realloc_fn) (void *, unsigned long))
-{
-	struct boot_param_header *bph = blob;
-
-	/* can't cope with version < 16 */
-	if (be32_to_cpu(bph->version) < 16)
-		return -1;
-
-	/* clear the cxt */
-	memset(cxt, 0, sizeof(*cxt));
-
-	/* alloc node_tbl to track node ptrs returned by ft_find_device */
-	++max_find_device;
-	cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
-	if (!cxt->node_tbl)
-		return -1;
-	memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
-	cxt->node_max = max_find_device;
-	cxt->nodes_used = 1;	/* don't use idx 0 b/c looks like NULL */
-
-	cxt->bph = bph;
-	cxt->max_size = max_size;
-	cxt->realloc = realloc_fn;
-
-	cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
-	cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
-	cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
-	cxt->rgn[FT_STRUCT].size = struct_size(cxt);
-	cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
-	cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
-
-	cxt->p = cxt->rgn[FT_STRUCT].start;
-	cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
-
-	return 0;
-}
-
-/* add a reserver physical area to the rsvmap */
-int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
-{
-	char *p;
-	struct ft_reserve *pres;
-
-	p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
-		- sizeof(struct ft_reserve);
-	if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
-		return -1;
-
-	pres = (struct ft_reserve *)p;
-	pres->start = cpu_to_be64(physaddr);
-	pres->len = cpu_to_be64(size);
-
-	return 0;
-}
-
-void ft_begin_tree(struct ft_cxt *cxt)
-{
-	cxt->p = ft_root_node(cxt);
-}
-
-void ft_end_tree(struct ft_cxt *cxt)
-{
-	struct boot_param_header *bph = cxt->bph;
-	char *p, *oldstr, *str, *endp;
-	unsigned long ssize;
-	int adj;
-
-	if (!cxt->isordered)
-		return;		/* we haven't touched anything */
-
-	/* adjust string offsets */
-	oldstr = cxt->rgn[FT_STRINGS].start;
-	adj = cxt->str_anchor - oldstr;
-	if (adj)
-		adjust_string_offsets(cxt, adj);
-
-	/* make strings end on 8-byte boundary */
-	ssize = cxt->rgn[FT_STRINGS].size;
-	endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
-			+ cxt->rgn[FT_STRUCT].size + ssize, 8);
-	str = endp - ssize;
-
-	/* move strings down to end of structs */
-	memmove(str, oldstr, ssize);
-	cxt->str_anchor = str;
-	cxt->rgn[FT_STRINGS].start = str;
-
-	/* fill in header fields */
-	p = (char *)bph;
-	bph->totalsize = cpu_to_be32(endp - p);
-	bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
-	bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
-	bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
-	bph->dt_strings_size = cpu_to_be32(ssize);
-}
-
-void *ft_find_device(struct ft_cxt *cxt, const void *top, const char *srch_path)
-{
-	char *node;
-
-	if (top) {
-		node = ft_node_ph2node(cxt, top);
-		if (node == NULL)
-			return NULL;
-	} else {
-		node = ft_root_node(cxt);
-	}
-
-	node = ft_find_descendent(cxt, node, srch_path);
-	return ft_get_phandle(cxt, node);
-}
-
-void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
-{
-	struct ft_atom atom;
-	char *p;
-	const char *cp, *q;
-	int cl;
-	int depth = -1;
-	int dmatch = 0;
-	const char *path_comp[FT_MAX_DEPTH];
-
-	cp = srch_path;
-	cl = 0;
-	p = top;
-
-	while ((p = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			++depth;
-			if (depth != dmatch)
-				break;
-			cxt->genealogy[depth] = atom.data;
-			cxt->genealogy[depth + 1] = NULL;
-			if (depth && !(strncmp(atom.name, cp, cl) == 0
-					&& (atom.name[cl] == '/'
-						|| atom.name[cl] == '\0'
-						|| atom.name[cl] == '@')))
-				break;
-			path_comp[dmatch] = cp;
-			/* it matches so far, advance to next path component */
-			cp += cl;
-			/* skip slashes */
-			while (*cp == '/')
-				++cp;
-			/* we're done if this is the end of the string */
-			if (*cp == 0)
-				return atom.data;
-			/* look for end of this component */
-			q = strchr(cp, '/');
-			if (q)
-				cl = q - cp;
-			else
-				cl = strlen(cp);
-			++dmatch;
-			break;
-		case OF_DT_END_NODE:
-			if (depth == 0)
-				return NULL;
-			if (dmatch > depth) {
-				--dmatch;
-				cl = cp - path_comp[dmatch] - 1;
-				cp = path_comp[dmatch];
-				while (cl > 0 && cp[cl - 1] == '/')
-					--cl;
-			}
-			--depth;
-			break;
-		}
-	}
-	return NULL;
-}
-
-void *__ft_get_parent(struct ft_cxt *cxt, void *node)
-{
-	int d;
-	struct ft_atom atom;
-	char *p;
-
-	for (d = 0; cxt->genealogy[d] != NULL; ++d)
-		if (cxt->genealogy[d] == node)
-			return d > 0 ? cxt->genealogy[d - 1] : NULL;
-
-	/* have to do it the hard way... */
-	p = ft_root_node(cxt);
-	d = 0;
-	while ((p = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			cxt->genealogy[d] = atom.data;
-			if (node == atom.data) {
-				/* found it */
-				cxt->genealogy[d + 1] = NULL;
-				return d > 0 ? cxt->genealogy[d - 1] : NULL;
-			}
-			++d;
-			break;
-		case OF_DT_END_NODE:
-			--d;
-			break;
-		}
-	}
-	return NULL;
-}
-
-void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
-{
-	void *node = ft_node_ph2node(cxt, phandle);
-	if (node == NULL)
-		return NULL;
-
-	node = __ft_get_parent(cxt, node);
-	return ft_get_phandle(cxt, node);
-}
-
-static const void *__ft_get_prop(struct ft_cxt *cxt, void *node,
-                                 const char *propname, unsigned int *len)
-{
-	struct ft_atom atom;
-	int depth = 0;
-
-	while ((node = ft_next(cxt, node, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			++depth;
-			break;
-
-		case OF_DT_PROP:
-			if (depth != 1 || strcmp(atom.name, propname))
-				break;
-
-			if (len)
-				*len = atom.size;
-
-			return atom.data;
-
-		case OF_DT_END_NODE:
-			if (--depth <= 0)
-				return NULL;
-		}
-	}
-
-	return NULL;
-}
-
-int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
-		void *buf, const unsigned int buflen)
-{
-	const void *data;
-	unsigned int size;
-
-	void *node = ft_node_ph2node(cxt, phandle);
-	if (!node)
-		return -1;
-
-	data = __ft_get_prop(cxt, node, propname, &size);
-	if (data) {
-		unsigned int clipped_size = min(size, buflen);
-		memcpy(buf, data, clipped_size);
-		return size;
-	}
-
-	return -1;
-}
-
-void *__ft_find_node_by_prop_value(struct ft_cxt *cxt, void *prev,
-                                   const char *propname, const char *propval,
-                                   unsigned int proplen)
-{
-	struct ft_atom atom;
-	char *p = ft_root_node(cxt);
-	char *next;
-	int past_prev = prev ? 0 : 1;
-	int depth = -1;
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		const void *data;
-		unsigned int size;
-
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			depth++;
-
-			if (prev == p) {
-				past_prev = 1;
-				break;
-			}
-
-			if (!past_prev || depth < 1)
-				break;
-
-			data = __ft_get_prop(cxt, p, propname, &size);
-			if (!data || size != proplen)
-				break;
-			if (memcmp(data, propval, size))
-				break;
-
-			return p;
-
-		case OF_DT_END_NODE:
-			if (depth-- == 0)
-				return NULL;
-
-			break;
-		}
-
-		p = next;
-	}
-
-	return NULL;
-}
-
-void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
-                                 const char *propname, const char *propval,
-                                 int proplen)
-{
-	void *node = NULL;
-
-	if (prev) {
-		node = ft_node_ph2node(cxt, prev);
-
-		if (!node)
-			return NULL;
-	}
-
-	node = __ft_find_node_by_prop_value(cxt, node, propname,
-	                                    propval, proplen);
-	return ft_get_phandle(cxt, node);
-}
-
-int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
-		const void *buf, const unsigned int buflen)
-{
-	struct ft_atom atom;
-	void *node;
-	char *p, *next;
-	int nextra;
-
-	node = ft_node_ph2node(cxt, phandle);
-	if (node == NULL)
-		return -1;
-
-	next = ft_next(cxt, node, &atom);
-	if (atom.tag != OF_DT_BEGIN_NODE)
-		/* phandle didn't point to a node */
-		return -1;
-	p = next;
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE: /* properties must go before subnodes */
-		case OF_DT_END_NODE:
-			/* haven't found the property, insert here */
-			cxt->p = p;
-			return ft_prop(cxt, propname, buf, buflen);
-		case OF_DT_PROP:
-			if (strcmp(atom.name, propname))
-				break;
-			/* found an existing property, overwrite it */
-			nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
-			cxt->p = atom.data;
-			if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
-						nextra))
-				return -1;
-			*(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
-			ft_put_bin(cxt, buf, buflen);
-			return 0;
-		}
-		p = next;
-	}
-	return -1;
-}
-
-int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
-{
-	struct ft_atom atom;
-	void *node;
-	char *p, *next;
-	int size;
-
-	node = ft_node_ph2node(cxt, phandle);
-	if (node == NULL)
-		return -1;
-
-	p = node;
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-		case OF_DT_END_NODE:
-			return -1;
-		case OF_DT_PROP:
-			if (strcmp(atom.name, propname))
-				break;
-			/* found the property, remove it */
-			size = 12 + -_ALIGN(atom.size, 4);
-			cxt->p = p;
-			if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
-				return -1;
-			return 0;
-		}
-		p = next;
-	}
-	return -1;
-}
-
-void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name)
-{
-	struct ft_atom atom;
-	char *p, *next, *ret;
-	int depth = 0;
-
-	if (parent) {
-		p = ft_node_ph2node(cxt, parent);
-		if (!p)
-			return NULL;
-	} else {
-		p = ft_root_node(cxt);
-	}
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			++depth;
-			if (depth == 1 && strcmp(atom.name, name) == 0)
-				/* duplicate node name, return error */
-				return NULL;
-			break;
-		case OF_DT_END_NODE:
-			--depth;
-			if (depth > 0)
-				break;
-			/* end of node, insert here */
-			cxt->p = p;
-			ret = ft_begin_node(cxt, name);
-			ft_end_node(cxt);
-			return ft_get_phandle(cxt, ret);
-		}
-		p = next;
-	}
-	return NULL;
-}
-
-/* Returns the start of the path within the provided buffer, or NULL on
- * error.
- */
-char *ft_get_path(struct ft_cxt *cxt, const void *phandle,
-                  char *buf, int len)
-{
-	const char *path_comp[FT_MAX_DEPTH];
-	struct ft_atom atom;
-	char *p, *next, *pos;
-	int depth = 0, i;
-	void *node;
-
-	node = ft_node_ph2node(cxt, phandle);
-	if (node == NULL)
-		return NULL;
-
-	p = ft_root_node(cxt);
-
-	while ((next = ft_next(cxt, p, &atom)) != NULL) {
-		switch (atom.tag) {
-		case OF_DT_BEGIN_NODE:
-			path_comp[depth++] = atom.name;
-			if (p == node)
-				goto found;
-
-			break;
-
-		case OF_DT_END_NODE:
-			if (--depth == 0)
-				return NULL;
-		}
-
-		p = next;
-	}
-
-found:
-	pos = buf;
-	for (i = 1; i < depth; i++) {
-		int this_len;
-
-		if (len <= 1)
-			return NULL;
-
-		*pos++ = '/';
-		len--;
-
-		strncpy(pos, path_comp[i], len);
-
-		if (pos[len - 1] != 0)
-			return NULL;
-
-		this_len = strlen(pos);
-		len -= this_len;
-		pos += this_len;
-	}
-
-	return buf;
-}
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
deleted file mode 100644
index b0957a2..0000000
--- a/arch/powerpc/boot/flatdevtree.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef FLATDEVTREE_H
-#define FLATDEVTREE_H
-
-#include "flatdevtree_env.h"
-
-/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER            0xd00dfeed      /* marker */
-#define OF_DT_BEGIN_NODE        0x1     /* Start of node, full name */
-#define OF_DT_END_NODE          0x2     /* End node */
-#define OF_DT_PROP              0x3     /* Property: name off, size, content */
-#define OF_DT_NOP               0x4     /* nop */
-#define OF_DT_END               0x9
-
-#define OF_DT_VERSION           0x10
-
-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 */
-	/* version 2 fields below */
-	u32 boot_cpuid_phys;    /* Physical CPU id we're booting on */
-	/* version 3 fields below */
-	u32 dt_strings_size;    /* size of the DT strings block */
-};
-
-struct ft_reserve {
-	u64 start;
-	u64 len;
-};
-
-struct ft_region {
-	char *start;
-	unsigned long size;
-};
-
-enum ft_rgn_id {
-	FT_RSVMAP,
-	FT_STRUCT,
-	FT_STRINGS,
-	FT_N_REGION
-};
-
-#define FT_MAX_DEPTH	50
-
-struct ft_cxt {
-	struct boot_param_header *bph;
-	int max_size;           /* maximum size of tree */
-	int isordered;		/* everything in standard order */
-	void *(*realloc)(void *, unsigned long);
-	char *str_anchor;
-	char *p;		/* current insertion point in structs */
-	struct ft_region rgn[FT_N_REGION];
-	void *genealogy[FT_MAX_DEPTH+1];
-	char **node_tbl;
-	unsigned int node_max;
-	unsigned int nodes_used;
-};
-
-char *ft_begin_node(struct ft_cxt *cxt, const char *name);
-void ft_end_node(struct ft_cxt *cxt);
-
-void ft_begin_tree(struct ft_cxt *cxt);
-void ft_end_tree(struct ft_cxt *cxt);
-
-void ft_nop(struct ft_cxt *cxt);
-int ft_prop(struct ft_cxt *cxt, const char *name,
-	    const void *data, unsigned int sz);
-int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
-int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
-void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
-	      void *(*realloc_fn)(void *, unsigned long));
-int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
-		unsigned int max_find_device,
-		void *(*realloc_fn)(void *, unsigned long));
-int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
-
-void ft_dump_blob(const void *bphp);
-void ft_merge_blob(struct ft_cxt *cxt, void *blob);
-void *ft_find_device(struct ft_cxt *cxt, const void *top,
-                     const char *srch_path);
-void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
-int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
-		void *buf, const unsigned int buflen);
-int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
-		const void *buf, const unsigned int buflen);
-void *ft_get_parent(struct ft_cxt *cxt, const void *phandle);
-void *ft_find_node_by_prop_value(struct ft_cxt *cxt, const void *prev,
-                                 const char *propname, const char *propval,
-                                 int proplen);
-void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *name);
-char *ft_get_path(struct ft_cxt *cxt, const void *phandle, char *buf, int len);
-
-#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
deleted file mode 100644
index b367009..0000000
--- a/arch/powerpc/boot/flatdevtree_misc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file does the necessary interface mapping between the bootwrapper
- * device tree operations and the interface provided by shared source
- * files flatdevicetree.[ch].
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * 2006 (c) MontaVista Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <stddef.h>
-#include "flatdevtree.h"
-#include "ops.h"
-
-static struct ft_cxt cxt;
-
-static void *fdtm_finddevice(const char *name)
-{
-	return ft_find_device(&cxt, NULL, name);
-}
-
-static int fdtm_getprop(const void *phandle, const char *propname,
-                        void *buf, const int buflen)
-{
-	return ft_get_prop(&cxt, phandle, propname, buf, buflen);
-}
-
-static int fdtm_setprop(const void *phandle, const char *propname,
-                        const void *buf, const int buflen)
-{
-	return ft_set_prop(&cxt, phandle, propname, buf, buflen);
-}
-
-static void *fdtm_get_parent(const void *phandle)
-{
-	return ft_get_parent(&cxt, phandle);
-}
-
-static void *fdtm_create_node(const void *phandle, const char *name)
-{
-	return ft_create_node(&cxt, phandle, name);
-}
-
-static void *fdtm_find_node_by_prop_value(const void *prev,
-                                          const char *propname,
-                                          const char *propval,
-                                          int proplen)
-{
-	return ft_find_node_by_prop_value(&cxt, prev, propname,
-	                                  propval, proplen);
-}
-
-static unsigned long fdtm_finalize(void)
-{
-	ft_end_tree(&cxt);
-	return (unsigned long)cxt.bph;
-}
-
-static char *fdtm_get_path(const void *phandle, char *buf, int len)
-{
-	return ft_get_path(&cxt, phandle, buf, len);
-}
-
-int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
-{
-	dt_ops.finddevice = fdtm_finddevice;
-	dt_ops.getprop = fdtm_getprop;
-	dt_ops.setprop = fdtm_setprop;
-	dt_ops.get_parent = fdtm_get_parent;
-	dt_ops.create_node = fdtm_create_node;
-	dt_ops.find_node_by_prop_value = fdtm_find_node_by_prop_value;
-	dt_ops.finalize = fdtm_finalize;
-	dt_ops.get_path = fdtm_get_path;
-
-	return ft_open(&cxt, dt_blob, max_size, max_find_device,
-			platform_ops.realloc);
-}
diff --git a/arch/powerpc/boot/holly.c b/arch/powerpc/boot/holly.c
index 199e783..58013b9 100644
--- a/arch/powerpc/boot/holly.c
+++ b/arch/powerpc/boot/holly.c
@@ -28,6 +28,6 @@
 	u32 heapsize = 0x8000000 - (u32)_end; /* 128M */
 
 	simple_alloc_init(_end, heapsize, 32, 64);
-	ft_init(_dtb_start, 0, 4);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
diff --git a/arch/powerpc/boot/libfdt-wrapper.c b/arch/powerpc/boot/libfdt-wrapper.c
new file mode 100644
index 0000000..97af36c
--- /dev/null
+++ b/arch/powerpc/boot/libfdt-wrapper.c
@@ -0,0 +1,184 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <page.h>
+#include <libfdt.h>
+#include "ops.h"
+
+#define DEBUG	0
+#define BAD_ERROR(err)	(((err) < 0) \
+			 && ((err) != -FDT_ERR_NOTFOUND) \
+			 && ((err) != -FDT_ERR_EXISTS))
+
+#define check_err(err) \
+	({ \
+		if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
+			printf("%s():%d  %s\n\r", __FUNCTION__, __LINE__, \
+			       fdt_strerror(err)); \
+		if (BAD_ERROR(err)) \
+			exit(); \
+		(err < 0) ? -1 : 0; \
+	})
+
+#define offset_devp(off)	\
+	({ \
+		int _offset = (off); \
+		check_err(_offset) ? NULL : (void *)(_offset+1); \
+	})
+
+#define devp_offset_find(devp)	(((int)(devp))-1)
+#define devp_offset(devp)	(devp ? ((int)(devp))-1 : 0)
+
+static void *fdt;
+static void *buf; /* = NULL */
+
+#define EXPAND_GRANULARITY	1024
+
+static void expand_buf(int minexpand)
+{
+	int size = fdt_totalsize(fdt);
+	int rc;
+
+	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
+	buf = platform_ops.realloc(buf, size);
+	if (!buf)
+		fatal("Couldn't find %d bytes to expand device tree\n\r", size);
+	rc = fdt_open_into(fdt, buf, size);
+	if (rc != 0)
+		fatal("Couldn't expand fdt into new buffer: %s\n\r",
+		      fdt_strerror(rc));
+
+	fdt = buf;
+}
+
+static void *fdt_wrapper_finddevice(const char *path)
+{
+	return offset_devp(fdt_path_offset(fdt, path));
+}
+
+static int fdt_wrapper_getprop(const void *devp, const char *name,
+			       void *buf, const int buflen)
+{
+	const void *p;
+	int len;
+
+	p = fdt_getprop(fdt, devp_offset(devp), name, &len);
+	if (!p)
+		return check_err(len);
+	memcpy(buf, p, min(len, buflen));
+	return len;
+}
+
+static int fdt_wrapper_setprop(const void *devp, const char *name,
+			       const void *buf, const int len)
+{
+	int rc;
+
+	rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+	if (rc == -FDT_ERR_NOSPACE) {
+		expand_buf(len + 16);
+		rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+	}
+
+	return check_err(rc);
+}
+
+static void *fdt_wrapper_get_parent(const void *devp)
+{
+	return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
+}
+
+static void *fdt_wrapper_create_node(const void *devp, const char *name)
+{
+	int offset;
+
+	offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+	if (offset == -FDT_ERR_NOSPACE) {
+		expand_buf(strlen(name) + 16);
+		offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+	}
+
+	return offset_devp(offset);
+}
+
+static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
+						 const char *name,
+						 const char *val,
+						 int len)
+{
+	int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
+	                                           name, val, len);
+	return offset_devp(offset);
+}
+
+static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
+{
+	int rc;
+
+	rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
+	if (check_err(rc))
+		return NULL;
+	return buf;
+}
+
+static unsigned long fdt_wrapper_finalize(void)
+{
+	int rc;
+
+	rc = fdt_pack(fdt);
+	if (rc != 0)
+		fatal("Couldn't pack flat tree: %s\n\r",
+		      fdt_strerror(rc));
+	return (unsigned long)fdt;
+}
+
+void fdt_init(void *blob)
+{
+	int err;
+
+	dt_ops.finddevice = fdt_wrapper_finddevice;
+	dt_ops.getprop = fdt_wrapper_getprop;
+	dt_ops.setprop = fdt_wrapper_setprop;
+	dt_ops.get_parent = fdt_wrapper_get_parent;
+	dt_ops.create_node = fdt_wrapper_create_node;
+	dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
+	dt_ops.get_path = fdt_wrapper_get_path;
+	dt_ops.finalize = fdt_wrapper_finalize;
+
+	/* Make sure the dt blob is the right version and so forth */
+	fdt = blob;
+	err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
+	if (err == -FDT_ERR_NOSPACE) {
+		int bufsize = fdt_totalsize(fdt) + 4;
+		buf = malloc(bufsize);
+		err = fdt_open_into(fdt, buf, bufsize);
+	}
+
+	if (err != 0)
+		fatal("fdt_init(): %s\n\r", fdt_strerror(err));
+
+	if (buf)
+		fdt = buf;
+}
diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/arch/powerpc/boot/libfdt/Makefile.libfdt
new file mode 100644
index 0000000..82f9c6a
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/Makefile.libfdt
@@ -0,0 +1,14 @@
+# Makefile.libfdt
+#
+# This is not a complete Makefile of itself.  Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_EXTRA = libfdt_internal.h
+LIBFDT_LIB = libfdt/libfdt.a
+
+LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+
+$(LIBFDT_objdir)/$(LIBFDT_LIB): $(addprefix $(LIBFDT_objdir)/,$(LIBFDT_OBJS))
+
diff --git a/arch/powerpc/boot/libfdt/fdt.c b/arch/powerpc/boot/libfdt/fdt.c
new file mode 100644
index 0000000..586a361
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt.c
@@ -0,0 +1,156 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		/* Complete tree */
+		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+	} else if (fdt_magic(fdt) == SW_MAGIC) {
+		/* Unfinished sequential-write blob */
+		if (fdt_size_dt_struct(fdt) == 0)
+			return -FDT_ERR_BADSTATE;
+	} else {
+		return -FDT_ERR_BADMAGIC;
+	}
+
+	return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+{
+	const void *p;
+
+	if (fdt_version(fdt) >= 0x11)
+		if (((offset + len) < offset)
+		    || ((offset + len) > fdt_size_dt_struct(fdt)))
+			return NULL;
+
+	p = _fdt_offset_ptr(fdt, offset);
+
+	if (p + len < p)
+		return NULL;
+	return p;
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+{
+	const uint32_t *tagp, *lenp;
+	uint32_t tag;
+	const char *p;
+
+	if (offset % FDT_TAGSIZE)
+		return -1;
+
+	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+	if (! tagp)
+		return FDT_END; /* premature end */
+	tag = fdt32_to_cpu(*tagp);
+	offset += FDT_TAGSIZE;
+
+	switch (tag) {
+	case FDT_BEGIN_NODE:
+		/* skip name */
+		do {
+			p = fdt_offset_ptr(fdt, offset++, 1);
+		} while (p && (*p != '\0'));
+		if (! p)
+			return FDT_END;
+		break;
+	case FDT_PROP:
+		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+		if (! lenp)
+			return FDT_END;
+		/* skip name offset, length and value */
+		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+		break;
+	}
+
+	if (nextoffset)
+		*nextoffset = ALIGN(offset, FDT_TAGSIZE);
+
+	return tag;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+	int len = strlen(s) + 1;
+	const char *last = strtab + tabsize - len;
+	const char *p;
+
+	for (p = strtab; p <= last; p++)
+		if (memeq(p, s, len))
+			return p;
+	return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+	int err = fdt_check_header(fdt);
+
+	if (err)
+		return err;
+
+	if (fdt_totalsize(fdt) > bufsize)
+		return -FDT_ERR_NOSPACE;
+
+	memmove(buf, fdt, fdt_totalsize(fdt));
+	return 0;
+}
diff --git a/arch/powerpc/boot/libfdt/fdt.h b/arch/powerpc/boot/libfdt/fdt.h
new file mode 100644
index 0000000..48ccfd9
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt.h
@@ -0,0 +1,60 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+	uint32_t magic;			 /* magic word FDT_MAGIC */
+	uint32_t totalsize;		 /* total size of DT block */
+	uint32_t off_dt_struct;		 /* offset to structure */
+	uint32_t off_dt_strings;	 /* offset to strings */
+	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
+	uint32_t version;		 /* format version */
+	uint32_t last_comp_version;	 /* last compatible version */
+
+	/* version 2 fields below */
+	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+	uint32_t size_dt_strings;	 /* size of the strings block */
+
+	/* version 17 fields below */
+	uint32_t size_dt_struct;	 /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+	uint64_t address;
+	uint64_t size;
+};
+
+struct fdt_node_header {
+	uint32_t tag;
+	char name[0];
+};
+
+struct fdt_property {
+	uint32_t tag;
+	uint32_t len;
+	uint32_t nameoff;
+	char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
+#define FDT_TAGSIZE	sizeof(uint32_t)
+
+#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
+#define FDT_END_NODE	0x2		/* End node */
+#define FDT_PROP	0x3		/* Property: name off,
+					   size, content */
+#define FDT_NOP		0x4		/* nop */
+#define FDT_END		0x9
+
+#define FDT_V1_SIZE	(7*sizeof(uint32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V16_SIZE	FDT_V3_SIZE
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+
+#endif /* _FDT_H */
diff --git a/arch/powerpc/boot/libfdt/fdt_ro.c b/arch/powerpc/boot/libfdt/fdt_ro.c
new file mode 100644
index 0000000..12a37d5
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_ro.c
@@ -0,0 +1,583 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+#define CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static int nodename_eq(const void *fdt, int offset,
+		       const char *s, int len)
+{
+	const char *p = fdt_offset_ptr(fdt, offset, len+1);
+
+	if (! p)
+		/* short match */
+		return 0;
+
+	if (memcmp(p, s, len) != 0)
+		return 0;
+
+	if (p[len] == '\0')
+		return 1;
+	else if (!memchr(s, '@', len) && (p[len] == '@'))
+		return 1;
+	else
+		return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+	CHECK_HEADER(fdt);
+	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+	return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+	int i = 0;
+
+	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+		i++;
+	return i;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen)
+{
+	int level = 0;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	CHECK_HEADER(fdt);
+
+	tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_TRUNCATED;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			if (level != 1)
+				continue;
+			if (nodename_eq(fdt, offset+FDT_TAGSIZE, name, namelen))
+				/* Found it! */
+				return offset;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (level >= 0);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+		       const char *name)
+{
+	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+	const char *end = path + strlen(path);
+	const char *p = path;
+	int offset = 0;
+
+	CHECK_HEADER(fdt);
+
+	if (*path != '/')
+		return -FDT_ERR_BADPATH;
+
+	while (*p) {
+		const char *q;
+
+		while (*p == '/')
+			p++;
+		if (! *p)
+			return offset;
+		q = strchr(p, '/');
+		if (! q)
+			q = end;
+
+		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+		if (offset < 0)
+			return offset;
+
+		p = q;
+	}
+
+	return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+	const struct fdt_node_header *nh;
+	int err;
+
+	if ((err = fdt_check_header(fdt)) != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
+	if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
+		goto fail;
+
+	if (len)
+		*len = strlen(nh->name);
+
+	return nh->name;
+
+ fail:
+	if (len)
+		*len = err;
+	return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+					    int nodeoffset,
+					    const char *name, int *lenp)
+{
+	uint32_t tag;
+	const struct fdt_property *prop;
+	int namestroff;
+	int offset, nextoffset;
+	int err;
+
+	if ((err = fdt_check_header(fdt)) != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	if (nodeoffset % FDT_TAGSIZE)
+		goto fail;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		goto fail;
+
+	do {
+		offset = nextoffset;
+
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			err = -FDT_ERR_TRUNCATED;
+			goto fail;
+
+		case FDT_BEGIN_NODE:
+		case FDT_END_NODE:
+		case FDT_NOP:
+			break;
+
+		case FDT_PROP:
+			err = -FDT_ERR_BADSTRUCTURE;
+			prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
+			if (! prop)
+				goto fail;
+			namestroff = fdt32_to_cpu(prop->nameoff);
+			if (streq(fdt_string(fdt, namestroff), name)) {
+				/* Found it! */
+				int len = fdt32_to_cpu(prop->len);
+				prop = fdt_offset_ptr(fdt, offset,
+						      sizeof(*prop)+len);
+				if (! prop)
+					goto fail;
+
+				if (lenp)
+					*lenp = len;
+
+				return prop;
+			}
+			break;
+
+		default:
+			err = -FDT_ERR_BADSTRUCTURE;
+			goto fail;
+		}
+	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+
+	err = -FDT_ERR_NOTFOUND;
+ fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+		  const char *name, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+	if (! prop)
+		return NULL;
+
+	return prop->data;
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+	const uint32_t *php;
+	int len;
+
+	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+	if (!php || (len != sizeof(*php)))
+		return 0;
+
+	return fdt32_to_cpu(*php);
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+	uint32_t tag;
+	int p = 0, overflow = 0;
+	int offset, nextoffset, namelen;
+	const char *name;
+
+	CHECK_HEADER(fdt);
+
+	tag = fdt_next_tag(fdt, 0, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADSTRUCTURE;
+
+	if (buflen < 2)
+		return -FDT_ERR_NOSPACE;
+	buf[0] = '/';
+	p = 1;
+
+	while (nextoffset <= nodeoffset) {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_BADOFFSET;
+
+		case FDT_BEGIN_NODE:
+			name = fdt_get_name(fdt, offset, &namelen);
+			if (!name)
+				return namelen;
+			if (overflow || ((p + namelen + 1) > buflen)) {
+				overflow++;
+				break;
+			}
+			memcpy(buf + p, name, namelen);
+			p += namelen;
+			buf[p++] = '/';
+			break;
+
+		case FDT_END_NODE:
+			if (overflow) {
+				overflow--;
+				break;
+			}
+			do {
+				p--;
+			} while  (buf[p-1] != '/');
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	}
+
+	if (overflow)
+		return -FDT_ERR_NOSPACE;
+
+	if (p > 1) /* special case so that root path is "/", not "" */
+		p--;
+	buf[p] = '\0';
+	return p;
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth)
+{
+	int level = -1;
+	uint32_t tag;
+	int offset, nextoffset = 0;
+	int supernodeoffset = -FDT_ERR_INTERNAL;
+
+	CHECK_HEADER(fdt);
+
+	if (supernodedepth < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_BADOFFSET;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			if (level == supernodedepth)
+				supernodeoffset = offset;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (offset < nodeoffset);
+
+	if (nodedepth)
+		*nodedepth = level;
+
+	if (supernodedepth > level)
+		return -FDT_ERR_NOTFOUND;
+	return supernodeoffset;
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+	int nodedepth;
+	int err;
+
+	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+	if (err)
+		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+	return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+	int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+	if (nodedepth < 0)
+		return nodedepth;
+	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+					    nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen)
+{
+	uint32_t tag;
+	int offset, nextoffset;
+	const void *val;
+	int len;
+
+	CHECK_HEADER(fdt);
+
+	if (startoffset >= 0) {
+		tag = fdt_next_tag(fdt, startoffset, &nextoffset);
+		if (tag != FDT_BEGIN_NODE)
+			return -FDT_ERR_BADOFFSET;
+	} else {
+		nextoffset = 0;
+	}
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_getprop(), then if that didn't
+	 * find what we want, we scan over them again making our way
+	 * to the next node.  Still it's the easiest to implement
+	 * approach; performance can come later. */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_BEGIN_NODE:
+			val = fdt_getprop(fdt, offset, propname, &len);
+			if (val
+			    && (len == proplen)
+			    && (memcmp(val, propval, len) == 0))
+				return offset;
+			break;
+
+		case FDT_PROP:
+		case FDT_END:
+		case FDT_END_NODE:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (tag != FDT_END);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+	if ((phandle == 0) || (phandle == -1))
+		return -FDT_ERR_BADPHANDLE;
+	phandle = cpu_to_fdt32(phandle);
+	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
+					     &phandle, sizeof(phandle));
+}
+
+int _stringlist_contains(const void *strlist, int listlen, const char *str)
+{
+	int len = strlen(str);
+	const void *p;
+
+	while (listlen >= len) {
+		if (memcmp(str, strlist, len+1) == 0)
+			return 1;
+		p = memchr(strlist, '\0', listlen);
+		if (!p)
+			return 0; /* malformed strlist.. */
+		listlen -= (p-strlist) + 1;
+		strlist = p + 1;
+	}
+	return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible)
+{
+	const void *prop;
+	int len;
+
+	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+	if (!prop)
+		return len;
+	if (_stringlist_contains(prop, len, compatible))
+		return 0;
+	else
+		return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible)
+{
+	uint32_t tag;
+	int offset, nextoffset;
+	int err;
+
+	CHECK_HEADER(fdt);
+
+	if (startoffset >= 0) {
+		tag = fdt_next_tag(fdt, startoffset, &nextoffset);
+		if (tag != FDT_BEGIN_NODE)
+			return -FDT_ERR_BADOFFSET;
+	} else {
+		nextoffset = 0;
+	}
+
+	/* FIXME: The algorithm here is pretty horrible: we scan each
+	 * property of a node in fdt_node_check_compatible(), then if
+	 * that didn't find what we want, we scan over them again
+	 * making our way to the next node.  Still it's the easiest to
+	 * implement approach; performance can come later. */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_BEGIN_NODE:
+			err = fdt_node_check_compatible(fdt, offset,
+							compatible);
+			if ((err < 0)
+			    && (err != -FDT_ERR_NOTFOUND))
+				return err;
+			else if (err == 0)
+				return offset;
+			break;
+
+		case FDT_PROP:
+		case FDT_END:
+		case FDT_END_NODE:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (tag != FDT_END);
+
+	return -FDT_ERR_NOTFOUND;
+}
diff --git a/arch/powerpc/boot/libfdt/fdt_rw.c b/arch/powerpc/boot/libfdt/fdt_rw.c
new file mode 100644
index 0000000..6673f8e
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_rw.c
@@ -0,0 +1,447 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _blocks_misordered(const void *fdt,
+			      int mem_rsv_size, int struct_size)
+{
+	return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
+		|| (fdt_off_dt_struct(fdt) <
+		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+		|| (fdt_off_dt_strings(fdt) <
+		    (fdt_off_dt_struct(fdt) + struct_size))
+		|| (fdt_totalsize(fdt) <
+		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int rw_check_header(void *fdt)
+{
+	int err;
+
+	if ((err = fdt_check_header(fdt)))
+		return err;
+	if (fdt_version(fdt) < 17)
+		return -FDT_ERR_BADVERSION;
+	if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+			       fdt_size_dt_struct(fdt)))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_version(fdt) > 17)
+		fdt_set_version(fdt, 17);
+
+	return 0;
+}
+
+#define RW_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = rw_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static inline int _blob_data_size(void *fdt)
+{
+	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
+{
+	void *end = fdt + _blob_data_size(fdt);
+
+	if (((p + oldlen) < p) || ((p + oldlen) > end))
+		return -FDT_ERR_BADOFFSET;
+	if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
+		return -FDT_ERR_NOSPACE;
+	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	return 0;
+}
+
+static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+				int oldn, int newn)
+{
+	int delta = (newn - oldn) * sizeof(*p);
+	int err;
+	err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+	if (err)
+		return err;
+	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _blob_splice_struct(void *fdt, void *p,
+			       int oldlen, int newlen)
+{
+	int delta = newlen - oldlen;
+	int err;
+
+	if ((err = _blob_splice(fdt, p, oldlen, newlen)))
+		return err;
+
+	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _blob_splice_string(void *fdt, int newlen)
+{
+	void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+	int err;
+
+	if ((err = _blob_splice(fdt, p, 0, newlen)))
+		return err;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+	return 0;
+}
+
+static int _find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+	const char *p;
+	char *new;
+	int len = strlen(s) + 1;
+	int err;
+
+	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+	if (p)
+		/* found it */
+		return (p - strtab);
+
+	new = strtab + fdt_size_dt_strings(fdt);
+	err = _blob_splice_string(fdt, len);
+	if (err)
+		return err;
+
+	memcpy(new, s, len);
+	return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+	err = _blob_splice_mem_rsv(fdt, re, 0, 1);
+	if (err)
+		return err;
+
+	re->address = cpu_to_fdt64(address);
+	re->size = cpu_to_fdt64(size);
+	return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+	if (n >= fdt_num_mem_rsv(fdt))
+		return -FDT_ERR_NOTFOUND;
+
+	err = _blob_splice_mem_rsv(fdt, re, 1, 0);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
+			    struct fdt_property **prop)
+{
+	int oldlen;
+	int err;
+
+	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (! (*prop))
+		return oldlen;
+
+	if ((err = _blob_splice_struct(fdt, (*prop)->data,
+				       ALIGN(oldlen, FDT_TAGSIZE),
+				       ALIGN(len, FDT_TAGSIZE))))
+		return err;
+
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
+			 struct fdt_property **prop)
+{
+	uint32_t tag;
+	int proplen;
+	int nextoffset;
+	int namestroff;
+	int err;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+
+	namestroff = _find_add_string(fdt, name);
+	if (namestroff < 0)
+		return namestroff;
+
+	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
+	proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
+
+	err = _blob_splice_struct(fdt, *prop, 0, proplen);
+	if (err)
+		return err;
+
+	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
+	(*prop)->nameoff = cpu_to_fdt32(namestroff);
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	err = _resize_property(fdt, nodeoffset, name, len, &prop);
+	if (err == -FDT_ERR_NOTFOUND)
+		err = _add_property(fdt, nodeoffset, name, len, &prop);
+	if (err)
+		return err;
+
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len, proplen;
+
+	RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
+	return _blob_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen)
+{
+	struct fdt_node_header *nh;
+	int offset, nextoffset;
+	int nodelen;
+	int err;
+	uint32_t tag;
+	uint32_t *endtag;
+
+	RW_CHECK_HEADER(fdt);
+
+	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+	if (offset >= 0)
+		return -FDT_ERR_EXISTS;
+	else if (offset != -FDT_ERR_NOTFOUND)
+		return offset;
+
+	/* Try to place the new node after the parent's properties */
+	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+	} while (tag == FDT_PROP);
+
+	nh = _fdt_offset_ptr_w(fdt, offset);
+	nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
+
+	err = _blob_splice_struct(fdt, nh, 0, nodelen);
+	if (err)
+		return err;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
+	memcpy(nh->name, name, namelen);
+	endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
+	*endtag = cpu_to_fdt32(FDT_END_NODE);
+
+	return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	RW_CHECK_HEADER(fdt);
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+				   endoffset - nodeoffset, 0);
+}
+
+static void _packblocks(const void *fdt, void *buf,
+		       int mem_rsv_size, int struct_size)
+{
+	int mem_rsv_off, struct_off, strings_off;
+
+	mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8);
+	struct_off = mem_rsv_off + mem_rsv_size;
+	strings_off = struct_off + struct_size;
+
+	memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size);
+	fdt_set_off_mem_rsvmap(buf, mem_rsv_off);
+
+	memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size);
+	fdt_set_off_dt_struct(buf, struct_off);
+	fdt_set_size_dt_struct(buf, struct_size);
+
+	memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt),
+		fdt_size_dt_strings(fdt));
+	fdt_set_off_dt_strings(buf, strings_off);
+	fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+	int err;
+	int mem_rsv_size, struct_size;
+	int newsize;
+	void *tmp;
+
+	err = fdt_check_header(fdt);
+	if (err)
+		return err;
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+
+	if (fdt_version(fdt) >= 17) {
+		struct_size = fdt_size_dt_struct(fdt);
+	} else {
+		struct_size = 0;
+		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+			;
+	}
+
+	if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+		/* no further work necessary */
+		err = fdt_move(fdt, buf, bufsize);
+		if (err)
+			return err;
+		fdt_set_version(buf, 17);
+		fdt_set_size_dt_struct(buf, struct_size);
+		fdt_set_totalsize(buf, bufsize);
+		return 0;
+	}
+
+	/* Need to reorder */
+	newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+		+ struct_size + fdt_size_dt_strings(fdt);
+
+	if (bufsize < newsize)
+		return -FDT_ERR_NOSPACE;
+
+	if (((buf + newsize) <= fdt)
+	    || (buf >= (fdt + fdt_totalsize(fdt)))) {
+		tmp = buf;
+	} else {
+		tmp = (void *)fdt + fdt_totalsize(fdt);
+		if ((tmp + newsize) > (buf + bufsize))
+			return -FDT_ERR_NOSPACE;
+	}
+
+	_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+	memmove(buf, tmp, newsize);
+
+	fdt_set_magic(buf, FDT_MAGIC);
+	fdt_set_totalsize(buf, bufsize);
+	fdt_set_version(buf, 17);
+	fdt_set_last_comp_version(buf, 16);
+	fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+	return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+	int mem_rsv_size;
+	int err;
+
+	err = rw_check_header(fdt);
+	if (err)
+		return err;
+
+	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+		* sizeof(struct fdt_reserve_entry);
+	_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+	fdt_set_totalsize(fdt, _blob_data_size(fdt));
+
+	return 0;
+}
diff --git a/arch/powerpc/boot/libfdt/fdt_strerror.c b/arch/powerpc/boot/libfdt/fdt_strerror.c
new file mode 100644
index 0000000..f9d32ef
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_strerror.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct errtabent {
+	const char *str;
+};
+
+#define ERRTABENT(val) \
+	[(val)] = { .str = #val, }
+
+static struct errtabent errtable[] = {
+	ERRTABENT(FDT_ERR_NOTFOUND),
+	ERRTABENT(FDT_ERR_EXISTS),
+	ERRTABENT(FDT_ERR_NOSPACE),
+
+	ERRTABENT(FDT_ERR_BADOFFSET),
+	ERRTABENT(FDT_ERR_BADPATH),
+	ERRTABENT(FDT_ERR_BADSTATE),
+
+	ERRTABENT(FDT_ERR_TRUNCATED),
+	ERRTABENT(FDT_ERR_BADMAGIC),
+	ERRTABENT(FDT_ERR_BADVERSION),
+	ERRTABENT(FDT_ERR_BADSTRUCTURE),
+	ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define ERRTABSIZE	(sizeof(errtable) / sizeof(errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+	if (errval > 0)
+		return "<valid offset/length>";
+	else if (errval == 0)
+		return "<no error>";
+	else if (errval > -ERRTABSIZE) {
+		const char *s = errtable[-errval].str;
+
+		if (s)
+			return s;
+	}
+
+	return "<unknown error>";
+}
diff --git a/arch/powerpc/boot/libfdt/fdt_sw.c b/arch/powerpc/boot/libfdt/fdt_sw.c
new file mode 100644
index 0000000..dda2de3
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_sw.c
@@ -0,0 +1,258 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int check_header_sw(void *fdt)
+{
+	if (fdt_magic(fdt) != SW_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	return 0;
+}
+
+static void *grab_space(void *fdt, int len)
+{
+	int offset = fdt_size_dt_struct(fdt);
+	int spaceleft;
+
+	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+		- fdt_size_dt_strings(fdt);
+
+	if ((offset + len < offset) || (offset + len > spaceleft))
+		return NULL;
+
+	fdt_set_size_dt_struct(fdt, offset + len);
+	return fdt_offset_ptr_w(fdt, offset, len);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+	void *fdt = buf;
+
+	if (bufsize < sizeof(struct fdt_header))
+		return -FDT_ERR_NOSPACE;
+
+	memset(buf, 0, bufsize);
+
+	fdt_set_magic(fdt, SW_MAGIC);
+	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_totalsize(fdt,  bufsize);
+
+	fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
+					  sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+	fdt_set_off_dt_strings(fdt, bufsize);
+
+	return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int err = check_header_sw(fdt);
+	int offset;
+
+	if (err)
+		return err;
+	if (fdt_size_dt_struct(fdt))
+		return -FDT_ERR_BADSTATE;
+
+	offset = fdt_off_dt_struct(fdt);
+	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+		return -FDT_ERR_NOSPACE;
+
+	re = (struct fdt_reserve_entry *)(fdt + offset);
+	re->address = cpu_to_fdt64(addr);
+	re->size = cpu_to_fdt64(size);
+
+	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+	return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+	return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+	struct fdt_node_header *nh;
+	int err = check_header_sw(fdt);
+	int namelen = strlen(name) + 1;
+
+	if (err)
+		return err;
+
+	nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
+	if (! nh)
+		return -FDT_ERR_NOSPACE;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memcpy(nh->name, name, namelen);
+	return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+	uint32_t *en;
+	int err = check_header_sw(fdt);
+
+	if (err)
+		return err;
+
+	en = grab_space(fdt, FDT_TAGSIZE);
+	if (! en)
+		return -FDT_ERR_NOSPACE;
+
+	*en = cpu_to_fdt32(FDT_END_NODE);
+	return 0;
+}
+
+static int find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	const char *p;
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+	int struct_top, offset;
+
+	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	/* Add it */
+	offset = -strtabsize - len;
+	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	if (fdt_totalsize(fdt) + offset < struct_top)
+		return 0; /* no more room :( */
+
+	memcpy(strtab + offset, s, len);
+	fdt_set_size_dt_strings(fdt, strtabsize + len);
+	return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err = check_header_sw(fdt);
+	int nameoff;
+
+	if (err)
+		return err;
+
+	nameoff = find_add_string(fdt, name);
+	if (nameoff == 0)
+		return -FDT_ERR_NOSPACE;
+
+	prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
+	if (! prop)
+		return -FDT_ERR_NOSPACE;
+
+	prop->tag = cpu_to_fdt32(FDT_PROP);
+	prop->nameoff = cpu_to_fdt32(nameoff);
+	prop->len = cpu_to_fdt32(len);
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+	int err = check_header_sw(fdt);
+	char *p = (char *)fdt;
+	uint32_t *end;
+	int oldstroffset, newstroffset;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	if (err)
+		return err;
+
+	/* Add terminator */
+	end = grab_space(fdt, sizeof(*end));
+	if (! end)
+		return -FDT_ERR_NOSPACE;
+	*end = cpu_to_fdt32(FDT_END);
+
+	/* Relocate the string table */
+	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+	fdt_set_off_dt_strings(fdt, newstroffset);
+
+	/* Walk the structure, correcting string offsets */
+	offset = 0;
+	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+		if (tag == FDT_PROP) {
+			struct fdt_property *prop =
+				fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+			int nameoff;
+
+			if (! prop)
+				return -FDT_ERR_BADSTRUCTURE;
+
+			nameoff = fdt32_to_cpu(prop->nameoff);
+			nameoff += fdt_size_dt_strings(fdt);
+			prop->nameoff = cpu_to_fdt32(nameoff);
+		}
+		offset = nextoffset;
+	}
+
+	/* Finally, adjust the header */
+	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+	fdt_set_magic(fdt, FDT_MAGIC);
+	return 0;
+}
diff --git a/arch/powerpc/boot/libfdt/fdt_wip.c b/arch/powerpc/boot/libfdt/fdt_wip.c
new file mode 100644
index 0000000..88e24b8
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/fdt_wip.c
@@ -0,0 +1,144 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len)
+{
+	void *propval;
+	int proplen;
+
+	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	if (! propval)
+		return proplen;
+
+	if (proplen != len)
+		return -FDT_ERR_NOSPACE;
+
+	memcpy(propval, val, len);
+	return 0;
+}
+
+static void nop_region(void *start, int len)
+{
+	uint32_t *p;
+
+	for (p = start; (void *)p < (start + len); p++)
+		*p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len;
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	nop_region(prop, len + sizeof(*prop));
+
+	return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int nodeoffset)
+{
+	int level = 0;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		switch (tag) {
+		case FDT_END:
+			return offset;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (level >= 0);
+
+	return nextoffset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
+	return 0;
+}
diff --git a/arch/powerpc/boot/libfdt/libfdt.h b/arch/powerpc/boot/libfdt/libfdt.h
new file mode 100644
index 0000000..6b2fb92
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/libfdt.h
@@ -0,0 +1,721 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#define FDT_FIRST_SUPPORTED_VERSION	0x10
+#define FDT_LAST_SUPPORTED_VERSION	0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND	1
+	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS		2
+	/* FDT_ERR_EXISTS: Attemped to create a node or property which
+	 * already exists */
+#define FDT_ERR_NOSPACE		3
+	/* FDT_ERR_NOSPACE: Operation needed to expand the device
+	 * tree, but its buffer did not have sufficient space to
+	 * contain the expanded tree. Use fdt_open_into() to move the
+	 * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET	4
+	/* FDT_ERR_BADOFFSET: Function was passed a structure block
+	 * offset which is out-of-bounds, or which points to an
+	 * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH		5
+	/* FDT_ERR_BADPATH: Function was passed a badly formatted path
+	 * (e.g. missing a leading / for a function which requires an
+	 * absolute path) */
+#define FDT_ERR_BADPHANDLE	6
+	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+	 * value.  phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE	7
+	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
+	 * tree created by the sequential-write functions, which is
+	 * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED	8
+	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
+	 * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC	9
+	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+	 * device tree at all - it is missing the flattened device
+	 * tree magic number. */
+#define FDT_ERR_BADVERSION	10
+	/* FDT_ERR_BADVERSION: Given device tree has a version which
+	 * can't be handled by the requested operation.  For
+	 * read-write functions, this may mean that fdt_open_into() is
+	 * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE	11
+	/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+	 * structure block or other serious error (e.g. misnested
+	 * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT	12
+	/* FDT_ERR_BADLAYOUT: For read-write functions, the given
+	 * device tree has it's sub-blocks in an order that the
+	 * function can't handle (memory reserve map, then structure,
+	 * then strings).  Use fdt_open_into() to reorganize the tree
+	 * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL	13
+	/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+	 * Should never be returned, if it is, it indicates a bug in
+	 * libfdt itself. */
+
+#define FDT_ERR_MAX		13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these)                */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+	return (void *)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* General functions                                                  */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) 			(fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt)		(fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) 	(fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) 	(fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) 	(fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+	static inline void fdt_set_##name(void *fdt, uint32_t val) \
+	{ \
+		struct fdt_header *fdth = fdt; \
+		fdth->name = cpu_to_fdt32(val); \
+	}
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ *     0, if the buffer appears to contain a valid device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize.  The buffer may overlap
+ * with the existing device tree blob at fdt.  Therefore,
+ *     fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions                                                */
+/**********************************************************************/
+
+/**
+ * fdt_string - retreive a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retreive the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map.  This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ *     the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retreive one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name.  This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name.  name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ *	structure block offset of the requested subnode (>=0), on success
+ *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ *	structure block offset of the node with the requested path (>=0), on success
+ *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ *	-FDT_ERR_NOTFOUND, if the requested node does not exist
+ *      -FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retreive the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset.  If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the node's name, on success
+ *		If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL *lenp contains an error code (<0):
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset.  If lenp is
+ * non-NULL, the length of the property value also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the structure representing the property
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+					    const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+						      const char *name,
+						      int *lenp)
+{
+	return (struct fdt_property *)fdt_get_property(fdt, nodeoffset,
+						       name, lenp);
+}
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ *	pointer to the property's value
+ *		if lenp is non-NULL, *lenp contains the length of the property
+ *		value (>=0)
+ *	NULL, on error
+ *		if lenp is non-NULL, *lenp contains an error code (<0):
+ *		-FDT_ERR_NOTFOUND, node does not have named property
+ *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *		-FDT_ERR_BADMAGIC,
+ *		-FDT_ERR_BADVERSION,
+ *		-FDT_ERR_BADSTATE,
+ *		-FDT_ERR_BADSTRUCTURE,
+ *		-FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+			const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+				  const char *name, int *lenp)
+{
+	return (void *)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retreive the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ *	the phandle of the node at nodeoffset, on succes (!= 0, != -1)
+ *	0, if the node has no phandle, or another error occurs
+ */
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	0, on success
+ *		buf contains the absolute path of the node at
+ *		nodeoffset, as a NUL-terminated string.
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ *		characters and will not fit in the given buffer.
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth).  So
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node.  If the node at
+ * nodeoffset has depth D, then:
+ *	fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ *	structure block offset of the node at node offset's ancestor
+ *		of depth supernodedepth (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+*	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+				 int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node.  The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ *	depth of the node at nodeoffset (>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ *	stucture block offset of the parent of the node at nodeoffset
+ *		(>=0), on success
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ *					       propval, proplen);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ *						       propval, proplen);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+				  const char *propname,
+				  const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the node
+ * which has the given phandle value.  If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0), on success
+ *	-FDT_ERR_NOTFOUND, no node with that phandle exists
+ *	-FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ *	0, if the node has a 'compatible' property listing the given string
+ *	1, if the node has a 'compatible' property, but it does not list
+ *		the given string
+ *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * 	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+			      const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ *	offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ *	while (offset != -FDT_ERR_NOTFOUND) {
+ *		// other code here
+ *		offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ *	}
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ *	structure block offset of the located node (>= 0, >startoffset),
+ *		 on success
+ *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ *		tree after startoffset
+ * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+				  const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions                                           */
+/**********************************************************************/
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len);
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+					   const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions                                         */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+#define fdt_property_string(fdt, name, str) \
+	fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions                                               */
+/**********************************************************************/
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
+int fdt_del_mem_rsv(void *fdt, int n);
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len);
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+				   uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen);
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions                                */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/arch/powerpc/boot/libfdt/libfdt_internal.h b/arch/powerpc/boot/libfdt/libfdt_internal.h
new file mode 100644
index 0000000..1e60936
--- /dev/null
+++ b/arch/powerpc/boot/libfdt/libfdt_internal.h
@@ -0,0 +1,89 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library 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 library 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 library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <fdt.h>
+
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#define PALIGN(p, a)	((void *)ALIGN((unsigned long)(p), (a)))
+
+#define memeq(p, q, n)	(memcmp((p), (q), (n)) == 0)
+#define streq(p, q)	(strcmp((p), (q)) == 0)
+
+uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+	return fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+	return (void *)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+	const struct fdt_reserve_entry *rsv_table =
+		fdt + fdt_off_mem_rsvmap(fdt);
+
+	return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+	return (void *)_fdt_mem_rsv(fdt, n);
+}
+
+#define SW_MAGIC		(~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/arch/powerpc/boot/libfdt_env.h b/arch/powerpc/boot/libfdt_env.h
new file mode 100644
index 0000000..a4b0fc9
--- /dev/null
+++ b/arch/powerpc/boot/libfdt_env.h
@@ -0,0 +1,17 @@
+#ifndef _ARCH_POWERPC_BOOT_LIBFDT_ENV_H
+#define _ARCH_POWERPC_BOOT_LIBFDT_ENV_H
+
+#include <types.h>
+#include <string.h>
+
+typedef u32 uint32_t;
+typedef u64 uint64_t;
+
+#define fdt16_to_cpu(x)		(x)
+#define cpu_to_fdt16(x)		(x)
+#define fdt32_to_cpu(x)		(x)
+#define cpu_to_fdt32(x)		(x)
+#define fdt64_to_cpu(x)		(x)
+#define cpu_to_fdt64(x)		(x)
+
+#endif /* _ARCH_POWERPC_BOOT_LIBFDT_ENV_H */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 1b496b3..9e7f3dd 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -16,7 +16,6 @@
 #include "stdio.h"
 #include "ops.h"
 #include "gunzip_util.h"
-#include "flatdevtree.h"
 #include "reg.h"
 
 static struct gunzip_state gzstate;
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index a180b65..6036a98e 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -79,7 +79,7 @@
 extern struct loader_info loader_info;
 
 void start(void);
-int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
+void fdt_init(void *blob);
 int serial_console_init(void);
 int ns16550_console_init(void *devp, struct serial_console_data *scdp);
 int mpsc_console_init(void *devp, struct serial_console_data *scdp);
diff --git a/arch/powerpc/boot/prpmc2800.c b/arch/powerpc/boot/prpmc2800.c
index 9614e1d..05c3245 100644
--- a/arch/powerpc/boot/prpmc2800.c
+++ b/arch/powerpc/boot/prpmc2800.c
@@ -547,8 +547,7 @@
 	if (!dtb)
 		exit();
 	memmove(dtb, _dtb_start, dt_size);
-	if (ft_init(dtb, dt_size, 16))
-		exit();
+	fdt_init(dtb);
 
 	bridge_base = mv64x60_get_bridge_base();
 
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c
index d666115..3b0ac4d 100644
--- a/arch/powerpc/boot/ps3.c
+++ b/arch/powerpc/boot/ps3.c
@@ -131,7 +131,7 @@
 	printf("\n-- PS3 bootwrapper --\n");
 
 	simple_alloc_init(_end, heapsize, 32, 64);
-	ft_init(_dtb_start, 0, 4);
+	fdt_init(_dtb_start);
 
 	chosen = finddevice("/chosen");
 
diff --git a/arch/powerpc/boot/treeboot-walnut.c b/arch/powerpc/boot/treeboot-walnut.c
index bb2c309..70ffce3 100644
--- a/arch/powerpc/boot/treeboot-walnut.c
+++ b/arch/powerpc/boot/treeboot-walnut.c
@@ -128,6 +128,6 @@
 	simple_alloc_init(_end, avail_ram, 32, 32);
 	platform_ops.fixups = walnut_fixups;
 	platform_ops.exit = ibm40x_dbcr_reset;
-	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	fdt_init(_dtb_start);
 	serial_console_init();
 }
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 31147a0..f961cde 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -45,6 +45,7 @@
 
 # directory for object and other files used by this script
 object=arch/powerpc/boot
+objbin=$object
 
 # directory for working files
 tmpdir=.
@@ -95,6 +96,7 @@
 	shift
 	[ "$#" -gt 0 ] || usage
 	object="$1"
+	objbin="$1"
 	;;
     -W)
 	shift
@@ -116,10 +118,13 @@
 done
 
 if [ -n "$dts" ]; then
+    if [ ! -r "$dts" -a -r "$object/dts/$dts" ]; then
+	dts="$object/dts/$dts"
+    fi
     if [ -z "$dtb" ]; then
 	dtb="$platform.dtb"
     fi
-    dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts"
+    $object/dtc -O dtb -o "$dtb" -b 0 "$dts"
 fi
 
 if [ -z "$kernel" ]; then
@@ -246,11 +251,11 @@
 # post-processing needed for some platforms
 case "$platform" in
 pseries|chrp)
-    $object/addnote "$ofile"
+    $objbin/addnote "$ofile"
     ;;
 coff)
     ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
-    $object/hack-coff "$ofile"
+    $objbin/hack-coff "$ofile"
     ;;
 cuboot*)
     gzip -f -9 "$ofile"
@@ -259,7 +264,7 @@
     ;;
 treeboot*)
     mv "$ofile" "$ofile.elf"
-    $object/mktree "$ofile.elf" "$ofile" "$base" "$entry"
+    $objbin/mktree "$ofile.elf" "$ofile" "$base" "$entry"
     if [ -z "$cacheit" ]; then
 	rm -f "$ofile.elf"
     fi
@@ -287,8 +292,6 @@
     overlay_dest="256"
     overlay_size="256"
 
-    rm -f "$object/otheros.bld"
-
     ${CROSS}objcopy -O binary "$ofile" "$ofile.bin"
 
     dd if="$ofile.bin" of="$ofile.bin" conv=notrunc   \
@@ -299,6 +302,8 @@
         skip=$system_reset_overlay seek=$overlay_dest \
         count=$overlay_size bs=1
 
-    gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld"
+    odir="$(dirname "$ofile.bin")"
+    rm -f "$odir/otheros.bld"
+    gzip --force -9 --stdout "$ofile.bin" > "$odir/otheros.bld"
     ;;
 esac
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index 421e08e..9ed2e09 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -50,7 +50,8 @@
 CONFIG_GENERIC_BUG=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
-# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_PPC_DCR_MMIO=y
+CONFIG_PPC_DCR=y
 CONFIG_PPC_OF_PLATFORM_PCI=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -148,7 +149,7 @@
 CONFIG_PPC_CELLEB=y
 # CONFIG_PPC_PS3 is not set
 CONFIG_PPC_CELL=y
-# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_CELL_NATIVE=y
 # CONFIG_PPC_IBM_CELL_BLADE is not set
 
 #
@@ -157,13 +158,19 @@
 CONFIG_SPU_FS=y
 CONFIG_SPU_FS_64K_LS=y
 CONFIG_SPU_BASE=y
+CONFIG_CBE_RAS=y
+# CONFIG_CBE_THERM is not set
 # CONFIG_PQ2ADS is not set
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
 CONFIG_PPC_UDBG_BEAT=y
-# CONFIG_MPIC is not set
+CONFIG_MPIC=y
 # CONFIG_MPIC_WEIRD is not set
 # CONFIG_PPC_I8259 is not set
 # CONFIG_U3_DART is not set
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+# CONFIG_RTAS_PROC is not set
 # CONFIG_MMIO_NVRAM is not set
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
@@ -593,10 +600,11 @@
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC is not set
+CONFIG_IBM_NEW_EMAC_ZMII=y
+CONFIG_IBM_NEW_EMAC_RGMII=y
+CONFIG_IBM_NEW_EMAC_TAH=y
+CONFIG_IBM_NEW_EMAC_EMAC4=y
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
 CONFIG_NETDEV_1000=y
@@ -741,6 +749,7 @@
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
 CONFIG_HVC_BEAT=y
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
@@ -822,6 +831,7 @@
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WATCHDOG_RTAS is not set
 
 #
 # PCI-based Watchdog Cards
@@ -1245,17 +1255,7 @@
 CONFIG_IRQSTACKS=y
 # CONFIG_VIRQ_DEBUG is not set
 # CONFIG_BOOTX_TEXT is not set
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
-# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
-CONFIG_PPC_EARLY_DEBUG_BEAT=y
-# CONFIG_PPC_EARLY_DEBUG_44x is not set
-# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/mpc837x_mds_defconfig b/arch/powerpc/configs/mpc837x_mds_defconfig
new file mode 100644
index 0000000..4f49aee
--- /dev/null
+++ b/arch/powerpc/configs/mpc837x_mds_defconfig
@@ -0,0 +1,878 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Wed Oct 10 16:31:39 2007
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC836x_MDS is not set
+CONFIG_MPC837x_MDS=y
+CONFIG_PPC_MPC837x=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
+CONFIG_FSL_SERDES=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_HIBERNATION_UP_POSSIBLE=y
+CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_FSL=y
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NETDEV_1000=y
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 5760b9f..7695a4c 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.24-rc4
-# Thu Dec  6 16:49:07 2007
+# Fri Dec 21 14:47:29 2007
 #
 CONFIG_PPC64=y
 
@@ -211,7 +211,7 @@
 CONFIG_MPIC_U3_HT_IRQS=y
 CONFIG_MPIC_BROKEN_REGREAD=y
 CONFIG_IBMVIO=y
-# CONFIG_IBMEBUS is not set
+CONFIG_IBMEBUS=y
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
 CONFIG_PPC_INDIRECT_IO=y
@@ -375,7 +375,7 @@
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+CONFIG_INET_LRO=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -929,6 +929,7 @@
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
+CONFIG_EHEA=m
 # CONFIG_IXGBE is not set
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
@@ -1558,6 +1559,7 @@
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
 # CONFIG_INFINIBAND_IPATH is not set
+CONFIG_INFINIBAND_EHCA=m
 # CONFIG_INFINIBAND_AMSO1100 is not set
 # CONFIG_MLX4_INFINIBAND is not set
 CONFIG_INFINIBAND_IPOIB=m
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ca51f0c..9374bc9 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -3,7 +3,7 @@
 #
 
 ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS	+= -mno-minimal-toc
+CFLAGS_prom_init.o	+= -mno-minimal-toc
 endif
 ifeq ($(CONFIG_PPC32),y)
 CFLAGS_prom_init.o      += -fPIC
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 9ed351f..7c21f52 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -888,7 +888,7 @@
 		.cpu_setup		= __setup_cpu_603,
 		.platform		= "ppc603",
 	},
-	{	/* e300c3 on 83xx  */
+	{	/* e300c3 (e300c1, plus one IU, half cache size) on 83xx */
 		.pvr_mask		= 0x7fff0000,
 		.pvr_value		= 0x00850000,
 		.cpu_name		= "e300c3",
@@ -899,6 +899,17 @@
 		.cpu_setup		= __setup_cpu_603,
 		.platform		= "ppc603",
 	},
+	{	/* e300c4 (e300c1, plus one IU) */
+		.pvr_mask		= 0x7fff0000,
+		.pvr_value		= 0x00860000,
+		.cpu_name		= "e300c4",
+		.cpu_features		= CPU_FTRS_E300,
+		.cpu_user_features	= COMMON_USER,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_603,
+		.platform		= "ppc603",
+	},
 	{	/* default match, we assume split I/D cache & TB (non-601)... */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 72fd871..caae49f 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -52,7 +52,7 @@
 struct bus_type ibmebus_bus_type;
 
 /* These devices will automatically be added to the bus during init */
-static struct of_device_id builtin_matches[] = {
+static struct of_device_id __initdata builtin_matches[] = {
 	{ .compatible = "IBM,lhca" },
 	{ .compatible = "IBM,lhea" },
 	{},
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 2d0c9ef..47c3fe5 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -526,16 +526,14 @@
 	return tbl;
 }
 
-void iommu_free_table(struct device_node *dn)
+void iommu_free_table(struct iommu_table *tbl, const char *node_name)
 {
-	struct pci_dn *pdn = dn->data;
-	struct iommu_table *tbl = pdn->iommu_table;
 	unsigned long bitmap_sz, i;
 	unsigned int order;
 
 	if (!tbl || !tbl->it_map) {
 		printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
-				dn->full_name);
+				node_name);
 		return;
 	}
 
@@ -544,7 +542,7 @@
 	for (i = 0; i < (tbl->it_size/64); i++) {
 		if (tbl->it_map[i] != 0) {
 			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
-				__FUNCTION__, dn->full_name);
+				__FUNCTION__, node_name);
 			break;
 		}
 	}
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
index f0f49d1..ee172aa 100644
--- a/arch/powerpc/kernel/isa-bridge.c
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -108,7 +108,7 @@
 	if (size > 0x10000)
 		size = 0x10000;
 
-	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range, "
 	       "mapping 64k\n");
 
 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
@@ -116,7 +116,7 @@
 	return;
 
 inval_range:
-	printk(KERN_ERR "no ISA IO ranges or unexpected isa range,"
+	printk(KERN_ERR "no ISA IO ranges or unexpected isa range, "
 	       "mapping 64k\n");
 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
 		     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
@@ -145,7 +145,7 @@
 	for_each_node_by_type(np, "isa") {
 		/* Look for our hose being a parent */
 		for (parent = of_get_parent(np); parent;) {
-			if (parent == hose->arch_data) {
+			if (parent == hose->dn) {
 				of_node_put(parent);
 				break;
 			}
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 4ed5887..b9cae6b 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -474,7 +474,7 @@
 
 	/*
 	 * Before we register the platfrom serial devices, we need
-	 * to fixup their interrutps and their IO ports.
+	 * to fixup their interrupts and their IO ports.
 	 */
 	DBG("Fixing serial ports interrupts and IO ports ...\n");
 
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index ff781b2..dcb89a8 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -41,7 +41,6 @@
 /* #define LPARCFG_DEBUG */
 
 static struct proc_dir_entry *proc_ppc64_lparcfg;
-#define LPARCFG_BUFF_SIZE 4096
 
 /*
  * Track sum of all purrs across all processors. This is used to further
@@ -595,13 +594,6 @@
 	ent = create_proc_entry("ppc64/lparcfg", mode, NULL);
 	if (ent) {
 		ent->proc_fops = &lparcfg_fops;
-		ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL);
-		if (!ent->data) {
-			printk(KERN_ERR
-			       "Failed to allocate buffer for lparcfg\n");
-			remove_proc_entry("lparcfg", ent->parent);
-			return -ENOMEM;
-		}
 	} else {
 		printk(KERN_ERR "Failed to create ppc64/lparcfg\n");
 		return -EIO;
@@ -613,10 +605,8 @@
 
 void __exit lparcfg_cleanup(void)
 {
-	if (proc_ppc64_lparcfg) {
-		kfree(proc_ppc64_lparcfg->data);
+	if (proc_ppc64_lparcfg)
 		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
-	}
 }
 
 module_init(lparcfg_init);
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index 330c9dc..74ce0c7 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -14,6 +14,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <asm/ppc_asm.h>
+#include <asm/unistd.h>
 
 	.text
 
@@ -43,3 +44,10 @@
 	add	r3,r3,r5
 	mtlr	r0
 	blr
+
+_GLOBAL(kernel_execve)
+	li	r0,__NR_execve
+	sc
+	bnslr
+	neg	r3,r3
+	blr
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 8b642ab..ea11378 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -793,13 +793,6 @@
 	addi	r1,r1,16
 	blr
 
-_GLOBAL(kernel_execve)
-	li	r0,__NR_execve
-	sc
-	bnslr
-	neg	r3,r3
-	blr
-
 /*
  * This routine is just here to keep GCC happy - sigh...
  */
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index bbb3ba5..a3c491e 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -518,13 +518,6 @@
 
 #endif /* CONFIG_ALTIVEC */
 
-_GLOBAL(kernel_execve)
-	li	r0,__NR_execve
-	sc
-	bnslr
-	neg	r3,r3
-	blr
-
 /* kexec_wait(phys_cpu)
  *
  * wait for the flag to change, indicating this kernel is going away but
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 07a89a3..eab3138 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/cache.h>
 #include <linux/bug.h>
+#include <linux/sort.h>
 
 #include "setup.h"
 
@@ -54,22 +55,60 @@
    addend) */
 static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
 {
-	unsigned int i, j, ret = 0;
+	unsigned int i, r_info, r_addend, _count_relocs;
 
-	/* Sure, this is order(n^2), but it's usually short, and not
-           time critical */
-	for (i = 0; i < num; i++) {
-		for (j = 0; j < i; j++) {
-			/* If this addend appeared before, it's
-                           already been counted */
-			if (ELF32_R_SYM(rela[i].r_info)
-			    == ELF32_R_SYM(rela[j].r_info)
-			    && rela[i].r_addend == rela[j].r_addend)
-				break;
+	_count_relocs = 0;
+	r_info = 0;
+	r_addend = 0;
+	for (i = 0; i < num; i++)
+		/* Only count 24-bit relocs, others don't need stubs */
+		if (ELF32_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
+		    (r_info != ELF32_R_SYM(rela[i].r_info) ||
+		     r_addend != rela[i].r_addend)) {
+			_count_relocs++;
+			r_info = ELF32_R_SYM(rela[i].r_info);
+			r_addend = rela[i].r_addend;
 		}
-		if (j == i) ret++;
+
+	return _count_relocs;
+}
+
+static int relacmp(const void *_x, const void *_y)
+{
+	const Elf32_Rela *x, *y;
+
+	y = (Elf32_Rela *)_x;
+	x = (Elf32_Rela *)_y;
+
+	/* Compare the entire r_info (as opposed to ELF32_R_SYM(r_info) only) to
+	 * make the comparison cheaper/faster. It won't affect the sorting or
+	 * the counting algorithms' performance
+	 */
+	if (x->r_info < y->r_info)
+		return -1;
+	else if (x->r_info > y->r_info)
+		return 1;
+	else if (x->r_addend < y->r_addend)
+		return -1;
+	else if (x->r_addend > y->r_addend)
+		return 1;
+	else
+		return 0;
+}
+
+static void relaswap(void *_x, void *_y, int size)
+{
+	uint32_t *x, *y, tmp;
+	int i;
+
+	y = (uint32_t *)_x;
+	x = (uint32_t *)_y;
+
+	for (i = 0; i < sizeof(Elf32_Rela) / sizeof(uint32_t); i++) {
+		tmp = x[i];
+		x[i] = y[i];
+		y[i] = tmp;
 	}
-	return ret;
 }
 
 /* Get the potential trampolines size required of the init and
@@ -100,6 +139,16 @@
 			DEBUGP("Ptr: %p.  Number: %u\n",
 			       (void *)hdr + sechdrs[i].sh_offset,
 			       sechdrs[i].sh_size / sizeof(Elf32_Rela));
+
+			/* Sort the relocation information based on a symbol and
+			 * addend key. This is a stable O(n*log n) complexity
+			 * alogrithm but it will reduce the complexity of
+			 * count_relocs() to linear complexity O(n)
+			 */
+			sort((void *)hdr + sechdrs[i].sh_offset,
+			     sechdrs[i].sh_size / sizeof(Elf32_Rela),
+			     sizeof(Elf32_Rela), relacmp, relaswap);
+
 			ret += count_relocs((void *)hdr
 					     + sechdrs[i].sh_offset,
 					     sechdrs[i].sh_size
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 75c7c4f..3a82b02 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -24,6 +24,7 @@
 #include <asm/module.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
+#include <linux/sort.h>
 
 #include "setup.h"
 
@@ -81,25 +82,23 @@
    different addend) */
 static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num)
 {
-	unsigned int i, j, ret = 0;
+	unsigned int i, r_info, r_addend, _count_relocs;
 
 	/* FIXME: Only count external ones --RR */
-	/* Sure, this is order(n^2), but it's usually short, and not
-           time critical */
-	for (i = 0; i < num; i++) {
+	_count_relocs = 0;
+	r_info = 0;
+	r_addend = 0;
+	for (i = 0; i < num; i++)
 		/* Only count 24-bit relocs, others don't need stubs */
-		if (ELF64_R_TYPE(rela[i].r_info) != R_PPC_REL24)
-			continue;
-		for (j = 0; j < i; j++) {
-			/* If this addend appeared before, it's
-                           already been counted */
-			if (rela[i].r_info == rela[j].r_info
-			    && rela[i].r_addend == rela[j].r_addend)
-				break;
+		if (ELF64_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
+		    (r_info != ELF64_R_SYM(rela[i].r_info) ||
+		     r_addend != rela[i].r_addend)) {
+			_count_relocs++;
+			r_info = ELF64_R_SYM(rela[i].r_info);
+			r_addend = rela[i].r_addend;
 		}
-		if (j == i) ret++;
-	}
-	return ret;
+
+	return _count_relocs;
 }
 
 void *module_alloc(unsigned long size)
@@ -118,6 +117,44 @@
            table entries. */
 }
 
+static int relacmp(const void *_x, const void *_y)
+{
+	const Elf64_Rela *x, *y;
+
+	y = (Elf64_Rela *)_x;
+	x = (Elf64_Rela *)_y;
+
+	/* Compare the entire r_info (as opposed to ELF64_R_SYM(r_info) only) to
+	 * make the comparison cheaper/faster. It won't affect the sorting or
+	 * the counting algorithms' performance
+	 */
+	if (x->r_info < y->r_info)
+		return -1;
+	else if (x->r_info > y->r_info)
+		return 1;
+	else if (x->r_addend < y->r_addend)
+		return -1;
+	else if (x->r_addend > y->r_addend)
+		return 1;
+	else
+		return 0;
+}
+
+static void relaswap(void *_x, void *_y, int size)
+{
+	uint64_t *x, *y, tmp;
+	int i;
+
+	y = (uint64_t *)_x;
+	x = (uint64_t *)_y;
+
+	for (i = 0; i < sizeof(Elf64_Rela) / sizeof(uint64_t); i++) {
+		tmp = x[i];
+		x[i] = y[i];
+		y[i] = tmp;
+	}
+}
+
 /* Get size of potential trampolines required. */
 static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
 				    const Elf64_Shdr *sechdrs)
@@ -133,6 +170,16 @@
 			DEBUGP("Ptr: %p.  Number: %lu\n",
 			       (void *)sechdrs[i].sh_addr,
 			       sechdrs[i].sh_size / sizeof(Elf64_Rela));
+
+			/* Sort the relocation information based on a symbol and
+			 * addend key. This is a stable O(n*log n) complexity
+			 * alogrithm but it will reduce the complexity of
+			 * count_relocs() to linear complexity O(n)
+			 */
+			sort((void *)sechdrs[i].sh_addr,
+			     sechdrs[i].sh_size / sizeof(Elf64_Rela),
+			     sizeof(Elf64_Rela), relacmp, relaswap);
+
 			relocs += count_relocs((void *)sechdrs[i].sh_addr,
 					       sechdrs[i].sh_size
 					       / sizeof(Elf64_Rela));
@@ -343,7 +390,7 @@
 			/* Simply set it */
 			*(u32 *)location = value;
 			break;
-			
+
 		case R_PPC64_ADDR64:
 			/* Simply set it */
 			*(unsigned long *)location = value;
@@ -399,7 +446,7 @@
 			}
 
 			/* Only replace bits 2 through 26 */
-			*(uint32_t *)location 
+			*(uint32_t *)location
 				= (*(uint32_t *)location & ~0x03fffffc)
 				| (value & 0x03fffffc);
 			break;
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index aeaa202..de36e23 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -40,7 +40,7 @@
  * a bus type in the list
  */
 
-static struct of_device_id of_default_bus_ids[] = {
+static const struct of_device_id of_default_bus_ids[] = {
 	{ .type = "soc", },
 	{ .compatible = "soc", },
 	{ .type = "spider", },
@@ -64,26 +64,6 @@
 
 postcore_initcall(of_bus_driver_init);
 
-int of_register_platform_driver(struct of_platform_driver *drv)
-{
-	/* initialize common driver fields */
-	if (!drv->driver.name)
-		drv->driver.name = drv->name;
-	if (!drv->driver.owner)
-		drv->driver.owner = drv->owner;
-	drv->driver.bus = &of_platform_bus_type;
-
-	/* register with core */
-	return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(of_register_platform_driver);
-
-void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
-	driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(of_unregister_platform_driver);
-
 struct of_device* of_platform_device_create(struct device_node *np,
 					    const char *bus_id,
 					    struct device *parent)
@@ -120,8 +100,8 @@
  * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
  * disallow recursive creation of child busses
  */
-static int of_platform_bus_create(struct device_node *bus,
-				  struct of_device_id *matches,
+static int of_platform_bus_create(const struct device_node *bus,
+				  const struct of_device_id *matches,
 				  struct device *parent)
 {
 	struct device_node *child;
@@ -157,7 +137,7 @@
  */
 
 int of_platform_bus_probe(struct device_node *root,
-			  struct of_device_id *matches,
+			  const struct of_device_id *matches,
 			  struct device *parent)
 {
 	struct device_node *child;
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2ae3b6f..571854f 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -48,32 +48,26 @@
 static DEFINE_SPINLOCK(hose_spinlock);
 
 /* XXX kill that some day ... */
-int global_phb_number;		/* Global phb counter */
+static int global_phb_number;		/* Global phb counter */
 
-extern struct list_head hose_list;
+/* ISA Memory physical address */
+resource_size_t isa_mem_base;
 
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-	memset(hose, 0, sizeof(struct pci_controller));
+/* Default PCI flags is 0 */
+unsigned int ppc_pci_flags;
 
-	spin_lock(&hose_spinlock);
-	hose->global_number = global_phb_number++;
-	list_add_tail(&hose->list_node, &hose_list);
-	spin_unlock(&hose_spinlock);
-}
-
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
 	struct pci_controller *phb;
 
-	phb = alloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
+	phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
 	if (phb == NULL)
 		return NULL;
-	pci_setup_pci_controller(phb);
-	phb->arch_data = dev;
+	spin_lock(&hose_spinlock);
+	phb->global_number = global_phb_number++;
+	list_add_tail(&phb->list_node, &hose_list);
+	spin_unlock(&hose_spinlock);
+	phb->dn = dev;
 	phb->is_dynamic = mem_init_done;
 #ifdef CONFIG_PPC64
 	if (dev) {
@@ -126,15 +120,10 @@
  */
 int pci_domain_nr(struct pci_bus *bus)
 {
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return 0;
-	else {
-		struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pci_controller *hose = pci_bus_to_host(bus);
 
-		return hose->global_number;
-	}
+	return hose->global_number;
 }
-
 EXPORT_SYMBOL(pci_domain_nr);
 
 #ifdef CONFIG_PPC_OF
@@ -153,7 +142,7 @@
 	while(node) {
 		struct pci_controller *hose, *tmp;
 		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-			if (hose->arch_data == node)
+			if (hose->dn == node)
 				return hose;
 		node = node->parent;
 	}
@@ -201,6 +190,20 @@
 	struct of_irq oirq;
 	unsigned int virq;
 
+	/* The current device-tree that iSeries generates from the HV
+	 * PCI informations doesn't contain proper interrupt routing,
+	 * and all the fallback would do is print out crap, so we
+	 * don't attempt to resolve the interrupts here at all, some
+	 * iSeries specific fixup does it.
+	 *
+	 * In the long run, we will hopefully fix the generated device-tree
+	 * instead.
+	 */
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return -1;
+#endif
+
 	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
 #ifdef DEBUG
@@ -222,10 +225,11 @@
 		if (pin == 0)
 			return -1;
 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff) {
+		    line == 0xff || line == 0) {
 			return -1;
 		}
-		DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+		DBG(" -> no map ! Using line %d (pin %d) from PCI config\n",
+		    line, pin);
 
 		virq = irq_create_mapping(NULL, line);
 		if (virq != NO_IRQ)
@@ -475,3 +479,722 @@
 	*start = rsrc->start - offset;
 	*end = rsrc->end - offset;
 }
+
+/**
+ * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
+ * @hose: newly allocated pci_controller to be setup
+ * @dev: device node of the host bridge
+ * @primary: set if primary bus (32 bits only, soon to be deprecated)
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping of a pci controller based on its
+ * content.
+ *
+ * Life would be boring if it wasn't for a few issues that we have to deal
+ * with here:
+ *
+ *   - We can only cope with one IO space range and up to 3 Memory space
+ *     ranges. However, some machines (thanks Apple !) tend to split their
+ *     space into lots of small contiguous ranges. So we have to coalesce.
+ *
+ *   - We can only cope with all memory ranges having the same offset
+ *     between CPU addresses and PCI addresses. Unfortunately, some bridges
+ *     are setup for a large 1:1 mapping along with a small "window" which
+ *     maps PCI address 0 to some arbitrary high address of the CPU space in
+ *     order to give access to the ISA memory hole.
+ *     The way out of here that I've chosen for now is to always set the
+ *     offset based on the first resource found, then override it if we
+ *     have a different offset and the previous was set by an ISA hole.
+ *
+ *   - Some busses have IO space not starting at 0, which causes trouble with
+ *     the way we do our IO resource renumbering. The code somewhat deals with
+ *     it for 64 bits but I would expect problems on 32 bits.
+ *
+ *   - Some 32 bits platforms such as 4xx can have physical space larger than
+ *     32 bits so we need to use 64 bits values for the parsing
+ */
+void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
+					    struct device_node *dev,
+					    int primary)
+{
+	const u32 *ranges;
+	int rlen;
+	int pna = of_n_addr_cells(dev);
+	int np = pna + 5;
+	int memno = 0, isa_hole = -1;
+	u32 pci_space;
+	unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
+	unsigned long long isa_mb = 0;
+	struct resource *res;
+
+	printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
+	       dev->full_name, primary ? "(primary)" : "");
+
+	/* Get ranges property */
+	ranges = of_get_property(dev, "ranges", &rlen);
+	if (ranges == NULL)
+		return;
+
+	/* Parse it */
+	while ((rlen -= np * 4) >= 0) {
+		/* Read next ranges element */
+		pci_space = ranges[0];
+		pci_addr = of_read_number(ranges + 1, 2);
+		cpu_addr = of_translate_address(dev, ranges + 3);
+		size = of_read_number(ranges + pna + 3, 2);
+		ranges += np;
+		if (cpu_addr == OF_BAD_ADDR || size == 0)
+			continue;
+
+		/* Now consume following elements while they are contiguous */
+		for (; rlen >= np * sizeof(u32);
+		     ranges += np, rlen -= np * 4) {
+			if (ranges[0] != pci_space)
+				break;
+			pci_next = of_read_number(ranges + 1, 2);
+			cpu_next = of_translate_address(dev, ranges + 3);
+			if (pci_next != pci_addr + size ||
+			    cpu_next != cpu_addr + size)
+				break;
+			size += of_read_number(ranges + pna + 3, 2);
+		}
+
+		/* Act based on address space type */
+		res = NULL;
+		switch ((pci_space >> 24) & 0x3) {
+		case 1:		/* PCI IO space */
+			printk(KERN_INFO
+			       "  IO 0x%016llx..0x%016llx -> 0x%016llx\n",
+			       cpu_addr, cpu_addr + size - 1, pci_addr);
+
+			/* We support only one IO range */
+			if (hose->pci_io_size) {
+				printk(KERN_INFO
+				       " \\--> Skipped (too many) !\n");
+				continue;
+			}
+#ifdef CONFIG_PPC32
+			/* On 32 bits, limit I/O space to 16MB */
+			if (size > 0x01000000)
+				size = 0x01000000;
+
+			/* 32 bits needs to map IOs here */
+			hose->io_base_virt = ioremap(cpu_addr, size);
+
+			/* Expect trouble if pci_addr is not 0 */
+			if (primary)
+				isa_io_base =
+					(unsigned long)hose->io_base_virt;
+#endif /* CONFIG_PPC32 */
+			/* pci_io_size and io_base_phys always represent IO
+			 * space starting at 0 so we factor in pci_addr
+			 */
+			hose->pci_io_size = pci_addr + size;
+			hose->io_base_phys = cpu_addr - pci_addr;
+
+			/* Build resource */
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = pci_addr;
+			break;
+		case 2:		/* PCI Memory space */
+			printk(KERN_INFO
+			       " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
+			       cpu_addr, cpu_addr + size - 1, pci_addr,
+			       (pci_space & 0x40000000) ? "Prefetch" : "");
+
+			/* We support only 3 memory ranges */
+			if (memno >= 3) {
+				printk(KERN_INFO
+				       " \\--> Skipped (too many) !\n");
+				continue;
+			}
+			/* Handles ISA memory hole space here */
+			if (pci_addr == 0) {
+				isa_mb = cpu_addr;
+				isa_hole = memno;
+				if (primary || isa_mem_base == 0)
+					isa_mem_base = cpu_addr;
+			}
+
+			/* We get the PCI/Mem offset from the first range or
+			 * the, current one if the offset came from an ISA
+			 * hole. If they don't match, bugger.
+			 */
+			if (memno == 0 ||
+			    (isa_hole >= 0 && pci_addr != 0 &&
+			     hose->pci_mem_offset == isa_mb))
+				hose->pci_mem_offset = cpu_addr - pci_addr;
+			else if (pci_addr != 0 &&
+				 hose->pci_mem_offset != cpu_addr - pci_addr) {
+				printk(KERN_INFO
+				       " \\--> Skipped (offset mismatch) !\n");
+				continue;
+			}
+
+			/* Build resource */
+			res = &hose->mem_resources[memno++];
+			res->flags = IORESOURCE_MEM;
+			if (pci_space & 0x40000000)
+				res->flags |= IORESOURCE_PREFETCH;
+			res->start = cpu_addr;
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + size - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+	}
+
+	/* Out of paranoia, let's put the ISA hole last if any */
+	if (isa_hole >= 0 && memno > 0 && isa_hole != (memno-1)) {
+		struct resource tmp = hose->mem_resources[isa_hole];
+		hose->mem_resources[isa_hole] = hose->mem_resources[memno-1];
+		hose->mem_resources[memno-1] = tmp;
+	}
+}
+
+/* Decide whether to display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+#ifdef CONFIG_PPC64
+	return hose->buid != 0;
+#else
+	if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+		return 0;
+	if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+		return hose->global_number != 0;
+	return 1;
+#endif
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			     struct resource *res)
+{
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+	if (!hose)
+		return;
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+
+	region->start = (res->start - offset) & mask;
+	region->end = (res->end - offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			     struct pci_bus_region *region)
+{
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+	if (!hose)
+		return;
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+	res->start = (region->start + offset) & mask;
+	res->end = (region->end + offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/* Fixup a bus resource into a linux resource */
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	resource_size_t offset = 0, mask = (resource_size_t)-1;
+
+	if (res->flags & IORESOURCE_IO) {
+		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+		mask = 0xffffffffu;
+	} else if (res->flags & IORESOURCE_MEM)
+		offset = hose->pci_mem_offset;
+
+	res->start = (res->start + offset) & mask;
+	res->end = (res->end + offset) & mask;
+
+	pr_debug("PCI:%s            %016llx-%016llx\n",
+		 pci_name(dev),
+		 (unsigned long long)res->start,
+		 (unsigned long long)res->end);
+}
+
+
+/* This header fixup will do the resource fixup for all devices as they are
+ * probed, but not for bridge ranges
+ */
+static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	int i;
+
+	if (!hose) {
+		printk(KERN_ERR "No host bridge for PCI dev %s !\n",
+		       pci_name(dev));
+		return;
+	}
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		struct resource *res = dev->resource + i;
+		if (!res->flags)
+			continue;
+		if (res->end == 0xffffffff) {
+			pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
+				 pci_name(dev), i,
+				 (unsigned long long)res->start,
+				 (unsigned long long)res->end,
+				 (unsigned int)res->flags);
+			res->end -= res->start;
+			res->start = 0;
+			res->flags |= IORESOURCE_UNSET;
+			continue;
+		}
+
+		pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
+			 pci_name(dev), i,
+			 (unsigned long long)res->start,\
+			 (unsigned long long)res->end,
+			 (unsigned int)res->flags);
+
+		fixup_resource(res, dev);
+	}
+
+	/* Call machine specific resource fixup */
+	if (ppc_md.pcibios_fixup_resources)
+		ppc_md.pcibios_fixup_resources(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
+
+static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pci_dev *dev = bus->self;
+
+	pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
+
+	/* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
+	 * now differently between 32 and 64 bits.
+	 */
+	if (dev != NULL) {
+		struct resource *res;
+		int i;
+
+		for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+			if ((res = bus->resource[i]) == NULL)
+				continue;
+			if (!res->flags || bus->self->transparent)
+				continue;
+
+			/* On PowerMac, Apple leaves bridge windows open over
+			 * an inaccessible region of memory space (0...fffff)
+			 * which is somewhat bogus, but that's what they think
+			 * means disabled...
+			 *
+			 * We clear those to force them to be reallocated later
+			 *
+			 * We detect such regions by the fact that the base is
+			 * equal to the pci_mem_offset of the host bridge and
+			 * their size is smaller than 1M.
+			 */
+			if (res->start == hose->pci_mem_offset &&
+			    res->end < 0x100000) {
+				printk(KERN_INFO
+				       "PCI: Closing bogus Apple Firmware"
+				       " region %d on bus 0x%02x\n",
+				       i, bus->number);
+				res->flags = 0;
+				continue;
+			}
+
+			pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
+				 pci_name(dev), i,
+				 (unsigned long long)res->start,\
+				 (unsigned long long)res->end,
+				 (unsigned int)res->flags);
+
+			fixup_resource(res, dev);
+		}
+	}
+
+	/* Additional setup that is different between 32 and 64 bits for now */
+	pcibios_do_bus_setup(bus);
+
+	/* Platform specific bus fixups */
+	if (ppc_md.pcibios_fixup_bus)
+		ppc_md.pcibios_fixup_bus(bus);
+
+	/* Read default IRQs and fixup if necessary */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (ppc_md.pci_irq_fixup)
+			ppc_md.pci_irq_fixup(dev);
+	}
+}
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* When called from the generic PCI probe, read PCI<->PCI bridge
+	 * bases before proceeding
+	 */
+	if (bus->self != NULL)
+		pci_read_bridge_bases(bus);
+	__pcibios_fixup_bus(bus);
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/* When building a bus from the OF tree rather than probing, we need a
+ * slightly different version of the fixup which doesn't read the
+ * bridge bases using config space accesses
+ */
+void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
+{
+	__pcibios_fixup_bus(bus);
+}
+
+static int skip_isa_ioresource_align(struct pci_dev *dev)
+{
+	if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+	    !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+		return 1;
+	return 0;
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		resource_size_t start = res->start;
+
+		if (skip_isa_ioresource_align(dev))
+			return;
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init reparent_resources(struct resource *parent,
+				     struct resource *res)
+{
+	struct resource *p, **pp;
+	struct resource **firstpp = NULL;
+
+	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+		if (p->end < res->start)
+			continue;
+		if (res->end < p->start)
+			break;
+		if (p->start < res->start || p->end > res->end)
+			return -1;	/* not completely contained */
+		if (firstpp == NULL)
+			firstpp = pp;
+	}
+	if (firstpp == NULL)
+		return -1;	/* didn't find any conflicting entries? */
+	res->parent = parent;
+	res->child = *firstpp;
+	res->sibling = *pp;
+	*firstpp = res;
+	*pp = NULL;
+	for (p = res->child; p != NULL; p = p->sibling) {
+		p->parent = res;
+		DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
+		    p->name,
+		    (unsigned long long)p->start,
+		    (unsigned long long)p->end, res->name);
+	}
+	return 0;
+}
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *	- I/O or memory regions not configured
+ *	- regions configured, but not enabled in the command register
+ *	- bogus I/O addresses above 64K used
+ *	- expansion ROMs left enabled (this may sound harmless, but given
+ *	  the fact the PCI specs explicitly allow address decoders to be
+ *	  shared between expansion ROMs and other resource regions, it's
+ *	  at least dangerous)
+ *
+ *  Our solution:
+ *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *	    This gives us fixed barriers on where we can allocate.
+ *	(2) Allocate resources for all enabled devices.  If there is
+ *	    a collision, just mark the resource as unallocated. Also
+ *	    disable expansion ROMs during this step.
+ *	(3) Try to allocate resources for disabled devices.  If the
+ *	    resources were assigned correctly, everything goes well,
+ *	    if they weren't, they won't disturb allocation of other
+ *	    resources.
+ *	(4) Assign new addresses to resources which were either
+ *	    not configured at all or misconfigured.  If explicitly
+ *	    requested by the user, configure expansion ROM address
+ *	    as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct pci_bus *bus;
+	int i;
+	struct resource *res, *pr;
+
+	/* Depth-First Search on bus tree */
+	list_for_each_entry(bus, bus_list, node) {
+		for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+			if ((res = bus->resource[i]) == NULL || !res->flags
+			    || res->start > res->end)
+				continue;
+			if (bus->parent == NULL)
+				pr = (res->flags & IORESOURCE_IO) ?
+					&ioport_resource : &iomem_resource;
+			else {
+				/* Don't bother with non-root busses when
+				 * re-assigning all resources. We clear the
+				 * resource flags as if they were colliding
+				 * and as such ensure proper re-allocation
+				 * later.
+				 */
+				if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+					goto clear_resource;
+				pr = pci_find_parent_resource(bus->self, res);
+				if (pr == res) {
+					/* this happens when the generic PCI
+					 * code (wrongly) decides that this
+					 * bridge is transparent  -- paulus
+					 */
+					continue;
+				}
+			}
+
+			DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
+			    "[0x%x], parent %p (%s)\n",
+			    bus->self ? pci_name(bus->self) : "PHB",
+			    bus->number, i,
+			    (unsigned long long)res->start,
+			    (unsigned long long)res->end,
+			    (unsigned int)res->flags,
+			    pr, (pr && pr->name) ? pr->name : "nil");
+
+			if (pr && !(pr->flags & IORESOURCE_UNSET)) {
+				if (request_resource(pr, res) == 0)
+					continue;
+				/*
+				 * Must be a conflict with an existing entry.
+				 * Move that entry (or entries) under the
+				 * bridge resource and try again.
+				 */
+				if (reparent_resources(pr, res) == 0)
+					continue;
+			}
+			printk(KERN_WARNING
+			       "PCI: Cannot allocate resource region "
+			       "%d of PCI bridge %d, will remap\n",
+			       i, bus->number);
+clear_resource:
+			res->flags = 0;
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static inline int __devinit alloc_resource(struct pci_dev *dev, int idx)
+{
+	struct resource *pr, *r = &dev->resource[idx];
+
+	DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
+	    pci_name(dev), idx,
+	    (unsigned long long)r->start,
+	    (unsigned long long)r->end,
+	    (unsigned int)r->flags);
+
+	pr = pci_find_parent_resource(dev, r);
+	if (!pr || (pr->flags & IORESOURCE_UNSET) ||
+	    request_resource(pr, r) < 0) {
+		printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
+		       " of device %s, will remap\n", idx, pci_name(dev));
+		if (pr)
+			DBG("PCI:  parent is %p: %016llx-%016llx [%x]\n", pr,
+			    (unsigned long long)pr->start,
+			    (unsigned long long)pr->end,
+			    (unsigned int)pr->flags);
+		/* We'll assign a new address later */
+		r->flags |= IORESOURCE_UNSET;
+		r->end -= r->start;
+		r->start = 0;
+
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+	int idx, disabled;
+	u16 command;
+	struct resource *r;
+
+	for_each_pci_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for (idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->flags || (r->flags & IORESOURCE_UNSET))
+				continue;	/* Not assigned at all */
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled && alloc_resource(dev, idx)) {
+				command &= ~(r->flags & (IORESOURCE_IO |
+							 IORESOURCE_MEM));
+				pci_write_config_word(dev,
+						      PCI_COMMAND, command);
+			}
+		}
+		if (pass)
+			continue;
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		if (r->flags & IORESOURCE_ROM_ENABLE) {
+			/* Turn the ROM off, leave the resource region,
+			 * but keep it unregistered.
+			 */
+			u32 reg;
+			DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+			r->flags &= ~IORESOURCE_ROM_ENABLE;
+			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+			pci_write_config_dword(dev, dev->rom_base_reg,
+					       reg & ~PCI_ROM_ADDRESS_ENABLE);
+		}
+	}
+}
+
+void __init pcibios_resource_survey(void)
+{
+	/* Allocate and assign resources. If we re-assign everything, then
+	 * we skip the allocate phase
+	 */
+	pcibios_allocate_bus_resources(&pci_root_buses);
+
+	if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+		pcibios_allocate_resources(0);
+		pcibios_allocate_resources(1);
+	}
+
+	if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+		DBG("PCI: Assigning unassigned resouces...\n");
+		pci_assign_unassigned_resources();
+	}
+
+	/* Call machine dependent fixup */
+	if (ppc_md.pcibios_fixup)
+		ppc_md.pcibios_fixup();
+}
+
+#ifdef CONFIG_HOTPLUG
+/* This is used by the pSeries hotplug driver to allocate resource
+ * of newly plugged busses. We can try to consolidate with the
+ * rest of the code later, for now, keep it as-is
+ */
+void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child_bus;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &bus->children, node)
+		pcibios_claim_one_bus(child_bus);
+}
+EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+#endif /* CONFIG_HOTPLUG */
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	if (ppc_md.pcibios_enable_device_hook)
+		if (ppc_md.pcibios_enable_device_hook(dev))
+			return -EINVAL;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+		r = &dev->resource[idx];
+		if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+		if ((idx == PCI_ROM_RESOURCE) &&
+				(!(r->flags & IORESOURCE_ROM_ENABLE)))
+			continue;
+		if (r->parent == NULL) {
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 0e2bee4..a9c6cb2 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -32,19 +32,12 @@
 #endif
 
 unsigned long isa_io_base     = 0;
-unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
-static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
-static int probe_resource(struct pci_bus *parent, struct resource *pr,
-			  struct resource *res, struct resource **conflict);
-static void update_bridge_base(struct pci_bus *bus, int i);
-static void pcibios_fixup_resources(struct pci_dev* dev);
 static void fixup_broken_pcnet32(struct pci_dev* dev);
-static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
@@ -53,7 +46,7 @@
 /* By default, we don't re-assign bus numbers. We do this only on
  * some pmacs
  */
-int pci_assign_all_buses;
+static int pci_assign_all_buses;
 
 LIST_HEAD(hose_list);
 
@@ -100,338 +93,6 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64);
 
-static void
-pcibios_fixup_resources(struct pci_dev *dev)
-{
-	struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
-	int i;
-	unsigned long offset;
-
-	if (!hose) {
-		printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
-		return;
-	}
-	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-		struct resource *res = dev->resource + i;
-		if (!res->flags)
-			continue;
-		if (res->end == 0xffffffff) {
-			DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
-			    pci_name(dev), i, (u64)res->start, (u64)res->end);
-			res->end -= res->start;
-			res->start = 0;
-			res->flags |= IORESOURCE_UNSET;
-			continue;
-		}
-		offset = 0;
-		if (res->flags & IORESOURCE_MEM) {
-			offset = hose->pci_mem_offset;
-		} else if (res->flags & IORESOURCE_IO) {
-			offset = (unsigned long) hose->io_base_virt
-				- isa_io_base;
-		}
-		if (offset != 0) {
-			res->start += offset;
-			res->end += offset;
-			DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
-			    i, res->flags, pci_name(dev),
-			    (u64)res->start - offset, (u64)res->start);
-		}
-	}
-
-	/* Call machine specific resource fixup */
-	if (ppc_md.pcibios_fixup_resources)
-		ppc_md.pcibios_fixup_resources(dev);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources);
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			struct resource *res)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = dev->sysdata;
-
-	if (hose && res->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - isa_io_base;
-	else if (hose && res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-	region->start = res->start - offset;
-	region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			     struct pci_bus_region *region)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = dev->sysdata;
-
-	if (hose && res->flags & IORESOURCE_IO)
-		offset = (unsigned long)hose->io_base_virt - isa_io_base;
-	else if (hose && res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-	res->start = region->start + offset;
-	res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-				resource_size_t size, resource_size_t align)
-{
-	struct pci_dev *dev = data;
-
-	if (res->flags & IORESOURCE_IO) {
-		resource_size_t start = res->start;
-
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-			       " (%lld bytes)\n", pci_name(dev),
-			       dev->resource - res, (unsigned long long)size);
-		}
-
-		if (start & 0x300) {
-			start = (start + 0x3ff) & ~0x3ff;
-			res->start = start;
-		}
-	}
-}
-EXPORT_SYMBOL(pcibios_align_resource);
-
-/*
- *  Handle resources of PCI devices.  If the world were perfect, we could
- *  just allocate all the resource regions and do nothing more.  It isn't.
- *  On the other hand, we cannot just re-allocate all devices, as it would
- *  require us to know lots of host bridge internals.  So we attempt to
- *  keep as much of the original configuration as possible, but tweak it
- *  when it's found to be wrong.
- *
- *  Known BIOS problems we have to work around:
- *	- I/O or memory regions not configured
- *	- regions configured, but not enabled in the command register
- *	- bogus I/O addresses above 64K used
- *	- expansion ROMs left enabled (this may sound harmless, but given
- *	  the fact the PCI specs explicitly allow address decoders to be
- *	  shared between expansion ROMs and other resource regions, it's
- *	  at least dangerous)
- *
- *  Our solution:
- *	(1) Allocate resources for all buses behind PCI-to-PCI bridges.
- *	    This gives us fixed barriers on where we can allocate.
- *	(2) Allocate resources for all enabled devices.  If there is
- *	    a collision, just mark the resource as unallocated. Also
- *	    disable expansion ROMs during this step.
- *	(3) Try to allocate resources for disabled devices.  If the
- *	    resources were assigned correctly, everything goes well,
- *	    if they weren't, they won't disturb allocation of other
- *	    resources.
- *	(4) Assign new addresses to resources which were either
- *	    not configured at all or misconfigured.  If explicitly
- *	    requested by the user, configure expansion ROM address
- *	    as well.
- */
-
-static void __init
-pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
-	struct pci_bus *bus;
-	int i;
-	struct resource *res, *pr;
-
-	/* Depth-First Search on bus tree */
-	list_for_each_entry(bus, bus_list, node) {
-		for (i = 0; i < 4; ++i) {
-			if ((res = bus->resource[i]) == NULL || !res->flags
-			    || res->start > res->end)
-				continue;
-			if (bus->parent == NULL)
-				pr = (res->flags & IORESOURCE_IO)?
-					&ioport_resource: &iomem_resource;
-			else {
-				pr = pci_find_parent_resource(bus->self, res);
-				if (pr == res) {
-					/* this happens when the generic PCI
-					 * code (wrongly) decides that this
-					 * bridge is transparent  -- paulus
-					 */
-					continue;
-				}
-			}
-
-			DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
-			    (u64)res->start, (u64)res->end, res->flags, pr);
-			if (pr) {
-				if (request_resource(pr, res) == 0)
-					continue;
-				/*
-				 * Must be a conflict with an existing entry.
-				 * Move that entry (or entries) under the
-				 * bridge resource and try again.
-				 */
-				if (reparent_resources(pr, res) == 0)
-					continue;
-			}
-			printk(KERN_ERR "PCI: Cannot allocate resource region "
-			       "%d of PCI bridge %d\n", i, bus->number);
-			if (pci_relocate_bridge_resource(bus, i))
-				bus->resource[i] = NULL;
-		}
-		pcibios_allocate_bus_resources(&bus->children);
-	}
-}
-
-/*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init
-reparent_resources(struct resource *parent, struct resource *res)
-{
-	struct resource *p, **pp;
-	struct resource **firstpp = NULL;
-
-	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
-		if (p->end < res->start)
-			continue;
-		if (res->end < p->start)
-			break;
-		if (p->start < res->start || p->end > res->end)
-			return -1;	/* not completely contained */
-		if (firstpp == NULL)
-			firstpp = pp;
-	}
-	if (firstpp == NULL)
-		return -1;	/* didn't find any conflicting entries? */
-	res->parent = parent;
-	res->child = *firstpp;
-	res->sibling = *pp;
-	*firstpp = res;
-	*pp = NULL;
-	for (p = res->child; p != NULL; p = p->sibling) {
-		p->parent = res;
-		DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
-		    p->name, (u64)p->start, (u64)p->end, res->name);
-	}
-	return 0;
-}
-
-/*
- * A bridge has been allocated a range which is outside the range
- * of its parent bridge, so it needs to be moved.
- */
-static int __init
-pci_relocate_bridge_resource(struct pci_bus *bus, int i)
-{
-	struct resource *res, *pr, *conflict;
-	unsigned long try, size;
-	int j;
-	struct pci_bus *parent = bus->parent;
-
-	if (parent == NULL) {
-		/* shouldn't ever happen */
-		printk(KERN_ERR "PCI: can't move host bridge resource\n");
-		return -1;
-	}
-	res = bus->resource[i];
-	if (res == NULL)
-		return -1;
-	pr = NULL;
-	for (j = 0; j < 4; j++) {
-		struct resource *r = parent->resource[j];
-		if (!r)
-			continue;
-		if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
-			continue;
-		if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
-			pr = r;
-			break;
-		}
-		if (res->flags & IORESOURCE_PREFETCH)
-			pr = r;
-	}
-	if (pr == NULL)
-		return -1;
-	size = res->end - res->start;
-	if (pr->start > pr->end || size > pr->end - pr->start)
-		return -1;
-	try = pr->end;
-	for (;;) {
-		res->start = try - size;
-		res->end = try;
-		if (probe_resource(bus->parent, pr, res, &conflict) == 0)
-			break;
-		if (conflict->start <= pr->start + size)
-			return -1;
-		try = conflict->start - 1;
-	}
-	if (request_resource(pr, res)) {
-		DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
-		    (u64)res->start, (u64)res->end);
-		return -1;		/* "can't happen" */
-	}
-	update_bridge_base(bus, i);
-	printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
-	       bus->number, i, (unsigned long long)res->start,
-	       (unsigned long long)res->end);
-	return 0;
-}
-
-static int __init
-probe_resource(struct pci_bus *parent, struct resource *pr,
-	       struct resource *res, struct resource **conflict)
-{
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-	struct resource *r;
-	int i;
-
-	for (r = pr->child; r != NULL; r = r->sibling) {
-		if (r->end >= res->start && res->end >= r->start) {
-			*conflict = r;
-			return 1;
-		}
-	}
-	list_for_each_entry(bus, &parent->children, node) {
-		for (i = 0; i < 4; ++i) {
-			if ((r = bus->resource[i]) == NULL)
-				continue;
-			if (!r->flags || r->start > r->end || r == res)
-				continue;
-			if (pci_find_parent_resource(bus->self, r) != pr)
-				continue;
-			if (r->end >= res->start && res->end >= r->start) {
-				*conflict = r;
-				return 1;
-			}
-		}
-	}
-	list_for_each_entry(dev, &parent->devices, bus_list) {
-		for (i = 0; i < 6; ++i) {
-			r = &dev->resource[i];
-			if (!r->flags || (r->flags & IORESOURCE_UNSET))
-				continue;
-			if (pci_find_parent_resource(dev, r) != pr)
-				continue;
-			if (r->end >= res->start && res->end >= r->start) {
-				*conflict = r;
-				return 1;
-			}
-		}
-	}
-	return 0;
-}
 
 void __init
 update_bridge_resource(struct pci_dev *dev, struct resource *res)
@@ -439,7 +100,7 @@
 	u8 io_base_lo, io_limit_lo;
 	u16 mem_base, mem_limit;
 	u16 cmd;
-	unsigned long start, end, off;
+	resource_size_t start, end, off;
 	struct pci_controller *hose = dev->sysdata;
 
 	if (!hose) {
@@ -489,115 +150,6 @@
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
-static void __init
-update_bridge_base(struct pci_bus *bus, int i)
-{
-	struct resource *res = bus->resource[i];
-	struct pci_dev *dev = bus->self;
-	update_bridge_resource(dev, res);
-}
-
-static inline void alloc_resource(struct pci_dev *dev, int idx)
-{
-	struct resource *pr, *r = &dev->resource[idx];
-
-	DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
-	    pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
-	pr = pci_find_parent_resource(dev, r);
-	if (!pr || request_resource(pr, r) < 0) {
-		printk(KERN_ERR "PCI: Cannot allocate resource region %d"
-		       " of device %s\n", idx, pci_name(dev));
-		if (pr)
-			DBG("PCI:  parent is %p: %016llx-%016llx (f=%lx)\n",
-			    pr, (u64)pr->start, (u64)pr->end, pr->flags);
-		/* We'll assign a new address later */
-		r->flags |= IORESOURCE_UNSET;
-		r->end -= r->start;
-		r->start = 0;
-	}
-}
-
-static void __init
-pcibios_allocate_resources(int pass)
-{
-	struct pci_dev *dev = NULL;
-	int idx, disabled;
-	u16 command;
-	struct resource *r;
-
-	for_each_pci_dev(dev) {
-		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for (idx = 0; idx < 6; idx++) {
-			r = &dev->resource[idx];
-			if (r->parent)		/* Already allocated */
-				continue;
-			if (!r->flags || (r->flags & IORESOURCE_UNSET))
-				continue;	/* Not assigned at all */
-			if (r->flags & IORESOURCE_IO)
-				disabled = !(command & PCI_COMMAND_IO);
-			else
-				disabled = !(command & PCI_COMMAND_MEMORY);
-			if (pass == disabled)
-				alloc_resource(dev, idx);
-		}
-		if (pass)
-			continue;
-		r = &dev->resource[PCI_ROM_RESOURCE];
-		if (r->flags & IORESOURCE_ROM_ENABLE) {
-			/* Turn the ROM off, leave the resource region, but keep it unregistered. */
-			u32 reg;
-			DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
-			r->flags &= ~IORESOURCE_ROM_ENABLE;
-			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-			pci_write_config_dword(dev, dev->rom_base_reg,
-					       reg & ~PCI_ROM_ADDRESS_ENABLE);
-		}
-	}
-}
-
-static void __init
-pcibios_assign_resources(void)
-{
-	struct pci_dev *dev = NULL;
-	int idx;
-	struct resource *r;
-
-	for_each_pci_dev(dev) {
-		int class = dev->class >> 8;
-
-		/* Don't touch classless devices and host bridges */
-		if (!class || class == PCI_CLASS_BRIDGE_HOST)
-			continue;
-
-		for (idx = 0; idx < 6; idx++) {
-			r = &dev->resource[idx];
-
-			/*
-			 * We shall assign a new address to this resource,
-			 * either because the BIOS (sic) forgot to do so
-			 * or because we have decided the old address was
-			 * unusable for some reason.
-			 */
-			if ((r->flags & IORESOURCE_UNSET) && r->end &&
-			    (!ppc_md.pcibios_enable_device_hook ||
-			     !ppc_md.pcibios_enable_device_hook(dev, 1))) {
-				int rc;
-
-				r->flags &= ~IORESOURCE_UNSET;
-				rc = pci_assign_resource(dev, idx);
-				BUG_ON(rc);
-			}
-		}
-
-#if 0 /* don't assign ROMs */
-		r = &dev->resource[PCI_ROM_RESOURCE];
-		r->end -= r->start;
-		r->start = 0;
-		if (r->end)
-			pci_assign_resource(dev, PCI_ROM_RESOURCE);
-#endif
-	}
-}
 
 #ifdef CONFIG_PPC_OF
 /*
@@ -662,8 +214,8 @@
 
 	/* For each hose, we begin searching bridges */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		struct device_node* node;	
-		node = (struct device_node *)hose->arch_data;
+		struct device_node* node = hose->dn;
+
 		if (!node)
 			continue;
 		make_one_node_map(node, hose->first_busno);
@@ -742,7 +294,7 @@
 		struct pci_controller *hose = pci_bus_to_host(bus);
 		if (hose == NULL)
 			return NULL;
-		return of_node_get(hose->arch_data);
+		return of_node_get(hose->dn);
 	}
 
 	/* not a root bus, we need to get our parent */
@@ -812,9 +364,9 @@
 		return -ENODEV;
 	/* Make sure it's really a PCI device */
 	hose = pci_find_hose_for_OF_device(node);
-	if (!hose || !hose->arch_data)
+	if (!hose || !hose->dn)
 		return -ENODEV;
-	if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
+	if (!scan_OF_pci_childs(hose->dn->child,
 			find_OF_pci_device_filter, (void *)node))
 		return -ENODEV;
 	reg = of_get_property(node, "reg", NULL);
@@ -843,120 +395,6 @@
 }
 EXPORT_SYMBOL(pci_device_from_OF_node);
 
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
-			   struct device_node *dev, int primary)
-{
-	static unsigned int static_lc_ranges[256] __initdata;
-	const unsigned int *dt_ranges;
-	unsigned int *lc_ranges, *ranges, *prev, size;
-	int rlen = 0, orig_rlen;
-	int memno = 0;
-	struct resource *res;
-	int np, na = of_n_addr_cells(dev);
-	np = na + 5;
-
-	/* First we try to merge ranges to fix a problem with some pmacs
-	 * that can have more than 3 ranges, fortunately using contiguous
-	 * addresses -- BenH
-	 */
-	dt_ranges = of_get_property(dev, "ranges", &rlen);
-	if (!dt_ranges)
-		return;
-	/* Sanity check, though hopefully that never happens */
-	if (rlen > sizeof(static_lc_ranges)) {
-		printk(KERN_WARNING "OF ranges property too large !\n");
-		rlen = sizeof(static_lc_ranges);
-	}
-	lc_ranges = static_lc_ranges;
-	memcpy(lc_ranges, dt_ranges, rlen);
-	orig_rlen = rlen;
-
-	/* Let's work on a copy of the "ranges" property instead of damaging
-	 * the device-tree image in memory
-	 */
-	ranges = lc_ranges;
-	prev = NULL;
-	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-		if (prev) {
-			if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
-				(prev[2] + prev[na+4]) == ranges[2] &&
-				(prev[na+2] + prev[na+4]) == ranges[na+2]) {
-				prev[na+4] += ranges[na+4];
-				ranges[0] = 0;
-				ranges += np;
-				continue;
-			}
-		}
-		prev = ranges;
-		ranges += np;
-	}
-
-	/*
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 2:	a PCI address
-	 *   cells 3 or 3+4:	a CPU physical address
-	 *			(size depending on dev->n_addr_cells)
-	 *   cells 4+5 or 5+6:	the size of the range
-	 */
-	ranges = lc_ranges;
-	rlen = orig_rlen;
-	while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		size = ranges[na+4];
-		switch ((ranges[0] >> 24) & 0x3) {
-		case 1:		/* I/O space */
-			if (ranges[2] != 0)
-				break;
-			hose->io_base_phys = ranges[na+2];
-			/* limit I/O space to 16MB */
-			if (size > 0x01000000)
-				size = 0x01000000;
-			hose->io_base_virt = ioremap(ranges[na+2], size);
-			if (primary)
-				isa_io_base = (unsigned long) hose->io_base_virt;
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = ranges[2];
-			DBG("PCI: IO 0x%llx -> 0x%llx\n",
-			    (u64)res->start, (u64)res->start + size - 1);
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			if (ranges[1] == 0 && ranges[2] == 0
-			    && ranges[na+4] <= (16 << 20)) {
-				/* 1st 16MB, i.e. ISA memory area */
-				if (primary)
-					isa_mem_base = ranges[na+2];
-				memno = 1;
-			}
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-			if (memno == 0)
-				hose->pci_mem_offset = ranges[na+2] - ranges[2];
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				if(ranges[0] & 0x40000000)
-					res->flags |= IORESOURCE_PREFETCH;
-				res->start = ranges[na+2];
-				DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
-				    (u64)res->start, (u64)res->start + size - 1);
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += np;
-	}
-}
-
 /* We create the "pci-OF-bus-map" property now so it appears in the
  * /proc device tree
  */
@@ -986,219 +424,7 @@
 }
 #endif /* CONFIG_PPC_OF */
 
-#ifdef CONFIG_PPC_PMAC
-/*
- * This set of routines checks for PCI<->PCI bridges that have closed
- * IO resources and have child devices. It tries to re-open an IO
- * window on them.
- *
- * This is a _temporary_ fix to workaround a problem with Apple's OF
- * closing IO windows on P2P bridges when the OF drivers of cards
- * below this bridge don't claim any IO range (typically ATI or
- * Adaptec).
- *
- * A more complete fix would be to use drivers/pci/setup-bus.c, which
- * involves a working pcibios_fixup_pbus_ranges(), some more care about
- * ordering when creating the host bus resources, and maybe a few more
- * minor tweaks
- */
-
-/* Initialize bridges with base/limit values we have collected */
-static void __init
-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
-{
-	struct pci_dev *bridge = bus->self;
-	struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
-	u32 l;
-	u16 w;
-	struct resource res;
-
-	if (bus->resource[0] == NULL)
-		return;
- 	res = *(bus->resource[0]);
-
-	DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
-	res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
-	res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
-	DBG("  IO window: %016llx-%016llx\n", res.start, res.end);
-
-	/* Set up the top and bottom of the PCI I/O segment for this bus. */
-	pci_read_config_dword(bridge, PCI_IO_BASE, &l);
-	l &= 0xffff000f;
-	l |= (res.start >> 8) & 0x00f0;
-	l |= res.end & 0xf000;
-	pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
-	if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
-		l = (res.start >> 16) | (res.end & 0xffff0000);
-		pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
-	}
-
-	pci_read_config_word(bridge, PCI_COMMAND, &w);
-	w |= PCI_COMMAND_IO;
-	pci_write_config_word(bridge, PCI_COMMAND, w);
-
-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
-	if (enable_vga) {
-		pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
-		w |= PCI_BRIDGE_CTL_VGA;
-		pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
-	}
-#endif
-}
-
-/* This function is pretty basic and actually quite broken for the
- * general case, it's enough for us right now though. It's supposed
- * to tell us if we need to open an IO range at all or not and what
- * size.
- */
-static int __init
-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
-{
-	struct pci_dev *dev;
-	int	i;
-	int	rc = 0;
-
-#define push_end(res, mask) do {		\
-	BUG_ON((mask+1) & mask);		\
-	res->end = (res->end + mask) | mask;	\
-} while (0)
-
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		u16 class = dev->class >> 8;
-
-		if (class == PCI_CLASS_DISPLAY_VGA ||
-		    class == PCI_CLASS_NOT_DEFINED_VGA)
-			*found_vga = 1;
-		if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
-			rc |= check_for_io_childs(dev->subordinate, res, found_vga);
-		if (class == PCI_CLASS_BRIDGE_CARDBUS)
-			push_end(res, 0xfff);
-
-		for (i=0; i<PCI_NUM_RESOURCES; i++) {
-			struct resource *r;
-			unsigned long r_size;
-
-			if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
-			    && i >= PCI_BRIDGE_RESOURCES)
-				continue;
-			r = &dev->resource[i];
-			r_size = r->end - r->start;
-			if (r_size < 0xfff)
-				r_size = 0xfff;
-			if (r->flags & IORESOURCE_IO && (r_size) != 0) {
-				rc = 1;
-				push_end(res, r_size);
-			}
-		}
-	}
-
-	return rc;
-}
-
-/* Here we scan all P2P bridges of a given level that have a closed
- * IO window. Note that the test for the presence of a VGA card should
- * be improved to take into account already configured P2P bridges,
- * currently, we don't see them and might end up configuring 2 bridges
- * with VGA pass through enabled
- */
-static void __init
-do_fixup_p2p_level(struct pci_bus *bus)
-{
-	struct pci_bus *b;
-	int i, parent_io;
-	int has_vga = 0;
-
-	for (parent_io=0; parent_io<4; parent_io++)
-		if (bus->resource[parent_io]
-		    && bus->resource[parent_io]->flags & IORESOURCE_IO)
-			break;
-	if (parent_io >= 4)
-		return;
-
-	list_for_each_entry(b, &bus->children, node) {
-		struct pci_dev *d = b->self;
-		struct pci_controller* hose = (struct pci_controller *)d->sysdata;
-		struct resource *res = b->resource[0];
-		struct resource tmp_res;
-		unsigned long max;
-		int found_vga = 0;
-
-		memset(&tmp_res, 0, sizeof(tmp_res));
-		tmp_res.start = bus->resource[parent_io]->start;
-
-		/* We don't let low addresses go through that closed P2P bridge, well,
-		 * that may not be necessary but I feel safer that way
-		 */
-		if (tmp_res.start == 0)
-			tmp_res.start = 0x1000;
-	
-		if (!list_empty(&b->devices) && res && res->flags == 0 &&
-		    res != bus->resource[parent_io] &&
-		    (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
-		    check_for_io_childs(b, &tmp_res, &found_vga)) {
-			u8 io_base_lo;
-
-			printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
-
-			if (found_vga) {
-				if (has_vga) {
-					printk(KERN_WARNING "Skipping VGA, already active"
-					    " on bus segment\n");
-					found_vga = 0;
-				} else
-					has_vga = 1;
-			}
-			pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
-
-			if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
-				max = ((unsigned long) hose->io_base_virt
-					- isa_io_base) + 0xffffffff;
-			else
-				max = ((unsigned long) hose->io_base_virt
-					- isa_io_base) + 0xffff;
-
-			*res = tmp_res;
-			res->flags = IORESOURCE_IO;
-			res->name = b->name;
-		
-			/* Find a resource in the parent where we can allocate */
-			for (i = 0 ; i < 4; i++) {
-				struct resource *r = bus->resource[i];
-				if (!r)
-					continue;
-				if ((r->flags & IORESOURCE_IO) == 0)
-					continue;
-				DBG("Trying to allocate from %016llx, size %016llx from parent"
-				    " res %d: %016llx -> %016llx\n",
-					res->start, res->end, i, r->start, r->end);
-			
-				if (allocate_resource(r, res, res->end + 1, res->start, max,
-				    res->end + 1, NULL, NULL) < 0) {
-					DBG("Failed !\n");
-					continue;
-				}
-				do_update_p2p_io_resource(b, found_vga);
-				break;
-			}
-		}
-		do_fixup_p2p_level(b);
-	}
-}
-
-static void
-pcibios_fixup_p2p_bridges(void)
-{
-	struct pci_bus *b;
-
-	list_for_each_entry(b, &pci_root_buses, node)
-		do_fixup_p2p_level(b);
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
-static int __init
-pcibios_init(void)
+static int __init pcibios_init(void)
 {
 	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
@@ -1206,6 +432,9 @@
 
 	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
+	if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+		pci_assign_all_buses = 1;
+
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		if (pci_assign_all_buses)
@@ -1213,9 +442,10 @@
 		hose->last_busno = 0xff;
 		bus = pci_scan_bus_parented(hose->parent, hose->first_busno,
 					    hose->ops, hose);
-		if (bus)
+		if (bus) {
 			pci_bus_add_devices(bus);
-		hose->last_busno = bus->subordinate;
+			hose->last_busno = bus->subordinate;
+		}
 		if (pci_assign_all_buses || next_busno <= hose->last_busno)
 			next_busno = hose->last_busno + pcibios_assign_bus_offset;
 	}
@@ -1228,18 +458,8 @@
 	if (pci_assign_all_buses && have_of)
 		pcibios_make_OF_bus_map();
 
-	/* Call machine dependent fixup */
-	if (ppc_md.pcibios_fixup)
-		ppc_md.pcibios_fixup();
-
-	/* Allocate and assign resources */
-	pcibios_allocate_bus_resources(&pci_root_buses);
-	pcibios_allocate_resources(0);
-	pcibios_allocate_resources(1);
-#ifdef CONFIG_PPC_PMAC
-	pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_PPC_PMAC */
-	pcibios_assign_resources();
+	/* Call common code to handle resource allocation */
+	pcibios_resource_survey();
 
 	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)
@@ -1250,14 +470,14 @@
 
 subsys_initcall(pcibios_init);
 
-void pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
 	unsigned long io_offset;
 	struct resource *res;
-	struct pci_dev *dev;
 	int i;
 
+	/* Hookup PHB resources */
 	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
 	if (bus->parent == NULL) {
 		/* This is a host bridge - fill in its resources */
@@ -1272,8 +492,8 @@
 			res->end = IO_SPACE_LIMIT;
 			res->flags = IORESOURCE_IO;
 		}
-		res->start += io_offset;
-		res->end += io_offset;
+		res->start = (res->start + io_offset) & 0xffffffffu;
+		res->end = (res->end + io_offset) & 0xffffffffu;
 
 		for (i = 0; i < 3; ++i) {
 			res = &hose->mem_resources[i];
@@ -1288,35 +508,6 @@
 			}
 			bus->resource[i+1] = res;
 		}
-	} else {
-		/* This is a subordinate bridge */
-		pci_read_bridge_bases(bus);
-
-		for (i = 0; i < 4; ++i) {
-			if ((res = bus->resource[i]) == NULL)
-				continue;
-			if (!res->flags || bus->self->transparent)
-				continue;
-			if (io_offset && (res->flags & IORESOURCE_IO)) {
-				res->start += io_offset;
-				res->end += io_offset;
-			} else if (hose->pci_mem_offset
-				   && (res->flags & IORESOURCE_MEM)) {
-				res->start += hose->pci_mem_offset;
-				res->end += hose->pci_mem_offset;
-			}
-		}
-	}
-
-	/* Platform specific bus fixups */
-	if (ppc_md.pcibios_fixup_bus)
-		ppc_md.pcibios_fixup_bus(bus);
-
-	/* Read default IRQs and fixup if necessary */
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_read_irq_line(dev);
-		if (ppc_md.pci_irq_fixup)
-			ppc_md.pci_irq_fixup(dev);
 	}
 }
 
@@ -1328,37 +519,6 @@
 	/* XXX FIXME - update OF device tree node interrupt property */
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	if (ppc_md.pcibios_enable_device_hook)
-		if (ppc_md.pcibios_enable_device_hook(dev, 0))
-			return -EINVAL;
-		
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx=0; idx<6; idx++) {
-		r = &dev->resource[idx];
-		if (r->flags & IORESOURCE_UNSET) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
 static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
@@ -1381,17 +541,6 @@
 	struct pci_controller* hose;
 	long result = -EOPNOTSUPP;
 
-	/* Argh ! Please forgive me for that hack, but that's the
-	 * simplest way to get existing XFree to not lockup on some
-	 * G5 machines... So when something asks for bus 0 io base
-	 * (bus 0 is HT root), we return the AGP one instead.
-	 */
-#ifdef CONFIG_PPC_PMAC
-	if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
-		if (bus == 0)
-			bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
 	hose = pci_bus_to_hose(bus);
 	if (!hose)
 		return -ENODEV;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 9f63bdc..5949bba 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -31,7 +31,6 @@
 #include <asm/byteorder.h>
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
-#include <asm/firmware.h>
 
 #ifdef DEBUG
 #include <asm/udbg.h>
@@ -41,10 +40,6 @@
 #endif
 
 unsigned long pci_probe_only = 1;
-int pci_assign_all_buses = 0;
-
-static void fixup_resource(struct resource *res, struct pci_dev *dev);
-static void do_bus_setup(struct pci_bus *bus);
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
@@ -70,6 +65,22 @@
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
+
+int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	return dma_set_mask(&dev->dev, mask);
+}
+
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	int rc;
+
+	rc = dma_set_mask(&dev->dev, mask);
+	dev->dev.coherent_dma_mask = dev->dma_mask;
+
+	return rc;
+}
+
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
 	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -79,130 +90,6 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
-void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			      struct resource *res)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-	if (!hose)
-		return;
-
-	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	if (res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-
-	region->start = res->start - offset;
-	region->end = res->end - offset;
-}
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			      struct pci_bus_region *region)
-{
-	unsigned long offset = 0;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-	if (!hose)
-		return;
-
-	if (res->flags & IORESOURCE_IO)
-	        offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-	if (res->flags & IORESOURCE_MEM)
-		offset = hose->pci_mem_offset;
-
-	res->start = region->start + offset;
-	res->end = region->end + offset;
-}
-
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-			    resource_size_t size, resource_size_t align)
-{
-	struct pci_dev *dev = data;
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	resource_size_t start = res->start;
-	unsigned long alignto;
-
-	if (res->flags & IORESOURCE_IO) {
-	        unsigned long offset = (unsigned long)hose->io_base_virt -
-					_IO_BASE;
-		/* Make sure we start at our min on all hoses */
-		if (start - offset < PCIBIOS_MIN_IO)
-			start = PCIBIOS_MIN_IO + offset;
-
-		/*
-		 * Put everything into 0x00-0xff region modulo 0x400
-		 */
-		if (start & 0x300)
-			start = (start + 0x3ff) & ~0x3ff;
-
-	} else if (res->flags & IORESOURCE_MEM) {
-		/* Make sure we start at our min on all hoses */
-		if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM)
-			start = PCIBIOS_MIN_MEM + hose->pci_mem_offset;
-
-		/* Align to multiple of size of minimum base.  */
-		alignto = max(0x1000UL, align);
-		start = ALIGN(start, alignto);
-	}
-
-	res->start = start;
-}
-
-void __devinit pcibios_claim_one_bus(struct pci_bus *b)
-{
-	struct pci_dev *dev;
-	struct pci_bus *child_bus;
-
-	list_for_each_entry(dev, &b->devices, bus_list) {
-		int i;
-
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			struct resource *r = &dev->resource[i];
-
-			if (r->parent || !r->start || !r->flags)
-				continue;
-			pci_claim_resource(dev, i);
-		}
-	}
-
-	list_for_each_entry(child_bus, &b->children, node)
-		pcibios_claim_one_bus(child_bus);
-}
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
-#endif
-
-static void __init pcibios_claim_of_setup(void)
-{
-	struct pci_bus *b;
-
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return;
-
-	list_for_each_entry(b, &pci_root_buses, node)
-		pcibios_claim_one_bus(b);
-}
 
 static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
 {
@@ -270,7 +157,6 @@
 		res->end = base + size - 1;
 		res->flags = flags;
 		res->name = pci_name(dev);
-		fixup_resource(res, dev);
 	}
 }
 
@@ -339,7 +225,7 @@
 EXPORT_SYMBOL(of_create_pci_dev);
 
 void __devinit of_scan_bus(struct device_node *node,
-				  struct pci_bus *bus)
+			   struct pci_bus *bus)
 {
 	struct device_node *child = NULL;
 	const u32 *reg;
@@ -348,6 +234,7 @@
 
 	DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
 
+	/* Scan direct children */
 	while ((child = of_get_next_child(node, child)) != NULL) {
 		DBG("  * %s\n", child->full_name);
 		reg = of_get_property(child, "reg", &reglen);
@@ -359,19 +246,26 @@
 		dev = of_create_pci_dev(child, bus, devfn);
 		if (!dev)
 			continue;
-		DBG("dev header type: %x\n", dev->hdr_type);
-
-		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
-		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-			of_scan_pci_bridge(child, dev);
+		DBG("    dev header type: %x\n", dev->hdr_type);
 	}
 
-	do_bus_setup(bus);
+	/* Ally all fixups */
+	pcibios_fixup_of_probed_bus(bus);
+
+	/* Now scan child busses */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+			struct device_node *child = pci_device_to_OF_node(dev);
+			if (dev)
+				of_scan_pci_bridge(child, dev);
+		}
+	}
 }
 EXPORT_SYMBOL(of_scan_bus);
 
 void __devinit of_scan_pci_bridge(struct device_node *node,
-			 	struct pci_dev *dev)
+				  struct pci_dev *dev)
 {
 	struct pci_bus *bus;
 	const u32 *busrange, *ranges;
@@ -441,7 +335,6 @@
 		res->start = of_read_number(&ranges[1], 2);
 		res->end = res->start + size - 1;
 		res->flags = flags;
-		fixup_resource(res, dev);
 	}
 	sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
 		bus->number);
@@ -462,12 +355,13 @@
 void __devinit scan_phb(struct pci_controller *hose)
 {
 	struct pci_bus *bus;
-	struct device_node *node = hose->arch_data;
+	struct device_node *node = hose->dn;
 	int i, mode;
 	struct resource *res;
 
-	DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+	DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
 
+	/* Create an empty bus for the toplevel */
 	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
 	if (bus == NULL) {
 		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
@@ -477,27 +371,29 @@
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
-	if (!firmware_has_feature(FW_FEATURE_ISERIES))
-		pcibios_map_io_space(bus);
+	/* Get some IO space for the new PHB */
+	pcibios_map_io_space(bus);
 
-	bus->resource[0] = res = &hose->io_resource;
-	if (res->flags && request_resource(&ioport_resource, res)) {
-		printk(KERN_ERR "Failed to request PCI IO region "
-		       "on PCI domain %04x\n", hose->global_number);
-		DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
-		    res->start, res->end);
+	/* Wire up PHB bus resources */
+	if (hose->io_resource.flags) {
+		DBG("PCI: PHB IO resource    = %016lx-%016lx [%lx]\n",
+		    hose->io_resource.start, hose->io_resource.end,
+		    hose->io_resource.flags);
+		bus->resource[0] = res = &hose->io_resource;
 	}
-
 	for (i = 0; i < 3; ++i) {
-		res = &hose->mem_resources[i];
-		bus->resource[i+1] = res;
-		if (res->flags && request_resource(&iomem_resource, res))
-			printk(KERN_ERR "Failed to request PCI memory region "
-			       "on PCI domain %04x\n", hose->global_number);
+		DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i,
+		    hose->mem_resources[i].start,
+		    hose->mem_resources[i].end,
+		    hose->mem_resources[i].flags);
+		bus->resource[i+1] = &hose->mem_resources[i];
 	}
+	DBG("PCI: PHB MEM offset     = %016lx\n", hose->pci_mem_offset);
+	DBG("PCI: PHB IO  offset     = %08lx\n",
+	    (unsigned long)hose->io_base_virt - _IO_BASE);
 
+	/* Get probe mode and perform scan */
 	mode = PCI_PROBE_NORMAL;
-
 	if (node && ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
 	DBG("    probe mode: %d\n", mode);
@@ -514,15 +410,15 @@
 {
 	struct pci_controller *hose, *tmp;
 
+	printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
 	/* For now, override phys_mem_access_prot. If we need it,
 	 * later, we may move that initialization to each ppc_md
 	 */
 	ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
 
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		iSeries_pcibios_init();
-
-	printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
+	if (pci_probe_only)
+		ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -530,19 +426,8 @@
 		pci_bus_add_devices(hose->bus);
 	}
 
-	if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
-		if (pci_probe_only)
-			pcibios_claim_of_setup();
-		else
-			/* FIXME: `else' will be removed when
-			   pci_assign_unassigned_resources() is able to work
-			   correctly with [partially] allocated PCI tree. */
-			pci_assign_unassigned_resources();
-	}
-
-	/* Call machine dependent final fixup */
-	if (ppc_md.pcibios_fixup)
-		ppc_md.pcibios_fixup();
+	/* Call common code to handle resource allocation */
+	pcibios_resource_survey();
 
 	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
@@ -551,141 +436,6 @@
 
 subsys_initcall(pcibios_init);
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	u16 cmd, oldcmd;
-	int i;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	oldcmd = cmd;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *res = &dev->resource[i];
-
-		/* Only set up the requested stuff */
-		if (!(mask & (1<<i)))
-			continue;
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-
-	if (cmd != oldcmd) {
-		printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
-		       pci_name(dev), cmd);
-                /* Enable the appropriate bits in the PCI command register.  */
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-}
-
-/* Decide whether to display the domain number in /proc */
-int pci_proc_domain(struct pci_bus *bus)
-{
-	if (firmware_has_feature(FW_FEATURE_ISERIES))
-		return 0;
-	else {
-		struct pci_controller *hose = pci_bus_to_host(bus);
-		return hose->buid != 0;
-	}
-}
-
-void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-					    struct device_node *dev, int prim)
-{
-	const unsigned int *ranges;
-	unsigned int pci_space;
-	unsigned long size;
-	int rlen = 0;
-	int memno = 0;
-	struct resource *res;
-	int np, na = of_n_addr_cells(dev);
-	unsigned long pci_addr, cpu_phys_addr;
-
-	np = na + 5;
-
-	/* From "PCI Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 2:	a PCI address
-	 *   cells 3 or 3+4:	a CPU physical address
-	 *			(size depending on dev->n_addr_cells)
-	 *   cells 4+5 or 5+6:	the size of the range
-	 */
-	ranges = of_get_property(dev, "ranges", &rlen);
-	if (ranges == NULL)
-		return;
-	hose->io_base_phys = 0;
-	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		pci_space = ranges[0];
-		pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
-		cpu_phys_addr = of_translate_address(dev, &ranges[3]);
-		size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
-		ranges += np;
-		if (size == 0)
-			continue;
-
-		/* Now consume following elements while they are contiguous */
-		while (rlen >= np * sizeof(unsigned int)) {
-			unsigned long addr, phys;
-
-			if (ranges[0] != pci_space)
-				break;
-			addr = ((unsigned long)ranges[1] << 32) | ranges[2];
-			phys = ranges[3];
-			if (na >= 2)
-				phys = (phys << 32) | ranges[4];
-			if (addr != pci_addr + size ||
-			    phys != cpu_phys_addr + size)
-				break;
-
-			size += ((unsigned long)ranges[na+3] << 32)
-				| ranges[na+4];
-			ranges += np;
-			rlen -= np * sizeof(unsigned int);
-		}
-
-		switch ((pci_space >> 24) & 0x3) {
-		case 1:		/* I/O space */
-			hose->io_base_phys = cpu_phys_addr - pci_addr;
-			/* handle from 0 to top of I/O window */
-			hose->pci_io_size = pci_addr + size;
-
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = pci_addr;
-			DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
-				    res->start, res->start + size - 1);
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-
-			if (memno == 0)
-				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				res->start = cpu_phys_addr;
-				DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
-					    res->start, res->start + size - 1);
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-	}
-}
-
 #ifdef CONFIG_HOTPLUG
 
 int pcibios_unmap_io_space(struct pci_bus *bus)
@@ -719,8 +469,7 @@
 	if (hose->io_base_alloc == 0)
 		return 0;
 
-	DBG("IO unmapping for PHB %s\n",
-	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("IO unmapping for PHB %s\n", hose->dn->full_name);
 	DBG("  alloc=0x%p\n", hose->io_base_alloc);
 
 	/* This is a PHB, we fully unmap the IO area */
@@ -779,8 +528,7 @@
 	hose->io_base_virt = (void __iomem *)(area->addr +
 					      hose->io_base_phys - phys_page);
 
-	DBG("IO mapping for PHB %s\n",
-	    ((struct device_node *)hose->arch_data)->full_name);
+	DBG("IO mapping for PHB %s\n", hose->dn->full_name);
 	DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
 	    hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
 	DBG("  size=0x%016lx (alloc=0x%016lx)\n",
@@ -803,51 +551,13 @@
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long offset;
-
-	if (res->flags & IORESOURCE_IO) {
-		offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-		res->start += offset;
-		res->end += offset;
-	} else if (res->flags & IORESOURCE_MEM) {
-		res->start += hose->pci_mem_offset;
-		res->end += hose->pci_mem_offset;
-	}
-}
-
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-					      struct pci_bus *bus)
-{
-	/* Update device resources.  */
-	int i;
-
-	DBG("%s: Fixup resources:\n", pci_name(dev));
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *res = &dev->resource[i];
-		if (!res->flags)
-			continue;
-
-		DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
-		    i, res->flags, res->start, res->end);
-
-		fixup_resource(res, dev);
-
-		DBG("       > %08lx:0x%016lx...0x%016lx\n",
-		    res->flags, res->start, res->end);
-	}
-}
-EXPORT_SYMBOL(pcibios_fixup_device_resources);
-
 void __devinit pcibios_setup_new_device(struct pci_dev *dev)
 {
 	struct dev_archdata *sd = &dev->dev.archdata;
 
 	sd->of_node = pci_device_to_OF_node(dev);
 
-	DBG("PCI device %s OF node: %s\n", pci_name(dev),
+	DBG("PCI: device %s OF node: %s\n", pci_name(dev),
 	    sd->of_node ? sd->of_node->full_name : "<none>");
 
 	sd->dma_ops = pci_dma_ops;
@@ -861,7 +571,7 @@
 }
 EXPORT_SYMBOL(pcibios_setup_new_device);
 
-static void __devinit do_bus_setup(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 
@@ -870,43 +580,8 @@
 
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		pcibios_setup_new_device(dev);
-
-	/* Read default IRQs and fixup if necessary */
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_read_irq_line(dev);
-		if (ppc_md.pci_irq_fixup)
-			ppc_md.pci_irq_fixup(dev);
-	}
 }
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct pci_dev *dev = bus->self;
-	struct device_node *np;
-
-	np = pci_bus_to_OF_node(bus);
-
-	DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>");
-
-	if (dev && pci_probe_only &&
-	    (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		/* This is a subordinate bridge */
-
-		pci_read_bridge_bases(bus);
-		pcibios_fixup_device_resources(dev, bus);
-	}
-
-	do_bus_setup(bus);
-
-	if (!pci_probe_only)
-		return;
-
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-			pcibios_fixup_device_resources(dev, bus);
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
 	struct pci_controller *hose, *tmp;
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index b483903..85d4d89 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -133,7 +133,7 @@
  */
 void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
 {
-	struct device_node * dn = (struct device_node *) phb->arch_data;
+	struct device_node *dn = phb->dn;
 	struct pci_dn *pdn;
 
 	/* PHB nodes themselves must not match */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index acc0d24..6c2d883 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -583,6 +583,20 @@
 		      ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
 }
 
+#ifdef CONFIG_PPC64
+static void __init check_cpu_slb_size(unsigned long node)
+{
+	u32 *slb_size_ptr;
+
+	slb_size_ptr = of_get_flat_dt_prop(node, "ibm,slb-size", NULL);
+	if (slb_size_ptr != NULL) {
+		mmu_slb_size = *slb_size_ptr;
+	}
+}
+#else
+#define check_cpu_slb_size(node) do { } while(0)
+#endif
+
 static struct feature_property {
 	const char *name;
 	u32 min_value;
@@ -713,6 +727,7 @@
 
 	check_cpu_feature_properties(node);
 	check_cpu_pa_features(node);
+	check_cpu_slb_size(node);
 
 #ifdef CONFIG_PPC_PSERIES
 	if (nthreads > 1)
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index b5c96af..90eb3a3 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -273,7 +273,7 @@
 #else
 			struct pci_controller *host;
 			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->arch_data : NULL;
+			ppnode = host ? host->dn : NULL;
 #endif
 			/* No node for host bridge ? give up */
 			if (ppnode == NULL)
@@ -419,7 +419,7 @@
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
 			    struct of_bus *pbus, u32 *addr,
-			    int na, int ns, int pna)
+			    int na, int ns, int pna, const char *rprop)
 {
 	const u32 *ranges;
 	unsigned int rlen;
@@ -438,7 +438,7 @@
 	 * to translate addresses that aren't supposed to be translated in
 	 * the first place. --BenH.
 	 */
-	ranges = of_get_property(parent, "ranges", &rlen);
+	ranges = of_get_property(parent, rprop, &rlen);
 	if (ranges == NULL || rlen == 0) {
 		offset = of_read_number(addr, na);
 		memset(addr, 0, pna * 4);
@@ -481,7 +481,8 @@
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
+			   const char *rprop)
 {
 	struct device_node *parent = NULL;
 	struct of_bus *bus, *pbus;
@@ -540,7 +541,7 @@
 		    pbus->name, pna, pns, parent->full_name);
 
 		/* Apply bus translation */
-		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
 			break;
 
 		/* Complete the move up one level */
@@ -556,8 +557,19 @@
 
 	return result;
 }
+
+u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+{
+	return __of_translate_address(dev, in_addr, "ranges");
+}
 EXPORT_SYMBOL(of_translate_address);
 
+u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
+{
+	return __of_translate_address(dev, in_addr, "dma-ranges");
+}
+EXPORT_SYMBOL(of_translate_dma_address);
+
 const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
 		    unsigned int *flags)
 {
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 21f14e5..99aaae3 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -260,7 +260,7 @@
 
 int __devinit rtas_setup_phb(struct pci_controller *phb)
 {
-	struct device_node *dev = phb->arch_data;
+	struct device_node *dev = phb->dn;
 
 	if (is_python(dev))
 		python_countermeasures(dev);
@@ -311,10 +311,12 @@
 		if (prop)
 			pci_probe_only = *prop;
 
+#ifdef CONFIG_PPC32 /* Will be made generic soon */
 		prop = of_get_property(of_chosen,
 				"linux,pci-assign-all-buses", NULL);
-		if (prop)
-			pci_assign_all_buses = *prop;
+		if (prop && *prop)
+			ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+#endif /* CONFIG_PPC32 */
 	}
 }
 
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 2de00f8..6adb5a1 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -33,6 +33,7 @@
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <linux/debugfs.h>
+#include <linux/percpu.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -57,6 +58,7 @@
 #include <asm/mmu.h>
 #include <asm/lmb.h>
 #include <asm/xmon.h>
+#include <asm/cputhreads.h>
 
 #include "setup.h"
 
@@ -327,6 +329,31 @@
 
 #ifdef CONFIG_SMP
 
+int threads_per_core, threads_shift;
+cpumask_t threads_core_mask;
+
+static void __init cpu_init_thread_core_maps(int tpc)
+{
+	int i;
+
+	threads_per_core = tpc;
+	threads_core_mask = CPU_MASK_NONE;
+
+	/* This implementation only supports power of 2 number of threads
+	 * for simplicity and performance
+	 */
+	threads_shift = ilog2(tpc);
+	BUG_ON(tpc != (1 << threads_shift));
+
+	for (i = 0; i < tpc; i++)
+		cpu_set(i, threads_core_mask);
+
+	printk(KERN_INFO "CPU maps initialized for %d thread%s per core\n",
+	       tpc, tpc > 1 ? "s" : "");
+	printk(KERN_DEBUG " (thread shift is %d)\n", threads_shift);
+}
+
+
 /**
  * setup_cpu_maps - initialize the following cpu maps:
  *                  cpu_possible_map
@@ -350,22 +377,32 @@
 {
 	struct device_node *dn = NULL;
 	int cpu = 0;
+	int nthreads = 1;
+
+	DBG("smp_setup_cpu_maps()\n");
 
 	while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
 		const int *intserv;
-		int j, len = sizeof(u32), nthreads = 1;
+		int j, len;
+
+		DBG("  * %s...\n", dn->full_name);
 
 		intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s",
 				&len);
-		if (intserv)
+		if (intserv) {
 			nthreads = len / sizeof(int);
-		else {
+			DBG("    ibm,ppc-interrupt-server#s -> %d threads\n",
+			    nthreads);
+		} else {
+			DBG("    no ibm,ppc-interrupt-server#s -> 1 thread\n");
 			intserv = of_get_property(dn, "reg", NULL);
 			if (!intserv)
 				intserv = &cpu;	/* assume logical == phys */
 		}
 
 		for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
+			DBG("    thread %d -> cpu %d (hard id %d)\n",
+			    j, cpu, intserv[j]);
 			cpu_set(cpu, cpu_present_map);
 			set_hard_smp_processor_id(cpu, intserv[j]);
 			cpu_set(cpu, cpu_possible_map);
@@ -373,6 +410,12 @@
 		}
 	}
 
+	/* If no SMT supported, nthreads is forced to 1 */
+	if (!cpu_has_feature(CPU_FTR_SMT)) {
+		DBG("  SMT disabled ! nthreads forced to 1\n");
+		nthreads = 1;
+	}
+
 #ifdef CONFIG_PPC64
 	/*
 	 * On pSeries LPAR, we need to know how many cpus
@@ -395,7 +438,7 @@
 
 		/* Double maxcpus for processors which have SMT capability */
 		if (cpu_has_feature(CPU_FTR_SMT))
-			maxcpus *= 2;
+			maxcpus *= nthreads;
 
 		if (maxcpus > NR_CPUS) {
 			printk(KERN_WARNING
@@ -412,9 +455,16 @@
 	out:
 		of_node_put(dn);
 	}
-
 	vdso_data->processorCount = num_present_cpus();
 #endif /* CONFIG_PPC64 */
+
+        /* Initialize CPU <=> thread mapping/
+	 *
+	 * WARNING: We assume that the number of threads is the same for
+	 * every CPU in the system. If that is not the case, then some code
+	 * here will have to be reworked
+	 */
+	cpu_init_thread_core_maps(nthreads);
 }
 
 /*
@@ -424,17 +474,19 @@
  */
 void __init smp_setup_cpu_sibling_map(void)
 {
-#if defined(CONFIG_PPC64)
-	int cpu;
+#ifdef CONFIG_PPC64
+	int i, cpu, base;
 
-	/*
-	 * Do the sibling map; assume only two threads per processor.
-	 */
 	for_each_possible_cpu(cpu) {
-		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
-		if (cpu_has_feature(CPU_FTR_SMT))
-			cpu_set(cpu ^ 0x1, per_cpu(cpu_sibling_map, cpu));
+		DBG("Sibling map for CPU %d:", cpu);
+		base = cpu_first_thread_in_core(cpu);
+		for (i = 0; i < threads_per_core; i++) {
+			cpu_set(base + i, per_cpu(cpu_sibling_map, cpu));
+			DBG(" %d", base + i);
+		}
+		DBG("\n");
 	}
+
 #endif /* CONFIG_PPC64 */
 }
 #endif /* CONFIG_SMP */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 6126bca8..d840bc7 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -24,13 +24,12 @@
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/elf.h>
+#include <linux/ptrace.h>
 #ifdef CONFIG_PPC64
 #include <linux/syscalls.h>
 #include <linux/compat.h>
-#include <linux/ptrace.h>
 #else
 #include <linux/wait.h>
-#include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a925a8e..5cd3db5 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -116,9 +116,12 @@
        .features       = CLOCK_EVT_FEAT_ONESHOT,
 };
 
-static DEFINE_PER_CPU(struct clock_event_device, decrementers);
-void init_decrementer_clockevent(void);
-static DEFINE_PER_CPU(u64, decrementer_next_tb);
+struct decrementer_clock {
+	struct clock_event_device event;
+	u64 next_tb;
+};
+
+static DEFINE_PER_CPU(struct decrementer_clock, decrementers);
 
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long __initdata iSeries_recal_titan;
@@ -216,7 +219,11 @@
  */
 static u64 read_spurr(u64 purr)
 {
-	if (cpu_has_feature(CPU_FTR_SPURR))
+	/*
+	 * cpus without PURR won't have a SPURR
+	 * We already know the former when we use this, so tell gcc
+	 */
+	if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR))
 		return mfspr(SPRN_SPURR);
 	return purr;
 }
@@ -227,29 +234,30 @@
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-	u64 now, nowscaled, delta, deltascaled;
+	u64 now, nowscaled, delta, deltascaled, sys_time;
 	unsigned long flags;
 
 	local_irq_save(flags);
 	now = read_purr();
-	delta = now - get_paca()->startpurr;
-	get_paca()->startpurr = now;
 	nowscaled = read_spurr(now);
+	delta = now - get_paca()->startpurr;
 	deltascaled = nowscaled - get_paca()->startspurr;
+	get_paca()->startpurr = now;
 	get_paca()->startspurr = nowscaled;
 	if (!in_interrupt()) {
 		/* deltascaled includes both user and system time.
 		 * Hence scale it based on the purr ratio to estimate
 		 * the system time */
+		sys_time = get_paca()->system_time;
 		if (get_paca()->user_time)
-			deltascaled = deltascaled * get_paca()->system_time /
-			     (get_paca()->system_time + get_paca()->user_time);
-		delta += get_paca()->system_time;
+			deltascaled = deltascaled * sys_time /
+			     (sys_time + get_paca()->user_time);
+		delta += sys_time;
 		get_paca()->system_time = 0;
 	}
 	account_system_time(tsk, 0, delta);
-	get_paca()->purrdelta = delta;
 	account_system_time_scaled(tsk, deltascaled);
+	get_paca()->purrdelta = delta;
 	get_paca()->spurrdelta = deltascaled;
 	local_irq_restore(flags);
 }
@@ -326,11 +334,9 @@
 	s64 stolen;
 	struct cpu_purr_data *pme;
 
-	if (!cpu_has_feature(CPU_FTR_PURR))
-		return;
-	pme = &per_cpu(cpu_purr_data, smp_processor_id());
+	pme = &__get_cpu_var(cpu_purr_data);
 	if (!pme->initialized)
-		return;		/* this can happen in early boot */
+		return;		/* !CPU_FTR_PURR or early in early boot */
 	tb = mftb();
 	purr = mfspr(SPRN_PURR);
 	stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -353,7 +359,7 @@
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
 	local_irq_save(flags);
-	pme = &per_cpu(cpu_purr_data, smp_processor_id());
+	pme = &__get_cpu_var(cpu_purr_data);
 	pme->tb = mftb();
 	pme->purr = mfspr(SPRN_PURR);
 	pme->initialized = 1;
@@ -556,8 +562,8 @@
 void timer_interrupt(struct pt_regs * regs)
 {
 	struct pt_regs *old_regs;
-	int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+	struct decrementer_clock *decrementer =  &__get_cpu_var(decrementers);
+	struct clock_event_device *evt = &decrementer->event;
 	u64 now;
 
 	/* Ensure a positive value is written to the decrementer, or else
@@ -570,9 +576,9 @@
 #endif
 
 	now = get_tb_or_rtc();
-	if (now < per_cpu(decrementer_next_tb, cpu)) {
+	if (now < decrementer->next_tb) {
 		/* not time for this event yet */
-		now = per_cpu(decrementer_next_tb, cpu) - now;
+		now = decrementer->next_tb - now;
 		if (now <= DECREMENTER_MAX)
 			set_dec((int)now);
 		return;
@@ -623,6 +629,45 @@
 	set_dec(ticks);
 }
 
+#ifdef CONFIG_SUSPEND
+void generic_suspend_disable_irqs(void)
+{
+	preempt_disable();
+
+	/* Disable the decrementer, so that it doesn't interfere
+	 * with suspending.
+	 */
+
+	set_dec(0x7fffffff);
+	local_irq_disable();
+	set_dec(0x7fffffff);
+}
+
+void generic_suspend_enable_irqs(void)
+{
+	wakeup_decrementer();
+
+	local_irq_enable();
+	preempt_enable();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_disable_irqs(void)
+{
+	if (ppc_md.suspend_disable_irqs)
+		ppc_md.suspend_disable_irqs();
+	generic_suspend_disable_irqs();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_enable_irqs(void)
+{
+	generic_suspend_enable_irqs();
+	if (ppc_md.suspend_enable_irqs)
+		ppc_md.suspend_enable_irqs();
+}
+#endif
+
 #ifdef CONFIG_SMP
 void __init smp_space_timers(unsigned int max_cpus)
 {
@@ -811,7 +856,7 @@
 static int decrementer_set_next_event(unsigned long evt,
 				      struct clock_event_device *dev)
 {
-	__get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
+	__get_cpu_var(decrementers).next_tb = get_tb_or_rtc() + evt;
 	set_dec(evt);
 	return 0;
 }
@@ -825,7 +870,7 @@
 
 static void register_decrementer_clockevent(int cpu)
 {
-	struct clock_event_device *dec = &per_cpu(decrementers, cpu);
+	struct clock_event_device *dec = &per_cpu(decrementers, cpu).event;
 
 	*dec = decrementer_clockevent;
 	dec->cpumask = cpumask_of_cpu(cpu);
@@ -836,7 +881,7 @@
 	clockevents_register_device(dec);
 }
 
-void init_decrementer_clockevent(void)
+static void __init init_decrementer_clockevent(void)
 {
 	int cpu = smp_processor_id();
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 59c464e..cad6484 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -622,6 +622,9 @@
 #define INST_POPCNTB		0x7c0000f4
 #define INST_POPCNTB_MASK	0xfc0007fe
 
+#define INST_ISEL		0x7c00001e
+#define INST_ISEL_MASK		0xfc00003e
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
 	u8 rT = (instword >> 21) & 0x1f;
@@ -707,6 +710,23 @@
 	return 0;
 }
 
+static int emulate_isel(struct pt_regs *regs, u32 instword)
+{
+	u8 rT = (instword >> 21) & 0x1f;
+	u8 rA = (instword >> 16) & 0x1f;
+	u8 rB = (instword >> 11) & 0x1f;
+	u8 BC = (instword >> 6) & 0x1f;
+	u8 bit;
+	unsigned long tmp;
+
+	tmp = (rA == 0) ? 0 : regs->gpr[rA];
+	bit = (regs->ccr >> (31 - BC)) & 0x1;
+
+	regs->gpr[rT] = bit ? tmp : regs->gpr[rB];
+
+	return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
@@ -749,6 +769,11 @@
 		return emulate_popcntb_inst(regs, instword);
 	}
 
+	/* Emulate isel (Integer Select) instruction */
+	if ((instword & INST_ISEL_MASK) == INST_ISEL) {
+		return emulate_isel(regs, instword);
+	}
+
 	return -EINVAL;
 }
 
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index d723070..eba148f 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -57,6 +57,10 @@
 #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
 	udbg_init_cpm();
 #endif
+
+#ifdef CONFIG_PPC_EARLY_DEBUG
+	console_loglevel = 10;
+#endif
 }
 
 /* udbg library, used by xmon et al */
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 833a3d0..df740ea 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -46,7 +46,7 @@
 
 #define LCR_DLAB 0x80
 
-static volatile struct NS16550 __iomem *udbg_comport;
+static struct NS16550 __iomem *udbg_comport;
 
 static void udbg_550_putc(char c)
 {
@@ -117,7 +117,7 @@
 {
 	unsigned int dll, dlm, divisor, prescaler, speed;
 	u8 old_lcr;
-	volatile struct NS16550 __iomem *port = comport;
+	struct NS16550 __iomem *port = comport;
 
 	old_lcr = in_8(&port->lcr);
 
@@ -162,7 +162,7 @@
 
 void __init udbg_init_maple_realmode(void)
 {
-	udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
+	udbg_comport = (struct NS16550 __iomem *)0xf40003f8;
 
 	udbg_putc = udbg_maple_real_putc;
 	udbg_getc = NULL;
@@ -184,7 +184,7 @@
 
 void udbg_init_pas_realmode(void)
 {
-	udbg_comport = (volatile struct NS16550 __iomem *)0xfcff03f8UL;
+	udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL;
 
 	udbg_putc = udbg_pas_real_putc;
 	udbg_getc = NULL;
@@ -219,7 +219,7 @@
 void __init udbg_init_44x_as1(void)
 {
 	udbg_comport =
-		(volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
+		(struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
 
 	udbg_putc = udbg_44x_as1_putc;
 	udbg_getc = udbg_44x_as1_getc;
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 8135da0..10dda22 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -189,7 +189,7 @@
 			return SIGSEGV;
 		/* in_atomic() in user mode is really bad,
 		   as is current->mm == NULL. */
-		printk(KERN_EMERG "Page fault in user mode with"
+		printk(KERN_EMERG "Page fault in user mode with "
 		       "in_atomic() = %d mm = %p\n", in_atomic(), mm);
 		printk(KERN_EMERG "NIP = %lx  MSR = %lx\n",
 		       regs->nip, regs->msr);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index f09730b..cbbd8b0 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -96,6 +96,7 @@
 int mmu_io_psize = MMU_PAGE_4K;
 int mmu_kernel_ssize = MMU_SEGSIZE_256M;
 int mmu_highuser_ssize = MMU_SEGSIZE_256M;
+u16 mmu_slb_size = 64;
 #ifdef CONFIG_HUGETLB_PAGE
 int mmu_huge_psize = MMU_PAGE_16M;
 unsigned int HPAGE_SHIFT;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index c12adc3dd..1666e7d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -24,6 +24,8 @@
 
 static int numa_enabled = 1;
 
+static char *cmdline __initdata;
+
 static int numa_debug;
 #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
 
@@ -39,6 +41,43 @@
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
 
+static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
+						unsigned int *nid)
+{
+	unsigned long long mem;
+	char *p = cmdline;
+	static unsigned int fake_nid = 0;
+	static unsigned long long curr_boundary = 0;
+
+	*nid = fake_nid;
+	if (!p)
+		return 0;
+
+	mem = memparse(p, &p);
+	if (!mem)
+		return 0;
+
+	if (mem < curr_boundary)
+		return 0;
+
+	curr_boundary = mem;
+
+	if ((end_pfn << PAGE_SHIFT) > mem) {
+		/*
+		 * Skip commas and spaces
+		 */
+		while (*p == ',' || *p == ' ' || *p == '\t')
+			p++;
+
+		cmdline = p;
+		fake_nid++;
+		*nid = fake_nid;
+		dbg("created new fake_node with id %d\n", fake_nid);
+		return 1;
+	}
+	return 0;
+}
+
 static void __cpuinit map_cpu_to_node(int cpu, int node)
 {
 	numa_cpu_lookup_table[cpu] = node;
@@ -344,12 +383,14 @@
 			if (nid == 0xffff || nid >= MAX_NUMNODES)
 				nid = default_nid;
 		}
-		node_set_online(nid);
 
 		size = numa_enforce_memory_limit(start, lmb_size);
 		if (!size)
 			continue;
 
+		fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
+		node_set_online(nid);
+
 		add_active_range(nid, start >> PAGE_SHIFT,
 				 (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
 	}
@@ -429,7 +470,6 @@
 		nid = of_node_to_nid_single(memory);
 		if (nid < 0)
 			nid = default_nid;
-		node_set_online(nid);
 
 		if (!(size = numa_enforce_memory_limit(start, size))) {
 			if (--ranges)
@@ -438,6 +478,9 @@
 				continue;
 		}
 
+		fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
+		node_set_online(nid);
+
 		add_active_range(nid, start >> PAGE_SHIFT,
 				(start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
 
@@ -461,7 +504,7 @@
 	unsigned long top_of_ram = lmb_end_of_DRAM();
 	unsigned long total_ram = lmb_phys_mem_size();
 	unsigned long start_pfn, end_pfn;
-	unsigned int i;
+	unsigned int i, nid = 0;
 
 	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
@@ -471,9 +514,11 @@
 	for (i = 0; i < lmb.memory.cnt; ++i) {
 		start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
 		end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
-		add_active_range(0, start_pfn, end_pfn);
+
+		fake_numa_create_new_node(end_pfn, &nid);
+		add_active_range(nid, start_pfn, end_pfn);
+		node_set_online(nid);
 	}
-	node_set_online(0);
 }
 
 void __init dump_numa_cpu_topology(void)
@@ -702,6 +747,10 @@
 	if (strstr(p, "debug"))
 		numa_debug = 1;
 
+	p = strstr(p, "fake=");
+	if (p)
+		cmdline = p + strlen("fake=");
+
 	return 0;
 }
 early_param("numa", early_numa);
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 27922df..3cf0802 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -256,6 +256,7 @@
 	static int slb_encoding_inited;
 	extern unsigned int *slb_miss_kernel_load_linear;
 	extern unsigned int *slb_miss_kernel_load_io;
+	extern unsigned int *slb_compare_rr_to_size;
 
 	/* Prepare our SLB miss handler based on our page size */
 	linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
@@ -269,6 +270,8 @@
 				   SLB_VSID_KERNEL | linear_llp);
 		patch_slb_encoding(slb_miss_kernel_load_io,
 				   SLB_VSID_KERNEL | io_llp);
+		patch_slb_encoding(slb_compare_rr_to_size,
+				   mmu_slb_size);
 
 		DBG("SLB: linear  LLP = %04x\n", linear_llp);
 		DBG("SLB: io      LLP = %04x\n", io_llp);
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 1328a81..657f6b3 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -227,8 +227,9 @@
 
 7:	ld	r10,PACASTABRR(r13)
 	addi	r10,r10,1
-	/* use a cpu feature mask if we ever change our slb size */
-	cmpldi	r10,SLB_NUM_ENTRIES
+	/* This gets soft patched on boot. */
+_GLOBAL(slb_compare_rr_to_size)
+	cmpldi	r10,0
 
 	blt+	4f
 	li	r10,SLB_NUM_BOLTED
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index bb6bff5..1392977 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -61,7 +61,7 @@
 #define NUM_THREADS 2         /* number of physical threads in
 			       * physical processor
 			       */
-#define NUM_TRACE_BUS_WORDS 4
+#define NUM_DEBUG_BUS_WORDS 4
 #define NUM_INPUT_BUS_WORDS 2
 
 #define MAX_SPU_COUNT 0xFFFFFF	/* maximum 24 bit LFSR value */
@@ -169,7 +169,6 @@
 
 static u32 ctr_enabled;
 
-static unsigned char trace_bus[NUM_TRACE_BUS_WORDS];
 static unsigned char input_bus[NUM_INPUT_BUS_WORDS];
 
 /*
@@ -298,7 +297,7 @@
 
 	p->signal_group = event / 100;
 	p->bus_word = bus_word;
-	p->sub_unit = (unit_mask & 0x0000f000) >> 12;
+	p->sub_unit = GET_SUB_UNIT(unit_mask);
 
 	pm_regs.pm07_cntrl[ctr] = 0;
 	pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
@@ -334,16 +333,16 @@
 		p->bit = signal_bit;
 	}
 
-	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++) {
+	for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) {
 		if (bus_word & (1 << i)) {
 			pm_regs.debug_bus_control |=
-			    (bus_type << (31 - (2 * i) + 1));
+			    (bus_type << (30 - (2 * i)));
 
 			for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) {
 				if (input_bus[j] == 0xff) {
 					input_bus[j] = i;
 					pm_regs.group_control |=
-					    (i << (31 - i));
+					    (i << (30 - (2 * j)));
 
 					break;
 				}
@@ -450,6 +449,12 @@
 	hdw_thread = 1 ^ hdw_thread;
 	next_hdw_thread = hdw_thread;
 
+	pm_regs.group_control = 0;
+	pm_regs.debug_bus_control = 0;
+
+	for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
+		input_bus[i] = 0xff;
+
 	/*
 	 * There are some per thread events.  Must do the
 	 * set event, for the thread that is being started
@@ -619,9 +624,6 @@
 		pmc_cntrl[1][i].vcntr = i;
 	}
 
-	for (i = 0; i < NUM_TRACE_BUS_WORDS; i++)
-		trace_bus[i] = 0xff;
-
 	for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
 		input_bus[i] = 0xff;
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 4c6c82a..262eda8 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -363,7 +363,7 @@
 
 	pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
 	if (of_address_to_resource(node, 0, &rsrc) != 0) {
 		printk(KERN_ERR "Can't get %s resources\n", node->full_name);
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
index a497cba..1b75902 100644
--- a/arch/powerpc/platforms/82xx/pq2.c
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -53,13 +53,13 @@
 	if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
 		goto err;
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
 	hose = pcibios_alloc_controller(np);
 	if (!hose)
 		return;
 
-	hose->arch_data = np;
+	hose->dn = np;
 
 	setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0);
 	pci_process_bridge_OF_ranges(hose, np, 1);
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index 4f457a9..1be5005 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -15,12 +15,12 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
 
 #include <asm/io.h>
 #include <asm/cpm2.h>
 #include <asm/udbg.h>
 #include <asm/machdep.h>
-#include <asm/of_platform.h>
 #include <asm/time.h>
 
 #include <sysdev/fsl_soc.h>
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index ec305f1..2430ac8 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -50,6 +50,11 @@
 	help
 	  This option enables support for the MPC836x MDS Processor Board.
 
+config MPC837x_MDS
+	bool "Freescale MPC837x MDS"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the MPC837x MDS Processor Board.
 endchoice
 
 config PPC_MPC831x
@@ -75,3 +80,9 @@
 	select PPC_UDBG_16550
 	select PPC_INDIRECT_PCI
 	default y if MPC836x_MDS
+
+config PPC_MPC837x
+	bool
+	select PPC_UDBG_16550
+	select PPC_INDIRECT_PCI
+	default y if MPC837x_MDS
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 5a98f88..df46629 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -9,3 +9,4 @@
 obj-$(CONFIG_MPC834x_ITX)	+= mpc834x_itx.o
 obj-$(CONFIG_MPC836x_MDS)	+= mpc836x_mds.o
 obj-$(CONFIG_MPC832x_MDS)	+= mpc832x_mds.o
+obj-$(CONFIG_MPC837x_MDS)	+= mpc837x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 33766b8..6fb8299 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -70,9 +70,9 @@
  */
 static int __init mpc8313_rdb_probe(void)
 {
-        unsigned long root = of_get_flat_dt_root();
+	unsigned long root = of_get_flat_dt_root();
 
-        return of_flat_dt_is_compatible(root, "MPC8313ERDB");
+	return of_flat_dt_is_compatible(root, "MPC8313ERDB");
 }
 
 define_machine(mpc8313_rdb) {
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 39ee7a1..1e570bb 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -23,9 +23,9 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index d4bd040..ffb2e93 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -19,8 +19,8 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
 #include <linux/mmc/host.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
 #include <asm/time.h>
 #include <asm/ipic.h>
 #include <asm/udbg.h>
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index a81bb3c..459fb72 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -106,14 +107,30 @@
 	ipic_set_default_priority();
 }
 
+static struct of_device_id mpc834x_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{},
+};
+
+static int __init mpc834x_declare_of_platform_devices(void)
+{
+	if (!machine_is(mpc834x_mds))
+		return 0;
+
+	of_platform_bus_probe(NULL, mpc834x_ids, NULL);
+	return 0;
+}
+device_initcall(mpc834x_declare_of_platform_devices);
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc834x_mds_probe(void)
 {
-        unsigned long root = of_get_flat_dt_root();
+	unsigned long root = of_get_flat_dt_root();
 
-        return of_flat_dt_is_compatible(root, "MPC834xMDS");
+	return of_flat_dt_is_compatible(root, "MPC834xMDS");
 }
 
 define_machine(mpc834x_mds) {
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index e40012f..2ac9890 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -29,9 +29,9 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
new file mode 100644
index 0000000..166c111
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -0,0 +1,104 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc837x_mds.c
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * MPC837x MDS board specific routines
+ *
+ * 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.
+ */
+
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+#include <asm/prom.h>
+
+#include "mpc83xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc837x_mds_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc837x_mds_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+		mpc83xx_add_bridge(np);
+#endif
+}
+
+static struct of_device_id mpc837x_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{},
+};
+
+static int __init mpc837x_declare_of_platform_devices(void)
+{
+	if (!machine_is(mpc837x_mds))
+		return 0;
+
+	/* Publish of_device */
+	of_platform_bus_probe(NULL, mpc837x_ids, NULL);
+
+	return 0;
+}
+device_initcall(mpc837x_declare_of_platform_devices);
+
+static void __init mpc837x_mds_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc837x_mds_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "fsl,mpc837xmds");
+}
+
+define_machine(mpc837x_mds) {
+	.name			= "MPC837x MDS",
+	.probe			= mpc837x_mds_probe,
+	.setup_arch		= mpc837x_mds_setup_arch,
+	.init_IRQ		= mpc837x_mds_init_IRQ,
+	.get_irq		= ipic_get_irq,
+	.restart		= mpc83xx_restart,
+	.time_init		= mpc83xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 80425d7..14f1080 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -54,7 +54,7 @@
 		       " bus 0\n", dev->full_name);
 	}
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 59c121a..bdb3d0b 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -123,7 +123,7 @@
 	struct device_node* node;
 	struct resource rsrc;
 
-	node = (struct device_node *)hose->arch_data;
+	node = hose->dn;
 	of_address_to_resource(node, 0, &rsrc);
 
 	if ((rsrc.start & 0xfffff) == primary_phb_addr) {
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 61b3eed..e6c63a5 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -30,9 +30,9 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 6390895..c6d2f48 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -124,7 +124,7 @@
 static void __devinit final_uli5288(struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	struct device_node *hosenode = hose ? hose->arch_data : NULL;
+	struct device_node *hosenode = hose ? hose->dn : NULL;
 	struct of_irq oirq;
 	int virq, pin = 2;
 	u32 laddr[3];
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 32a531a..14f4e52 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -116,7 +116,7 @@
 	struct device_node* node;	
 	struct resource rsrc;
 
-	node = (struct device_node *)hose->arch_data;
+	node = hose->dn;
 	of_address_to_resource(node, 0, &rsrc);
 
 	if ((rsrc.start & 0xfffff) == 0x8000) {
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index bd28655..91fbe42 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -18,6 +18,7 @@
 config MPC86XADS
 	bool "MPC86XADS"
 	select CPM1
+	select PPC_CPM_NEW_BINDING
 	help
 	  MPC86x Application Development System by Freescale Semiconductor.
 	  The MPC86xADS is meant to serve as a platform for s/w and h/w
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index d35eda8..ba645c2 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -120,7 +120,7 @@
 	ppc_tb_freq /= 16;
 	ppc_proc_freq = 50000000;
 	if (!get_freq("clock-frequency", &ppc_proc_freq))
-		printk(KERN_ERR "WARNING: Estimating processor frequency"
+		printk(KERN_ERR "WARNING: Estimating processor frequency "
 		                "(not found)\n");
 
 	printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
diff --git a/arch/powerpc/platforms/8xx/mpc86xads.h b/arch/powerpc/platforms/8xx/mpc86xads.h
index cffa194..17b1fe7 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads.h
+++ b/arch/powerpc/platforms/8xx/mpc86xads.h
@@ -15,27 +15,6 @@
 #ifndef __ASM_MPC86XADS_H__
 #define __ASM_MPC86XADS_H__
 
-#include <sysdev/fsl_soc.h>
-
-/* U-Boot maps BCSR to 0xff080000 */
-#define BCSR_ADDR		((uint)0xff080000)
-#define BCSR_SIZE		((uint)32)
-#define BCSR0			((uint)(BCSR_ADDR + 0x00))
-#define BCSR1			((uint)(BCSR_ADDR + 0x04))
-#define BCSR2			((uint)(BCSR_ADDR + 0x08))
-#define BCSR3			((uint)(BCSR_ADDR + 0x0c))
-#define BCSR4			((uint)(BCSR_ADDR + 0x10))
-
-#define CFG_PHYDEV_ADDR		((uint)0xff0a0000)
-#define BCSR5			((uint)(CFG_PHYDEV_ADDR + 0x300))
-
-#define MPC8xx_CPM_OFFSET	(0x9c0)
-#define CPM_MAP_ADDR		(get_immrbase() + MPC8xx_CPM_OFFSET)
-#define CPM_IRQ_OFFSET		16     // for compability with cpm_uart driver
-
-#define PCMCIA_MEM_ADDR		((uint)0xff020000)
-#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
-
 /* Bits of interest in the BCSRs.
  */
 #define BCSR1_ETHEN		((uint)0x20000000)
@@ -64,28 +43,5 @@
 #define BCSR5_MII1_EN		0x02
 #define BCSR5_MII1_RST		0x01
 
-/* Interrupt level assignments */
-#define PHY_INTERRUPT	SIU_IRQ7	/* PHY link change interrupt */
-#define SIU_INT_FEC1	SIU_LEVEL1	/* FEC1 interrupt */
-#define FEC_INTERRUPT	SIU_INT_FEC1	/* FEC interrupt */
-
-/* We don't use the 8259 */
-#define NR_8259_INTS	0
-
-/* CPM Ethernet through SCC1 */
-#define PA_ENET_RXD     ((ushort)0x0001)
-#define PA_ENET_TXD     ((ushort)0x0002)
-#define PA_ENET_TCLK    ((ushort)0x0100)
-#define PA_ENET_RCLK    ((ushort)0x0200)
-#define PB_ENET_TENA    ((uint)0x00001000)
-#define PC_ENET_CLSN    ((ushort)0x0010)
-#define PC_ENET_RENA    ((ushort)0x0020)
-
-/* Control bits in the SICR to route TCLK (CLK1) and RCLK (CLK2) to
- * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
- */
-#define SICR_ENET_MASK  ((uint)0x000000ff)
-#define SICR_ENET_CLKRT ((uint)0x0000002c)
-
 #endif /* __ASM_MPC86XADS_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index 4901283..d2927a4 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -6,265 +6,135 @@
  *
  * Copyright 2005 MontaVista Software Inc.
  *
+ * Heavily modified by Scott Wood <scottwood@freescale.com>
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ *
  * This file is licensed under the terms of the GNU General Public License
  * version 2. This program is licensed "as is" without any warranty of any
  * kind, whether express or implied.
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/root_dev.h>
+#include <linux/of_platform.h>
 
-#include <linux/fs_enet_pd.h>
-#include <linux/fs_uart_pd.h>
-#include <linux/mii.h>
-
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/page.h>
-#include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/commproc.h>
 #include <asm/fs_pd.h>
-#include <asm/prom.h>
+#include <asm/udbg.h>
 
 #include <sysdev/commproc.h>
 
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_scc1_ioports(struct fs_platform_info* ptr);
+#include "mpc86xads.h"
 
-void __init mpc86xads_board_setup(void)
+struct cpm_pin {
+	int port, pin, flags;
+};
+
+static struct cpm_pin mpc866ads_pins[] = {
+	/* SMC1 */
+	{CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
+	{CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
+
+	/* SMC2 */
+	{CPM_PORTB, 21, CPM_PIN_INPUT}, /* RX */
+	{CPM_PORTB, 20, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
+
+	/* SCC1 */
+	{CPM_PORTA, 6, CPM_PIN_INPUT}, /* CLK1 */
+	{CPM_PORTA, 7, CPM_PIN_INPUT}, /* CLK2 */
+	{CPM_PORTA, 14, CPM_PIN_INPUT}, /* TX */
+	{CPM_PORTA, 15, CPM_PIN_INPUT}, /* RX */
+	{CPM_PORTB, 19, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TENA */
+	{CPM_PORTC, 10, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* RENA */
+	{CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CLSN */
+
+	/* MII */
+	{CPM_PORTD, 3, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 4, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 5, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 6, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 7, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 8, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 9, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 10, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 11, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 12, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 13, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 14, CPM_PIN_OUTPUT},
+	{CPM_PORTD, 15, CPM_PIN_OUTPUT},
+};
+
+static void __init init_ioports(void)
 {
-	cpm8xx_t *cp;
- 	unsigned int *bcsr_io;
-	u8 tmpval8;
+	int i;
 
-	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-	cp = (cpm8xx_t *)immr_map(im_cpm);
-
-	if (bcsr_io == NULL) {
-		printk(KERN_CRIT "Could not remap BCSR\n");
-		return;
-	}
-#ifdef CONFIG_SERIAL_CPM_SMC1
-	clrbits32(bcsr_io, BCSR1_RS232EN_1);
-	clrbits32(&cp->cp_simode, 0xe0000000 >> 17);	/* brg1 */
-	tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX);
-	out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
-	clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);
-#else
-	setbits32(bcsr_io,BCSR1_RS232EN_1);
-	out_be16(&cp->cp_smc[0].smc_smcmr, 0);
-	out_8(&cp->cp_smc[0].smc_smce, 0);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SMC2
-	clrbits32(bcsr_io,BCSR1_RS232EN_2);
-	clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
-	setbits32(&cp->cp_simode, 0x20000000 >> 1);	/* brg2 */
-	tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
-	out_8(&(cp->cp_smc[1].smc_smcm), tmpval8);
-	clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN);
-
-	init_smc2_uart_ioports(0);
-#else
-	setbits32(bcsr_io,BCSR1_RS232EN_2);
-	out_be16(&cp->cp_smc[1].smc_smcmr, 0);
-	out_8(&cp->cp_smc[1].smc_smce, 0);
-#endif
-	immr_unmap(cp);
-	iounmap(bcsr_io);
-}
-
-
-static void init_fec1_ioports(struct fs_platform_info* ptr)
-{
-	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
-
-	/* configure FEC1 pins  */
-
-	setbits16(&io_port->iop_pdpar, 0x1fff);
-	setbits16(&io_port->iop_pddir, 0x1fff);
-
-	immr_unmap(io_port);
-}
-
-void init_fec_ioports(struct fs_platform_info *fpi)
-{
-	int fec_no = fs_get_fec_index(fpi->fs_no);
-
-	switch (fec_no) {
-	case 0:
-		init_fec1_ioports(fpi);
-		break;
-	default:
-		printk(KERN_ERR "init_fec_ioports: invalid FEC number\n");
-		return;
-	}
-}
-
-static void init_scc1_ioports(struct fs_platform_info* fpi)
-{
-	unsigned *bcsr_io;
-	iop8xx_t *io_port;
-	cpm8xx_t *cp;
-
-	bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
-	io_port = (iop8xx_t *)immr_map(im_ioport);
-	cp = (cpm8xx_t *)immr_map(im_cpm);
-
-	if (bcsr_io == NULL) {
-		printk(KERN_CRIT "Could not remap BCSR\n");
-		return;
+	for (i = 0; i < ARRAY_SIZE(mpc866ads_pins); i++) {
+		struct cpm_pin *pin = &mpc866ads_pins[i];
+		cpm1_set_pin(pin->port, pin->pin, pin->flags);
 	}
 
-	/* Configure port A pins for Txd and Rxd.
-	 */
-	setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
-	clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD);
-	clrbits16(&io_port->iop_paodr, PA_ENET_TXD);
+	cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
+	cpm1_clk_setup(CPM_CLK_SMC2, CPM_BRG2, CPM_CLK_RTX);
+	cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK1, CPM_CLK_TX);
+	cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK2, CPM_CLK_RX);
 
-	/* Configure port C pins to enable CLSN and RENA.
-	 */
-	clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
-	clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
-	setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
-
-	/* Configure port A for TCLK and RCLK.
-	 */
-	setbits16(&io_port->iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
-        clrbits16(&io_port->iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
-        clrbits32(&cp->cp_pbpar, PB_ENET_TENA);
-        clrbits32(&cp->cp_pbdir, PB_ENET_TENA);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all SCC bits to zero, then set the ones we want.
-	 */
-	clrbits32(&cp->cp_sicr, SICR_ENET_MASK);
-	setbits32(&cp->cp_sicr, SICR_ENET_CLKRT);
-
-	/* In the original SCC enet driver the following code is placed at
-	   the end of the initialization */
-        setbits32(&cp->cp_pbpar, PB_ENET_TENA);
-        setbits32(&cp->cp_pbdir, PB_ENET_TENA);
-
-	clrbits32(bcsr_io+1, BCSR1_ETHEN);
-	iounmap(bcsr_io);
-	immr_unmap(cp);
-	immr_unmap(io_port);
-}
-
-void init_scc_ioports(struct fs_platform_info *fpi)
-{
-	int scc_no = fs_get_scc_index(fpi->fs_no);
-
-	switch (scc_no) {
-	case 0:
-		init_scc1_ioports(fpi);
-		break;
-	default:
-		printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
-		return;
-	}
-}
-
-
-
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
-{
-        unsigned *bcsr_io;
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-
-	setbits32(&cp->cp_pbpar, 0x000000c0);
-	clrbits32(&cp->cp_pbdir, 0x000000c0);
-	clrbits16(&cp->cp_pbodr, 0x00c0);
-	immr_unmap(cp);
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
-        iounmap(bcsr_io);
-}
-
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
-{
-        unsigned *bcsr_io;
-	cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-
-	setbits32(&cp->cp_pbpar, 0x00000c00);
-	clrbits32(&cp->cp_pbdir, 0x00000c00);
-	clrbits16(&cp->cp_pbodr, 0x0c00);
-	immr_unmap(cp);
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        iounmap(bcsr_io);
-}
-
-void init_smc_ioports(struct fs_uart_platform_info *data)
-{
-	int smc_no = fs_uart_id_fsid2smc(data->fs_no);
-
-	switch (smc_no) {
-	case 0:
-		init_smc1_uart_ioports(data);
-		data->brg = data->clk_rx;
-		break;
-	case 1:
-		init_smc2_uart_ioports(data);
-		data->brg = data->clk_rx;
-		break;
-	default:
-		printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
-		return;
-	}
-}
-
-int platform_device_skip(const char *model, int id)
-{
-	return 0;
+	/* Set FEC1 and FEC2 to MII mode */
+	clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180);
 }
 
 static void __init mpc86xads_setup_arch(void)
 {
+	struct device_node *np;
+	u32 __iomem *bcsr_io;
+
 	cpm_reset();
+	init_ioports();
 
-	mpc86xads_board_setup();
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc866ads-bcsr");
+	if (!np) {
+		printk(KERN_CRIT "Could not find fsl,mpc866ads-bcsr node\n");
+		return;
+	}
 
-	ROOT_DEV = Root_NFS;
+	bcsr_io = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR\n");
+		return;
+	}
+
+	clrbits32(bcsr_io, BCSR1_RS232EN_1 | BCSR1_RS232EN_2 | BCSR1_ETHEN);
+	iounmap(bcsr_io);
 }
 
 static int __init mpc86xads_probe(void)
 {
-	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-					  "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strcmp(model, "MPC866ADS"))
-		return 0;
-
-	return 1;
+	unsigned long root = of_get_flat_dt_root();
+	return of_flat_dt_is_compatible(root, "fsl,mpc866ads");
 }
 
+static struct of_device_id __initdata of_bus_ids[] = {
+	{ .name = "soc", },
+	{ .name = "cpm", },
+	{ .name = "localbus", },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	if (machine_is(mpc86x_ads))
+		of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+	return 0;
+}
+device_initcall(declare_of_platform_devices);
+
 define_machine(mpc86x_ads) {
 	.name			= "MPC86x ADS",
 	.probe			= mpc86xads_probe,
@@ -275,4 +145,5 @@
 	.calibrate_decr		= mpc8xx_calibrate_decr,
 	.set_rtc_time		= mpc8xx_set_rtc_time,
 	.get_rtc_time		= mpc8xx_get_rtc_time,
+	.progress		= udbg_progress,
 };
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 61d12f1..3cd565a 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -19,7 +19,7 @@
 spu-manage-$(CONFIG_PPC_CELL_NATIVE)	+= spu_manage.o
 
 obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
-					   spu_syscalls.o \
+					   spu_syscalls.o spu_fault.o \
 					   $(spu-priv1-y) \
 					   $(spu-manage-y) \
 					   spufs/
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index 13d5a87..ec7c8f4 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -21,8 +21,9 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+
 #include <asm/machdep.h>
-#include <asm/of_platform.h>
 #include <asm/prom.h>
 #include <asm/cell-regs.h>
 #include "cbe_cpufreq.h"
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
index 6a2c1b0..69288f6 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
@@ -23,7 +23,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <asm/of_platform.h>
+#include <linux/of_platform.h>
+
 #include <asm/processor.h>
 #include <asm/prom.h>
 #include <asm/pmi.h>
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index 16a9b07..dbc338f 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -9,13 +9,13 @@
 #include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 /*
@@ -256,6 +256,7 @@
 			printk(KERN_ERR "cbe_regs: More BE chips than supported"
 			       "!\n");
 			cbe_regs_map_count--;
+			of_node_put(cpu);
 			return;
 		}
 		map->cpu_node = cpu;
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index 9d7c2ef..b86076e 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -238,7 +238,7 @@
 static void __init spider_pci_add_one(struct pci_controller *phb)
 {
 	struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count];
-	struct device_node *np = phb->arch_data;
+	struct device_node *np = phb->dn;
 	struct resource rsrc;
 	void __iomem *regs;
 
@@ -317,7 +317,7 @@
 	 * update this code to cope with dynamically added busses
 	 */
 	list_for_each_entry(phb, &hose_list, list_node) {
-		struct device_node *np = phb->arch_data;
+		struct device_node *np = phb->dn;
 		const char *model = of_get_property(np, "model", NULL);
 
 		/* If no model property or name isn't exactly "pci", skip */
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index faabc3f..1221c6d 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -26,14 +26,15 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
+#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/udbg.h>
-#include <asm/of_platform.h>
 #include <asm/lmb.h>
+#include <asm/firmware.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
@@ -699,7 +700,8 @@
 {
 	struct device_node *np;
 
-	if (!machine_is(cell))
+	if (!machine_is(cell) &&
+	    !machine_is(celleb_native))
 		return -ENODEV;
 
 	/* If IOMMU is disabled or we have little enough RAM to not need
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 1ed3036..99d688e 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -213,7 +213,7 @@
 		break;
 
 	case pm_interval:
-		READ_SHADOW_REG(val, pm_interval);
+		READ_MMIO_UPPER32(val, pm_interval);
 		break;
 
 	case pm_start_stop:
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 98e7ef8..4f6347c 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -30,6 +30,7 @@
 #include <linux/console.h>
 #include <linux/mutex.h>
 #include <linux/memory_hotplug.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -51,7 +52,6 @@
 #include <asm/spu_priv1.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index e443845..efb3964 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -42,6 +42,7 @@
 #include <asm/firmware.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
+#include <asm/cputhreads.h>
 
 #include "interrupt.h"
 #include <asm/udbg.h>
@@ -182,7 +183,7 @@
 	 */
 	if (system_state < SYSTEM_RUNNING &&
 	    cpu_has_feature(CPU_FTR_SMT) &&
-	    !smt_enabled_at_boot && nr % 2 != 0)
+	    !smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
 		return 0;
 
 	return 1;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index c83c3e3..fb266ae 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -34,6 +34,7 @@
 #include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
+#include <asm/spu_csa.h>
 #include <asm/xmon.h>
 #include <asm/prom.h>
 
@@ -47,6 +48,13 @@
 EXPORT_SYMBOL_GPL(cbe_spu_info);
 
 /*
+ * The spufs fault-handling code needs to call force_sig_info to raise signals
+ * on DMA errors. Export it here to avoid general kernel-wide access to this
+ * function
+ */
+EXPORT_SYMBOL_GPL(force_sig_info);
+
+/*
  * Protects cbe_spu_info and spu->number.
  */
 static DEFINE_SPINLOCK(spu_lock);
@@ -66,6 +74,10 @@
 static DEFINE_SPINLOCK(spu_full_list_lock);
 static DEFINE_MUTEX(spu_full_list_mutex);
 
+struct spu_slb {
+	u64 esid, vsid;
+};
+
 void spu_invalidate_slbs(struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -114,26 +126,11 @@
 }
 EXPORT_SYMBOL_GPL(spu_associate_mm);
 
-static int __spu_trap_invalid_dma(struct spu *spu)
+int spu_64k_pages_available(void)
 {
-	pr_debug("%s\n", __FUNCTION__);
-	spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
-	return 0;
+	return mmu_psize_defs[MMU_PAGE_64K].shift != 0;
 }
-
-static int __spu_trap_dma_align(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
-	return 0;
-}
-
-static int __spu_trap_error(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
-	return 0;
-}
+EXPORT_SYMBOL_GPL(spu_64k_pages_available);
 
 static void spu_restart_dma(struct spu *spu)
 {
@@ -143,11 +140,22 @@
 		out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
 }
 
-static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+	pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
+			__func__, slbe, slb->vsid, slb->esid);
+
+	out_be64(&priv2->slb_index_W, slbe);
+	out_be64(&priv2->slb_vsid_RW, slb->vsid);
+	out_be64(&priv2->slb_esid_RW, slb->esid);
+}
+
+static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+{
 	struct mm_struct *mm = spu->mm;
-	u64 esid, vsid, llp;
+	struct spu_slb slb;
 	int psize;
 
 	pr_debug("%s\n", __FUNCTION__);
@@ -159,7 +167,7 @@
 		printk("%s: invalid access during switch!\n", __func__);
 		return 1;
 	}
-	esid = (ea & ESID_MASK) | SLB_ESID_V;
+	slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
 
 	switch(REGION_ID(ea)) {
 	case USER_REGION_ID:
@@ -168,21 +176,21 @@
 #else
 		psize = mm->context.user_psize;
 #endif
-		vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-				SLB_VSID_USER;
+		slb.vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_USER;
 		break;
 	case VMALLOC_REGION_ID:
 		if (ea < VMALLOC_END)
 			psize = mmu_vmalloc_psize;
 		else
 			psize = mmu_io_psize;
-		vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-			SLB_VSID_KERNEL;
+		slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
 		break;
 	case KERNEL_REGION_ID:
 		psize = mmu_linear_psize;
-		vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-			SLB_VSID_KERNEL;
+		slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+				<< SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
 		break;
 	default:
 		/* Future: support kernel segments so that drivers
@@ -191,11 +199,9 @@
 		pr_debug("invalid region access at %016lx\n", ea);
 		return 1;
 	}
-	llp = mmu_psize_defs[psize].sllp;
+	slb.vsid |= mmu_psize_defs[psize].sllp;
 
-	out_be64(&priv2->slb_index_W, spu->slb_replace);
-	out_be64(&priv2->slb_vsid_RW, vsid | llp);
-	out_be64(&priv2->slb_esid_RW, esid);
+	spu_load_slb(spu, spu->slb_replace, &slb);
 
 	spu->slb_replace++;
 	if (spu->slb_replace >= 8)
@@ -225,13 +231,83 @@
 		return 1;
 	}
 
+	spu->class_0_pending = 0;
 	spu->dar = ea;
 	spu->dsisr = dsisr;
-	mb();
+
 	spu->stop_callback(spu);
+
 	return 0;
 }
 
+static void __spu_kernel_slb(void *addr, struct spu_slb *slb)
+{
+	unsigned long ea = (unsigned long)addr;
+	u64 llp;
+
+	if (REGION_ID(ea) == KERNEL_REGION_ID)
+		llp = mmu_psize_defs[mmu_linear_psize].sllp;
+	else
+		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+
+	slb->vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
+		SLB_VSID_KERNEL | llp;
+	slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
+}
+
+/**
+ * Given an array of @nr_slbs SLB entries, @slbs, return non-zero if the
+ * address @new_addr is present.
+ */
+static inline int __slb_present(struct spu_slb *slbs, int nr_slbs,
+		void *new_addr)
+{
+	unsigned long ea = (unsigned long)new_addr;
+	int i;
+
+	for (i = 0; i < nr_slbs; i++)
+		if (!((slbs[i].esid ^ ea) & ESID_MASK))
+			return 1;
+
+	return 0;
+}
+
+/**
+ * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
+ * need to map both the context save area, and the save/restore code.
+ *
+ * Because the lscsa and code may cross segment boundaires, we check to see
+ * if mappings are required for the start and end of each range. We currently
+ * assume that the mappings are smaller that one segment - if not, something
+ * is seriously wrong.
+ */
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size)
+{
+	struct spu_slb slbs[4];
+	int i, nr_slbs = 0;
+	/* start and end addresses of both mappings */
+	void *addrs[] = {
+		lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
+		code, code + code_size - 1
+	};
+
+	/* check the set of addresses, and create a new entry in the slbs array
+	 * if there isn't already a SLB for that address */
+	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+		if (__slb_present(slbs, nr_slbs, addrs[i]))
+			continue;
+
+		__spu_kernel_slb(addrs[i], &slbs[nr_slbs]);
+		nr_slbs++;
+	}
+
+	/* Add the set of SLBs */
+	for (i = 0; i < nr_slbs; i++)
+		spu_load_slb(spu, i, &slbs[i]);
+}
+EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
+
 static irqreturn_t
 spu_irq_class_0(int irq, void *data)
 {
@@ -240,12 +316,13 @@
 
 	spu = data;
 
-	mask = spu_int_mask_get(spu, 0);
-	stat = spu_int_stat_get(spu, 0);
-	stat &= mask;
-
 	spin_lock(&spu->register_lock);
+	mask = spu_int_mask_get(spu, 0);
+	stat = spu_int_stat_get(spu, 0) & mask;
+
 	spu->class_0_pending |= stat;
+	spu->dsisr = spu_mfc_dsisr_get(spu);
+	spu->dar = spu_mfc_dar_get(spu);
 	spin_unlock(&spu->register_lock);
 
 	spu->stop_callback(spu);
@@ -255,31 +332,6 @@
 	return IRQ_HANDLED;
 }
 
-int
-spu_irq_class_0_bottom(struct spu *spu)
-{
-	unsigned long flags;
-	unsigned long stat;
-
-	spin_lock_irqsave(&spu->register_lock, flags);
-	stat = spu->class_0_pending;
-	spu->class_0_pending = 0;
-
-	if (stat & 1) /* invalid DMA alignment */
-		__spu_trap_dma_align(spu);
-
-	if (stat & 2) /* invalid MFC DMA */
-		__spu_trap_invalid_dma(spu);
-
-	if (stat & 4) /* error on SPU */
-		__spu_trap_error(spu);
-
-	spin_unlock_irqrestore(&spu->register_lock, flags);
-
-	return (stat & 0x7) ? -EIO : 0;
-}
-EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
-
 static irqreturn_t
 spu_irq_class_1(int irq, void *data)
 {
@@ -294,24 +346,23 @@
 	stat  = spu_int_stat_get(spu, 1) & mask;
 	dar   = spu_mfc_dar_get(spu);
 	dsisr = spu_mfc_dsisr_get(spu);
-	if (stat & 2) /* mapping fault */
+	if (stat & CLASS1_STORAGE_FAULT_INTR)
 		spu_mfc_dsisr_set(spu, 0ul);
 	spu_int_stat_clear(spu, 1, stat);
 	spin_unlock(&spu->register_lock);
 	pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
 			dar, dsisr);
 
-	if (stat & 1) /* segment fault */
+	if (stat & CLASS1_SEGMENT_FAULT_INTR)
 		__spu_trap_data_seg(spu, dar);
 
-	if (stat & 2) { /* mapping fault */
+	if (stat & CLASS1_STORAGE_FAULT_INTR)
 		__spu_trap_data_map(spu, dar, dsisr);
-	}
 
-	if (stat & 4) /* ls compare & suspend on get */
+	if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR)
 		;
 
-	if (stat & 8) /* ls compare & suspend on put */
+	if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR)
 		;
 
 	return stat ? IRQ_HANDLED : IRQ_NONE;
@@ -323,6 +374,8 @@
 	struct spu *spu;
 	unsigned long stat;
 	unsigned long mask;
+	const int mailbox_intrs =
+		CLASS2_MAILBOX_THRESHOLD_INTR | CLASS2_MAILBOX_INTR;
 
 	spu = data;
 	spin_lock(&spu->register_lock);
@@ -330,31 +383,30 @@
 	mask = spu_int_mask_get(spu, 2);
 	/* ignore interrupts we're not waiting for */
 	stat &= mask;
-	/*
-	 * mailbox interrupts (0x1 and 0x10) are level triggered.
-	 * mask them now before acknowledging.
-	 */
-	if (stat & 0x11)
-		spu_int_mask_and(spu, 2, ~(stat & 0x11));
+
+	/* mailbox interrupts are level triggered. mask them now before
+	 * acknowledging */
+	if (stat & mailbox_intrs)
+		spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs));
 	/* acknowledge all interrupts before the callbacks */
 	spu_int_stat_clear(spu, 2, stat);
 	spin_unlock(&spu->register_lock);
 
 	pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
 
-	if (stat & 1)  /* PPC core mailbox */
+	if (stat & CLASS2_MAILBOX_INTR)
 		spu->ibox_callback(spu);
 
-	if (stat & 2) /* SPU stop-and-signal */
+	if (stat & CLASS2_SPU_STOP_INTR)
 		spu->stop_callback(spu);
 
-	if (stat & 4) /* SPU halted */
+	if (stat & CLASS2_SPU_HALT_INTR)
 		spu->stop_callback(spu);
 
-	if (stat & 8) /* DMA tag group complete */
+	if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR)
 		spu->mfc_callback(spu);
 
-	if (stat & 0x10) /* SPU mailbox threshold */
+	if (stat & CLASS2_MAILBOX_THRESHOLD_INTR)
 		spu->wbox_callback(spu);
 
 	spu->stats.class2_intr++;
@@ -479,13 +531,27 @@
 int spu_add_sysdev_attr_group(struct attribute_group *attrs)
 {
 	struct spu *spu;
+	int rc = 0;
 
 	mutex_lock(&spu_full_list_mutex);
-	list_for_each_entry(spu, &spu_full_list, full_list)
-		sysfs_create_group(&spu->sysdev.kobj, attrs);
+	list_for_each_entry(spu, &spu_full_list, full_list) {
+		rc = sysfs_create_group(&spu->sysdev.kobj, attrs);
+
+		/* we're in trouble here, but try unwinding anyway */
+		if (rc) {
+			printk(KERN_ERR "%s: can't create sysfs group '%s'\n",
+					__func__, attrs->name);
+
+			list_for_each_entry_continue_reverse(spu,
+					&spu_full_list, full_list)
+				sysfs_remove_group(&spu->sysdev.kobj, attrs);
+			break;
+		}
+	}
+
 	mutex_unlock(&spu_full_list_mutex);
 
-	return 0;
+	return rc;
 }
 EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
 
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
new file mode 100644
index 0000000..c8b1cd4
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_fault.c
@@ -0,0 +1,98 @@
+/*
+ * SPU mm fault handler
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ * Author: Jeremy Kerr <jk@ozlabs.org>
+ *
+ * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+
+/*
+ * This ought to be kept in sync with the powerpc specific do_page_fault
+ * function. Currently, there are a few corner cases that we haven't had
+ * to handle fortunately.
+ */
+int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+		unsigned long dsisr, unsigned *flt)
+{
+	struct vm_area_struct *vma;
+	unsigned long is_write;
+	int ret;
+
+#if 0
+	if (!IS_VALID_EA(ea)) {
+		return -EFAULT;
+	}
+#endif /* XXX */
+	if (mm == NULL) {
+		return -EFAULT;
+	}
+	if (mm->pgd == NULL) {
+		return -EFAULT;
+	}
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, ea);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= ea)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, ea))
+		goto bad_area;
+good_area:
+	is_write = dsisr & MFC_DSISR_ACCESS_PUT;
+	if (is_write) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else {
+		if (dsisr & MFC_DSISR_ACCESS_DENIED)
+			goto bad_area;
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+	ret = 0;
+	*flt = handle_mm_fault(mm, vma, ea, is_write);
+	if (unlikely(*flt & VM_FAULT_ERROR)) {
+		if (*flt & VM_FAULT_OOM) {
+			ret = -ENOMEM;
+			goto bad_area;
+		} else if (*flt & VM_FAULT_SIGBUS) {
+			ret = -EFAULT;
+			goto bad_area;
+		}
+		BUG();
+	}
+	if (*flt & VM_FAULT_MAJOR)
+		current->maj_flt++;
+	else
+		current->min_flt++;
+	up_read(&mm->mmap_sem);
+	return ret;
+
+bad_area:
+	up_read(&mm->mmap_sem);
+	return -EFAULT;
+}
+EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 1b01070..d351bde 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -35,6 +35,7 @@
 #include <asm/firmware.h>
 #include <asm/prom.h>
 
+#include "spufs/spufs.h"
 #include "interrupt.h"
 
 struct device_node *spu_devnode(struct spu *spu)
@@ -345,7 +346,7 @@
 		}
 		ret = spu_map_interrupts_old(spu, spe);
 		if (ret) {
-			printk(KERN_ERR "%s: could not map interrupts",
+			printk(KERN_ERR "%s: could not map interrupts\n",
 				spu->name);
 			goto out_unmap;
 		}
@@ -369,6 +370,16 @@
 	return 0;
 }
 
+static void enable_spu_by_master_run(struct spu_context *ctx)
+{
+	ctx->ops->master_start(ctx);
+}
+
+static void disable_spu_by_master_run(struct spu_context *ctx)
+{
+	ctx->ops->master_stop(ctx);
+}
+
 /* Hardcoded affinity idxs for qs20 */
 #define QS20_SPES_PER_BE 8
 static int qs20_reg_idxs[QS20_SPES_PER_BE] =   { 0, 2, 4, 6, 7, 5, 3, 1 };
@@ -411,10 +422,15 @@
 
 static int of_has_vicinity(void)
 {
-	struct spu* spu;
+	struct device_node *dn;
 
-	spu = list_first_entry(&cbe_spu_info[0].spus, struct spu, cbe_list);
-	return of_find_property(spu_devnode(spu), "vicinity", NULL) != NULL;
+	for_each_node_by_type(dn, "spe") {
+		if (of_find_property(dn, "vicinity", NULL))  {
+			of_node_put(dn);
+			return 1;
+		}
+	}
+	return 0;
 }
 
 static struct spu *devnode_spu(int cbe, struct device_node *dn)
@@ -525,7 +541,7 @@
 		if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
 			init_affinity_qs20_harcoded();
 		else
-			printk("No affinity configuration found");
+			printk("No affinity configuration found\n");
 	}
 
 	return 0;
@@ -535,5 +551,7 @@
 	.enumerate_spus = of_enumerate_spus,
 	.create_spu = of_create_spu,
 	.destroy_spu = of_destroy_spu,
+	.enable_spu = enable_spu_by_master_run,
+	.disable_spu = disable_spu_by_master_run,
 	.init_affinity = init_affinity,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index 328afcf..d3a349f 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,8 +1,8 @@
-obj-y += switch.o fault.o lscsa_alloc.o
 
 obj-$(CONFIG_SPU_FS) += spufs.o
 spufs-y += inode.o file.o context.o syscalls.o coredump.o
 spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
+spufs-y += switch.o fault.o lscsa_alloc.o
 
 # Rules to build switch.o with the help of SPU tool chain
 SPU_CROSS	:= spu-
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
index ec01214..50d98a1 100644
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -106,16 +106,20 @@
 		if (stat & 0xff0000)
 			ret |= POLLIN | POLLRDNORM;
 		else {
-			ctx->csa.priv1.int_stat_class0_RW &= ~0x1;
-			ctx->csa.priv1.int_mask_class2_RW |= 0x1;
+			ctx->csa.priv1.int_stat_class2_RW &=
+				~CLASS2_MAILBOX_INTR;
+			ctx->csa.priv1.int_mask_class2_RW |=
+				CLASS2_ENABLE_MAILBOX_INTR;
 		}
 	}
 	if (events & (POLLOUT | POLLWRNORM)) {
 		if (stat & 0x00ff00)
 			ret = POLLOUT | POLLWRNORM;
 		else {
-			ctx->csa.priv1.int_stat_class0_RW &= ~0x10;
-			ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+			ctx->csa.priv1.int_stat_class2_RW &=
+				~CLASS2_MAILBOX_THRESHOLD_INTR;
+			ctx->csa.priv1.int_mask_class2_RW |=
+				CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
 		}
 	}
 	spin_unlock_irq(&ctx->csa.register_lock);
@@ -139,7 +143,7 @@
 		ret = 4;
 	} else {
 		/* make sure we get woken up by the interrupt */
-		ctx->csa.priv1.int_mask_class2_RW |= 0x1UL;
+		ctx->csa.priv1.int_mask_class2_RW |= CLASS2_ENABLE_MAILBOX_INTR;
 		ret = 0;
 	}
 	spin_unlock(&ctx->csa.register_lock);
@@ -169,7 +173,8 @@
 	} else {
 		/* make sure we get woken up by the interrupt when space
 		   becomes available */
-		ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+		ctx->csa.priv1.int_mask_class2_RW |=
+			CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
 		ret = 0;
 	}
 	spin_unlock(&ctx->csa.register_lock);
@@ -268,6 +273,11 @@
 	return ctx->csa.lscsa->ls;
 }
 
+static void spu_backing_privcntl_write(struct spu_context *ctx, u64 val)
+{
+	ctx->csa.priv2.spu_privcntl_RW = val;
+}
+
 static u32 spu_backing_runcntl_read(struct spu_context *ctx)
 {
 	return ctx->csa.prob.spu_runcntl_RW;
@@ -285,6 +295,11 @@
 	spin_unlock(&ctx->csa.register_lock);
 }
 
+static void spu_backing_runcntl_stop(struct spu_context *ctx)
+{
+	spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
+}
+
 static void spu_backing_master_start(struct spu_context *ctx)
 {
 	struct spu_state *csa = &ctx->csa;
@@ -358,7 +373,7 @@
 
 static void spu_backing_restart_dma(struct spu_context *ctx)
 {
-	/* nothing to do here */
+	ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND;
 }
 
 struct spu_context_ops spu_backing_ops = {
@@ -379,8 +394,10 @@
 	.npc_write = spu_backing_npc_write,
 	.status_read = spu_backing_status_read,
 	.get_ls = spu_backing_get_ls,
+	.privcntl_write = spu_backing_privcntl_write,
 	.runcntl_read = spu_backing_runcntl_read,
 	.runcntl_write = spu_backing_runcntl_write,
+	.runcntl_stop = spu_backing_runcntl_stop,
 	.master_start = spu_backing_master_start,
 	.master_stop = spu_backing_master_stop,
 	.set_mfc_query = spu_backing_set_mfc_query,
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 9cb081c..237e152 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -52,6 +52,7 @@
 	init_waitqueue_head(&ctx->wbox_wq);
 	init_waitqueue_head(&ctx->stop_wq);
 	init_waitqueue_head(&ctx->mfc_wq);
+	init_waitqueue_head(&ctx->run_wq);
 	ctx->state = SPU_STATE_SAVED;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
@@ -105,7 +106,17 @@
 void spu_forget(struct spu_context *ctx)
 {
 	struct mm_struct *mm;
-	spu_acquire_saved(ctx);
+
+	/*
+	 * This is basically an open-coded spu_acquire_saved, except that
+	 * we don't acquire the state mutex interruptible.
+	 */
+	mutex_lock(&ctx->state_mutex);
+	if (ctx->state != SPU_STATE_SAVED) {
+		set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
+		spu_deactivate(ctx);
+	}
+
 	mm = ctx->owner;
 	ctx->owner = NULL;
 	mmput(mm);
@@ -133,47 +144,23 @@
 }
 
 /**
- * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
- * @ctx:	spu contex to lock
- *
- * Note:
- *	Returns 0 and with the context locked on success
- *	Returns negative error and with the context _unlocked_ on failure.
- */
-int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags)
-{
-	int ret = -EINVAL;
-
-	spu_acquire(ctx);
-	if (ctx->state == SPU_STATE_SAVED) {
-		/*
-		 * Context is about to be freed, so we can't acquire it anymore.
-		 */
-		if (!ctx->owner)
-			goto out_unlock;
-		ret = spu_activate(ctx, flags);
-		if (ret)
-			goto out_unlock;
-	}
-
-	return 0;
-
- out_unlock:
-	spu_release(ctx);
-	return ret;
-}
-
-/**
  * spu_acquire_saved - lock spu contex and make sure it is in saved state
  * @ctx:	spu contex to lock
  */
-void spu_acquire_saved(struct spu_context *ctx)
+int spu_acquire_saved(struct spu_context *ctx)
 {
-	spu_acquire(ctx);
+	int ret;
+
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
+
 	if (ctx->state != SPU_STATE_SAVED) {
 		set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
 		spu_deactivate(ctx);
 	}
+
+	return 0;
 }
 
 /**
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 80f6236..0c6a96b8 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -148,7 +148,9 @@
 
 	fd = 0;
 	while ((ctx = coredump_next_context(&fd)) != NULL) {
-		spu_acquire_saved(ctx);
+		rc = spu_acquire_saved(ctx);
+		if (rc)
+			break;
 		rc = spufs_ctx_note_size(ctx, fd);
 		spu_release_saved(ctx);
 		if (rc < 0)
@@ -224,7 +226,9 @@
 
 	fd = 0;
 	while ((ctx = coredump_next_context(&fd)) != NULL) {
-		spu_acquire_saved(ctx);
+		rc = spu_acquire_saved(ctx);
+		if (rc)
+			return rc;
 
 		for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
 			rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index 917eab4..eff4d29 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -28,117 +28,71 @@
 
 #include "spufs.h"
 
-/*
- * This ought to be kept in sync with the powerpc specific do_page_fault
- * function. Currently, there are a few corner cases that we haven't had
- * to handle fortunately.
+/**
+ * Handle an SPE event, depending on context SPU_CREATE_EVENTS_ENABLED flag.
+ *
+ * If the context was created with events, we just set the return event.
+ * Otherwise, send an appropriate signal to the process.
  */
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
-		unsigned long dsisr, unsigned *flt)
-{
-	struct vm_area_struct *vma;
-	unsigned long is_write;
-	int ret;
-
-#if 0
-	if (!IS_VALID_EA(ea)) {
-		return -EFAULT;
-	}
-#endif /* XXX */
-	if (mm == NULL) {
-		return -EFAULT;
-	}
-	if (mm->pgd == NULL) {
-		return -EFAULT;
-	}
-
-	down_read(&mm->mmap_sem);
-	vma = find_vma(mm, ea);
-	if (!vma)
-		goto bad_area;
-	if (vma->vm_start <= ea)
-		goto good_area;
-	if (!(vma->vm_flags & VM_GROWSDOWN))
-		goto bad_area;
-	if (expand_stack(vma, ea))
-		goto bad_area;
-good_area:
-	is_write = dsisr & MFC_DSISR_ACCESS_PUT;
-	if (is_write) {
-		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;
-	} else {
-		if (dsisr & MFC_DSISR_ACCESS_DENIED)
-			goto bad_area;
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-			goto bad_area;
-	}
-	ret = 0;
-	*flt = handle_mm_fault(mm, vma, ea, is_write);
-	if (unlikely(*flt & VM_FAULT_ERROR)) {
-		if (*flt & VM_FAULT_OOM) {
-			ret = -ENOMEM;
-			goto bad_area;
-		} else if (*flt & VM_FAULT_SIGBUS) {
-			ret = -EFAULT;
-			goto bad_area;
-		}
-		BUG();
-	}
-	if (*flt & VM_FAULT_MAJOR)
-		current->maj_flt++;
-	else
-		current->min_flt++;
-	up_read(&mm->mmap_sem);
-	return ret;
-
-bad_area:
-	up_read(&mm->mmap_sem);
-	return -EFAULT;
-}
-
-static void spufs_handle_dma_error(struct spu_context *ctx,
+static void spufs_handle_event(struct spu_context *ctx,
 				unsigned long ea, int type)
 {
+	siginfo_t info;
+
 	if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
 		ctx->event_return |= type;
 		wake_up_all(&ctx->stop_wq);
-	} else {
-		siginfo_t info;
-		memset(&info, 0, sizeof(info));
-
-		switch (type) {
-		case SPE_EVENT_INVALID_DMA:
-			info.si_signo = SIGBUS;
-			info.si_code = BUS_OBJERR;
-			break;
-		case SPE_EVENT_SPE_DATA_STORAGE:
-			info.si_signo = SIGBUS;
-			info.si_addr = (void __user *)ea;
-			info.si_code = BUS_ADRERR;
-			break;
-		case SPE_EVENT_DMA_ALIGNMENT:
-			info.si_signo = SIGBUS;
-			/* DAR isn't set for an alignment fault :( */
-			info.si_code = BUS_ADRALN;
-			break;
-		case SPE_EVENT_SPE_ERROR:
-			info.si_signo = SIGILL;
-			info.si_addr = (void __user *)(unsigned long)
-				ctx->ops->npc_read(ctx) - 4;
-			info.si_code = ILL_ILLOPC;
-			break;
-		}
-		if (info.si_signo)
-			force_sig_info(info.si_signo, &info, current);
+		return;
 	}
+
+	memset(&info, 0, sizeof(info));
+
+	switch (type) {
+	case SPE_EVENT_INVALID_DMA:
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_OBJERR;
+		break;
+	case SPE_EVENT_SPE_DATA_STORAGE:
+		info.si_signo = SIGSEGV;
+		info.si_addr = (void __user *)ea;
+		info.si_code = SEGV_ACCERR;
+		ctx->ops->restart_dma(ctx);
+		break;
+	case SPE_EVENT_DMA_ALIGNMENT:
+		info.si_signo = SIGBUS;
+		/* DAR isn't set for an alignment fault :( */
+		info.si_code = BUS_ADRALN;
+		break;
+	case SPE_EVENT_SPE_ERROR:
+		info.si_signo = SIGILL;
+		info.si_addr = (void __user *)(unsigned long)
+			ctx->ops->npc_read(ctx) - 4;
+		info.si_code = ILL_ILLOPC;
+		break;
+	}
+
+	if (info.si_signo)
+		force_sig_info(info.si_signo, &info, current);
 }
 
-void spufs_dma_callback(struct spu *spu, int type)
+int spufs_handle_class0(struct spu_context *ctx)
 {
-	spufs_handle_dma_error(spu->ctx, spu->dar, type);
+	unsigned long stat = ctx->csa.class_0_pending & CLASS0_INTR_MASK;
+
+	if (likely(!stat))
+		return 0;
+
+	if (stat & CLASS0_DMA_ALIGNMENT_INTR)
+		spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT);
+
+	if (stat & CLASS0_INVALID_DMA_COMMAND_INTR)
+		spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA);
+
+	if (stat & CLASS0_SPU_ERROR_INTR)
+		spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR);
+
+	return -EIO;
 }
-EXPORT_SYMBOL_GPL(spufs_dma_callback);
 
 /*
  * bottom half handler for page faults, we can't do this from
@@ -154,7 +108,7 @@
 	u64 ea, dsisr, access;
 	unsigned long flags;
 	unsigned flt = 0;
-	int ret;
+	int ret, ret2;
 
 	/*
 	 * dar and dsisr get passed from the registers
@@ -165,16 +119,8 @@
 	 * in time, we can still expect to get the same fault
 	 * the immediately after the context restore.
 	 */
-	if (ctx->state == SPU_STATE_RUNNABLE) {
-		ea = ctx->spu->dar;
-		dsisr = ctx->spu->dsisr;
-		ctx->spu->dar= ctx->spu->dsisr = 0;
-	} else {
-		ea = ctx->csa.priv1.mfc_dar_RW;
-		dsisr = ctx->csa.priv1.mfc_dsisr_RW;
-		ctx->csa.priv1.mfc_dar_RW = 0;
-		ctx->csa.priv1.mfc_dsisr_RW = 0;
-	}
+	ea = ctx->csa.dar;
+	dsisr = ctx->csa.dsisr;
 
 	if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
 		return 0;
@@ -201,7 +147,22 @@
 	if (ret)
 		ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
-	spu_acquire(ctx);
+	/*
+	 * If spu_acquire fails due to a pending signal we just want to return
+	 * EINTR to userspace even if that means missing the dma restart or
+	 * updating the page fault statistics.
+	 */
+	ret2 = spu_acquire(ctx);
+	if (ret2)
+		goto out;
+
+	/*
+	 * Clear dsisr under ctxt lock after handling the fault, so that
+	 * time slicing will not preempt the context while the page fault
+	 * handler is running. Context switch code removes mappings.
+	 */
+	ctx->csa.dar = ctx->csa.dsisr = 0;
+
 	/*
 	 * If we handled the fault successfully and are in runnable
 	 * state, restart the DMA.
@@ -222,9 +183,9 @@
 		if (ctx->spu)
 			ctx->ops->restart_dma(ctx);
 	} else
-		spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
+		spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+ out:
 	spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index d9e56a5..3fcd064 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -40,6 +40,120 @@
 
 #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
 
+/* Simple attribute files */
+struct spufs_attr {
+	int (*get)(void *, u64 *);
+	int (*set)(void *, u64);
+	char get_buf[24];       /* enough to store a u64 and "\n\0" */
+	char set_buf[24];
+	void *data;
+	const char *fmt;        /* format for read operation */
+	struct mutex mutex;     /* protects access to these buffers */
+};
+
+static int spufs_attr_open(struct inode *inode, struct file *file,
+		int (*get)(void *, u64 *), int (*set)(void *, u64),
+		const char *fmt)
+{
+	struct spufs_attr *attr;
+
+	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	attr->get = get;
+	attr->set = set;
+	attr->data = inode->i_private;
+	attr->fmt = fmt;
+	mutex_init(&attr->mutex);
+	file->private_data = attr;
+
+	return nonseekable_open(inode, file);
+}
+
+static int spufs_attr_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+	return 0;
+}
+
+static ssize_t spufs_attr_read(struct file *file, char __user *buf,
+		size_t len, loff_t *ppos)
+{
+	struct spufs_attr *attr;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+	if (!attr->get)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	if (*ppos) {		/* continued read */
+		size = strlen(attr->get_buf);
+	} else {		/* first read */
+		u64 val;
+		ret = attr->get(attr->data, &val);
+		if (ret)
+			goto out;
+
+		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+				 attr->fmt, (unsigned long long)val);
+	}
+
+	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+
+static ssize_t spufs_attr_write(struct file *file, const char __user *buf,
+		size_t len, loff_t *ppos)
+{
+	struct spufs_attr *attr;
+	u64 val;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+	if (!attr->set)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	size = min(sizeof(attr->set_buf) - 1, len);
+	if (copy_from_user(attr->set_buf, buf, size))
+		goto out;
+
+	ret = len; /* claim we got the whole input */
+	attr->set_buf[size] = '\0';
+	val = simple_strtol(attr->set_buf, NULL, 0);
+	attr->set(attr->data, val);
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+
+#define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)	\
+static int __fops ## _open(struct inode *inode, struct file *file)	\
+{									\
+	__simple_attr_check_format(__fmt, 0ull);			\
+	return spufs_attr_open(inode, file, __get, __set, __fmt);	\
+}									\
+static struct file_operations __fops = {				\
+	.owner	 = THIS_MODULE,						\
+	.open	 = __fops ## _open,					\
+	.release = spufs_attr_release,					\
+	.read	 = spufs_attr_read,					\
+	.write	 = spufs_attr_write,					\
+};
+
 
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
@@ -84,9 +198,12 @@
 	struct spu_context *ctx = file->private_data;
 	ssize_t ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ret = __spufs_mem_read(ctx, buffer, size, pos);
 	spu_release(ctx);
+
 	return ret;
 }
 
@@ -106,7 +223,10 @@
 	if (size > LS_SIZE - pos)
 		size = LS_SIZE - pos;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
+
 	local_store = ctx->ops->get_ls(ctx);
 	ret = copy_from_user(local_store + pos, buffer, size);
 	spu_release(ctx);
@@ -146,7 +266,8 @@
 	pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n",
 		 addr0, address, offset);
 
-	spu_acquire(ctx);
+	if (spu_acquire(ctx))
+		return NOPFN_REFAULT;
 
 	if (ctx->state == SPU_STATE_SAVED) {
 		vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
@@ -236,23 +357,32 @@
 {
 	struct spu_context *ctx = vma->vm_file->private_data;
 	unsigned long area, offset = address - vma->vm_start;
-	int ret;
 
 	offset += vma->vm_pgoff << PAGE_SHIFT;
 	if (offset >= ps_size)
 		return NOPFN_SIGBUS;
 
-	/* error here usually means a signal.. we might want to test
-	 * the error code more precisely though
+	/*
+	 * We have to wait for context to be loaded before we have
+	 * pages to hand out to the user, but we don't want to wait
+	 * with the mmap_sem held.
+	 * It is possible to drop the mmap_sem here, but then we need
+	 * to return NOPFN_REFAULT because the mappings may have
+	 * hanged.
 	 */
-	ret = spu_acquire_runnable(ctx, 0);
-	if (ret)
+	if (spu_acquire(ctx))
 		return NOPFN_REFAULT;
 
-	area = ctx->spu->problem_phys + ps_offs;
-	vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
-	spu_release(ctx);
+	if (ctx->state == SPU_STATE_SAVED) {
+		up_read(&current->mm->mmap_sem);
+		spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
+		down_read(&current->mm->mmap_sem);
+	} else {
+		area = ctx->spu->problem_phys + ps_offs;
+		vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
+	}
 
+	spu_release(ctx);
 	return NOPFN_REFAULT;
 }
 
@@ -286,25 +416,32 @@
 #define spufs_cntl_mmap NULL
 #endif /* !SPUFS_MMAP_4K */
 
-static u64 spufs_cntl_get(void *data)
+static int spufs_cntl_get(void *data, u64 *val)
 {
 	struct spu_context *ctx = data;
-	u64 val;
+	int ret;
 
-	spu_acquire(ctx);
-	val = ctx->ops->status_read(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
+	*val = ctx->ops->status_read(ctx);
 	spu_release(ctx);
 
-	return val;
+	return 0;
 }
 
-static void spufs_cntl_set(void *data, u64 val)
+static int spufs_cntl_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
+	int ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->runcntl_write(ctx, val);
 	spu_release(ctx);
+
+	return 0;
 }
 
 static int spufs_cntl_open(struct inode *inode, struct file *file)
@@ -317,7 +454,7 @@
 	if (!i->i_openers++)
 		ctx->cntl = inode->i_mapping;
 	mutex_unlock(&ctx->mapping_lock);
-	return simple_attr_open(inode, file, spufs_cntl_get,
+	return spufs_attr_open(inode, file, spufs_cntl_get,
 					spufs_cntl_set, "0x%08lx");
 }
 
@@ -327,7 +464,7 @@
 	struct spufs_inode_info *i = SPUFS_I(inode);
 	struct spu_context *ctx = i->i_ctx;
 
-	simple_attr_close(inode, file);
+	spufs_attr_release(inode, file);
 
 	mutex_lock(&ctx->mapping_lock);
 	if (!--i->i_openers)
@@ -339,8 +476,8 @@
 static const struct file_operations spufs_cntl_fops = {
 	.open = spufs_cntl_open,
 	.release = spufs_cntl_release,
-	.read = simple_attr_read,
-	.write = simple_attr_write,
+	.read = spufs_attr_read,
+	.write = spufs_attr_write,
 	.mmap = spufs_cntl_mmap,
 };
 
@@ -368,7 +505,9 @@
 	int ret;
 	struct spu_context *ctx = file->private_data;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	ret = __spufs_regs_read(ctx, buffer, size, pos);
 	spu_release_saved(ctx);
 	return ret;
@@ -387,7 +526,9 @@
 		return -EFBIG;
 	*pos += size;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 
 	ret = copy_from_user(lscsa->gprs + *pos - size,
 			     buffer, size) ? -EFAULT : size;
@@ -419,7 +560,9 @@
 	int ret;
 	struct spu_context *ctx = file->private_data;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	ret = __spufs_fpcr_read(ctx, buffer, size, pos);
 	spu_release_saved(ctx);
 	return ret;
@@ -436,10 +579,12 @@
 	size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
 	if (size <= 0)
 		return -EFBIG;
+
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
+
 	*pos += size;
-
-	spu_acquire_saved(ctx);
-
 	ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
 			     buffer, size) ? -EFAULT : size;
 
@@ -486,7 +631,10 @@
 
 	udata = (void __user *)buf;
 
-	spu_acquire(ctx);
+	count = spu_acquire(ctx);
+	if (count)
+		return count;
+
 	for (count = 0; (count + 4) <= len; count += 4, udata++) {
 		int ret;
 		ret = ctx->ops->mbox_read(ctx, &mbox_data);
@@ -522,12 +670,15 @@
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	ssize_t ret;
 	u32 mbox_stat;
 
 	if (len < 4)
 		return -EINVAL;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 
 	mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
 
@@ -562,6 +713,9 @@
 {
 	struct spu_context *ctx = spu->ctx;
 
+	if (!ctx)
+		return;
+
 	wake_up_all(&ctx->ibox_wq);
 	kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
 }
@@ -593,7 +747,9 @@
 
 	udata = (void __user *)buf;
 
-	spu_acquire(ctx);
+	count = spu_acquire(ctx);
+	if (count)
+		return count;
 
 	/* wait only for the first element */
 	count = 0;
@@ -639,7 +795,11 @@
 
 	poll_wait(file, &ctx->ibox_wq, wait);
 
-	spu_acquire(ctx);
+	/*
+	 * For now keep this uninterruptible and also ignore the rule
+	 * that poll should not sleep.  Will be fixed later.
+	 */
+	mutex_lock(&ctx->state_mutex);
 	mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
 	spu_release(ctx);
 
@@ -657,12 +817,15 @@
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	ssize_t ret;
 	u32 ibox_stat;
 
 	if (len < 4)
 		return -EINVAL;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
 	spu_release(ctx);
 
@@ -698,6 +861,9 @@
 {
 	struct spu_context *ctx = spu->ctx;
 
+	if (!ctx)
+		return;
+
 	wake_up_all(&ctx->wbox_wq);
 	kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
 }
@@ -731,7 +897,9 @@
 	if (__get_user(wbox_data, udata))
 		return -EFAULT;
 
-	spu_acquire(ctx);
+	count = spu_acquire(ctx);
+	if (count)
+		return count;
 
 	/*
 	 * make sure we can at least write one element, by waiting
@@ -772,7 +940,11 @@
 
 	poll_wait(file, &ctx->wbox_wq, wait);
 
-	spu_acquire(ctx);
+	/*
+	 * For now keep this uninterruptible and also ignore the rule
+	 * that poll should not sleep.  Will be fixed later.
+	 */
+	mutex_lock(&ctx->state_mutex);
 	mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
 	spu_release(ctx);
 
@@ -790,12 +962,15 @@
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	ssize_t ret;
 	u32 wbox_stat;
 
 	if (len < 4)
 		return -EINVAL;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
 	spu_release(ctx);
 
@@ -866,7 +1041,9 @@
 	int ret;
 	struct spu_context *ctx = file->private_data;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	ret = __spufs_signal1_read(ctx, buf, len, pos);
 	spu_release_saved(ctx);
 
@@ -877,6 +1054,7 @@
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx;
+	ssize_t ret;
 	u32 data;
 
 	ctx = file->private_data;
@@ -887,7 +1065,9 @@
 	if (copy_from_user(&data, buf, 4))
 		return -EFAULT;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->signal1_write(ctx, data);
 	spu_release(ctx);
 
@@ -997,7 +1177,9 @@
 	struct spu_context *ctx = file->private_data;
 	int ret;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	ret = __spufs_signal2_read(ctx, buf, len, pos);
 	spu_release_saved(ctx);
 
@@ -1008,6 +1190,7 @@
 			size_t len, loff_t *pos)
 {
 	struct spu_context *ctx;
+	ssize_t ret;
 	u32 data;
 
 	ctx = file->private_data;
@@ -1018,7 +1201,9 @@
 	if (copy_from_user(&data, buf, 4))
 		return -EFAULT;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->signal2_write(ctx, data);
 	spu_release(ctx);
 
@@ -1086,33 +1271,42 @@
 #define SPU_ATTR_ACQUIRE_SAVED	2
 
 #define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire)	\
-static u64 __##__get(void *data)					\
+static int __##__get(void *data, u64 *val)				\
 {									\
 	struct spu_context *ctx = data;					\
-	u64 ret;							\
+	int ret = 0;							\
 									\
 	if (__acquire == SPU_ATTR_ACQUIRE) {				\
-		spu_acquire(ctx);					\
-		ret = __get(ctx);					\
+		ret = spu_acquire(ctx);					\
+		if (ret)						\
+			return ret;					\
+		*val = __get(ctx);					\
 		spu_release(ctx);					\
 	} else if (__acquire == SPU_ATTR_ACQUIRE_SAVED)	{		\
-		spu_acquire_saved(ctx);					\
-		ret = __get(ctx);					\
+		ret = spu_acquire_saved(ctx);				\
+		if (ret)						\
+			return ret;					\
+		*val = __get(ctx);					\
 		spu_release_saved(ctx);					\
 	} else								\
-		ret = __get(ctx);					\
+		*val = __get(ctx);					\
 									\
-	return ret;							\
+	return 0;							\
 }									\
-DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
+DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
 
-static void spufs_signal1_type_set(void *data, u64 val)
+static int spufs_signal1_type_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
+	int ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->signal1_type_set(ctx, val);
 	spu_release(ctx);
+
+	return 0;
 }
 
 static u64 spufs_signal1_type_get(struct spu_context *ctx)
@@ -1123,13 +1317,18 @@
 		       spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
 
 
-static void spufs_signal2_type_set(void *data, u64 val)
+static int spufs_signal2_type_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
+	int ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->signal2_type_set(ctx, val);
 	spu_release(ctx);
+
+	return 0;
 }
 
 static u64 spufs_signal2_type_get(struct spu_context *ctx)
@@ -1329,6 +1528,9 @@
 {
 	struct spu_context *ctx = spu->ctx;
 
+	if (!ctx)
+		return;
+
 	wake_up_all(&ctx->mfc_wq);
 
 	pr_debug("%s %s\n", __FUNCTION__, spu->name);
@@ -1375,12 +1577,17 @@
 	if (size != 4)
 		goto out;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
+
+	ret = -EINVAL;
 	if (file->f_flags & O_NONBLOCK) {
 		status = ctx->ops->read_mfc_tagstatus(ctx);
 		if (!(status & ctx->tagwait))
 			ret = -EAGAIN;
 		else
+			/* XXX(hch): shouldn't we clear ret here? */
 			ctx->tagwait &= ~status;
 	} else {
 		ret = spufs_wait(ctx->mfc_wq,
@@ -1505,7 +1712,11 @@
 	if (ret)
 		goto out;
 
-	ret = spu_acquire_runnable(ctx, 0);
+	ret = spu_acquire(ctx);
+	if (ret)
+		goto out;
+
+	ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
 	if (ret)
 		goto out;
 
@@ -1539,7 +1750,11 @@
 
 	poll_wait(file, &ctx->mfc_wq, wait);
 
-	spu_acquire(ctx);
+	/*
+	 * For now keep this uninterruptible and also ignore the rule
+	 * that poll should not sleep.  Will be fixed later.
+	 */
+	mutex_lock(&ctx->state_mutex);
 	ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
 	free_elements = ctx->ops->get_mfc_free_elements(ctx);
 	tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
@@ -1562,7 +1777,9 @@
 	struct spu_context *ctx = file->private_data;
 	int ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 #if 0
 /* this currently hangs */
 	ret = spufs_wait(ctx->mfc_wq,
@@ -1605,12 +1822,18 @@
 	.mmap	 = spufs_mfc_mmap,
 };
 
-static void spufs_npc_set(void *data, u64 val)
+static int spufs_npc_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
-	spu_acquire(ctx);
+	int ret;
+
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
 	ctx->ops->npc_write(ctx, val);
 	spu_release(ctx);
+
+	return 0;
 }
 
 static u64 spufs_npc_get(struct spu_context *ctx)
@@ -1620,13 +1843,19 @@
 DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
 		       "0x%llx\n", SPU_ATTR_ACQUIRE);
 
-static void spufs_decr_set(void *data, u64 val)
+static int spufs_decr_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
 	struct spu_lscsa *lscsa = ctx->csa.lscsa;
-	spu_acquire_saved(ctx);
+	int ret;
+
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	lscsa->decr.slot[0] = (u32) val;
 	spu_release_saved(ctx);
+
+	return 0;
 }
 
 static u64 spufs_decr_get(struct spu_context *ctx)
@@ -1637,15 +1866,21 @@
 DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
 		       "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
 
-static void spufs_decr_status_set(void *data, u64 val)
+static int spufs_decr_status_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
-	spu_acquire_saved(ctx);
+	int ret;
+
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	if (val)
 		ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING;
 	else
 		ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
 	spu_release_saved(ctx);
+
+	return 0;
 }
 
 static u64 spufs_decr_status_get(struct spu_context *ctx)
@@ -1659,13 +1894,19 @@
 		       spufs_decr_status_set, "0x%llx\n",
 		       SPU_ATTR_ACQUIRE_SAVED);
 
-static void spufs_event_mask_set(void *data, u64 val)
+static int spufs_event_mask_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
 	struct spu_lscsa *lscsa = ctx->csa.lscsa;
-	spu_acquire_saved(ctx);
+	int ret;
+
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	lscsa->event_mask.slot[0] = (u32) val;
 	spu_release_saved(ctx);
+
+	return 0;
 }
 
 static u64 spufs_event_mask_get(struct spu_context *ctx)
@@ -1690,13 +1931,19 @@
 DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
 		       NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
 
-static void spufs_srr0_set(void *data, u64 val)
+static int spufs_srr0_set(void *data, u64 val)
 {
 	struct spu_context *ctx = data;
 	struct spu_lscsa *lscsa = ctx->csa.lscsa;
-	spu_acquire_saved(ctx);
+	int ret;
+
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	lscsa->srr0.slot[0] = (u32) val;
 	spu_release_saved(ctx);
+
+	return 0;
 }
 
 static u64 spufs_srr0_get(struct spu_context *ctx)
@@ -1727,10 +1974,12 @@
 	return ctx->object_id;
 }
 
-static void spufs_object_id_set(void *data, u64 id)
+static int spufs_object_id_set(void *data, u64 id)
 {
 	struct spu_context *ctx = data;
 	ctx->object_id = id;
+
+	return 0;
 }
 
 DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
@@ -1777,13 +2026,13 @@
 static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
 			char __user *buf, size_t len, loff_t *pos)
 {
-	u32 mbox_stat;
 	u32 data;
 
-	mbox_stat = ctx->csa.prob.mb_stat_R;
-	if (mbox_stat & 0x0000ff) {
-		data = ctx->csa.prob.pu_mb_R;
-	}
+	/* EOF if there's no entry in the mbox */
+	if (!(ctx->csa.prob.mb_stat_R & 0x0000ff))
+		return 0;
+
+	data = ctx->csa.prob.pu_mb_R;
 
 	return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
 }
@@ -1797,7 +2046,9 @@
 	if (!access_ok(VERIFY_WRITE, buf, len))
 		return -EFAULT;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	spin_lock(&ctx->csa.register_lock);
 	ret = __spufs_mbox_info_read(ctx, buf, len, pos);
 	spin_unlock(&ctx->csa.register_lock);
@@ -1815,13 +2066,13 @@
 static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
 				char __user *buf, size_t len, loff_t *pos)
 {
-	u32 ibox_stat;
 	u32 data;
 
-	ibox_stat = ctx->csa.prob.mb_stat_R;
-	if (ibox_stat & 0xff0000) {
-		data = ctx->csa.priv2.puint_mb_R;
-	}
+	/* EOF if there's no entry in the ibox */
+	if (!(ctx->csa.prob.mb_stat_R & 0xff0000))
+		return 0;
+
+	data = ctx->csa.priv2.puint_mb_R;
 
 	return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
 }
@@ -1835,7 +2086,9 @@
 	if (!access_ok(VERIFY_WRITE, buf, len))
 		return -EFAULT;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	spin_lock(&ctx->csa.register_lock);
 	ret = __spufs_ibox_info_read(ctx, buf, len, pos);
 	spin_unlock(&ctx->csa.register_lock);
@@ -1876,7 +2129,9 @@
 	if (!access_ok(VERIFY_WRITE, buf, len))
 		return -EFAULT;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	spin_lock(&ctx->csa.register_lock);
 	ret = __spufs_wbox_info_read(ctx, buf, len, pos);
 	spin_unlock(&ctx->csa.register_lock);
@@ -1926,7 +2181,9 @@
 	if (!access_ok(VERIFY_WRITE, buf, len))
 		return -EFAULT;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	spin_lock(&ctx->csa.register_lock);
 	ret = __spufs_dma_info_read(ctx, buf, len, pos);
 	spin_unlock(&ctx->csa.register_lock);
@@ -1977,7 +2234,9 @@
 	struct spu_context *ctx = file->private_data;
 	int ret;
 
-	spu_acquire_saved(ctx);
+	ret = spu_acquire_saved(ctx);
+	if (ret)
+		return ret;
 	spin_lock(&ctx->csa.register_lock);
 	ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
 	spin_unlock(&ctx->csa.register_lock);
@@ -2066,8 +2325,12 @@
 static int spufs_show_stat(struct seq_file *s, void *private)
 {
 	struct spu_context *ctx = s->private;
+	int ret;
 
-	spu_acquire(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		return ret;
+
 	seq_printf(s, "%s %llu %llu %llu %llu "
 		      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
 		ctx_state_names[ctx->stats.util_state],
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index fc4ed1f..64f8540 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -76,16 +76,18 @@
 		if (stat & 0xff0000)
 			ret |= POLLIN | POLLRDNORM;
 		else {
-			spu_int_stat_clear(spu, 2, 0x1);
-			spu_int_mask_or(spu, 2, 0x1);
+			spu_int_stat_clear(spu, 2, CLASS2_MAILBOX_INTR);
+			spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
 		}
 	}
 	if (events & (POLLOUT | POLLWRNORM)) {
 		if (stat & 0x00ff00)
 			ret = POLLOUT | POLLWRNORM;
 		else {
-			spu_int_stat_clear(spu, 2, 0x10);
-			spu_int_mask_or(spu, 2, 0x10);
+			spu_int_stat_clear(spu, 2,
+					CLASS2_MAILBOX_THRESHOLD_INTR);
+			spu_int_mask_or(spu, 2,
+					CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
 		}
 	}
 	spin_unlock_irq(&spu->register_lock);
@@ -106,7 +108,7 @@
 		ret = 4;
 	} else {
 		/* make sure we get woken up by the interrupt */
-		spu_int_mask_or(spu, 2, 0x1);
+		spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
 		ret = 0;
 	}
 	spin_unlock_irq(&spu->register_lock);
@@ -127,7 +129,7 @@
 	} else {
 		/* make sure we get woken up by the interrupt when space
 		   becomes available */
-		spu_int_mask_or(spu, 2, 0x10);
+		spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
 		ret = 0;
 	}
 	spin_unlock_irq(&spu->register_lock);
@@ -206,6 +208,11 @@
 	return ctx->spu->local_store;
 }
 
+static void spu_hw_privcntl_write(struct spu_context *ctx, u64 val)
+{
+	out_be64(&ctx->spu->priv2->spu_privcntl_RW, val);
+}
+
 static u32 spu_hw_runcntl_read(struct spu_context *ctx)
 {
 	return in_be32(&ctx->spu->problem->spu_runcntl_RW);
@@ -215,11 +222,21 @@
 {
 	spin_lock_irq(&ctx->spu->register_lock);
 	if (val & SPU_RUNCNTL_ISOLATE)
-		out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
+		spu_hw_privcntl_write(ctx,
+			SPU_PRIVCNT_LOAD_REQUEST_ENABLE_MASK);
 	out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
 	spin_unlock_irq(&ctx->spu->register_lock);
 }
 
+static void spu_hw_runcntl_stop(struct spu_context *ctx)
+{
+	spin_lock_irq(&ctx->spu->register_lock);
+	out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+	while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
+		cpu_relax();
+	spin_unlock_irq(&ctx->spu->register_lock);
+}
+
 static void spu_hw_master_start(struct spu_context *ctx)
 {
 	struct spu *spu = ctx->spu;
@@ -319,8 +336,10 @@
 	.npc_write = spu_hw_npc_write,
 	.status_read = spu_hw_status_read,
 	.get_ls = spu_hw_get_ls,
+	.privcntl_write = spu_hw_privcntl_write,
 	.runcntl_read = spu_hw_runcntl_read,
 	.runcntl_write = spu_hw_runcntl_write,
+	.runcntl_stop = spu_hw_runcntl_stop,
 	.master_start = spu_hw_master_start,
 	.master_stop = spu_hw_master_stop,
 	.set_mfc_query = spu_hw_set_mfc_query,
diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
index f4b3c05..0e9f325 100644
--- a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
+++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
@@ -28,6 +28,8 @@
 #include <asm/spu_csa.h>
 #include <asm/mmu.h>
 
+#include "spufs.h"
+
 static int spu_alloc_lscsa_std(struct spu_state *csa)
 {
 	struct spu_lscsa *lscsa;
@@ -73,7 +75,7 @@
 	int		i, j, n_4k;
 
 	/* Check availability of 64K pages */
-	if (mmu_psize_defs[MMU_PAGE_64K].shift == 0)
+	if (!spu_64k_pages_available())
 		goto fail;
 
 	csa->use_big_pages = 1;
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
index 1ce5e22..c01a09d 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -15,24 +15,55 @@
 {
 	struct spu_context *ctx = spu->ctx;
 
-	wake_up_all(&ctx->stop_wq);
+	/*
+	 * It should be impossible to preempt a context while an exception
+	 * is being processed, since the context switch code is specially
+	 * coded to deal with interrupts ... But, just in case, sanity check
+	 * the context pointer.  It is OK to return doing nothing since
+	 * the exception will be regenerated when the context is resumed.
+	 */
+	if (ctx) {
+		/* Copy exception arguments into module specific structure */
+		ctx->csa.class_0_pending = spu->class_0_pending;
+		ctx->csa.dsisr = spu->dsisr;
+		ctx->csa.dar = spu->dar;
+
+		/* ensure that the exception status has hit memory before a
+		 * thread waiting on the context's stop queue is woken */
+		smp_wmb();
+
+		wake_up_all(&ctx->stop_wq);
+	}
+
+	/* Clear callback arguments from spu structure */
+	spu->class_0_pending = 0;
+	spu->dsisr = 0;
+	spu->dar = 0;
 }
 
-static inline int spu_stopped(struct spu_context *ctx, u32 *stat)
+int spu_stopped(struct spu_context *ctx, u32 *stat)
 {
-	struct spu *spu;
-	u64 pte_fault;
+	u64 dsisr;
+	u32 stopped;
 
 	*stat = ctx->ops->status_read(ctx);
 
-	spu = ctx->spu;
-	if (ctx->state != SPU_STATE_RUNNABLE ||
-	    test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
+	if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
 		return 1;
-	pte_fault = spu->dsisr &
-	    (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
-	return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
-		1 : 0;
+
+	stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
+		SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
+	if (*stat & stopped)
+		return 1;
+
+	dsisr = ctx->csa.dsisr;
+	if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
+		return 1;
+
+	if (ctx->csa.class_0_pending)
+		return 1;
+
+	return 0;
 }
 
 static int spu_setup_isolated(struct spu_context *ctx)
@@ -128,34 +159,66 @@
 
 static int spu_run_init(struct spu_context *ctx, u32 *npc)
 {
+	unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
+	int ret;
+
 	spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
 
-	if (ctx->flags & SPU_CREATE_ISOLATE) {
-		unsigned long runcntl;
+	/*
+	 * NOSCHED is synchronous scheduling with respect to the caller.
+	 * The caller waits for the context to be loaded.
+	 */
+	if (ctx->flags & SPU_CREATE_NOSCHED) {
+		if (ctx->state == SPU_STATE_SAVED) {
+			ret = spu_activate(ctx, 0);
+			if (ret)
+				return ret;
+		}
+	}
 
+	/*
+	 * Apply special setup as required.
+	 */
+	if (ctx->flags & SPU_CREATE_ISOLATE) {
 		if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
-			int ret = spu_setup_isolated(ctx);
+			ret = spu_setup_isolated(ctx);
 			if (ret)
 				return ret;
 		}
 
-		/* if userspace has set the runcntrl register (eg, to issue an
-		 * isolated exit), we need to re-set it here */
+		/*
+		 * If userspace has set the runcntrl register (eg, to
+		 * issue an isolated exit), we need to re-set it here
+		 */
 		runcntl = ctx->ops->runcntl_read(ctx) &
 			(SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
 		if (runcntl == 0)
 			runcntl = SPU_RUNCNTL_RUNNABLE;
-		ctx->ops->runcntl_write(ctx, runcntl);
-	} else {
-		unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
-		ctx->ops->npc_write(ctx, *npc);
-		if (test_thread_flag(TIF_SINGLESTEP))
-			mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
-		out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
-		ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
 	}
 
-	spuctx_switch_state(ctx, SPU_UTIL_USER);
+	if (ctx->flags & SPU_CREATE_NOSCHED) {
+		spuctx_switch_state(ctx, SPU_UTIL_USER);
+		ctx->ops->runcntl_write(ctx, runcntl);
+	} else {
+		unsigned long privcntl;
+
+		if (test_thread_flag(TIF_SINGLESTEP))
+			privcntl = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+		else
+			privcntl = SPU_PRIVCNTL_MODE_NORMAL;
+
+		ctx->ops->npc_write(ctx, *npc);
+		ctx->ops->privcntl_write(ctx, privcntl);
+		ctx->ops->runcntl_write(ctx, runcntl);
+
+		if (ctx->state == SPU_STATE_SAVED) {
+			ret = spu_activate(ctx, 0);
+			if (ret)
+				return ret;
+		} else {
+			spuctx_switch_state(ctx, SPU_UTIL_USER);
+		}
+	}
 
 	return 0;
 }
@@ -165,6 +228,8 @@
 {
 	int ret = 0;
 
+	spu_del_from_rq(ctx);
+
 	*status = ctx->ops->status_read(ctx);
 	*npc = ctx->ops->npc_read(ctx);
 
@@ -177,26 +242,6 @@
 	return ret;
 }
 
-static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
-				         u32 *status)
-{
-	int ret;
-
-	ret = spu_run_fini(ctx, npc, status);
-	if (ret)
-		return ret;
-
-	if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT))
-		return *status;
-
-	ret = spu_acquire_runnable(ctx, 0);
-	if (ret)
-		return ret;
-
-	spuctx_switch_state(ctx, SPU_UTIL_USER);
-	return 0;
-}
-
 /*
  * SPU syscall restarting is tricky because we violate the basic
  * assumption that the signal handler is running on the interrupted
@@ -247,7 +292,7 @@
 	u32 ls_pointer, npc;
 	void __iomem *ls;
 	long spu_ret;
-	int ret;
+	int ret, ret2;
 
 	/* get syscall block from local store */
 	npc = ctx->ops->npc_read(ctx) & ~3;
@@ -269,9 +314,11 @@
 		if (spu_ret <= -ERESTARTSYS) {
 			ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
 		}
-		spu_acquire(ctx);
+		ret2 = spu_acquire(ctx);
 		if (ret == -ERESTARTSYS)
 			return ret;
+		if (ret2)
+			return -EINTR;
 	}
 
 	/* write result, jump over indirect pointer */
@@ -281,18 +328,6 @@
 	return ret;
 }
 
-static inline int spu_process_events(struct spu_context *ctx)
-{
-	struct spu *spu = ctx->spu;
-	int ret = 0;
-
-	if (spu->class_0_pending)
-		ret = spu_irq_class_0_bottom(spu);
-	if (!ret && signal_pending(current))
-		ret = -ERESTARTSYS;
-	return ret;
-}
-
 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
 {
 	int ret;
@@ -302,29 +337,14 @@
 	if (mutex_lock_interruptible(&ctx->run_mutex))
 		return -ERESTARTSYS;
 
-	ctx->ops->master_start(ctx);
+	spu_enable_spu(ctx);
 	ctx->event_return = 0;
 
-	spu_acquire(ctx);
-	if (ctx->state == SPU_STATE_SAVED) {
-		__spu_update_sched_info(ctx);
-		spu_set_timeslice(ctx);
+	ret = spu_acquire(ctx);
+	if (ret)
+		goto out_unlock;
 
-		ret = spu_activate(ctx, 0);
-		if (ret) {
-			spu_release(ctx);
-			goto out;
-		}
-	} else {
-		/*
-		 * We have to update the scheduling priority under active_mutex
-		 * to protect against find_victim().
-		 *
-		 * No need to update the timeslice ASAP, it will get updated
-		 * once the current one has expired.
-		 */
-		spu_update_sched_info(ctx);
-	}
+	spu_update_sched_info(ctx);
 
 	ret = spu_run_init(ctx, npc);
 	if (ret) {
@@ -358,14 +378,12 @@
 		if (ret)
 			break;
 
-		if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
-			ret = spu_reacquire_runnable(ctx, npc, &status);
-			if (ret)
-				goto out2;
-			continue;
-		}
-		ret = spu_process_events(ctx);
+		ret = spufs_handle_class0(ctx);
+		if (ret)
+			break;
 
+		if (signal_pending(current))
+			ret = -ERESTARTSYS;
 	} while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
 				      SPU_STATUS_STOPPED_BY_HALT |
 				       SPU_STATUS_SINGLE_STEP)));
@@ -376,11 +394,10 @@
 		ctx->stats.libassist++;
 
 
-	ctx->ops->master_stop(ctx);
+	spu_disable_spu(ctx);
 	ret = spu_run_fini(ctx, npc, &status);
 	spu_yield(ctx);
 
-out2:
 	if ((ret == 0) ||
 	    ((ret == -ERESTARTSYS) &&
 	     ((status & SPU_STATUS_STOPPED_BY_HALT) ||
@@ -401,6 +418,7 @@
 
 out:
 	*event = ctx->event_return;
+out_unlock:
 	mutex_unlock(&ctx->run_mutex);
 	return ret;
 }
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 4d257b3..8c8af11 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -58,6 +58,7 @@
 static struct spu_prio_array *spu_prio;
 static struct task_struct *spusched_task;
 static struct timer_list spusched_timer;
+static struct timer_list spuloadavg_timer;
 
 /*
  * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
@@ -105,15 +106,21 @@
 void __spu_update_sched_info(struct spu_context *ctx)
 {
 	/*
-	 * 32-Bit assignment are atomic on powerpc, and we don't care about
-	 * memory ordering here because retriving the controlling thread is
-	 * per defintion racy.
+	 * assert that the context is not on the runqueue, so it is safe
+	 * to change its scheduling parameters.
+	 */
+	BUG_ON(!list_empty(&ctx->rq));
+
+	/*
+	 * 32-Bit assignments are atomic on powerpc, and we don't care about
+	 * memory ordering here because retrieving the controlling thread is
+	 * per definition racy.
 	 */
 	ctx->tid = current->pid;
 
 	/*
 	 * We do our own priority calculations, so we normally want
-	 * ->static_prio to start with. Unfortunately thies field
+	 * ->static_prio to start with. Unfortunately this field
 	 * contains junk for threads with a realtime scheduling
 	 * policy so we have to look at ->prio in this case.
 	 */
@@ -124,23 +131,32 @@
 	ctx->policy = current->policy;
 
 	/*
-	 * A lot of places that don't hold list_mutex poke into
-	 * cpus_allowed, including grab_runnable_context which
-	 * already holds the runq_lock.  So abuse runq_lock
-	 * to protect this field aswell.
+	 * TO DO: the context may be loaded, so we may need to activate
+	 * it again on a different node. But it shouldn't hurt anything
+	 * to update its parameters, because we know that the scheduler
+	 * is not actively looking at this field, since it is not on the
+	 * runqueue. The context will be rescheduled on the proper node
+	 * if it is timesliced or preempted.
 	 */
-	spin_lock(&spu_prio->runq_lock);
 	ctx->cpus_allowed = current->cpus_allowed;
-	spin_unlock(&spu_prio->runq_lock);
 }
 
 void spu_update_sched_info(struct spu_context *ctx)
 {
-	int node = ctx->spu->node;
+	int node;
 
-	mutex_lock(&cbe_spu_info[node].list_mutex);
-	__spu_update_sched_info(ctx);
-	mutex_unlock(&cbe_spu_info[node].list_mutex);
+	if (ctx->state == SPU_STATE_RUNNABLE) {
+		node = ctx->spu->node;
+
+		/*
+		 * Take list_mutex to sync with find_victim().
+		 */
+		mutex_lock(&cbe_spu_info[node].list_mutex);
+		__spu_update_sched_info(ctx);
+		mutex_unlock(&cbe_spu_info[node].list_mutex);
+	} else {
+		__spu_update_sched_info(ctx);
+	}
 }
 
 static int __node_allowed(struct spu_context *ctx, int node)
@@ -182,7 +198,7 @@
 	 * Wake up the active spu_contexts.
 	 *
 	 * When the awakened processes see their "notify_active" flag is set,
-	 * they will call spu_switch_notify();
+	 * they will call spu_switch_notify().
 	 */
 	for_each_online_node(node) {
 		struct spu *spu;
@@ -245,7 +261,6 @@
 	spu->wbox_callback = spufs_wbox_callback;
 	spu->stop_callback = spufs_stop_callback;
 	spu->mfc_callback = spufs_mfc_callback;
-	spu->dma_callback = spufs_dma_callback;
 	mb();
 	spu_unmap_mappings(ctx);
 	spu_restore(&ctx->csa, spu);
@@ -433,7 +448,6 @@
 	spu->wbox_callback = NULL;
 	spu->stop_callback = NULL;
 	spu->mfc_callback = NULL;
-	spu->dma_callback = NULL;
 	spu_associate_mm(spu, NULL);
 	spu->pid = 0;
 	spu->tgid = 0;
@@ -478,6 +492,13 @@
 	}
 }
 
+static void spu_add_to_rq(struct spu_context *ctx)
+{
+	spin_lock(&spu_prio->runq_lock);
+	__spu_add_to_rq(ctx);
+	spin_unlock(&spu_prio->runq_lock);
+}
+
 static void __spu_del_from_rq(struct spu_context *ctx)
 {
 	int prio = ctx->prio;
@@ -492,10 +513,24 @@
 	}
 }
 
+void spu_del_from_rq(struct spu_context *ctx)
+{
+	spin_lock(&spu_prio->runq_lock);
+	__spu_del_from_rq(ctx);
+	spin_unlock(&spu_prio->runq_lock);
+}
+
 static void spu_prio_wait(struct spu_context *ctx)
 {
 	DEFINE_WAIT(wait);
 
+	/*
+	 * The caller must explicitly wait for a context to be loaded
+	 * if the nosched flag is set.  If NOSCHED is not set, the caller
+	 * queues the context and waits for an spu event or error.
+	 */
+	BUG_ON(!(ctx->flags & SPU_CREATE_NOSCHED));
+
 	spin_lock(&spu_prio->runq_lock);
 	prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
 	if (!signal_pending(current)) {
@@ -579,7 +614,7 @@
 	/*
 	 * Look for a possible preemption candidate on the local node first.
 	 * If there is no candidate look at the other nodes.  This isn't
-	 * exactly fair, but so far the whole spu schedule tries to keep
+	 * exactly fair, but so far the whole spu scheduler tries to keep
 	 * a strong node affinity.  We might want to fine-tune this in
 	 * the future.
 	 */
@@ -595,6 +630,7 @@
 			struct spu_context *tmp = spu->ctx;
 
 			if (tmp && tmp->prio > ctx->prio &&
+			    !(tmp->flags & SPU_CREATE_NOSCHED) &&
 			    (!victim || tmp->prio > victim->prio))
 				victim = spu->ctx;
 		}
@@ -606,6 +642,10 @@
 			 * higher priority contexts before lower priority
 			 * ones, so this is safe until we introduce
 			 * priority inheritance schemes.
+			 *
+			 * XXX if the highest priority context is locked,
+			 * this can loop a long time.  Might be better to
+			 * look at another context or give up after X retries.
 			 */
 			if (!mutex_trylock(&victim->state_mutex)) {
 				victim = NULL;
@@ -613,10 +653,10 @@
 			}
 
 			spu = victim->spu;
-			if (!spu) {
+			if (!spu || victim->prio <= ctx->prio) {
 				/*
 				 * This race can happen because we've dropped
-				 * the active list mutex.  No a problem, just
+				 * the active list mutex.  Not a problem, just
 				 * restart the search.
 				 */
 				mutex_unlock(&victim->state_mutex);
@@ -631,13 +671,10 @@
 
 			victim->stats.invol_ctx_switch++;
 			spu->stats.invol_ctx_switch++;
+			spu_add_to_rq(victim);
+
 			mutex_unlock(&victim->state_mutex);
-			/*
-			 * We need to break out of the wait loop in spu_run
-			 * manually to ensure this context gets put on the
-			 * runqueue again ASAP.
-			 */
-			wake_up(&victim->stop_wq);
+
 			return spu;
 		}
 	}
@@ -645,6 +682,50 @@
 	return NULL;
 }
 
+static void __spu_schedule(struct spu *spu, struct spu_context *ctx)
+{
+	int node = spu->node;
+	int success = 0;
+
+	spu_set_timeslice(ctx);
+
+	mutex_lock(&cbe_spu_info[node].list_mutex);
+	if (spu->ctx == NULL) {
+		spu_bind_context(spu, ctx);
+		cbe_spu_info[node].nr_active++;
+		spu->alloc_state = SPU_USED;
+		success = 1;
+	}
+	mutex_unlock(&cbe_spu_info[node].list_mutex);
+
+	if (success)
+		wake_up_all(&ctx->run_wq);
+	else
+		spu_add_to_rq(ctx);
+}
+
+static void spu_schedule(struct spu *spu, struct spu_context *ctx)
+{
+	/* not a candidate for interruptible because it's called either
+	   from the scheduler thread or from spu_deactivate */
+	mutex_lock(&ctx->state_mutex);
+	__spu_schedule(spu, ctx);
+	spu_release(ctx);
+}
+
+static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
+{
+	int node = spu->node;
+
+	mutex_lock(&cbe_spu_info[node].list_mutex);
+	cbe_spu_info[node].nr_active--;
+	spu->alloc_state = SPU_FREE;
+	spu_unbind_context(spu, ctx);
+	ctx->stats.invol_ctx_switch++;
+	spu->stats.invol_ctx_switch++;
+	mutex_unlock(&cbe_spu_info[node].list_mutex);
+}
+
 /**
  * spu_activate - find a free spu for a context and execute it
  * @ctx:	spu context to schedule
@@ -656,39 +737,47 @@
  */
 int spu_activate(struct spu_context *ctx, unsigned long flags)
 {
-	do {
-		struct spu *spu;
+	struct spu *spu;
 
-		/*
-		 * If there are multiple threads waiting for a single context
-		 * only one actually binds the context while the others will
-		 * only be able to acquire the state_mutex once the context
-		 * already is in runnable state.
-		 */
-		if (ctx->spu)
-			return 0;
+	/*
+	 * If there are multiple threads waiting for a single context
+	 * only one actually binds the context while the others will
+	 * only be able to acquire the state_mutex once the context
+	 * already is in runnable state.
+	 */
+	if (ctx->spu)
+		return 0;
 
-		spu = spu_get_idle(ctx);
-		/*
-		 * If this is a realtime thread we try to get it running by
-		 * preempting a lower priority thread.
-		 */
-		if (!spu && rt_prio(ctx->prio))
-			spu = find_victim(ctx);
-		if (spu) {
-			int node = spu->node;
+spu_activate_top:
+	if (signal_pending(current))
+		return -ERESTARTSYS;
 
-			mutex_lock(&cbe_spu_info[node].list_mutex);
-			spu_bind_context(spu, ctx);
-			cbe_spu_info[node].nr_active++;
-			mutex_unlock(&cbe_spu_info[node].list_mutex);
-			return 0;
-		}
+	spu = spu_get_idle(ctx);
+	/*
+	 * If this is a realtime thread we try to get it running by
+	 * preempting a lower priority thread.
+	 */
+	if (!spu && rt_prio(ctx->prio))
+		spu = find_victim(ctx);
+	if (spu) {
+		unsigned long runcntl;
 
+		runcntl = ctx->ops->runcntl_read(ctx);
+		__spu_schedule(spu, ctx);
+		if (runcntl & SPU_RUNCNTL_RUNNABLE)
+			spuctx_switch_state(ctx, SPU_UTIL_USER);
+
+		return 0;
+	}
+
+	if (ctx->flags & SPU_CREATE_NOSCHED) {
 		spu_prio_wait(ctx);
-	} while (!signal_pending(current));
+		goto spu_activate_top;
+	}
 
-	return -ERESTARTSYS;
+	spu_add_to_rq(ctx);
+
+	return 0;
 }
 
 /**
@@ -730,21 +819,19 @@
 	if (spu) {
 		new = grab_runnable_context(max_prio, spu->node);
 		if (new || force) {
-			int node = spu->node;
-
-			mutex_lock(&cbe_spu_info[node].list_mutex);
-			spu_unbind_context(spu, ctx);
-			spu->alloc_state = SPU_FREE;
-			cbe_spu_info[node].nr_active--;
-			mutex_unlock(&cbe_spu_info[node].list_mutex);
-
-			ctx->stats.vol_ctx_switch++;
-			spu->stats.vol_ctx_switch++;
-
-			if (new)
-				wake_up(&new->stop_wq);
+			spu_unschedule(spu, ctx);
+			if (new) {
+				if (new->flags & SPU_CREATE_NOSCHED)
+					wake_up(&new->stop_wq);
+				else {
+					spu_release(ctx);
+					spu_schedule(spu, new);
+					/* this one can't easily be made
+					   interruptible */
+					mutex_lock(&ctx->state_mutex);
+				}
+			}
 		}
-
 	}
 
 	return new != NULL;
@@ -781,43 +868,38 @@
 
 static noinline void spusched_tick(struct spu_context *ctx)
 {
+	struct spu_context *new = NULL;
+	struct spu *spu = NULL;
+	u32 status;
+
+	if (spu_acquire(ctx))
+		BUG();	/* a kernel thread never has signals pending */
+
+	if (ctx->state != SPU_STATE_RUNNABLE)
+		goto out;
+	if (spu_stopped(ctx, &status))
+		goto out;
 	if (ctx->flags & SPU_CREATE_NOSCHED)
-		return;
+		goto out;
 	if (ctx->policy == SCHED_FIFO)
-		return;
+		goto out;
 
 	if (--ctx->time_slice)
-		return;
+		goto out;
 
-	/*
-	 * Unfortunately list_mutex ranks outside of state_mutex, so
-	 * we have to trylock here.  If we fail give the context another
-	 * tick and try again.
-	 */
-	if (mutex_trylock(&ctx->state_mutex)) {
-		struct spu *spu = ctx->spu;
-		struct spu_context *new;
-
-		new = grab_runnable_context(ctx->prio + 1, spu->node);
-		if (new) {
-			spu_unbind_context(spu, ctx);
-			ctx->stats.invol_ctx_switch++;
-			spu->stats.invol_ctx_switch++;
-			spu->alloc_state = SPU_FREE;
-			cbe_spu_info[spu->node].nr_active--;
-			wake_up(&new->stop_wq);
-			/*
-			 * We need to break out of the wait loop in
-			 * spu_run manually to ensure this context
-			 * gets put on the runqueue again ASAP.
-			 */
-			wake_up(&ctx->stop_wq);
-		}
-		spu_set_timeslice(ctx);
-		mutex_unlock(&ctx->state_mutex);
+	spu = ctx->spu;
+	new = grab_runnable_context(ctx->prio + 1, spu->node);
+	if (new) {
+		spu_unschedule(spu, ctx);
+		spu_add_to_rq(ctx);
 	} else {
 		ctx->time_slice++;
 	}
+out:
+	spu_release(ctx);
+
+	if (new)
+		spu_schedule(spu, new);
 }
 
 /**
@@ -841,35 +923,31 @@
 }
 
 /**
- * spu_calc_load - given tick count, update the avenrun load estimates.
- * @tick:	tick count
+ * spu_calc_load - update the avenrun load estimates.
  *
  * No locking against reading these values from userspace, as for
  * the CPU loadavg code.
  */
-static void spu_calc_load(unsigned long ticks)
+static void spu_calc_load(void)
 {
 	unsigned long active_tasks; /* fixed-point */
-	static int count = LOAD_FREQ;
 
-	count -= ticks;
-
-	if (unlikely(count < 0)) {
-		active_tasks = count_active_contexts() * FIXED_1;
-		do {
-			CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
-			CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
-			CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
-			count += LOAD_FREQ;
-		} while (count < 0);
-	}
+	active_tasks = count_active_contexts() * FIXED_1;
+	CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+	CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+	CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
 }
 
 static void spusched_wake(unsigned long data)
 {
 	mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
 	wake_up_process(spusched_task);
-	spu_calc_load(SPUSCHED_TICK);
+}
+
+static void spuloadavg_wake(unsigned long data)
+{
+	mod_timer(&spuloadavg_timer, jiffies + LOAD_FREQ);
+	spu_calc_load();
 }
 
 static int spusched_thread(void *unused)
@@ -881,17 +959,58 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 		for (node = 0; node < MAX_NUMNODES; node++) {
-			mutex_lock(&cbe_spu_info[node].list_mutex);
-			list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list)
-				if (spu->ctx)
-					spusched_tick(spu->ctx);
-			mutex_unlock(&cbe_spu_info[node].list_mutex);
+			struct mutex *mtx = &cbe_spu_info[node].list_mutex;
+
+			mutex_lock(mtx);
+			list_for_each_entry(spu, &cbe_spu_info[node].spus,
+					cbe_list) {
+				struct spu_context *ctx = spu->ctx;
+
+				if (ctx) {
+					mutex_unlock(mtx);
+					spusched_tick(ctx);
+					mutex_lock(mtx);
+				}
+			}
+			mutex_unlock(mtx);
 		}
 	}
 
 	return 0;
 }
 
+void spuctx_switch_state(struct spu_context *ctx,
+		enum spu_utilization_state new_state)
+{
+	unsigned long long curtime;
+	signed long long delta;
+	struct timespec ts;
+	struct spu *spu;
+	enum spu_utilization_state old_state;
+
+	ktime_get_ts(&ts);
+	curtime = timespec_to_ns(&ts);
+	delta = curtime - ctx->stats.tstamp;
+
+	WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+	WARN_ON(delta < 0);
+
+	spu = ctx->spu;
+	old_state = ctx->stats.util_state;
+	ctx->stats.util_state = new_state;
+	ctx->stats.tstamp = curtime;
+
+	/*
+	 * Update the physical SPU utilization statistics.
+	 */
+	if (spu) {
+		ctx->stats.times[old_state] += delta;
+		spu->stats.times[old_state] += delta;
+		spu->stats.util_state = new_state;
+		spu->stats.tstamp = curtime;
+	}
+}
+
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
@@ -905,7 +1024,7 @@
 
 	/*
 	 * Note that last_pid doesn't really make much sense for the
-	 * SPU loadavg (it even seems very odd on the CPU side..),
+	 * SPU loadavg (it even seems very odd on the CPU side...),
 	 * but we include it here to have a 100% compatible interface.
 	 */
 	seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
@@ -946,6 +1065,7 @@
 	spin_lock_init(&spu_prio->runq_lock);
 
 	setup_timer(&spusched_timer, spusched_wake, 0);
+	setup_timer(&spuloadavg_timer, spuloadavg_wake, 0);
 
 	spusched_task = kthread_run(spusched_thread, NULL, "spusched");
 	if (IS_ERR(spusched_task)) {
@@ -953,6 +1073,8 @@
 		goto out_free_spu_prio;
 	}
 
+	mod_timer(&spuloadavg_timer, 0);
+
 	entry = create_proc_entry("spu_loadavg", 0, NULL);
 	if (!entry)
 		goto out_stop_kthread;
@@ -978,6 +1100,7 @@
 	remove_proc_entry("spu_loadavg", NULL);
 
 	del_timer_sync(&spusched_timer);
+	del_timer_sync(&spuloadavg_timer);
 	kthread_stop(spusched_task);
 
 	for (node = 0; node < MAX_NUMNODES; node++) {
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index ca47b99..0e11403 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -71,6 +71,7 @@
 	wait_queue_head_t wbox_wq;
 	wait_queue_head_t stop_wq;
 	wait_queue_head_t mfc_wq;
+	wait_queue_head_t run_wq;
 	struct fasync_struct *ibox_fasync;
 	struct fasync_struct *wbox_fasync;
 	struct fasync_struct *mfc_fasync;
@@ -168,8 +169,10 @@
 	void (*npc_write) (struct spu_context * ctx, u32 data);
 	 u32(*status_read) (struct spu_context * ctx);
 	char*(*get_ls) (struct spu_context * ctx);
+	void (*privcntl_write) (struct spu_context *ctx, u64 data);
 	 u32 (*runcntl_read) (struct spu_context * ctx);
 	void (*runcntl_write) (struct spu_context * ctx, u32 data);
+	void (*runcntl_stop) (struct spu_context * ctx);
 	void (*master_start) (struct spu_context * ctx);
 	void (*master_stop) (struct spu_context * ctx);
 	int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
@@ -219,15 +222,16 @@
 
 /* fault handling */
 int spufs_handle_class1(struct spu_context *ctx);
+int spufs_handle_class0(struct spu_context *ctx);
 
 /* affinity */
 struct spu *affinity_check(struct spu_context *ctx);
 
 /* context management */
 extern atomic_t nr_spu_contexts;
-static inline void spu_acquire(struct spu_context *ctx)
+static inline int __must_check spu_acquire(struct spu_context *ctx)
 {
-	mutex_lock(&ctx->state_mutex);
+	return mutex_lock_interruptible(&ctx->state_mutex);
 }
 
 static inline void spu_release(struct spu_context *ctx)
@@ -242,10 +246,11 @@
 void spu_unmap_mappings(struct spu_context *ctx);
 
 void spu_forget(struct spu_context *ctx);
-int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags);
-void spu_acquire_saved(struct spu_context *ctx);
+int __must_check spu_acquire_saved(struct spu_context *ctx);
 void spu_release_saved(struct spu_context *ctx);
 
+int spu_stopped(struct spu_context *ctx, u32 * stat);
+void spu_del_from_rq(struct spu_context *ctx);
 int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
@@ -279,7 +284,9 @@
 		}							\
 		spu_release(ctx);					\
 		schedule();						\
-		spu_acquire(ctx);					\
+		__ret = spu_acquire(ctx);				\
+		if (__ret)						\
+			break;						\
 	}								\
 	finish_wait(&(wq), &__wait);					\
 	__ret;								\
@@ -306,41 +313,16 @@
 extern struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
-/*
- * This function is a little bit too large for an inline, but
- * as fault.c is built into the kernel we can't move it out of
- * line.
- */
-static inline void spuctx_switch_state(struct spu_context *ctx,
-		enum spu_utilization_state new_state)
-{
-	unsigned long long curtime;
-	signed long long delta;
-	struct timespec ts;
-	struct spu *spu;
-	enum spu_utilization_state old_state;
+extern int spu_init_csa(struct spu_state *csa);
+extern void spu_fini_csa(struct spu_state *csa);
+extern int spu_save(struct spu_state *prev, struct spu *spu);
+extern int spu_restore(struct spu_state *new, struct spu *spu);
+extern int spu_switch(struct spu_state *prev, struct spu_state *new,
+		      struct spu *spu);
+extern int spu_alloc_lscsa(struct spu_state *csa);
+extern void spu_free_lscsa(struct spu_state *csa);
 
-	ktime_get_ts(&ts);
-	curtime = timespec_to_ns(&ts);
-	delta = curtime - ctx->stats.tstamp;
-
-	WARN_ON(!mutex_is_locked(&ctx->state_mutex));
-	WARN_ON(delta < 0);
-
-	spu = ctx->spu;
-	old_state = ctx->stats.util_state;
-	ctx->stats.util_state = new_state;
-	ctx->stats.tstamp = curtime;
-
-	/*
-	 * Update the physical SPU utilization statistics.
-	 */
-	if (spu) {
-		ctx->stats.times[old_state] += delta;
-		spu->stats.times[old_state] += delta;
-		spu->stats.util_state = new_state;
-		spu->stats.tstamp = curtime;
-	}
-}
+extern void spuctx_switch_state(struct spu_context *ctx,
+		enum spu_utilization_state new_state);
 
 #endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 3d64c81..6063c88 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -48,6 +48,8 @@
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 
+#include "spufs.h"
+
 #include "spu_save_dump.h"
 #include "spu_restore_dump.h"
 
@@ -691,35 +693,9 @@
 	out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void get_kernel_slb(u64 ea, u64 slb[2])
+static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu,
+		unsigned int *code, int code_size)
 {
-	u64 llp;
-
-	if (REGION_ID(ea) == KERNEL_REGION_ID)
-		llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	else
-		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
-	slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-		SLB_VSID_KERNEL | llp;
-	slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
-}
-
-static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
-{
-	struct spu_priv2 __iomem *priv2 = spu->priv2;
-
-	out_be64(&priv2->slb_index_W, slbe);
-	eieio();
-	out_be64(&priv2->slb_vsid_RW, slb[0]);
-	out_be64(&priv2->slb_esid_RW, slb[1]);
-	eieio();
-}
-
-static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
-{
-	u64 code_slb[2];
-	u64 lscsa_slb[2];
-
 	/* Save, Step 47:
 	 * Restore, Step 30.
 	 *     If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
@@ -735,11 +711,7 @@
 	 *     translation is desired by OS environment).
 	 */
 	spu_invalidate_slbs(spu);
-	get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
-	get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
-	load_mfc_slb(spu, code_slb, 0);
-	if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
-		load_mfc_slb(spu, lscsa_slb, 1);
+	spu_setup_kernel_slbs(spu, csa->lscsa, code, code_size);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
@@ -768,9 +740,9 @@
 	 *     (translation) interrupts.
 	 */
 	spin_lock_irq(&spu->register_lock);
-	spu_int_stat_clear(spu, 0, ~0ul);
-	spu_int_stat_clear(spu, 1, ~0ul);
-	spu_int_stat_clear(spu, 2, ~0ul);
+	spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+	spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+	spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
 	spu_int_mask_set(spu, 0, 0ul);
 	spu_int_mask_set(spu, 1, class1_mask);
 	spu_int_mask_set(spu, 2, 0ul);
@@ -927,8 +899,8 @@
 	POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask);
 
 	local_irq_save(flags);
-	spu_int_stat_clear(spu, 0, ~(0ul));
-	spu_int_stat_clear(spu, 2, ~(0ul));
+	spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+	spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
 	local_irq_restore(flags);
 }
 
@@ -946,8 +918,8 @@
 	POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
 
 	local_irq_save(flags);
-	spu_int_stat_clear(spu, 0, ~(0ul));
-	spu_int_stat_clear(spu, 2, ~(0ul));
+	spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+	spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
 	local_irq_restore(flags);
 }
 
@@ -1423,9 +1395,9 @@
 	spu_int_mask_set(spu, 0, 0ul);
 	spu_int_mask_set(spu, 1, 0ul);
 	spu_int_mask_set(spu, 2, 0ul);
-	spu_int_stat_clear(spu, 0, ~0ul);
-	spu_int_stat_clear(spu, 1, ~0ul);
-	spu_int_stat_clear(spu, 2, ~0ul);
+	spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+	spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+	spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
 	spin_unlock_irq(&spu->register_lock);
 }
 
@@ -1866,7 +1838,8 @@
 	 */
 
 	resume_mfc_queue(prev, spu);	/* Step 46. */
-	setup_mfc_slbs(prev, spu);	/* Step 47. */
+	/* Step 47. */
+	setup_mfc_slbs(prev, spu, spu_save_code, sizeof(spu_save_code));
 	set_switch_active(prev, spu);	/* Step 48. */
 	enable_interrupts(prev, spu);	/* Step 49. */
 	save_ls_16kb(prev, spu);	/* Step 50. */
@@ -1971,7 +1944,8 @@
 	setup_spu_status_part1(next, spu);	/* Step 27. */
 	setup_spu_status_part2(next, spu);	/* Step 28. */
 	restore_mfc_rag(next, spu);	        /* Step 29. */
-	setup_mfc_slbs(next, spu);	        /* Step 30. */
+	/* Step 30. */
+	setup_mfc_slbs(next, spu, spu_restore_code, sizeof(spu_restore_code));
 	set_spu_npc(next, spu);	                /* Step 31. */
 	set_signot1(next, spu);	                /* Step 32. */
 	set_signot2(next, spu);	                /* Step 33. */
@@ -2103,10 +2077,6 @@
 	int rc;
 
 	acquire_spu_lock(spu);	        /* Step 1.     */
-	prev->dar = spu->dar;
-	prev->dsisr = spu->dsisr;
-	spu->dar = 0;
-	spu->dsisr = 0;
 	rc = __do_spu_save(prev, spu);	/* Steps 2-53. */
 	release_spu_lock(spu);
 	if (rc != 0 && rc != 2 && rc != 6) {
@@ -2133,9 +2103,6 @@
 	acquire_spu_lock(spu);
 	harvest(NULL, spu);
 	spu->slb_replace = 0;
-	new->dar = 0;
-	new->dsisr = 0;
-	spu->class_0_pending = 0;
 	rc = __do_spu_restore(new, spu);
 	release_spu_lock(spu);
 	if (rc) {
@@ -2215,10 +2182,8 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
 	spu_free_lscsa(csa);
 }
-EXPORT_SYMBOL_GPL(spu_fini_csa);
diff --git a/arch/powerpc/platforms/celleb/Kconfig b/arch/powerpc/platforms/celleb/Kconfig
index 04748d4..372891e 100644
--- a/arch/powerpc/platforms/celleb/Kconfig
+++ b/arch/powerpc/platforms/celleb/Kconfig
@@ -2,6 +2,8 @@
 	bool "Toshiba's Cell Reference Set 'Celleb' Architecture"
 	depends on PPC_MULTIPLATFORM && PPC64
 	select PPC_CELL
+	select PPC_CELL_NATIVE
+	select PPC_RTAS
 	select PPC_INDIRECT_IO
 	select PPC_OF_PLATFORM_PCI
 	select HAS_TXX9_SERIAL
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c
index 2b91214..b939c0e 100644
--- a/arch/powerpc/platforms/celleb/io-workarounds.c
+++ b/arch/powerpc/platforms/celleb/io-workarounds.c
@@ -222,7 +222,7 @@
 			       void (*dummy_read)(struct pci_controller *))
 {
 	struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count];
-	struct device_node *np = phb->arch_data;
+	struct device_node *np = phb->dn;
 
 	if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) {
 		printk(KERN_ERR "Too many pci bridges, workarounds"
@@ -256,13 +256,13 @@
 
 	celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!celleb_dummy_page_va) {
-		printk(KERN_ERR "Celleb: dummy read disabled."
+		printk(KERN_ERR "Celleb: dummy read disabled. "
 			"Alloc celleb_dummy_page_va failed\n");
 		return 1;
 	}
 
 	list_for_each_entry(phb, &hose_list, list_node) {
-		node = phb->arch_data;
+		node = phb->dn;
 		match = of_match_node(celleb_pci_workaround_match, node);
 
 		if (match) {
diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c
index 755d869..fbe718d 100644
--- a/arch/powerpc/platforms/celleb/iommu.c
+++ b/arch/powerpc/platforms/celleb/iommu.c
@@ -22,8 +22,9 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
+#include <asm/machdep.h>
 
 #include "beat_wrapper.h"
 
@@ -91,7 +92,7 @@
 
 static int __init celleb_init_iommu(void)
 {
-	if (!machine_is(celleb))
+	if (!machine_is(celleb_beat))
 		return -ENODEV;
 
 	celleb_init_direct_mapping();
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index 6bc32fd..5d399e0 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -138,8 +138,6 @@
 		*val = celleb_fake_config_readl(p);
 		break;
 	}
-
-	return;
 }
 
 static void celleb_config_write_fake(unsigned char *config, int where,
@@ -158,7 +156,6 @@
 		celleb_fake_config_writel(val, p);
 		break;
 	}
-	return;
 }
 
 static int celleb_fake_pci_read_config(struct pci_bus *bus,
@@ -351,6 +348,10 @@
 	wi1 = of_get_property(node, "vendor-id", NULL);
 	wi2 = of_get_property(node, "class-code", NULL);
 	wi3 = of_get_property(node, "revision-id", NULL);
+	if (!wi0 || !wi1 || !wi2 || !wi3) {
+		printk(KERN_ERR "PCI: Missing device tree properties.\n");
+		goto error;
+	}
 
 	celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
 	celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
@@ -372,6 +373,10 @@
 	celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
 
 	li = of_get_property(node, "interrupts", &rlen);
+	if (!li) {
+		printk(KERN_ERR "PCI: interrupts not found.\n");
+		goto error;
+	}
 	val = li[0];
 	celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
 	celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
@@ -475,7 +480,7 @@
 
 int __init celleb_setup_phb(struct pci_controller *phb)
 {
-	struct device_node *dev = phb->arch_data;
+	struct device_node *dev = phb->dn;
 	const struct of_device_id *match;
 	int (*setup_func)(struct device_node *, struct pci_controller *);
 
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
index 9d076426..a3c7cfb 100644
--- a/arch/powerpc/platforms/celleb/scc_epci.c
+++ b/arch/powerpc/platforms/celleb/scc_epci.c
@@ -95,7 +95,7 @@
 	private->dummy_page_da = dma_map_single(hose->parent,
 		celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE);
 	if (private->dummy_page_da == DMA_ERROR_CODE) {
-		printk(KERN_ERR "EPCI: dummy read disabled."
+		printk(KERN_ERR "EPCI: dummy read disabled. "
 		       "Map dummy page failed.\n");
 		return;
 	}
diff --git a/arch/powerpc/platforms/celleb/scc_uhc.c b/arch/powerpc/platforms/celleb/scc_uhc.c
index b59c38a..cb43079 100644
--- a/arch/powerpc/platforms/celleb/scc_uhc.c
+++ b/arch/powerpc/platforms/celleb/scc_uhc.c
@@ -47,7 +47,8 @@
 	u32 val = 0;
 	int i;
 
-	if (!machine_is(celleb))
+	if (!machine_is(celleb_beat) &&
+	    !machine_is(celleb_native))
 		return;
 
 	uhc_base = ioremap(pci_resource_start(dev, 0),
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index ddfb35a..0f0c468 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -40,6 +40,7 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/console.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -52,12 +53,16 @@
 #include <asm/time.h>
 #include <asm/spu_priv1.h>
 #include <asm/firmware.h>
-#include <asm/of_platform.h>
+#include <asm/rtas.h>
+#include <asm/cell-regs.h>
 
 #include "interrupt.h"
 #include "beat_wrapper.h"
 #include "beat.h"
 #include "pci.h"
+#include "../cell/interrupt.h"
+#include "../cell/pervasive.h"
+#include "../cell/ras.h"
 
 static char celleb_machine_type[128] = "Celleb";
 
@@ -88,17 +93,8 @@
 	printk("*** %04x : %s\n", hex, s ? s : "");
 }
 
-static void __init celleb_setup_arch(void)
+static void __init celleb_setup_arch_common(void)
 {
-#ifdef CONFIG_SPU_BASE
-	spu_priv1_ops = &spu_priv1_beat_ops;
-	spu_management_ops = &spu_management_of_ops;
-#endif
-
-#ifdef CONFIG_SMP
-	smp_init_celleb();
-#endif
-
 	/* init to some ~sane value until calibrate_delay() runs */
 	loops_per_jiffy = 50000000;
 
@@ -107,18 +103,6 @@
 #endif
 }
 
-static int __init celleb_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	if (!of_flat_dt_is_compatible(root, "Beat"))
-		return 0;
-
-	powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
-	hpte_init_beat_v3();
-	return 1;
-}
-
 static struct of_device_id celleb_bus_ids[] __initdata = {
 	{ .type = "scc", },
 	{ .type = "ioif", },	/* old style */
@@ -127,8 +111,9 @@
 
 static int __init celleb_publish_devices(void)
 {
-	if (!machine_is(celleb))
-		return 0;
+	if (!machine_is(celleb_beat) &&
+	    !machine_is(celleb_native))
+		return -ENODEV;
 
 	/* Publish OF platform devices for southbridge IOs */
 	of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
@@ -139,10 +124,94 @@
 }
 device_initcall(celleb_publish_devices);
 
-define_machine(celleb) {
-	.name			= "Cell Reference Set",
-	.probe			= celleb_probe,
-	.setup_arch		= celleb_setup_arch,
+
+/*
+ * functions for Celleb-Beat
+ */
+static void __init celleb_setup_arch_beat(void)
+{
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops		= &spu_priv1_beat_ops;
+	spu_management_ops	= &spu_management_of_ops;
+#endif
+
+#ifdef CONFIG_SMP
+	smp_init_celleb();
+#endif
+
+	celleb_setup_arch_common();
+}
+
+static int __init celleb_probe_beat(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "Beat"))
+		return 0;
+
+	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+		| FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+	hpte_init_beat_v3();
+
+	return 1;
+}
+
+
+/*
+ * functions for Celleb-native
+ */
+static void __init celleb_init_IRQ_native(void)
+{
+	iic_init_IRQ();
+	spider_init_IRQ();
+}
+
+static void __init celleb_setup_arch_native(void)
+{
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops		= &spu_priv1_mmio_ops;
+	spu_management_ops	= &spu_management_of_ops;
+#endif
+
+	cbe_regs_init();
+
+#ifdef CONFIG_CBE_RAS
+	cbe_ras_init();
+#endif
+
+#ifdef CONFIG_SMP
+	smp_init_cell();
+#endif
+
+	cbe_pervasive_init();
+
+	/* XXX: nvram initialization should be added */
+
+	celleb_setup_arch_common();
+}
+
+static int __init celleb_probe_native(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "Beat") ||
+	    !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
+		return 0;
+
+	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+	hpte_init_native();
+
+	return 1;
+}
+
+
+/*
+ * machine definitions
+ */
+define_machine(celleb_beat) {
+	.name			= "Cell Reference Set (Beat)",
+	.probe			= celleb_probe_beat,
+	.setup_arch		= celleb_setup_arch_beat,
 	.show_cpuinfo		= celleb_show_cpuinfo,
 	.restart		= beat_restart,
 	.power_off		= beat_power_off,
@@ -167,3 +236,26 @@
 	.machine_crash_shutdown	= default_machine_crash_shutdown,
 #endif
 };
+
+define_machine(celleb_native) {
+	.name			= "Cell Reference Set (native)",
+	.probe			= celleb_probe_native,
+	.setup_arch		= celleb_setup_arch_native,
+	.show_cpuinfo		= celleb_show_cpuinfo,
+	.restart		= rtas_restart,
+	.power_off		= rtas_power_off,
+	.halt			= rtas_halt,
+	.get_boot_time		= rtas_get_boot_time,
+	.get_rtc_time		= rtas_get_rtc_time,
+	.set_rtc_time		= rtas_set_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= celleb_progress,
+	.pci_probe_mode 	= celleb_pci_probe_mode,
+	.pci_setup_phb		= celleb_setup_phb,
+	.init_IRQ		= celleb_init_IRQ_native,
+#ifdef CONFIG_KEXEC
+	.machine_kexec		= default_machine_kexec,
+	.machine_kexec_prepare	= default_machine_kexec_prepare,
+	.machine_crash_shutdown	= default_machine_crash_shutdown,
+#endif
+};
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 0340a34..d51f83a 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -198,7 +198,7 @@
 		printk ("RTAS supporting Pegasos OF not found, please upgrade"
 			" your firmware\n");
 	}
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	/* keep the reference to the root node */
 }
 
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 5930626..42a21ba 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -115,7 +115,7 @@
 	seq_printf(m, "machine\t\t: CHRP %s\n", model);
 
 	/* longtrail (goldengate) stuff */
-	if (!strncmp(model, "IBM,LongTrail", 13)) {
+	if (model && !strncmp(model, "IBM,LongTrail", 13)) {
 		/* VLSI VAS96011/12 `Golden Gate 2' */
 		/* Memory banks */
 		sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
@@ -203,15 +203,20 @@
 static void __init sio_init(void)
 {
 	struct device_node *root;
+	const char *model;
 
-	if ((root = of_find_node_by_path("/")) &&
-	    !strncmp(of_get_property(root, "model", NULL),
-			"IBM,LongTrail", 13)) {
+	root = of_find_node_by_path("/");
+	if (!root)
+		return;
+
+	model = of_get_property(root, "model", NULL);
+	if (model && !strncmp(model, "IBM,LongTrail", 13)) {
 		/* logical device 0 (KBC/Keyboard) */
 		sio_fixup_irq("keyboard", 0, 1, 2);
 		/* select logical device 1 (KBC/Mouse) */
 		sio_fixup_irq("mouse", 1, 12, 2);
 	}
+
 	of_node_put(root);
 }
 
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c
index b6de2b5..b21fde5 100644
--- a/arch/powerpc/platforms/embedded6xx/holly.c
+++ b/arch/powerpc/platforms/embedded6xx/holly.c
@@ -20,12 +20,12 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_core.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -39,7 +39,6 @@
 #include <asm/tsi108_irq.h>
 #include <asm/tsi108_pci.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 
 #undef DEBUG
 
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index a65f1b4..cc7161f 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -5,7 +5,7 @@
 obj-y += exception.o
 obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
 	hvcall.o proc.o htab.o iommu.o misc.o irq.o
-obj-$(CONFIG_PCI) += pci.o vpdinfo.o
+obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_VIOPATH) += viopath.o vio.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 49e9c66..6a0c6f6 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -163,8 +163,10 @@
 		    (it->it_type == TCE_PCI) &&
 		    (it->it_offset == tbl->it_offset) &&
 		    (it->it_index == tbl->it_index) &&
-		    (it->it_size == tbl->it_size))
+		    (it->it_size == tbl->it_size)) {
+			of_node_put(node);
 			return it;
+		}
 	}
 	return NULL;
 }
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index 275f494..e5b40e3 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -239,7 +239,7 @@
 			 * other CPUs, and that the deleted handler isn't
 			 * still running on another CPU when we return.
 			 */
-			synchronize_rcu();
+			synchronize_sched();
 			return 0;
 		}
 	}
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index da87162..30e3d99 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2001 Allan Trautman, IBM Corporation
+ * Copyright (C) 2005,2007  Stephen Rothwell, IBM Corp
  *
  * iSeries specific routines for PCI.
  *
@@ -19,6 +20,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -26,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 
+#include <asm/types.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
@@ -35,6 +40,7 @@
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
+#include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
 #include <asm/iseries/iommu.h>
@@ -45,15 +51,8 @@
 #include "pci.h"
 #include "call_pci.h"
 
-/*
- * Forward declares of prototypes.
- */
-static struct device_node *find_Device_Node(int bus, int devfn);
-
-static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
-static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
-
-static struct pci_ops iSeries_pci_ops;
+#define PCI_RETRY_MAX	3
+static int limit_pci_retries = 1;	/* Set Retry Error on. */
 
 /*
  * Table defines
@@ -62,6 +61,7 @@
 #define IOMM_TABLE_MAX_ENTRIES	1024
 #define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
 #define BASE_IO_MEMORY		0xE000000000000000UL
+#define END_IO_MEMORY		0xEFFFFFFFFFFFFFFFUL
 
 static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
@@ -72,10 +72,234 @@
 static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
 static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
 /*
+ * Generate a Direct Select Address for the Hypervisor
+ */
+static inline u64 iseries_ds_addr(struct device_node *node)
+{
+	struct pci_dn *pdn = PCI_DN(node);
+
+	return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40)
+			+ ((u64)0x10 << 32);
+}
+
+/*
+ * Size of Bus VPD data
+ */
+#define BUS_VPDSIZE      1024
+
+/*
+ * Bus Vpd Tags
+ */
+#define VPD_END_OF_AREA		0x79
+#define VPD_ID_STRING		0x82
+#define VPD_VENDOR_AREA		0x84
+
+/*
+ * Mfg Area Tags
+ */
+#define VPD_FRU_FRAME_ID	0x4649	/* "FI" */
+#define VPD_SLOT_MAP_FORMAT	0x4D46	/* "MF" */
+#define VPD_SLOT_MAP		0x534D	/* "SM" */
+
+/*
+ * Structures of the areas
+ */
+struct mfg_vpd_area {
+	u16	tag;
+	u8	length;
+	u8	data1;
+	u8	data2;
+};
+#define MFG_ENTRY_SIZE   3
+
+struct slot_map {
+	u8	agent;
+	u8	secondary_agent;
+	u8	phb;
+	char	card_location[3];
+	char	parms[8];
+	char	reserved[2];
+};
+#define SLOT_ENTRY_SIZE   16
+
+/*
+ * Parse the Slot Area
+ */
+static void __init iseries_parse_slot_area(struct slot_map *map, int len,
+		HvAgentId agent, u8 *phb, char card[4])
+{
+	/*
+	 * Parse Slot label until we find the one requested
+	 */
+	while (len > 0) {
+		if (map->agent == agent) {
+			/*
+			 * If Phb wasn't found, grab the entry first one found.
+			 */
+			if (*phb == 0xff)
+				*phb = map->phb;
+			/* Found it, extract the data. */
+			if (map->phb == *phb) {
+				memcpy(card, &map->card_location, 3);
+				card[3]  = 0;
+				break;
+			}
+		}
+		/* Point to the next Slot */
+		map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
+		len -= SLOT_ENTRY_SIZE;
+	}
+}
+
+/*
+ * Parse the Mfg Area
+ */
+static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
+		HvAgentId agent, u8 *phb, u8 *frame, char card[4])
+{
+	u16 slot_map_fmt = 0;
+
+	/* Parse Mfg Data */
+	while (len > 0) {
+		int mfg_tag_len = area->length;
+		/* Frame ID         (FI 4649020310 ) */
+		if (area->tag == VPD_FRU_FRAME_ID)
+			*frame = area->data1;
+		/* Slot Map Format  (MF 4D46020004 ) */
+		else if (area->tag == VPD_SLOT_MAP_FORMAT)
+			slot_map_fmt = (area->data1 * 256)
+				+ area->data2;
+		/* Slot Map         (SM 534D90 */
+		else if (area->tag == VPD_SLOT_MAP) {
+			struct slot_map *slot_map;
+
+			if (slot_map_fmt == 0x1004)
+				slot_map = (struct slot_map *)((char *)area
+						+ MFG_ENTRY_SIZE + 1);
+			else
+				slot_map = (struct slot_map *)((char *)area
+						+ MFG_ENTRY_SIZE);
+			iseries_parse_slot_area(slot_map, mfg_tag_len,
+					agent, phb, card);
+		}
+		/*
+		 * Point to the next Mfg Area
+		 * Use defined size, sizeof give wrong answer
+		 */
+		area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
+				+ MFG_ENTRY_SIZE);
+		len -= (mfg_tag_len + MFG_ENTRY_SIZE);
+	}
+}
+
+/*
+ * Look for "BUS".. Data is not Null terminated.
+ * PHBID of 0xFF indicates PHB was not found in VPD Data.
+ */
+static u8 __init iseries_parse_phbid(u8 *area, int len)
+{
+	while (len > 0) {
+		if ((*area == 'B') && (*(area + 1) == 'U')
+				&& (*(area + 2) == 'S')) {
+			area += 3;
+			while (*area == ' ')
+				area++;
+			return *area & 0x0F;
+		}
+		area++;
+		len--;
+	}
+	return 0xff;
+}
+
+/*
+ * Parse out the VPD Areas
+ */
+static void __init iseries_parse_vpd(u8 *data, int data_len,
+		HvAgentId agent, u8 *frame, char card[4])
+{
+	u8 phb = 0xff;
+
+	while (data_len > 0) {
+		int len;
+		u8 tag = *data;
+
+		if (tag == VPD_END_OF_AREA)
+			break;
+		len = *(data + 1) + (*(data + 2) * 256);
+		data += 3;
+		data_len -= 3;
+		if (tag == VPD_ID_STRING)
+			phb = iseries_parse_phbid(data, len);
+		else if (tag == VPD_VENDOR_AREA)
+			iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
+					agent, &phb, frame, card);
+		/* Point to next Area. */
+		data += len;
+		data_len -= len;
+	}
+}
+
+static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
+		u8 *frame, char card[4])
+{
+	int status = 0;
+	int bus_vpd_len = 0;
+	u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+
+	if (bus_vpd == NULL) {
+		printk("PCI: Bus VPD Buffer allocation failure.\n");
+		return 0;
+	}
+	bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
+					BUS_VPDSIZE);
+	if (bus_vpd_len == 0) {
+		printk("PCI: Bus VPD Buffer zero length.\n");
+		goto out_free;
+	}
+	/* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
+	/* Make sure this is what I think it is */
+	if (*bus_vpd != VPD_ID_STRING) {
+		printk("PCI: Bus VPD Buffer missing starting tag.\n");
+		goto out_free;
+	}
+	iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
+	status = 1;
+out_free:
+	kfree(bus_vpd);
+	return status;
+}
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
+ * controller
+ */
+static void __init iseries_device_information(struct pci_dev *pdev,
+					      u16 bus, HvSubBusNumber subbus)
+{
+	u8 frame = 0;
+	char card[4];
+	HvAgentId agent;
+
+	agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+			ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+
+	if (iseries_get_location_code(bus, agent, &frame, card)) {
+		printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
+		       "Card %4s  0x%04X\n", pci_name(pdev), pdev->vendor,
+		       frame, card, (int)(pdev->class >> 8));
+	}
+}
+
+/*
  * iomm_table_allocate_entry
  *
  * Adds pci_dev entry in address translation table
@@ -87,7 +311,7 @@
  * - CurrentIndex is incremented to keep track of the last entry.
  * - Builds the resource entry for allocated BARs.
  */
-static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
+static void __init iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
 {
 	struct resource *bar_res = &dev->resource[bar_num];
 	long bar_size = pci_resource_len(dev, bar_num);
@@ -101,7 +325,6 @@
 	 * Set Resource values.
 	 */
 	spin_lock(&iomm_table_lock);
-	bar_res->name = pci_io_text;
 	bar_res->start = BASE_IO_MEMORY +
 		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
 	bar_res->end = bar_res->start + bar_size - 1;
@@ -130,7 +353,7 @@
  * - Loops through The Bar resources(0 - 5) including the ROM
  *   is resource(6).
  */
-static void allocate_device_bars(struct pci_dev *dev)
+static void __init allocate_device_bars(struct pci_dev *dev)
 {
 	int bar_num;
 
@@ -145,79 +368,19 @@
  * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
  * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
  */
-static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
-		int AgentId, int HvRc)
+static void pci_log_error(char *error, int bus, int subbus,
+		int agent, int hv_res)
 {
-	if (HvRc == 0x0302)
+	if (hv_res == 0x0302)
 		return;
 	printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
-	       Error_Text, Bus, SubBus, AgentId, HvRc);
-}
-
-/*
- * iSeries_pci_final_fixup(void)
- */
-void __init iSeries_pci_final_fixup(void)
-{
-	struct pci_dev *pdev = NULL;
-	struct device_node *node;
-	int DeviceCount = 0;
-
-	/* Fix up at the device node and pci_dev relationship */
-	mf_display_src(0xC9000100);
-
-	printk("pcibios_final_fixup\n");
-	for_each_pci_dev(pdev) {
-		node = find_Device_Node(pdev->bus->number, pdev->devfn);
-		printk("pci dev %p (%x.%x), node %p\n", pdev,
-		       pdev->bus->number, pdev->devfn, node);
-
-		if (node != NULL) {
-			struct pci_dn *pdn = PCI_DN(node);
-			const u32 *agent;
-
-			agent = of_get_property(node, "linux,agent-id", NULL);
-			if ((pdn != NULL) && (agent != NULL)) {
-				u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
-						pdn->bussubno);
-				int err;
-
-				err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
-						*agent, irq);
-				if (err)
-					pci_Log_Error("Connect Bus Unit",
-						pdn->busno, pdn->bussubno, *agent, err);
-				else {
-					err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
-							*agent,
-							PCI_INTERRUPT_LINE,
-							irq);
-					if (err)
-						pci_Log_Error("PciCfgStore Irq Failed!",
-							pdn->busno, pdn->bussubno, *agent, err);
-				}
-				if (!err)
-					pdev->irq = irq;
-			}
-
-			++DeviceCount;
-			pdev->sysdata = (void *)node;
-			PCI_DN(node)->pcidev = pdev;
-			allocate_device_bars(pdev);
-			iSeries_Device_Information(pdev, DeviceCount);
-			iommu_devnode_init_iSeries(pdev, node);
-		} else
-			printk("PCI: Device Tree not found for 0x%016lX\n",
-					(unsigned long)pdev);
-	}
-	iSeries_activate_IRQs();
-	mf_display_src(0xC9000200);
+	       error, bus, subbus, agent, hv_res);
 }
 
 /*
  * Look down the chain to find the matching Device Device
  */
-static struct device_node *find_Device_Node(int bus, int devfn)
+static struct device_node *find_device_node(int bus, int devfn)
 {
 	struct device_node *node;
 
@@ -230,22 +393,67 @@
 	return NULL;
 }
 
-#if 0
 /*
- * Returns the device node for the passed pci_dev
- * Sanity Check Node PciDev to passed pci_dev
- * If none is found, returns a NULL which the client must handle.
+ * iSeries_pcibios_fixup_resources
+ *
+ * Fixes up all resources for devices
  */
-static struct device_node *get_Device_Node(struct pci_dev *pdev)
+void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
 {
+	const u32 *agent;
+	const u32 *sub_bus;
+	unsigned char bus = pdev->bus->number;
 	struct device_node *node;
+	int i;
 
-	node = pdev->sysdata;
-	if (node == NULL || PCI_DN(node)->pcidev != pdev)
-		node = find_Device_Node(pdev->bus->number, pdev->devfn);
-	return node;
+	node = find_device_node(bus, pdev->devfn);
+	pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
+		 pci_name(pdev), pdev, node);
+	if (!node) {
+		printk("PCI: %s disabled, device tree entry not found !\n",
+		       pci_name(pdev));
+		for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+			pdev->resource[i].flags = 0;
+		return;
+	}
+	sub_bus = of_get_property(node, "linux,subbus", NULL);
+	agent = of_get_property(node, "linux,agent-id", NULL);
+	if (agent && sub_bus) {
+		u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
+		int err;
+
+		err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
+		if (err)
+			pci_log_error("Connect Bus Unit",
+				      bus, *sub_bus, *agent, err);
+		else {
+			err = HvCallPci_configStore8(bus, *sub_bus,
+					*agent, PCI_INTERRUPT_LINE, irq);
+			if (err)
+				pci_log_error("PciCfgStore Irq Failed!",
+						bus, *sub_bus, *agent, err);
+			else
+				pdev->irq = irq;
+		}
+	}
+
+	pdev->sysdata = node;
+	PCI_DN(node)->pcidev = pdev;
+	allocate_device_bars(pdev);
+	iseries_device_information(pdev, bus, *sub_bus);
+	iommu_devnode_init_iSeries(pdev, node);
 }
-#endif
+
+/*
+ * iSeries_pci_final_fixup(void)
+ */
+void __init iSeries_pci_final_fixup(void)
+{
+	/* Fix up at the device node and pci_dev relationship */
+	mf_display_src(0xC9000100);
+	iSeries_activate_IRQs();
+	mf_display_src(0xC9000200);
+}
 
 /*
  * Config space read and write functions.
@@ -269,7 +477,7 @@
 static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
 		int offset, int size, u32 *val)
 {
-	struct device_node *node = find_Device_Node(bus->number, devfn);
+	struct device_node *node = find_device_node(bus->number, devfn);
 	u64 fn;
 	struct HvCallPci_LoadReturn ret;
 
@@ -299,7 +507,7 @@
 static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 		int offset, int size, u32 val)
 {
-	struct device_node *node = find_Device_Node(bus->number, devfn);
+	struct device_node *node = find_device_node(bus->number, devfn);
 	u64 fn;
 	u64 ret;
 
@@ -331,22 +539,22 @@
  * PCI: Device 23.90 ReadL Retry( 1)
  * PCI: Device 23.90 ReadL Retry Successful(1)
  */
-static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
+static int check_return_code(char *type, struct device_node *dn,
 		int *retry, u64 ret)
 {
 	if (ret != 0)  {
-		struct pci_dn *pdn = PCI_DN(DevNode);
+		struct pci_dn *pdn = PCI_DN(dn);
 
 		(*retry)++;
 		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
-				TextHdr, pdn->busno, pdn->devfn,
+				type, pdn->busno, pdn->devfn,
 				*retry, (int)ret);
 		/*
 		 * Bump the retry and check for retry count exceeded.
 		 * If, Exceeded, panic the system.
 		 */
-		if (((*retry) > Pci_Retry_Max) &&
-				(Pci_Error_Flag > 0)) {
+		if (((*retry) > PCI_RETRY_MAX) &&
+				(limit_pci_retries > 0)) {
 			mf_display_src(0xB6000103);
 			panic_timeout = 0;
 			panic("PCI: Hardware I/O Error, SRC B6000103, "
@@ -363,28 +571,40 @@
  * the exposure of being device global.
  */
 static inline struct device_node *xlate_iomm_address(
-		const volatile void __iomem *IoAddress,
-		u64 *dsaptr, u64 *BarOffsetPtr)
+		const volatile void __iomem *addr,
+		u64 *dsaptr, u64 *bar_offset, const char *func)
 {
-	unsigned long OrigIoAddr;
-	unsigned long BaseIoAddr;
-	unsigned long TableIndex;
-	struct device_node *DevNode;
+	unsigned long orig_addr;
+	unsigned long base_addr;
+	unsigned long ind;
+	struct device_node *dn;
 
-	OrigIoAddr = (unsigned long __force)IoAddress;
-	if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
+	orig_addr = (unsigned long __force)addr;
+	if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
+		static unsigned long last_jiffies;
+		static int num_printed;
+
+		if ((jiffies - last_jiffies) > 60 * HZ) {
+			last_jiffies = jiffies;
+			num_printed = 0;
+		}
+		if (num_printed++ < 10)
+			printk(KERN_ERR
+				"iSeries_%s: invalid access at IO address %p\n",
+				func, addr);
 		return NULL;
-	BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY;
-	TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE;
-	DevNode = iomm_table[TableIndex];
+	}
+	base_addr = orig_addr - BASE_IO_MEMORY;
+	ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
+	dn = iomm_table[ind];
 
-	if (DevNode != NULL) {
-		int barnum = iobar_table[TableIndex];
-		*dsaptr = iseries_ds_addr(DevNode) | (barnum << 24);
-		*BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE;
+	if (dn != NULL) {
+		int barnum = iobar_table[ind];
+		*dsaptr = iseries_ds_addr(dn) | (barnum << 24);
+		*bar_offset = base_addr % IOMM_TABLE_ENTRY_SIZE;
 	} else
-		panic("PCI: Invalid PCI IoAddress detected!\n");
-	return DevNode;
+		panic("PCI: Invalid PCI IO address detected!\n");
+	return dn;
 }
 
 /*
@@ -392,91 +612,58 @@
  * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
  * else, data is returned in Big Endian format.
  */
-static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
+static u8 iseries_readb(const volatile void __iomem *addr)
 {
-	u64 BarOffset;
+	u64 bar_offset;
 	u64 dsa;
 	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
 
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
-			       IoAddress);
+	if (dn == NULL)
 		return 0xff;
-	}
 	do {
-		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
-	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
+		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
+	} while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
 
 	return ret.value;
 }
 
-static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
+static u16 iseries_readw_be(const volatile void __iomem *addr)
 {
-	u64 BarOffset;
+	u64 bar_offset;
 	u64 dsa;
 	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
 
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
-			       IoAddress);
+	if (dn == NULL)
 		return 0xffff;
-	}
 	do {
 		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
-				BarOffset, 0);
-	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
+				bar_offset, 0);
+	} while (check_return_code("RDW", dn, &retry, ret.rc) != 0);
 
 	return ret.value;
 }
 
-static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
+static u32 iseries_readl_be(const volatile void __iomem *addr)
 {
-	u64 BarOffset;
+	u64 bar_offset;
 	u64 dsa;
 	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
 
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",
-			       IoAddress);
+	if (dn == NULL)
 		return 0xffffffff;
-	}
 	do {
 		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
-				BarOffset, 0);
-	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
+				bar_offset, 0);
+	} while (check_return_code("RDL", dn, &retry, ret.rc) != 0);
 
 	return ret.value;
 }
@@ -485,134 +672,72 @@
  * Write MM I/O Instructions for the iSeries
  *
  */
-static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
-{
-	u64 BarOffset;
-	u64 dsa;
-	int retry = 0;
-	u64 rc;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
-
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);
-		return;
-	}
-	do {
-		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
-	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
-}
-
-static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
-{
-	u64 BarOffset;
-	u64 dsa;
-	int retry = 0;
-	u64 rc;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
-
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",
-			       IoAddress);
-		return;
-	}
-	do {
-		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0);
-	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
-}
-
-static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
-{
-	u64 BarOffset;
-	u64 dsa;
-	int retry = 0;
-	u64 rc;
-	struct device_node *DevNode =
-		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
-
-	if (DevNode == NULL) {
-		static unsigned long last_jiffies;
-		static int num_printed;
-
-		if ((jiffies - last_jiffies) > 60 * HZ) {
-			last_jiffies = jiffies;
-			num_printed = 0;
-		}
-		if (num_printed++ < 10)
-			printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",
-			       IoAddress);
-		return;
-	}
-	do {
-		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0);
-	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
-}
-
-static u8 iseries_readb(const volatile void __iomem *addr)
-{
-	return iSeries_Read_Byte(addr);
-}
-
-static u16 iseries_readw(const volatile void __iomem *addr)
-{
-	return le16_to_cpu(iSeries_Read_Word(addr));
-}
-
-static u32 iseries_readl(const volatile void __iomem *addr)
-{
-	return le32_to_cpu(iSeries_Read_Long(addr));
-}
-
-static u16 iseries_readw_be(const volatile void __iomem *addr)
-{
-	return iSeries_Read_Word(addr);
-}
-
-static u32 iseries_readl_be(const volatile void __iomem *addr)
-{
-	return iSeries_Read_Long(addr);
-}
-
 static void iseries_writeb(u8 data, volatile void __iomem *addr)
 {
-	iSeries_Write_Byte(data, addr);
-}
+	u64 bar_offset;
+	u64 dsa;
+	int retry = 0;
+	u64 rc;
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
 
-static void iseries_writew(u16 data, volatile void __iomem *addr)
-{
-	iSeries_Write_Word(cpu_to_le16(data), addr);
-}
-
-static void iseries_writel(u32 data, volatile void __iomem *addr)
-{
-	iSeries_Write_Long(cpu_to_le32(data), addr);
+	if (dn == NULL)
+		return;
+	do {
+		rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
+	} while (check_return_code("WWB", dn, &retry, rc) != 0);
 }
 
 static void iseries_writew_be(u16 data, volatile void __iomem *addr)
 {
-	iSeries_Write_Word(data, addr);
+	u64 bar_offset;
+	u64 dsa;
+	int retry = 0;
+	u64 rc;
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
+
+	if (dn == NULL)
+		return;
+	do {
+		rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
+	} while (check_return_code("WWW", dn, &retry, rc) != 0);
 }
 
 static void iseries_writel_be(u32 data, volatile void __iomem *addr)
 {
-	iSeries_Write_Long(data, addr);
+	u64 bar_offset;
+	u64 dsa;
+	int retry = 0;
+	u64 rc;
+	struct device_node *dn =
+		xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
+
+	if (dn == NULL)
+		return;
+	do {
+		rc = HvCall4(HvCallPciBarStore32, dsa, bar_offset, data, 0);
+	} while (check_return_code("WWL", dn, &retry, rc) != 0);
+}
+
+static u16 iseries_readw(const volatile void __iomem *addr)
+{
+	return le16_to_cpu(iseries_readw_be(addr));
+}
+
+static u32 iseries_readl(const volatile void __iomem *addr)
+{
+	return le32_to_cpu(iseries_readl_be(addr));
+}
+
+static void iseries_writew(u16 data, volatile void __iomem *addr)
+{
+	iseries_writew_be(cpu_to_le16(data), addr);
+}
+
+static void iseries_writel(u32 data, volatile void __iomem *addr)
+{
+	iseries_writel(cpu_to_le32(data), addr);
 }
 
 static void iseries_readsb(const volatile void __iomem *addr, void *buf,
@@ -620,7 +745,7 @@
 {
 	u8 *dst = buf;
 	while(count-- > 0)
-		*(dst++) = iSeries_Read_Byte(addr);
+		*(dst++) = iseries_readb(addr);
 }
 
 static void iseries_readsw(const volatile void __iomem *addr, void *buf,
@@ -628,7 +753,7 @@
 {
 	u16 *dst = buf;
 	while(count-- > 0)
-		*(dst++) = iSeries_Read_Word(addr);
+		*(dst++) = iseries_readw_be(addr);
 }
 
 static void iseries_readsl(const volatile void __iomem *addr, void *buf,
@@ -636,7 +761,7 @@
 {
 	u32 *dst = buf;
 	while(count-- > 0)
-		*(dst++) = iSeries_Read_Long(addr);
+		*(dst++) = iseries_readl_be(addr);
 }
 
 static void iseries_writesb(volatile void __iomem *addr, const void *buf,
@@ -644,7 +769,7 @@
 {
 	const u8 *src = buf;
 	while(count-- > 0)
-		iSeries_Write_Byte(*(src++), addr);
+		iseries_writeb(*(src++), addr);
 }
 
 static void iseries_writesw(volatile void __iomem *addr, const void *buf,
@@ -652,7 +777,7 @@
 {
 	const u16 *src = buf;
 	while(count-- > 0)
-		iSeries_Write_Word(*(src++), addr);
+		iseries_writew_be(*(src++), addr);
 }
 
 static void iseries_writesl(volatile void __iomem *addr, const void *buf,
@@ -660,7 +785,7 @@
 {
 	const u32 *src = buf;
 	while(count-- > 0)
-		iSeries_Write_Long(*(src++), addr);
+		iseries_writel_be(*(src++), addr);
 }
 
 static void iseries_memset_io(volatile void __iomem *addr, int c,
@@ -669,7 +794,7 @@
 	volatile char __iomem *d = addr;
 
 	while (n-- > 0)
-		iSeries_Write_Byte(c, d++);
+		iseries_writeb(c, d++);
 }
 
 static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
@@ -679,7 +804,7 @@
 	const volatile char __iomem *s = src;
 
 	while (n-- > 0)
-		*d++ = iSeries_Read_Byte(s++);
+		*d++ = iseries_readb(s++);
 }
 
 static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
@@ -689,7 +814,7 @@
 	volatile char __iomem *d = dest;
 
 	while (n-- > 0)
-		iSeries_Write_Byte(*s++, d++);
+		iseries_writeb(*s++, d++);
 }
 
 /* We only set MMIO ops. The default PIO ops will be default
@@ -742,6 +867,8 @@
 	/* Install IO hooks */
 	ppc_pci_io = iseries_pci_io;
 
+	pci_probe_only = 1;
+
 	/* iSeries has no IO space in the common sense, it needs to set
 	 * the IO base to 0
 	 */
@@ -767,11 +894,21 @@
 		phb = pcibios_alloc_controller(node);
 		if (phb == NULL)
 			continue;
+		/* All legacy iSeries PHBs are in domain zero */
+		phb->global_number = 0;
 
-		phb->pci_mem_offset = bus;
 		phb->first_busno = bus;
 		phb->last_busno = bus;
 		phb->ops = &iSeries_pci_ops;
+		phb->io_base_virt = (void __iomem *)_IO_BASE;
+		phb->io_resource.flags = IORESOURCE_IO;
+		phb->io_resource.start = BASE_IO_MEMORY;
+		phb->io_resource.end = END_IO_MEMORY;
+		phb->io_resource.name = "iSeries PCI IO";
+		phb->mem_resources[0].flags = IORESOURCE_MEM;
+		phb->mem_resources[0].start = BASE_IO_MEMORY;
+		phb->mem_resources[0].end = END_IO_MEMORY;
+		phb->mem_resources[0].name = "Series PCI MEM";
 	}
 
 	of_node_put(root);
diff --git a/arch/powerpc/platforms/iseries/pci.h b/arch/powerpc/platforms/iseries/pci.h
index 33a8489..d9cf974 100644
--- a/arch/powerpc/platforms/iseries/pci.h
+++ b/arch/powerpc/platforms/iseries/pci.h
@@ -30,10 +30,6 @@
  * End Change Activity
  */
 
-#include <asm/pci-bridge.h>
-
-struct pci_dev;				/* For Forward Reference */
-
 /*
  * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
  * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
@@ -47,17 +43,16 @@
 #define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)		((subbus >> 5) & 0x7)
 #define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)	((subbus >> 2) & 0x7)
 
-/*
- * Generate a Direct Select Address for the Hypervisor
- */
-static inline u64 iseries_ds_addr(struct device_node *node)
-{
-	struct pci_dn *pdn = PCI_DN(node);
+struct pci_dev;
 
-	return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40)
-			+ ((u64)0x10 << 32);
-}
-
-extern void	iSeries_Device_Information(struct pci_dev*, int);
+#ifdef CONFIG_PCI
+extern void	iSeries_pcibios_init(void);
+extern void	iSeries_pci_final_fixup(void);
+extern void 	iSeries_pcibios_fixup_resources(struct pci_dev *dev);
+#else
+static inline void	iSeries_pcibios_init(void) { }
+static inline void	iSeries_pci_final_fixup(void) { }
+static inline void 	iSeries_pcibios_fixup_resources(struct pci_dev *dev) {}
+#endif
 
 #endif /* _PLATFORMS_ISERIES_PCI_H */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 0877a88..b721207 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -63,6 +63,7 @@
 #include "main_store.h"
 #include "call_sm.h"
 #include "call_hpt.h"
+#include "pci.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -74,11 +75,6 @@
 static unsigned long build_iSeries_Memory_Map(void);
 static void iseries_shared_idle(void);
 static void iseries_dedicated_idle(void);
-#ifdef CONFIG_PCI
-extern void iSeries_pci_final_fixup(void);
-#else
-static void iSeries_pci_final_fixup(void) { }
-#endif
 
 
 struct MemoryBlock {
@@ -112,13 +108,13 @@
 	 * correctly.
 	 */
 	mb_array[0].logicalStart = 0;
-	mb_array[0].logicalEnd = 0x100000000;
+	mb_array[0].logicalEnd = 0x100000000UL;
 	mb_array[0].absStart = 0;
-	mb_array[0].absEnd = 0x100000000;
+	mb_array[0].absEnd = 0x100000000UL;
 
 	if (holeSize) {
 		numMemoryBlocks = 2;
-		holeStart = holeStart & 0x000fffffffffffff;
+		holeStart = holeStart & 0x000fffffffffffffUL;
 		holeStart = addr_to_chunk(holeStart);
 		holeFirstChunk = holeStart;
 		holeSize = addr_to_chunk(holeSize);
@@ -128,9 +124,9 @@
 		mb_array[0].logicalEnd = holeFirstChunk;
 		mb_array[0].absEnd = holeFirstChunk;
 		mb_array[1].logicalStart = holeFirstChunk;
-		mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks;
+		mb_array[1].logicalEnd = 0x100000000UL - holeSizeChunks;
 		mb_array[1].absStart = holeFirstChunk + holeSizeChunks;
-		mb_array[1].absEnd = 0x100000000;
+		mb_array[1].absEnd = 0x100000000UL;
 	}
 	return numMemoryBlocks;
 }
@@ -234,9 +230,9 @@
 				mb_array[i].logicalEnd,
 				mb_array[i].absStart, mb_array[i].absEnd);
 		mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
-				0x000fffffffffffff);
+				0x000fffffffffffffUL);
 		mb_array[i].absEnd = addr_to_chunk(mb_array[i].absEnd &
-				0x000fffffffffffff);
+				0x000fffffffffffffUL);
 		mb_array[i].logicalStart =
 			addr_to_chunk(mb_array[i].logicalStart);
 		mb_array[i].logicalEnd = addr_to_chunk(mb_array[i].logicalEnd);
@@ -320,7 +316,7 @@
 };
 EXPORT_SYMBOL(mschunks_map);
 
-void mschunks_alloc(unsigned long num_chunks)
+static void mschunks_alloc(unsigned long num_chunks)
 {
 	klimit = _ALIGN(klimit, sizeof(u32));
 	mschunks_map.mapping = (u32 *)klimit;
@@ -499,6 +495,8 @@
 			itVpdAreas.xSlicMaxLogicalProcs);
 	printk("Max physical processors = %d\n",
 			itVpdAreas.xSlicMaxPhysicalProcs);
+
+	iSeries_pcibios_init();
 }
 
 static void iSeries_show_cpuinfo(struct seq_file *m)
@@ -641,24 +639,25 @@
 }
 
 define_machine(iseries) {
-	.name		= "iSeries",
-	.setup_arch	= iSeries_setup_arch,
-	.show_cpuinfo	= iSeries_show_cpuinfo,
-	.init_IRQ	= iSeries_init_IRQ,
-	.get_irq	= iSeries_get_irq,
-	.init_early	= iSeries_init_early,
-	.pcibios_fixup	= iSeries_pci_final_fixup,
-	.restart	= mf_reboot,
-	.power_off	= mf_power_off,
-	.halt		= mf_power_off,
-	.get_boot_time	= iSeries_get_boot_time,
-	.set_rtc_time	= iSeries_set_rtc_time,
-	.get_rtc_time	= iSeries_get_rtc_time,
-	.calibrate_decr	= generic_calibrate_decr,
-	.progress	= iSeries_progress,
-	.probe		= iseries_probe,
-	.ioremap	= iseries_ioremap,
-	.iounmap	= iseries_iounmap,
+	.name			= "iSeries",
+	.setup_arch		= iSeries_setup_arch,
+	.show_cpuinfo		= iSeries_show_cpuinfo,
+	.init_IRQ		= iSeries_init_IRQ,
+	.get_irq		= iSeries_get_irq,
+	.init_early		= iSeries_init_early,
+	.pcibios_fixup		= iSeries_pci_final_fixup,
+	.pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
+	.restart		= mf_reboot,
+	.power_off		= mf_power_off,
+	.halt			= mf_power_off,
+	.get_boot_time		= iSeries_get_boot_time,
+	.set_rtc_time		= iSeries_set_rtc_time,
+	.get_rtc_time		= iSeries_get_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= iSeries_progress,
+	.probe			= iseries_probe,
+	.ioremap		= iseries_ioremap,
+	.iounmap		= iseries_iounmap,
 	/* XXX Implement enable_pmcs for iSeries */
 };
 
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 0a47ac5..729754b 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -17,6 +17,7 @@
 #ifndef	__ISERIES_SETUP_H__
 #define	__ISERIES_SETUP_H__
 
+extern void *iSeries_early_setup(void);
 extern unsigned long iSeries_get_boot_time(void);
 extern int iSeries_set_rtc_time(struct rtc_time *tm);
 extern void iSeries_get_rtc_time(struct rtc_time *tm);
diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c
deleted file mode 100644
index 9f83878..0000000
--- a/arch/powerpc/platforms/iseries/vpdinfo.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * This code gets the card location of the hardware
- * Copyright (C) 2001  <Allan H Trautman> <IBM Corp>
- * Copyright (C) 2005  Stephen Rothwel, IBM Corp
- *
- * 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
- *
- * Change Activity:
- *   Created, Feb 2, 2001
- *   Ported to ppc64, August 20, 2001
- * End Change Activity
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <asm/types.h>
-#include <asm/resource.h>
-#include <asm/abs_addr.h>
-#include <asm/pci-bridge.h>
-#include <asm/iseries/hv_types.h>
-
-#include "pci.h"
-#include "call_pci.h"
-
-/*
- * Size of Bus VPD data
- */
-#define BUS_VPDSIZE      1024
-
-/*
- * Bus Vpd Tags
- */
-#define  VpdEndOfAreaTag   0x79
-#define  VpdIdStringTag    0x82
-#define  VpdVendorAreaTag  0x84
-
-/*
- * Mfg Area Tags
- */
-#define  VpdFruFrameId    0x4649     // "FI"
-#define  VpdSlotMapFormat 0x4D46     // "MF"
-#define  VpdSlotMap       0x534D     // "SM"
-
-/*
- * Structures of the areas
- */
-struct MfgVpdAreaStruct {
-	u16 Tag;
-	u8  TagLength;
-	u8  AreaData1;
-	u8  AreaData2;
-};
-typedef struct MfgVpdAreaStruct MfgArea;
-#define MFG_ENTRY_SIZE   3
-
-struct SlotMapStruct {
-	u8   AgentId;
-	u8   SecondaryAgentId;
-	u8   PhbId;
-	char CardLocation[3];
-	char Parms[8];
-	char Reserved[2];
-};
-typedef struct SlotMapStruct SlotMap;
-#define SLOT_ENTRY_SIZE   16
-
-/*
- * Parse the Slot Area
- */
-static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
-		HvAgentId agent, u8 *PhbId, char card[4])
-{
-	int SlotMapLen = MapLen;
-	SlotMap *SlotMapPtr = MapPtr;
-
-	/*
-	 * Parse Slot label until we find the one requested
-	 */
-	while (SlotMapLen > 0) {
-		if (SlotMapPtr->AgentId == agent) {
-			/*
-			 * If Phb wasn't found, grab the entry first one found.
-			 */
-			if (*PhbId == 0xff)
-				*PhbId = SlotMapPtr->PhbId;
-			/* Found it, extract the data. */
-			if (SlotMapPtr->PhbId == *PhbId) {
-				memcpy(card, &SlotMapPtr->CardLocation, 3);
-				card[3]  = 0;
-				break;
-			}
-		}
-		/* Point to the next Slot */
-		SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE);
-		SlotMapLen -= SLOT_ENTRY_SIZE;
-	}
-}
-
-/*
- * Parse the Mfg Area
- */
-static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
-		HvAgentId agent, u8 *PhbId,
-		u8 *frame, char card[4])
-{
-	MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
-	int MfgAreaLen = AreaLen;
-	u16 SlotMapFmt = 0;
-
-	/* Parse Mfg Data */
-	while (MfgAreaLen > 0) {
-		int MfgTagLen = MfgAreaPtr->TagLength;
-		/* Frame ID         (FI 4649020310 ) */
-		if (MfgAreaPtr->Tag == VpdFruFrameId)		/* FI  */
-			*frame = MfgAreaPtr->AreaData1;
-		/* Slot Map Format  (MF 4D46020004 ) */
-		else if (MfgAreaPtr->Tag == VpdSlotMapFormat)	/* MF  */
-			SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
-				+ MfgAreaPtr->AreaData2;
-		/* Slot Map         (SM 534D90 */
-		else if (MfgAreaPtr->Tag == VpdSlotMap)	{	/* SM  */
-			SlotMap *SlotMapPtr;
-
-			if (SlotMapFmt == 0x1004)
-				SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
-						+ MFG_ENTRY_SIZE + 1);
-			else
-				SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
-						+ MFG_ENTRY_SIZE);
-			iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
-					agent, PhbId, card);
-		}
-		/*
-		 * Point to the next Mfg Area
-		 * Use defined size, sizeof give wrong answer
-		 */
-		MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
-				+ MFG_ENTRY_SIZE);
-		MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
-	}
-}
-
-/*
- * Look for "BUS".. Data is not Null terminated.
- * PHBID of 0xFF indicates PHB was not found in VPD Data.
- */
-static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
-{
-	u8 *PhbPtr = AreaPtr;
-	int DataLen = AreaLength;
-	char PhbId = 0xFF;
-
-	while (DataLen > 0) {
-		if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
-				&& (*(PhbPtr + 2) == 'S')) {
-			PhbPtr += 3;
-			while (*PhbPtr == ' ')
-				++PhbPtr;
-			PhbId = (*PhbPtr & 0x0F);
-			break;
-		}
-		++PhbPtr;
-		--DataLen;
-	}
-	return PhbId;
-}
-
-/*
- * Parse out the VPD Areas
- */
-static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
-		HvAgentId agent, u8 *frame, char card[4])
-{
-	u8 *TagPtr = VpdData;
-	int DataLen = VpdDataLen - 3;
-	u8 PhbId = 0xff;
-
-	while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
-		int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
-		u8 *AreaData  = TagPtr + 3;
-
-		if (*TagPtr == VpdIdStringTag)
-			PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
-		else if (*TagPtr == VpdVendorAreaTag)
-			iSeries_Parse_MfgArea(AreaData, AreaLen,
-					agent, &PhbId, frame, card);
-		/* Point to next Area. */
-		TagPtr  = AreaData + AreaLen;
-		DataLen -= AreaLen;
-	}
-}
-
-static int __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
-		u8 *frame, char card[4])
-{
-	int status = 0;
-	int BusVpdLen = 0;
-	u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
-
-	if (BusVpdPtr == NULL) {
-		printk("PCI: Bus VPD Buffer allocation failure.\n");
-		return 0;
-	}
-	BusVpdLen = HvCallPci_getBusVpd(bus, iseries_hv_addr(BusVpdPtr),
-					BUS_VPDSIZE);
-	if (BusVpdLen == 0) {
-		printk("PCI: Bus VPD Buffer zero length.\n");
-		goto out_free;
-	}
-	/* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
-	/* Make sure this is what I think it is */
-	if (*BusVpdPtr != VpdIdStringTag) {	/* 0x82 */
-		printk("PCI: Bus VPD Buffer missing starting tag.\n");
-		goto out_free;
-	}
-	iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
-	status = 1;
-out_free:
-	kfree(BusVpdPtr);
-	return status;
-}
-
-/*
- * Prints the device information.
- * - Pass in pci_dev* pointer to the device.
- * - Pass in the device count
- *
- * Format:
- * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
- * controller
- */
-void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
-{
-	struct device_node *DevNode = PciDev->sysdata;
-	struct pci_dn *pdn;
-	u16 bus;
-	u8 frame = 0;
-	char card[4];
-	HvSubBusNumber subbus;
-	HvAgentId agent;
-
-	if (DevNode == NULL) {
-		printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
-				count);
-		return;
-	}
-
-	pdn = PCI_DN(DevNode);
-	bus = pdn->busno;
-	subbus = pdn->bussubno;
-	agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
-			ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
-
-	if (iSeries_Get_Location_Code(bus, agent, &frame, card)) {
-		printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
-			"Card %4s  0x%04X\n", count, bus,
-			PCI_SLOT(PciDev->devfn), PciDev->vendor, frame,
-			card, (int)(PciDev->class >> 8));
-	}
-}
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig
index f7c95eb..a6467a5 100644
--- a/arch/powerpc/platforms/maple/Kconfig
+++ b/arch/powerpc/platforms/maple/Kconfig
@@ -1,6 +1,7 @@
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM && PPC64
 	bool "Maple 970FX Evaluation Board"
+	select PCI
 	select MPIC
 	select U3_DART
 	select MPIC_U3_HT_IRQS
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 771ed0c..3ffa0ac 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -558,7 +558,7 @@
 	 * safe assumptions hopefully.
 	 */
 	if (u3_agp) {
-		struct device_node *np = u3_agp->arch_data;
+		struct device_node *np = u3_agp->dn;
 		PCI_DN(np)->busno = 0xf0;
 		for (np = np->child; np; np = np->sibling)
 			PCI_DN(np)->busno = 0xf0;
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig
index 735e153..b3458a1 100644
--- a/arch/powerpc/platforms/pasemi/Kconfig
+++ b/arch/powerpc/platforms/pasemi/Kconfig
@@ -3,6 +3,7 @@
 	bool "PA Semi SoC-based platforms"
 	default n
 	select MPIC
+	select PCI
 	select PPC_UDBG_16550
 	select PPC_NATIVE
 	select MPIC_BROKEN_REGREAD
@@ -17,7 +18,7 @@
 	bool "PA Semi IOMMU support"
 	depends on PPC_PASEMI
 	help
-	  IOMMU support for PA6T-1682M
+	  IOMMU support for PA Semi PWRficient
 
 config PPC_PASEMI_IOMMU_DMA_FORCE
 	bool "Force DMA engine to use IOMMU"
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 1cfb8b0..58556b0 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -32,6 +32,7 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/time.h>
+#include <asm/smp.h>
 
 #define SDCASR_REG		0x0100
 #define SDCASR_REG_STRIDE	0x1000
@@ -124,6 +125,11 @@
 	local_irq_restore(flags);
 }
 
+int check_astate(void)
+{
+	return get_cur_astate(hard_smp_processor_id());
+}
+
 void restore_astate(int cpu)
 {
 	set_astate(cpu, current_astate);
@@ -147,7 +153,10 @@
 	if (!cpu)
 		goto out;
 
-	dn = of_find_compatible_node(NULL, "sdc", "1682m-sdc");
+	dn = of_find_compatible_node(NULL, NULL, "1682m-sdc");
+	if (!dn)
+		dn = of_find_compatible_node(NULL, NULL,
+					     "pasemi,pwrficient-sdc");
 	if (!dn)
 		goto out;
 	err = of_address_to_resource(dn, 0, &res);
@@ -160,7 +169,10 @@
 		goto out;
 	}
 
-	dn = of_find_compatible_node(NULL, "gizmo", "1682m-gizmo");
+	dn = of_find_compatible_node(NULL, NULL, "1682m-gizmo");
+	if (!dn)
+		dn = of_find_compatible_node(NULL, NULL,
+					     "pasemi,pwrficient-gizmo");
 	if (!dn) {
 		err = -ENODEV;
 		goto out_unmap_sdcasr;
@@ -292,7 +304,8 @@
 
 static int __init pas_cpufreq_init(void)
 {
-	if (!machine_is_compatible("PA6T-1682M"))
+	if (!machine_is_compatible("PA6T-1682M") &&
+	    !machine_is_compatible("pasemi,pwrficient"))
 		return -ENODEV;
 
 	return cpufreq_register_driver(&pas_cpufreq_driver);
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index dae9f65..b465429 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -30,7 +30,7 @@
 #include <linux/interrupt.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
-#include <asm/of_platform.h>
+#include <linux/of_platform.h>
 
 #define DELAY 1
 
@@ -218,45 +218,27 @@
 				     const struct of_device_id *match)
 {
 	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->node;
-	struct device_node *gpio_np;
+	struct device_node *phy_dn, *np = ofdev->node;
 	struct mii_bus *new_bus;
-	struct resource res;
 	struct gpio_priv *priv;
 	const unsigned int *prop;
-	int err = 0;
+	int err;
 	int i;
 
-	gpio_np = of_find_compatible_node(NULL, "gpio", "1682m-gpio");
-
-	if (!gpio_np)
-		return -ENODEV;
-
-	err = of_address_to_resource(gpio_np, 0, &res);
-	of_node_put(gpio_np);
-
-	if (err)
-		return -EINVAL;
-
-	if (!gpio_regs)
-		gpio_regs = ioremap(res.start, 0x100);
-
-	if (!gpio_regs)
-		return -EPERM;
-
+	err = -ENOMEM;
 	priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
+	if (!priv)
+		goto out;
 
 	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
 
-	if (new_bus == NULL)
-		return -ENOMEM;
+	if (!new_bus)
+		goto out_free_priv;
 
-	new_bus->name = "pasemi gpio mdio bus",
-	new_bus->read = &gpio_mdio_read,
-	new_bus->write = &gpio_mdio_write,
-	new_bus->reset = &gpio_mdio_reset,
+	new_bus->name = "pasemi gpio mdio bus";
+	new_bus->read = &gpio_mdio_read;
+	new_bus->write = &gpio_mdio_write;
+	new_bus->reset = &gpio_mdio_reset;
 
 	prop = of_get_property(np, "reg", NULL);
 	new_bus->id = *prop;
@@ -265,9 +247,24 @@
 	new_bus->phy_mask = 0;
 
 	new_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-	for(i = 0; i < PHY_MAX_ADDR; ++i)
-		new_bus->irq[i] = irq_create_mapping(NULL, 10);
 
+	if (!new_bus->irq)
+		goto out_free_bus;
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		new_bus->irq[i] = NO_IRQ;
+
+	for (phy_dn = of_get_next_child(np, NULL);
+	     phy_dn != NULL;
+	     phy_dn = of_get_next_child(np, phy_dn)) {
+		const unsigned int *ip, *regp;
+
+		ip = of_get_property(phy_dn, "interrupts", NULL);
+		regp = of_get_property(phy_dn, "reg", NULL);
+		if (!ip || !regp || *regp >= PHY_MAX_ADDR)
+			continue;
+		new_bus->irq[*regp] = irq_create_mapping(NULL, *ip);
+	}
 
 	prop = of_get_property(np, "mdc-pin", NULL);
 	priv->mdc_pin = *prop;
@@ -280,17 +277,21 @@
 
 	err = mdiobus_register(new_bus);
 
-	if (0 != err) {
+	if (err != 0) {
 		printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
 				new_bus->name, err);
-		goto bus_register_fail;
+		goto out_free_irq;
 	}
 
 	return 0;
 
-bus_register_fail:
+out_free_irq:
+	kfree(new_bus->irq);
+out_free_bus:
 	kfree(new_bus);
-
+out_free_priv:
+	kfree(priv);
+out:
 	return err;
 }
 
@@ -317,6 +318,7 @@
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, gpio_mdio_match);
 
 static struct of_platform_driver gpio_mdio_driver =
 {
@@ -330,12 +332,32 @@
 
 int gpio_mdio_init(void)
 {
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "1682m-gpio");
+	if (!np)
+		np = of_find_compatible_node(NULL, NULL,
+					     "pasemi,pwrficient-gpio");
+	if (!np)
+		return -ENODEV;
+	gpio_regs = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!gpio_regs)
+		return -ENODEV;
+
 	return of_register_platform_driver(&gpio_mdio_driver);
 }
+module_init(gpio_mdio_init);
 
 void gpio_mdio_exit(void)
 {
 	of_unregister_platform_driver(&gpio_mdio_driver);
+	if (gpio_regs)
+		iounmap(gpio_regs);
 }
-device_initcall(gpio_mdio_init);
+module_exit(gpio_mdio_exit);
 
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("Driver for MDIO over GPIO on PA Semi PWRficient-based boards");
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h
index 516acab..c96127b 100644
--- a/arch/powerpc/platforms/pasemi/pasemi.h
+++ b/arch/powerpc/platforms/pasemi/pasemi.h
@@ -16,8 +16,14 @@
 
 /* Restore astate to last set */
 #ifdef CONFIG_PPC_PASEMI_CPUFREQ
+extern int check_astate(void);
 extern void restore_astate(int cpu);
 #else
+static inline int check_astate(void)
+{
+	/* Always return >0 so we never power save */
+	return 1;
+}
 static inline void restore_astate(int cpu)
 {
 }
diff --git a/arch/powerpc/platforms/pasemi/powersave.S b/arch/powerpc/platforms/pasemi/powersave.S
index 6d0fba6..56f45ad 100644
--- a/arch/powerpc/platforms/pasemi/powersave.S
+++ b/arch/powerpc/platforms/pasemi/powersave.S
@@ -62,7 +62,16 @@
 	mflr	r0
 	std	r0, 16(r1)
 	stdu	r1,-64(r1)
+#ifdef CONFIG_PPC_PASEMI_CPUFREQ
+	std	r3, 48(r1)
 
+	/* Only do power savings when in astate 0 */
+	bl	.check_astate
+	cmpwi	r3,0
+	bne	1f
+
+	ld	r3, 48(r1)
+#endif
 	LOAD_REG_IMMEDIATE(r6,MSR_DR|MSR_IR|MSR_ME|MSR_EE)
 	mfmsr	r4
 	andc	r5,r4,r6
@@ -73,7 +82,7 @@
 
 	mtmsrd	r4,0
 
-	addi	r1,r1,64
+1:	addi	r1,r1,64
 	ld	r0,16(r1)
 	mtlr	r0
 	blr
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index 3d62060..b5dfd42 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/console.h>
 #include <linux/pci.h>
+#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 #include <asm/system.h>
@@ -35,7 +36,7 @@
 #include <asm/mpic.h>
 #include <asm/smp.h>
 #include <asm/time.h>
-#include <asm/of_platform.h>
+#include <asm/mmu.h>
 
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
@@ -43,6 +44,10 @@
 
 #include "pasemi.h"
 
+#if !defined(CONFIG_SMP)
+static void smp_send_stop(void) {}
+#endif
+
 /* SDC reset register, must be pre-mapped at reset time */
 static void __iomem *reset_reg;
 
@@ -60,6 +65,9 @@
 
 static void pas_restart(char *cmd)
 {
+	/* Need to put others cpu in hold loop so they're not sleeping */
+	smp_send_stop();
+	udelay(10000);
 	printk("Restarting...\n");
 	while (1)
 		out_le32(reset_reg, 0x6000000);
@@ -215,7 +223,7 @@
 
 	mpic = mpic_alloc(mpic_node, openpic_addr,
 			  MPIC_PRIMARY|MPIC_LARGE_VECTORS,
-			  0, 0, " PAS-OPIC  ");
+			  0, 0, "PASEMI-OPIC");
 	BUG_ON(!mpic);
 
 	mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
@@ -295,7 +303,7 @@
 		int i;
 
 		printk(KERN_ERR "slb contents:\n");
-		for (i = 0; i < SLB_NUM_ENTRIES; i++) {
+		for (i = 0; i < mmu_slb_size; i++) {
 			asm volatile("slbmfee  %0,%1" : "=r" (e) : "r" (i));
 			asm volatile("slbmfev  %0,%1" : "=r" (v) : "r" (i));
 			printk(KERN_ERR "%02d %016lx %016lx\n", i, e, v);
@@ -362,8 +370,12 @@
 
 
 static struct of_device_id pasemi_bus_ids[] = {
+	/* Unfortunately needed for legacy firmwares */
 	{ .type = "localbus", },
 	{ .type = "sdc", },
+	/* These are the proper entries, which newer firmware uses */
+	{ .compatible = "pasemi,localbus", },
+	{ .compatible = "pasemi,sdc", },
 	{},
 };
 
@@ -389,7 +401,8 @@
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (!of_flat_dt_is_compatible(root, "PA6T-1682M"))
+	if (!of_flat_dt_is_compatible(root, "PA6T-1682M") &&
+	    !of_flat_dt_is_compatible(root, "pasemi,pwrficient"))
 		return 0;
 
 	hpte_init_native();
@@ -400,7 +413,7 @@
 }
 
 define_machine(pasemi) {
-	.name			= "PA Semi PA6T-1682M",
+	.name			= "PA Semi PWRficient",
 	.probe			= pas_probe,
 	.setup_arch		= pas_setup_arch,
 	.init_early		= pas_init_early,
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index f852ae3..1c58db9 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -40,8 +40,6 @@
 static int has_uninorth;
 #ifdef CONFIG_PPC64
 static struct pci_controller *u3_agp;
-static struct pci_controller *u4_pcie;
-static struct pci_controller *u3_ht;
 #else
 static int has_second_ohare;
 #endif /* CONFIG_PPC64 */
@@ -314,12 +312,15 @@
 
 	/* We only allow config cycles to devices that are in OF device-tree
 	 * as we are apparently having some weird things going on with some
-	 * revs of K2 on recent G5s
+	 * revs of K2 on recent G5s, except for the host bridge itself, which
+	 * is missing from the tree but we know we can probe.
 	 */
 	if (bus->self)
 		busdn = pci_device_to_OF_node(bus->self);
+	else if (devfn == 0)
+		return 0;
 	else
-		busdn = hose->arch_data;
+		busdn = hose->dn;
 	for (dn = busdn->child; dn; dn = dn->sibling)
 		if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn)
 			break;
@@ -344,14 +345,15 @@
 		+ (((unsigned int)bus) << 16) \
 		+ 0x01000000UL)
 
-static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
-					     u8 bus, u8 devfn, u8 offset)
+static void __iomem *u3_ht_cfg_access(struct pci_controller *hose, u8 bus,
+				      u8 devfn, u8 offset, int *swap)
 {
+	*swap = 1;
 	if (bus == hose->first_busno) {
-		/* For now, we don't self probe U3 HT bridge */
-		if (PCI_SLOT(devfn) == 0)
-			return NULL;
-		return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+		if (devfn != 0)
+			return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+		*swap = 0;
+		return ((void __iomem *)hose->cfg_addr) + (offset << 2);
 	} else
 		return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
 }
@@ -360,14 +362,15 @@
 				    int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	volatile void __iomem *addr;
+	void __iomem *addr;
+	int swap;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	if (offset >= 0x100)
 		return  PCIBIOS_BAD_REGISTER_NUMBER;
-	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -397,10 +400,10 @@
 		*val = in_8(addr);
 		break;
 	case 2:
-		*val = in_le16(addr);
+		*val = swap ? in_le16(addr) : in_be16(addr);
 		break;
 	default:
-		*val = in_le32(addr);
+		*val = swap ? in_le32(addr) : in_be32(addr);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -410,14 +413,15 @@
 				     int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	volatile void __iomem *addr;
+	void __iomem *addr;
+	int swap;
 
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	if (offset >= 0x100)
 		return  PCIBIOS_BAD_REGISTER_NUMBER;
-	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -439,10 +443,10 @@
 		out_8(addr, val);
 		break;
 	case 2:
-		out_le16(addr, val);
+		swap ? out_le16(addr, val) : out_be16(addr, val);
 		break;
 	default:
-		out_le32((u32 __iomem *)addr, val);
+		swap ? out_le32(addr, val) : out_be32(addr, val);
 		break;
 	}
 	return PCIBIOS_SUCCESSFUL;
@@ -725,7 +729,7 @@
 static int __init setup_uninorth(struct pci_controller *hose,
 				 struct resource *addr)
 {
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	has_uninorth = 1;
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -773,31 +777,72 @@
 	 */
 	hose->first_busno = 0x00;
 	hose->last_busno = 0xff;
-	u4_pcie = hose;
+}
+
+static void __init parse_region_decode(struct pci_controller *hose,
+				       u32 decode)
+{
+	unsigned long base, end, next = -1;
+	int i, cur = -1;
+
+	/* Iterate through all bits. We ignore the last bit as this region is
+	 * reserved for the ROM among other niceties
+	 */
+	for (i = 0; i < 31; i++) {
+		if ((decode & (0x80000000 >> i)) == 0)
+			continue;
+		if (i < 16) {
+			base = 0xf0000000 | (((u32)i) << 24);
+			end = base + 0x00ffffff;
+		} else {
+			base = ((u32)i-16) << 28;
+			end = base + 0x0fffffff;
+		}
+		if (base != next) {
+			if (++cur >= 3) {
+				printk(KERN_WARNING "PCI: Too many ranges !\n");
+				break;
+			}
+			hose->mem_resources[cur].flags = IORESOURCE_MEM;
+			hose->mem_resources[cur].name = hose->dn->full_name;
+			hose->mem_resources[cur].start = base;
+			hose->mem_resources[cur].end = end;
+			DBG("  %d: 0x%08lx-0x%08lx\n", cur, base, end);
+		} else {
+			DBG("   :           -0x%08lx\n", end);
+			hose->mem_resources[cur].end = end;
+		}
+		next = end + 1;
+	}
 }
 
 static void __init setup_u3_ht(struct pci_controller* hose)
 {
-	struct device_node *np = (struct device_node *)hose->arch_data;
-	struct pci_controller *other = NULL;
-	int i, cur;
-
+	struct device_node *np = hose->dn;
+	struct resource cfg_res, self_res;
+	u32 decode;
 
 	hose->ops = &u3_ht_pci_ops;
 
-	/* We hard code the address because of the different size of
-	 * the reg address cell, we shall fix that by killing struct
-	 * reg_property and using some accessor functions instead
+	/* Get base addresses from OF tree
 	 */
-	hose->cfg_data = ioremap(0xf2000000, 0x02000000);
+	if (of_address_to_resource(np, 0, &cfg_res) ||
+	    of_address_to_resource(np, 1, &self_res)) {
+		printk(KERN_ERR "PCI: Failed to get U3/U4 HT resources !\n");
+		return;
+	}
+
+	/* Map external cfg space access into cfg_data and self registers
+	 * into cfg_addr
+	 */
+	hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
+	hose->cfg_addr = ioremap(self_res.start,
+				 self_res.end - self_res.start + 1);
 
 	/*
-	 * /ht node doesn't expose a "ranges" property, so we "remove"
-	 * regions that have been allocated to AGP. So far, this version of
-	 * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions
-	 * to /ht. We need to fix that sooner or later by either parsing all
-	 * child "ranges" properties or figuring out the U3 address space
-	 * decoding logic and then read its configuration register (if any).
+	 * /ht node doesn't expose a "ranges" property, we read the register
+	 * that controls the decoding logic and use that for memory regions.
+	 * The IO region is hard coded since it is fixed in HW as well.
 	 */
 	hose->io_base_phys = 0xf4000000;
 	hose->pci_io_size = 0x00400000;
@@ -808,76 +853,33 @@
 	hose->pci_mem_offset = 0;
 	hose->first_busno = 0;
 	hose->last_busno = 0xef;
-	hose->mem_resources[0].name = np->full_name;
-	hose->mem_resources[0].start = 0x80000000;
-	hose->mem_resources[0].end = 0xefffffff;
-	hose->mem_resources[0].flags = IORESOURCE_MEM;
 
-	u3_ht = hose;
+	/* Note: fix offset when cfg_addr becomes a void * */
+	decode = in_be32(hose->cfg_addr + 0x80);
 
-	if (u3_agp != NULL)
-		other = u3_agp;
-	else if (u4_pcie != NULL)
-		other = u4_pcie;
+	DBG("PCI: Apple HT bridge decode register: 0x%08x\n", decode);
 
-	if (other == NULL) {
-		DBG("U3/4 has no AGP/PCIE, using full resource range\n");
-		return;
-	}
-
-	/* Fixup bus range vs. PCIE */
-	if (u4_pcie)
-		hose->last_busno = u4_pcie->first_busno - 1;
-
-	/* We "remove" the AGP resources from the resources allocated to HT,
-	 * that is we create "holes". However, that code does assumptions
-	 * that so far happen to be true (cross fingers...), typically that
-	 * resources in the AGP node are properly ordered
+	/* NOTE: The decode register setup is a bit weird... region
+	 * 0xf8000000 for example is marked as enabled in there while it's
+	 & actually the memory controller registers.
+	 * That means that we are incorrectly attributing it to HT.
+	 *
+	 * In a similar vein, region 0xf4000000 is actually the HT IO space but
+	 * also marked as enabled in here and 0xf9000000 is used by some other
+	 * internal bits of the northbridge.
+	 *
+	 * Unfortunately, we can't just mask out those bit as we would end
+	 * up with more regions than we can cope (linux can only cope with
+	 * 3 memory regions for a PHB at this stage).
+	 *
+	 * So for now, we just do a little hack. We happen to -know- that
+	 * Apple firmware doesn't assign things below 0xfa000000 for that
+	 * bridge anyway so we mask out all bits we don't want.
 	 */
-	cur = 0;
-	for (i=0; i<3; i++) {
-		struct resource *res = &other->mem_resources[i];
-		if (res->flags != IORESOURCE_MEM)
-			continue;
-		/* We don't care about "fine" resources */
-		if (res->start >= 0xf0000000)
-			continue;
-		/* Check if it's just a matter of "shrinking" us in one
-		 * direction
-		 */
-		if (hose->mem_resources[cur].start == res->start) {
-			DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
-			    cur, hose->mem_resources[cur].start,
-			    res->end + 1);
-			hose->mem_resources[cur].start = res->end + 1;
-			continue;
-		}
-		if (hose->mem_resources[cur].end == res->end) {
-			DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
-			    cur, hose->mem_resources[cur].end,
-			    res->start - 1);
-			hose->mem_resources[cur].end = res->start - 1;
-			continue;
-		}
-		/* No, it's not the case, we need a hole */
-		if (cur == 2) {
-			/* not enough resources for a hole, we drop part
-			 * of the range
-			 */
-			printk(KERN_WARNING "Running out of resources"
-			       " for /ht host !\n");
-			hose->mem_resources[cur].end = res->start - 1;
-			continue;
-		}
-		cur++;
-		DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
-		    cur-1, res->start - 1, cur, res->end + 1);
-		hose->mem_resources[cur].name = np->full_name;
-		hose->mem_resources[cur].flags = IORESOURCE_MEM;
-		hose->mem_resources[cur].start = res->end + 1;
-		hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
-		hose->mem_resources[cur-1].end = res->start - 1;
-	}
+	decode &= 0x003fffff;
+
+	/* Now parse the resulting bits and build resources */
+	parse_region_decode(hose, decode);
 }
 #endif /* CONFIG_PPC64 */
 
@@ -994,6 +996,8 @@
 	struct device_node *np, *root;
 	struct device_node *ht = NULL;
 
+	ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+
 	root = of_find_node_by_path("/");
 	if (root == NULL) {
 		printk(KERN_CRIT "pmac_pci_init: can't find root "
@@ -1032,15 +1036,15 @@
 	 * future though
 	 */
 	if (u3_agp) {
-		struct device_node *np = u3_agp->arch_data;
+		struct device_node *np = u3_agp->dn;
 		PCI_DN(np)->busno = 0xf0;
 		for (np = np->child; np; np = np->sibling)
 			PCI_DN(np)->busno = 0xf0;
 	}
 	/* pmac_check_ht_link(); */
 
-	/* Tell pci.c to not use the common resource allocation mechanism */
-	pci_probe_only = 1;
+	/* We can allocate missing resources if any */
+	pci_probe_only = 0;
 
 #else /* CONFIG_PPC64 */
 	init_p2pbridge();
@@ -1051,13 +1055,13 @@
 	 * some offset between bus number and domains for now when we
 	 * assign all busses should help for now
 	 */
-	if (pci_assign_all_buses)
+	if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
 		pcibios_assign_bus_offset = 0x10;
 #endif
 }
 
-int
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+#ifdef CONFIG_PPC32
+int pmac_pci_enable_device_hook(struct pci_dev *dev)
 {
 	struct device_node* node;
 	int updatecfg = 0;
@@ -1099,24 +1103,21 @@
 		updatecfg = 1;
 	}
 
+	/*
+	 * Fixup various header fields on 32 bits. We don't do that on
+	 * 64 bits as some of these have strange values behind the HT
+	 * bridge and we must not, for example, enable MWI or set the
+	 * cache line size on them.
+	 */
 	if (updatecfg) {
 		u16 cmd;
 
-		/*
-		 * Make sure PCI is correctly configured
-		 *
-		 * We use old pci_bios versions of the function since, by
-		 * default, gmac is not powered up, and so will be absent
-		 * from the kernel initial PCI lookup.
-		 *
-		 * Should be replaced by 2.4 new PCI mechanisms and really
-		 * register the device.
-		 */
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
 			| PCI_COMMAND_INVALIDATE;
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+
 		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
 				      L1_CACHE_BYTES >> 2);
 	}
@@ -1124,6 +1125,18 @@
 	return 0;
 }
 
+void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
+{
+	struct device_node *node = pci_device_to_OF_node(dev);
+
+	/* We don't want to assign resources to USB controllers
+	 * absent from the OF tree (iBook second controller)
+	 */
+	if (dev->class == PCI_CLASS_SERIAL_USB_OHCI && !node)
+		dev->resource[0].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_ANY_ID, pmac_pci_fixup_ohci);
+
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
@@ -1171,7 +1184,6 @@
 	of_node_put(nd);
 }
 
-#ifdef CONFIG_PPC32
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 {
 	if (!machine_is(powermac))
@@ -1259,7 +1271,7 @@
 	}
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
-#endif
+#endif /* CONFIG_PPC32 */
 
 /*
  * Disable second function on K2-SATA, it's broken
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index fcde070..b3abaaf 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -26,7 +26,7 @@
 extern void pmac_nvram_update(void);
 extern unsigned char pmac_nvram_read_byte(int addr);
 extern void pmac_nvram_write_byte(int addr, unsigned char val);
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev);
 extern void pmac_pcibios_after_init(void);
 extern int of_show_percpuinfo(struct seq_file *m, int i);
 
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 02c5330..adad4e9 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -51,6 +51,8 @@
 #include <linux/root_dev.h>
 #include <linux/bitops.h>
 #include <linux/suspend.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/reg.h>
 #include <asm/sections.h>
@@ -68,8 +70,6 @@
 #include <asm/btext.h>
 #include <asm/pmac_feature.h>
 #include <asm/time.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/mmu_context.h>
 #include <asm/iommu.h>
 #include <asm/smu.h>
@@ -94,7 +94,6 @@
 #define DEFAULT_ROOT_DEVICE Root_SDA1	/* sda1 - slightly silly choice */
 
 #ifdef CONFIG_PPC64
-#include <asm/udbg.h>
 int sccdbg;
 #endif
 
@@ -613,9 +612,11 @@
 
 	/* We need to use normal PCI probing for the AGP bus,
 	 * since the device for the AGP bridge isn't in the tree.
+	 * Same for the PCIe host on U4 and the HT host bridge.
 	 */
 	if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
-				  of_device_is_compatible(node, "u4-pcie")))
+				  of_device_is_compatible(node, "u4-pcie") ||
+				  of_device_is_compatible(node, "u3-ht")))
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index bf9da56..bbbefd6 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -84,12 +84,14 @@
 	return delta;
 }
 
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
 static void to_rtc_time(unsigned long now, struct rtc_time *tm)
 {
 	to_tm(now, tm);
 	tm->tm_year -= 1900;
 	tm->tm_mon -= 1;
 }
+#endif
 
 static unsigned long from_rtc_time(struct rtc_time *tm)
 {
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index d1630a0..5ad4118 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -28,6 +28,7 @@
 #include <asm/spu_priv1.h>
 #include <asm/lv1call.h>
 
+#include "../cell/spufs/spufs.h"
 #include "platform.h"
 
 /* spu_management_ops */
@@ -419,10 +420,34 @@
 	return 0;
 }
 
+/**
+ * ps3_enable_spu - Enable SPU run control.
+ *
+ * An outstanding enhancement for the PS3 would be to add a guard to check
+ * for incorrect access to the spu problem state when the spu context is
+ * disabled.  This check could be implemented with a flag added to the spu
+ * context that would inhibit mapping problem state pages, and a routine
+ * to unmap spu problem state pages.  When the spu is enabled with
+ * ps3_enable_spu() the flag would be set allowing pages to be mapped,
+ * and when the spu is disabled with ps3_disable_spu() the flag would be
+ * cleared and the mapped problem state pages would be unmapped.
+ */
+
+static void ps3_enable_spu(struct spu_context *ctx)
+{
+}
+
+static void ps3_disable_spu(struct spu_context *ctx)
+{
+	ctx->ops->runcntl_stop(ctx);
+}
+
 const struct spu_management_ops spu_management_ps3_ops = {
 	.enumerate_spus = ps3_enumerate_spus,
 	.create_spu = ps3_create_spu,
 	.destroy_spu = ps3_destroy_spu,
+	.enable_spu = ps3_enable_spu,
+	.disable_spu = ps3_disable_spu,
 	.init_affinity = ps3_init_affinity,
 };
 
@@ -505,8 +530,6 @@
 	static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
 		| MFC_STATE1_PROBLEM_STATE_MASK);
 
-	sr1 |= MFC_STATE1_MASTER_RUN_CONTROL_MASK;
-
 	BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
 
 	spu_pdata(spu)->cache.sr1 = sr1;
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index fb3d636..aa14a85 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -480,6 +480,7 @@
 		no_dn++;
 		return 0;
 	}
+	dn = find_device_pe(dn);
 	pdn = PCI_DN(dn);
 
 	/* Access to IO BARs might get this far and still not want checking. */
@@ -545,7 +546,7 @@
 
 	/* Note that config-io to empty slots may fail;
 	 * they are empty when they don't have children. */
-	if ((rets[0] == 5) && (dn->child == NULL)) {
+	if ((rets[0] == 5) && (rets[2] == 0) && (dn->child == NULL)) {
 		false_positives++;
 		pdn->eeh_false_positives ++;
 		rc = 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 57e025e..68ea5ee 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -310,8 +310,6 @@
 	const char *location, *pci_str, *drv_str;
 
 	frozen_dn = find_device_pe(event->dn);
-	frozen_bus = pcibios_find_pci_bus(frozen_dn);
-
 	if (!frozen_dn) {
 
 		location = of_get_property(event->dn, "ibm,loc-code", NULL);
@@ -321,6 +319,8 @@
 		        location, pci_name(event->dev));
 		return NULL;
 	}
+
+	frozen_bus = pcibios_find_pci_bus(frozen_dn);
 	location = of_get_property(frozen_dn, "ibm,loc-code", NULL);
 	location = location ? location : "unknown";
 
@@ -354,13 +354,6 @@
 	if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
 		goto excess_failures;
 
-	/* Get the current PCI slot state. */
-	rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
-	if (rc < 0) {
-		printk(KERN_WARNING "EEH: Permanent failure\n");
-		goto hard_fail;
-	}
-
 	printk(KERN_WARNING
 	   "EEH: This PCI device has failed %d times in the last hour:\n",
 		frozen_pdn->eeh_freeze_count);
@@ -376,6 +369,14 @@
 	 */
 	pci_walk_bus(frozen_bus, eeh_report_error, &result);
 
+	/* Get the current PCI slot state. This can take a long time,
+	 * sometimes over 3 seconds for certain systems. */
+	rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
+	if (rc < 0) {
+		printk(KERN_WARNING "EEH: Permanent failure\n");
+		goto hard_fail;
+	}
+
 	/* Since rtas may enable MMIO when posting the error log,
 	 * don't post the error log until after all dev drivers
 	 * have been informed.
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index be17d23..a65c763 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -251,7 +251,7 @@
 	const unsigned long *basep;
 	const u32 *sizep;
 
-	node = (struct device_node *)phb->arch_data;
+	node = phb->dn;
 
 	basep = of_get_property(node, "linux,tce-base", NULL);
 	sizep = of_get_property(node, "linux,tce-size", NULL);
@@ -296,11 +296,12 @@
 static void iommu_table_setparms_lpar(struct pci_controller *phb,
 				      struct device_node *dn,
 				      struct iommu_table *tbl,
-				      const void *dma_window)
+				      const void *dma_window,
+				      int bussubno)
 {
 	unsigned long offset, size;
 
-	tbl->it_busno  = PCI_DN(dn)->bussubno;
+	tbl->it_busno  = bussubno;
 	of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
 
 	tbl->it_base   = 0;
@@ -420,17 +421,10 @@
 	    pdn->full_name, ppci->iommu_table);
 
 	if (!ppci->iommu_table) {
-		/* Bussubno hasn't been copied yet.
-		 * Do it now because iommu_table_setparms_lpar needs it.
-		 */
-
-		ppci->bussubno = bus->number;
-
 		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
 				   ppci->phb->node);
-
-		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
-
+		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
+			bus->number);
 		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
 		DBG("  created table: %p\n", ppci->iommu_table);
 	}
@@ -523,14 +517,10 @@
 
 	pci = PCI_DN(pdn);
 	if (!pci->iommu_table) {
-		/* iommu_table_setparms_lpar needs bussubno. */
-		pci->bussubno = pci->phb->bus->number;
-
 		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
 				   pci->phb->node);
-
-		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
-
+		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
+			pci->phb->bus->number);
 		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 		DBG("  created table: %p\n", pci->iommu_table);
 	} else {
@@ -556,7 +546,7 @@
 	case PSERIES_RECONFIG_REMOVE:
 		if (pci && pci->iommu_table &&
 		    of_get_property(np, "ibm,dma-window", NULL))
-			iommu_free_table(np);
+			iommu_free_table(pci->iommu_table, np->full_name);
 		break;
 	default:
 		err = NOTIFY_DONE;
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 47f0e08..5a5a19e 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -83,7 +83,7 @@
 
 /* Must be called before pci_bus_add_devices */
 void
-pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+pcibios_fixup_new_pci_devices(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 
@@ -98,8 +98,6 @@
 			/* Fill device archdata and setup iommu table */
 			pcibios_setup_new_device(dev);
 
-			if(fix_bus)
-				pcibios_fixup_device_resources(dev, bus);
 			pci_read_irq_line(dev);
 			for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 				struct resource *r = &dev->resource[i];
@@ -132,8 +130,8 @@
 
 	pci_scan_child_bus(child_bus);
 
-	/* Fixup new pci devices without touching bus struct */
-	pcibios_fixup_new_pci_devices(child_bus, 0);
+	/* Fixup new pci devices */
+	pcibios_fixup_new_pci_devices(child_bus);
 
 	/* Make the discovered devices available */
 	pci_bus_add_devices(child_bus);
@@ -169,7 +167,7 @@
 		/* use ofdt-based probe */
 		of_scan_bus(dn, bus);
 		if (!list_empty(&bus->devices)) {
-			pcibios_fixup_new_pci_devices(bus, 0);
+			pcibios_fixup_new_pci_devices(bus);
 			pci_bus_add_devices(bus);
 			eeh_add_device_tree_late(bus);
 		}
@@ -178,7 +176,7 @@
 		slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
 		num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
 		if (num) {
-			pcibios_fixup_new_pci_devices(bus, 1);
+			pcibios_fixup_new_pci_devices(bus);
 			pci_bus_add_devices(bus);
 			eeh_add_device_tree_late(bus);
 		}
@@ -208,7 +206,7 @@
 		eeh_add_device_tree_early(dn);
 
 	scan_phb(phb);
-	pcibios_fixup_new_pci_devices(phb->bus, 0);
+	pcibios_fixup_new_pci_devices(phb->bus);
 	pci_bus_add_devices(phb->bus);
 	eeh_add_device_tree_late(phb->bus);
 
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index d003c80..d8680b5 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -8,11 +8,6 @@
 	return plpar_hcall_norets(H_POLL_PENDING);
 }
 
-static inline long prod_processor(void)
-{
-	return plpar_hcall_norets(H_PROD);
-}
-
 static inline long cede_processor(void)
 {
 	return plpar_hcall_norets(H_CEDE);
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 116305b..ea4c659 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -46,6 +46,7 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
+#include <asm/cputhreads.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -202,7 +203,7 @@
 	 */
 	if (system_state < SYSTEM_RUNNING &&
 	    cpu_has_feature(CPU_FTR_SMT) &&
-	    !smt_enabled_at_boot && nr % 2 != 0)
+	    !smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
 		return 0;
 
 	return 1;
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 66e7d68..8f8dd9c 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -87,19 +87,25 @@
 /* Direct HW low level accessors */
 
 
-static inline unsigned int direct_xirr_info_get(int n_cpu)
+static inline unsigned int direct_xirr_info_get(void)
 {
-	return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
+	int cpu = smp_processor_id();
+
+	return in_be32(&xics_per_cpu[cpu]->xirr.word);
 }
 
-static inline void direct_xirr_info_set(int n_cpu, int value)
+static inline void direct_xirr_info_set(int value)
 {
-	out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
+	int cpu = smp_processor_id();
+
+	out_be32(&xics_per_cpu[cpu]->xirr.word, value);
 }
 
-static inline void direct_cppr_info(int n_cpu, u8 value)
+static inline void direct_cppr_info(u8 value)
 {
-	out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
+	int cpu = smp_processor_id();
+
+	out_8(&xics_per_cpu[cpu]->xirr.bytes[0], value);
 }
 
 static inline void direct_qirr_info(int n_cpu, u8 value)
@@ -111,7 +117,7 @@
 /* LPAR low level accessors */
 
 
-static inline unsigned int lpar_xirr_info_get(int n_cpu)
+static inline unsigned int lpar_xirr_info_get(void)
 {
 	unsigned long lpar_rc;
 	unsigned long return_value;
@@ -122,7 +128,7 @@
 	return (unsigned int)return_value;
 }
 
-static inline void lpar_xirr_info_set(int n_cpu, int value)
+static inline void lpar_xirr_info_set(int value)
 {
 	unsigned long lpar_rc;
 	unsigned long val64 = value & 0xffffffff;
@@ -133,7 +139,7 @@
 		      val64);
 }
 
-static inline void lpar_cppr_info(int n_cpu, u8 value)
+static inline void lpar_cppr_info(u8 value)
 {
 	unsigned long lpar_rc;
 
@@ -275,21 +281,19 @@
 
 static void xics_eoi_direct(unsigned int virq)
 {
-	int cpu = smp_processor_id();
 	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
 	iosync();
-	direct_xirr_info_set(cpu, (0xff << 24) | irq);
+	direct_xirr_info_set((0xff << 24) | irq);
 }
 
 
 static void xics_eoi_lpar(unsigned int virq)
 {
-	int cpu = smp_processor_id();
 	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
 	iosync();
-	lpar_xirr_info_set(cpu, (0xff << 24) | irq);
+	lpar_xirr_info_set((0xff << 24) | irq);
 }
 
 static inline unsigned int xics_remap_irq(unsigned int vec)
@@ -312,16 +316,12 @@
 
 static unsigned int xics_get_irq_direct(void)
 {
-	unsigned int cpu = smp_processor_id();
-
-	return xics_remap_irq(direct_xirr_info_get(cpu));
+	return xics_remap_irq(direct_xirr_info_get());
 }
 
 static unsigned int xics_get_irq_lpar(void)
 {
-	unsigned int cpu = smp_processor_id();
-
-	return xics_remap_irq(lpar_xirr_info_get(cpu));
+	return xics_remap_irq(lpar_xirr_info_get());
 }
 
 #ifdef CONFIG_SMP
@@ -387,12 +387,12 @@
 
 #endif /* CONFIG_SMP */
 
-static void xics_set_cpu_priority(int cpu, unsigned char cppr)
+static void xics_set_cpu_priority(unsigned char cppr)
 {
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		lpar_cppr_info(cpu, cppr);
+		lpar_cppr_info(cppr);
 	else
-		direct_cppr_info(cpu, cppr);
+		direct_cppr_info(cppr);
 	iosync();
 }
 
@@ -440,9 +440,7 @@
 
 void xics_setup_cpu(void)
 {
-	int cpu = smp_processor_id();
-
-	xics_set_cpu_priority(cpu, 0xff);
+	xics_set_cpu_priority(0xff);
 
 	/*
 	 * Put the calling processor into the GIQ.  This is really only
@@ -783,7 +781,7 @@
 	unsigned int ipi;
 	struct irq_desc *desc;
 
-	xics_set_cpu_priority(cpu, 0);
+	xics_set_cpu_priority(0);
 
 	/*
 	 * Clear IPI
@@ -824,10 +822,11 @@
 void xics_migrate_irqs_away(void)
 {
 	int status;
-	unsigned int irq, virq, cpu = smp_processor_id();
+	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
+	unsigned int irq, virq;
 
 	/* Reject any interrupt that was queued to us... */
-	xics_set_cpu_priority(cpu, 0);
+	xics_set_cpu_priority(0);
 
 	/* remove ourselves from the global interrupt queue */
 	status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
@@ -835,7 +834,7 @@
 	WARN_ON(status < 0);
 
 	/* Allow IPIs again... */
-	xics_set_cpu_priority(cpu, DEFAULT_PRIORITY);
+	xics_set_cpu_priority(DEFAULT_PRIORITY);
 
 	for_each_irq(virq) {
 		struct irq_desc *desc;
@@ -874,7 +873,7 @@
 		 * The irq has to be migrated only in the single cpu
 		 * case.
 		 */
-		if (xics_status[0] != get_hard_smp_processor_id(cpu))
+		if (xics_status[0] != hw_cpu)
 			goto unlock;
 
 		printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index db0ec3b..9ffd809 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -21,9 +21,6 @@
 extern  void xics_request_IPIs(void);
 extern void xics_migrate_irqs_away(void);
 
-/* first argument is ignored for now*/
-void pSeriesLP_cppr_info(int n_cpu, u8 value);
-
 struct xics_ipi_struct {
 	volatile unsigned long value;
 } ____cacheline_aligned;
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 99a77d7..85cf8c6 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -2,7 +2,7 @@
 EXTRA_CFLAGS			+= -mno-minimal-toc
 endif
 
-mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o
+mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)
 
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 5eaf3e3..d359d6e 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -42,8 +42,9 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
 #include <asm/page.h>
 #include <asm/prom.h>
 
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.h b/arch/powerpc/sysdev/bestcomm/bestcomm.h
index e802cb4..c960a8b 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.h
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.h
@@ -20,7 +20,7 @@
 
 
 /* ======================================================================== */
-/* Generic task managment                                                   */
+/* Generic task management                                                   */
 /* ======================================================================== */
 
 /**
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index f6a6378..621bc6c 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -240,6 +240,34 @@
 #endif
 }
 
+static DEFINE_SPINLOCK(cmd_lock);
+
+#define MAX_CR_CMD_LOOPS        10000
+
+int cpm_command(u32 command, u8 opcode)
+{
+	int i, ret;
+	unsigned long flags;
+
+	if (command & 0xffffff0f)
+		return -EINVAL;
+
+	spin_lock_irqsave(&cmd_lock, flags);
+
+	ret = 0;
+	out_be16(&cpmp->cp_cpcr, command | CPM_CR_FLG | (opcode << 8));
+	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+		if ((in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+			goto out;
+
+	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
+	ret = -EIO;
+out:
+	spin_unlock_irqrestore(&cmd_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(cpm_command);
+
 /* We used to do this earlier, but have to postpone as long as possible
  * to ensure the kernel VM is now running.
  */
@@ -408,7 +436,7 @@
 #endif /* !CONFIG_PPC_CPM_NEW_BINDING */
 
 struct cpm_ioport16 {
-	__be16 dir, par, sor, dat, intr;
+	__be16 dir, par, odr_sor, dat, intr;
 	__be16 res[3];
 };
 
@@ -438,6 +466,13 @@
 	else
 		clrbits32(&iop->par, pin);
 
+	if (port == CPM_PORTB) {
+		if (flags & CPM_PIN_OPENDRAIN)
+			setbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
+		else
+			clrbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
+	}
+
 	if (port == CPM_PORTE) {
 		if (flags & CPM_PIN_SECONDARY)
 			setbits32(&iop->sor, pin);
@@ -471,11 +506,17 @@
 	else
 		clrbits16(&iop->par, pin);
 
+	if (port == CPM_PORTA) {
+		if (flags & CPM_PIN_OPENDRAIN)
+			setbits16(&iop->odr_sor, pin);
+		else
+			clrbits16(&iop->odr_sor, pin);
+	}
 	if (port == CPM_PORTC) {
 		if (flags & CPM_PIN_SECONDARY)
-			setbits16(&iop->sor, pin);
+			setbits16(&iop->odr_sor, pin);
 		else
-			clrbits16(&iop->sor, pin);
+			clrbits16(&iop->odr_sor, pin);
 	}
 }
 
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index c1d8240..f7188e2 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -82,6 +82,31 @@
 	cpmp = &cpm2_immr->im_cpm;
 }
 
+static DEFINE_SPINLOCK(cmd_lock);
+
+#define MAX_CR_CMD_LOOPS        10000
+
+int cpm_command(u32 command, u8 opcode)
+{
+	int i, ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cmd_lock, flags);
+
+	ret = 0;
+	out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
+	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+		if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+			goto out;
+
+	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
+	ret = -EIO;
+out:
+	spin_unlock_irqrestore(&cmd_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(cpm_command);
+
 /* Set a baud rate generator.  This needs lots of work.  There are
  * eight BRGs, which can be connected to the CPM channels or output
  * as clocks.  The BRGs are in two different block of internal
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 33df4c3..4b1d512 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -202,7 +202,7 @@
 		printk(KERN_WARNING "Can't get bus-range for %s, assume"
 			" bus 0\n", dev->full_name);
 
-	pci_assign_all_buses = 1;
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	hose = pcibios_alloc_controller(dev);
 	if (!hose)
 		return -ENOMEM;
@@ -222,7 +222,7 @@
 			hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
 	}
 
-	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx."
+	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
 		"Firmware bus number: %d->%d\n",
 		(unsigned long long)rsrc.start, hose->first_busno,
 		hose->last_busno);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 3ace747..4baad80 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -132,15 +132,18 @@
 
 static int __init gfar_mdio_of_init(void)
 {
-	struct device_node *np;
-	unsigned int i;
+	struct device_node *np = NULL;
 	struct platform_device *mdio_dev;
 	struct resource res;
 	int ret;
 
-	for (np = NULL, i = 0;
-	     (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
-	     i++) {
+	np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+
+	/* try the deprecated version */
+	if (!np)
+		np = of_find_compatible_node(np, "mdio", "gianfar");
+
+	if (np) {
 		int k;
 		struct device_node *child = NULL;
 		struct gianfar_mdio_data mdio_data;
@@ -179,11 +182,13 @@
 			goto unreg;
 	}
 
+	of_node_put(np);
 	return 0;
 
 unreg:
 	platform_device_unregister(mdio_dev);
 err:
+	of_node_put(np);
 	return ret;
 }
 
@@ -390,13 +395,11 @@
 static int __init fsl_i2c_of_init(void)
 {
 	struct device_node *np;
-	unsigned int i;
+	unsigned int i = 0;
 	struct platform_device *i2c_dev;
 	int ret;
 
-	for (np = NULL, i = 0;
-	     (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
-	     i++) {
+	for_each_compatible_node(np, NULL, "fsl-i2c") {
 		struct resource r[2];
 		struct fsl_i2c_platform_data i2c_data;
 		const unsigned char *flags = NULL;
@@ -432,7 +435,7 @@
 		if (ret)
 			goto unreg;
 
-		of_register_i2c_devices(np, i);
+		of_register_i2c_devices(np, i++);
 	}
 
 	return 0;
diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c
index 11ad562..d502927 100644
--- a/arch/powerpc/sysdev/grackle.c
+++ b/arch/powerpc/sysdev/grackle.c
@@ -57,7 +57,7 @@
 {
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
 	if (machine_is_compatible("PowerMac1,1"))
-		pci_assign_all_buses = 1;
+		ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 	if (machine_is_compatible("AAPL,PowerBook1998"))
 		grackle_set_loop_snoop(hose, 1);
 #if 0	/* Disabled for now, HW problems ??? */
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 05a56e5..7274750 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -30,11 +30,32 @@
 #include "ipic.h"
 
 static struct ipic * primary_ipic;
+static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
 static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
+	[1] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_C,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 16,
+		.prio_mask = 0,
+	},
+	[2] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_C,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 17,
+		.prio_mask = 1,
+	},
+	[4] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_C,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 19,
+		.prio_mask = 3,
+	},
 	[9] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -42,7 +63,6 @@
 		.prio_mask = 0,
 	},
 	[10] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -50,15 +70,27 @@
 		.prio_mask = 1,
 	},
 	[11] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
 		.bit	= 26,
 		.prio_mask = 2,
 	},
+	[12] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 27,
+		.prio_mask = 3,
+	},
+	[13] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 28,
+		.prio_mask = 4,
+	},
 	[14] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -66,7 +98,6 @@
 		.prio_mask = 5,
 	},
 	[15] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -74,7 +105,6 @@
 		.prio_mask = 6,
 	},
 	[16] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_D,
 		.force	= IPIC_SIFCR_H,
@@ -82,7 +112,7 @@
 		.prio_mask = 7,
 	},
 	[17] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -90,7 +120,7 @@
 		.prio_mask = 5,
 	},
 	[18] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -98,7 +128,7 @@
 		.prio_mask = 6,
 	},
 	[19] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -106,7 +136,7 @@
 		.prio_mask = 7,
 	},
 	[20] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -114,7 +144,7 @@
 		.prio_mask = 4,
 	},
 	[21] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -122,7 +152,7 @@
 		.prio_mask = 5,
 	},
 	[22] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -130,7 +160,7 @@
 		.prio_mask = 6,
 	},
 	[23] = {
-		.pend	= IPIC_SEPNR,
+		.ack	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -138,7 +168,6 @@
 		.prio_mask = 7,
 	},
 	[32] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -146,7 +175,6 @@
 		.prio_mask = 0,
 	},
 	[33] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -154,7 +182,6 @@
 		.prio_mask = 1,
 	},
 	[34] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -162,7 +189,6 @@
 		.prio_mask = 2,
 	},
 	[35] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -170,7 +196,6 @@
 		.prio_mask = 3,
 	},
 	[36] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -178,7 +203,6 @@
 		.prio_mask = 4,
 	},
 	[37] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -186,7 +210,6 @@
 		.prio_mask = 5,
 	},
 	[38] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
@@ -194,15 +217,48 @@
 		.prio_mask = 6,
 	},
 	[39] = {
-		.pend	= IPIC_SIPNR_H,
 		.mask	= IPIC_SIMSR_H,
 		.prio	= IPIC_SIPRR_A,
 		.force	= IPIC_SIFCR_H,
 		.bit	= 7,
 		.prio_mask = 7,
 	},
+	[42] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_B,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 10,
+		.prio_mask = 2,
+	},
+	[44] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_B,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 12,
+		.prio_mask = 4,
+	},
+	[45] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_B,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 13,
+		.prio_mask = 5,
+	},
+	[46] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_B,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 14,
+		.prio_mask = 6,
+	},
+	[47] = {
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_B,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 15,
+		.prio_mask = 7,
+	},
 	[48] = {
-		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -210,7 +266,6 @@
 		.prio_mask = 4,
 	},
 	[64] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -218,7 +273,6 @@
 		.prio_mask = 0,
 	},
 	[65] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -226,7 +280,6 @@
 		.prio_mask = 1,
 	},
 	[66] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -234,7 +287,6 @@
 		.prio_mask = 2,
 	},
 	[67] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SIFCR_L,
@@ -242,7 +294,6 @@
 		.prio_mask = 3,
 	},
 	[68] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -250,7 +301,6 @@
 		.prio_mask = 0,
 	},
 	[69] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -258,7 +308,6 @@
 		.prio_mask = 1,
 	},
 	[70] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -266,7 +315,6 @@
 		.prio_mask = 2,
 	},
 	[71] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SIFCR_L,
@@ -274,91 +322,114 @@
 		.prio_mask = 3,
 	},
 	[72] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 8,
 	},
 	[73] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 9,
 	},
 	[74] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 10,
 	},
 	[75] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 11,
 	},
 	[76] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 12,
 	},
 	[77] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 13,
 	},
 	[78] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 14,
 	},
 	[79] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 15,
 	},
 	[80] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 16,
 	},
+	[81] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 17,
+	},
+	[82] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 18,
+	},
 	[84] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 20,
 	},
 	[85] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 21,
 	},
+	[86] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 22,
+	},
+	[87] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 23,
+	},
+	[88] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 24,
+	},
+	[89] = {
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 25,
+	},
 	[90] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
 		.bit	= 26,
 	},
 	[91] = {
-		.pend	= IPIC_SIPNR_L,
 		.mask	= IPIC_SIMSR_L,
 		.prio	= 0,
 		.force	= IPIC_SIFCR_L,
@@ -412,6 +483,10 @@
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
+	/* mb() can't guarantee that masking is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
+
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
@@ -424,9 +499,13 @@
 
 	spin_lock_irqsave(&ipic_lock, flags);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp = ipic_read(ipic->regs, ipic_info[src].ack);
 	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+	ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+	/* mb() can't guarantee that ack is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
 
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -444,9 +523,13 @@
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
-	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp = ipic_read(ipic->regs, ipic_info[src].ack);
 	temp |= (1 << (31 - ipic_info[src].bit));
-	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+	ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+	/* mb() can't guarantee that ack is finished.  But it does finish
+	 * for nearly all cases. */
+	mb();
 
 	spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -468,14 +551,22 @@
 			flow_type);
 		return -EINVAL;
 	}
+	/* ipic supports only edge mode on external interrupts */
+	if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
+		printk(KERN_ERR "ipic: edge sense not supported on internal "
+				"interrupts\n");
+		return -EINVAL;
+	}
 
 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
 		desc->status |= IRQ_LEVEL;
 		desc->handle_irq = handle_level_irq;
+		desc->chip = &ipic_level_irq_chip;
 	} else {
 		desc->handle_irq = handle_edge_irq;
+		desc->chip = &ipic_edge_irq_chip;
 	}
 
 	/* only EXT IRQ senses are programmable on ipic
@@ -500,7 +591,16 @@
 	return 0;
 }
 
-static struct irq_chip ipic_irq_chip = {
+/* level interrupts and edge interrupts have different ack operations */
+static struct irq_chip ipic_level_irq_chip = {
+	.typename	= " IPIC  ",
+	.unmask		= ipic_unmask_irq,
+	.mask		= ipic_mask_irq,
+	.mask_ack	= ipic_mask_irq,
+	.set_type	= ipic_set_irq_type,
+};
+
+static struct irq_chip ipic_edge_irq_chip = {
 	.typename	= " IPIC  ",
 	.unmask		= ipic_unmask_irq,
 	.mask		= ipic_mask_irq,
@@ -519,13 +619,9 @@
 			 irq_hw_number_t hw)
 {
 	struct ipic *ipic = h->host_data;
-	struct irq_chip *chip;
-
-	/* Default chip */
-	chip = &ipic->hc_irq;
 
 	set_irq_chip_data(virq, ipic);
-	set_irq_chip_and_handler(virq, chip, handle_level_irq);
+	set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 
 	/* Set default irq type */
 	set_irq_type(virq, IRQ_TYPE_NONE);
@@ -584,7 +680,6 @@
 	ipic->regs = ioremap(res.start, res.end - res.start + 1);
 
 	ipic->irqhost->host_data = ipic;
-	ipic->hc_irq = ipic_irq_chip;
 
 	/* init hw */
 	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
@@ -593,6 +688,10 @@
 	 * configure SICFR accordingly */
 	if (flags & IPIC_SPREADMODE_GRP_A)
 		temp |= SICFR_IPSA;
+	if (flags & IPIC_SPREADMODE_GRP_B)
+		temp |= SICFR_IPSB;
+	if (flags & IPIC_SPREADMODE_GRP_C)
+		temp |= SICFR_IPSC;
 	if (flags & IPIC_SPREADMODE_GRP_D)
 		temp |= SICFR_IPSD;
 	if (flags & IPIC_SPREADMODE_MIX_A)
@@ -600,7 +699,7 @@
 	if (flags & IPIC_SPREADMODE_MIX_B)
 		temp |= SICFR_MPSB;
 
-	ipic_write(ipic->regs, IPIC_SICNR, temp);
+	ipic_write(ipic->regs, IPIC_SICFR, temp);
 
 	/* handle MCP route */
 	temp = 0;
@@ -672,10 +771,12 @@
 
 void ipic_set_default_priority(void)
 {
-	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
-	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
-	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
-	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
 }
 
 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index bb309a5..9391c57 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -23,13 +23,12 @@
 #define IPIC_IRQ_EXT7 23
 
 /* Default Priority Registers */
-#define IPIC_SIPRR_A_DEFAULT 0x05309770
-#define IPIC_SIPRR_D_DEFAULT 0x05309770
-#define IPIC_SMPRR_A_DEFAULT 0x05309770
-#define IPIC_SMPRR_B_DEFAULT 0x05309770
+#define IPIC_PRIORITY_DEFAULT 0x05309770
 
 /* System Global Interrupt Configuration Register */
 #define	SICFR_IPSA	0x00010000
+#define	SICFR_IPSB	0x00020000
+#define	SICFR_IPSC	0x00040000
 #define	SICFR_IPSD	0x00080000
 #define	SICFR_MPSA	0x00200000
 #define	SICFR_MPSB	0x00400000
@@ -45,13 +44,11 @@
 
 	/* The remapper for this IPIC */
 	struct irq_host		*irqhost;
-
-	/* The "linux" controller struct */
-	struct irq_chip		hc_irq;
 };
 
 struct ipic_info {
-	u8	pend;		/* pending register offset from base */
+	u8	ack;		/* pending register offset from base if the irq
+				   supports ack operation */
 	u8	mask;		/* mask register offset from base */
 	u8	prio;		/* priority register offset from base */
 	u8	force;		/* force register offset from base */
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index e073e24..7b49633a 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -99,7 +99,7 @@
 	nvram_addr = r.start;
 	mmio_nvram_len = r.end - r.start + 1;
 	if ( (!mmio_nvram_len) || (!nvram_addr) ) {
-		printk(KERN_WARNING "nvram: address or lenght is 0\n");
+		printk(KERN_WARNING "nvram: address or length is 0\n");
 		ret = -EIO;
 		goto out;
 	}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index e4793889..f74fe26 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -612,12 +612,11 @@
 }
 
 #ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
+static irqreturn_t mpic_ipi_action(int irq, void *data)
 {
-	struct mpic *mpic;
+	long ipi = (long)data;
 
-	mpic = mpic_find(irq, NULL);
-	smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]);
+	smp_message_recv(ipi);
 
 	return IRQ_HANDLED;
 }
@@ -842,6 +841,24 @@
 	return 0;
 }
 
+void mpic_set_vector(unsigned int virq, unsigned int vector)
+{
+	struct mpic *mpic = mpic_from_irq(virq);
+	unsigned int src = mpic_irq_to_hw(virq);
+	unsigned int vecpri;
+
+	DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
+	    mpic, virq, src, vector);
+
+	if (src >= mpic->irq_count)
+		return;
+
+	vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+	vecpri = vecpri & ~MPIC_INFO(VECPRI_VECTOR_MASK);
+	vecpri |= vector;
+	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+}
+
 static struct irq_chip mpic_irq_chip = {
 	.mask		= mpic_mask_irq,
 	.unmask		= mpic_unmask_irq,
@@ -1230,6 +1247,8 @@
 		mpic_u3msi_init(mpic);
 	}
 
+	mpic_pasemi_msi_init(mpic);
+
 	for (i = 0; i < mpic->num_sources; i++) {
 		/* start with vector = source number, and masked */
 		u32 vecpri = MPIC_VECPRI_MASK | i |
@@ -1457,7 +1476,7 @@
 void mpic_request_ipis(void)
 {
 	struct mpic *mpic = mpic_primary;
-	int i, err;
+	long i, err;
 	static char *ipi_names[] = {
 		"IPI0 (call function)",
 		"IPI1 (reschedule)",
@@ -1472,14 +1491,14 @@
 		unsigned int vipi = irq_create_mapping(mpic->irqhost,
 						       mpic->ipi_vecs[0] + i);
 		if (vipi == NO_IRQ) {
-			printk(KERN_ERR "Failed to map IPI %d\n", i);
+			printk(KERN_ERR "Failed to map IPI %ld\n", i);
 			break;
 		}
 		err = request_irq(vipi, mpic_ipi_action,
 				  IRQF_DISABLED|IRQF_PERCPU,
-				  ipi_names[i], mpic);
+				  ipi_names[i], (void *)i);
 		if (err) {
-			printk(KERN_ERR "Request of irq %d for IPI %d failed\n",
+			printk(KERN_ERR "Request of irq %d for IPI %ld failed\n",
 			       vipi, i);
 			break;
 		}
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 1cb6bd8..4783c6e 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -17,6 +17,7 @@
 extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
 extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
 extern int mpic_u3msi_init(struct mpic *mpic);
+extern int mpic_pasemi_msi_init(struct mpic *mpic);
 #else
 static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
 					  irq_hw_number_t hwirq)
@@ -28,9 +29,15 @@
 {
 	return -1;
 }
+
+static inline int mpic_pasemi_msi_init(struct mpic *mpic)
+{
+	return -1;
+}
 #endif
 
 extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern void mpic_set_vector(unsigned int virq, unsigned int vector);
 extern void mpic_end_irq(unsigned int irq);
 extern void mpic_mask_irq(unsigned int irq);
 extern void mpic_unmask_irq(unsigned int irq);
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
new file mode 100644
index 0000000..d6bfda3
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2007, Olof Johansson, PA Semi
+ *
+ * Based on arch/powerpc/sysdev/mpic_u3msi.c:
+ *
+ * Copyright 2006, Segher Boessenkool, IBM Corporation.
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * 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; version 2 of the
+ * License.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* Allocate 16 interrupts per device, to give an alignment of 16,
+ * since that's the size of the grouping w.r.t. affinity. If someone
+ * needs more than 32 MSI's down the road we'll have to rethink this,
+ * but it should be OK for now.
+ */
+#define ALLOC_CHUNK 16
+
+#define PASEMI_MSI_ADDR 0xfc080000
+
+/* A bit ugly, can we get this from the pci_dev somehow? */
+static struct mpic *msi_mpic;
+
+
+static void mpic_pasemi_msi_mask_irq(unsigned int irq)
+{
+	pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq);
+	mask_msi_irq(irq);
+	mpic_mask_irq(irq);
+}
+
+static void mpic_pasemi_msi_unmask_irq(unsigned int irq)
+{
+	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq);
+	mpic_unmask_irq(irq);
+	unmask_msi_irq(irq);
+}
+
+static struct irq_chip mpic_pasemi_msi_chip = {
+	.shutdown	= mpic_pasemi_msi_mask_irq,
+	.mask		= mpic_pasemi_msi_mask_irq,
+	.unmask		= mpic_pasemi_msi_unmask_irq,
+	.eoi		= mpic_end_irq,
+	.set_type	= mpic_set_irq_type,
+	.set_affinity	= mpic_set_affinity,
+	.typename	= "PASEMI-MSI ",
+};
+
+static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+	if (type == PCI_CAP_ID_MSIX)
+		pr_debug("pasemi_msi: MSI-X untested, trying anyway\n");
+
+	return 0;
+}
+
+static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
+{
+	struct msi_desc *entry;
+
+	pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		if (entry->irq == NO_IRQ)
+			continue;
+
+		set_irq_msi(entry->irq, NULL);
+		mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq),
+				     ALLOC_CHUNK);
+		irq_dispose_mapping(entry->irq);
+	}
+
+	return;
+}
+
+static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+	irq_hw_number_t hwirq;
+	unsigned int virq;
+	struct msi_desc *entry;
+	struct msi_msg msg;
+	u64 addr;
+
+	pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",
+		 pdev, nvec, type);
+
+	msg.address_hi = 0;
+	msg.address_lo = PASEMI_MSI_ADDR;
+
+	list_for_each_entry(entry, &pdev->msi_list, list) {
+		/* Allocate 16 interrupts for now, since that's the grouping for
+		 * affinity. This can be changed later if it turns out 32 is too
+		 * few MSIs for someone, but restrictions will apply to how the
+		 * sources can be changed independently.
+		 */
+		hwirq = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK);
+		if (hwirq < 0) {
+			pr_debug("pasemi_msi: failed allocating hwirq\n");
+			return hwirq;
+		}
+
+		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+		if (virq == NO_IRQ) {
+			pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq);
+			mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK);
+			return -ENOSPC;
+		}
+
+		/* Vector on MSI is really an offset, the hardware adds
+		 * it to the value written at the magic address. So set
+		 * it to 0 to remain sane.
+		 */
+		mpic_set_vector(virq, 0);
+
+		set_irq_msi(virq, entry);
+		set_irq_chip(virq, &mpic_pasemi_msi_chip);
+		set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+
+		pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n",
+			  virq, hwirq, addr);
+
+		/* Likewise, the device writes [0...511] into the target
+		 * register to generate MSI [512...1023]
+		 */
+		msg.data = hwirq-0x200;
+		write_msi_msg(virq, &msg);
+	}
+
+	return 0;
+}
+
+int mpic_pasemi_msi_init(struct mpic *mpic)
+{
+	int rc;
+
+	if (!mpic->irqhost->of_node ||
+	    !of_device_is_compatible(mpic->irqhost->of_node,
+				     "pasemi,pwrficient-openpic"))
+		return -ENODEV;
+
+	rc = mpic_msi_init_allocator(mpic);
+	if (rc) {
+		pr_debug("pasemi_msi: Error allocating bitmap!\n");
+		return rc;
+	}
+
+	pr_debug("pasemi_msi: Registering PA Semi MPIC MSI callbacks\n");
+
+	msi_mpic = mpic;
+	WARN_ON(ppc_md.setup_msi_irqs);
+	ppc_md.setup_msi_irqs = pasemi_msi_setup_msi_irqs;
+	ppc_md.teardown_msi_irqs = pasemi_msi_teardown_msi_irqs;
+	ppc_md.msi_check_device = pasemi_msi_check_device;
+
+	return 0;
+}
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 20edd1e..c858749 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -28,9 +28,9 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/io.h>
 #include <asm/pmi.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 3d57d38..21e0106 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -167,19 +167,20 @@
 
 /* Program the BRG to the given sampling rate and multiplier
  *
- * @brg: the BRG, 1-16
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
  * @rate: the desired sampling rate
  * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
  * GUMR_L[TDCR].  E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
  * then 'multiplier' should be 8.
- *
- * Also note that the value programmed into the BRGC register must be even.
  */
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
 {
 	u32 divisor, tempval;
 	u32 div16 = 0;
 
+	if ((brg < QE_BRG1) || (brg > QE_BRG16))
+		return -EINVAL;
+
 	divisor = get_brg_clk() / (rate * multiplier);
 
 	if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,8 +197,43 @@
 	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
 		QE_BRGC_ENABLE | div16;
 
-	out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
+	out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
+
+	return 0;
 }
+EXPORT_SYMBOL(qe_setbrg);
+
+/* Convert a string to a QE clock source enum
+ *
+ * This function takes a string, typically from a property in the device
+ * tree, and returns the corresponding "enum qe_clock" value.
+*/
+enum qe_clock qe_clock_source(const char *source)
+{
+	unsigned int i;
+
+	if (strcasecmp(source, "none") == 0)
+		return QE_CLK_NONE;
+
+	if (strncasecmp(source, "brg", 3) == 0) {
+		i = simple_strtoul(source + 3, NULL, 10);
+		if ((i >= 1) && (i <= 16))
+			return (QE_BRG1 - 1) + i;
+		else
+			return QE_CLK_DUMMY;
+	}
+
+	if (strncasecmp(source, "clk", 3) == 0) {
+		i = simple_strtoul(source + 3, NULL, 10);
+		if ((i >= 1) && (i <= 24))
+			return (QE_CLK1 - 1) + i;
+		else
+			return QE_CLK_DUMMY;
+	}
+
+	return QE_CLK_DUMMY;
+}
+EXPORT_SYMBOL(qe_clock_source);
 
 /* Initialize SNUMs (thread serial numbers) according to
  * QE Module Control chapter, SNUM table
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 121b04d..865e367 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -153,6 +153,10 @@
 
 static int do_spu_cmd(void);
 
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void);
+#endif
+
 int xmon_no_auto_backtrace;
 
 extern void xmon_enter(void);
@@ -231,6 +235,9 @@
 #ifdef CONFIG_PPC_STD_MMU_32
 "  u	dump segment registers\n"
 #endif
+#ifdef CONFIG_44x
+"  u	dump TLB\n"
+#endif
 "  ?	help\n"
 "  zr	reboot\n\
   zh	halt\n"
@@ -856,6 +863,11 @@
 			dump_segments();
 			break;
 #endif
+#ifdef CONFIG_4xx
+		case 'u':
+			dump_tlb_44x();
+			break;
+#endif
 		default:
 			printf("Unrecognized command: ");
 		        do {
@@ -2527,16 +2539,33 @@
 static void dump_slb(void)
 {
 	int i;
-	unsigned long tmp;
+	unsigned long esid,vsid,valid;
+	unsigned long llp;
 
 	printf("SLB contents of cpu %x\n", smp_processor_id());
 
-	for (i = 0; i < SLB_NUM_ENTRIES; i++) {
-		asm volatile("slbmfee  %0,%1" : "=r" (tmp) : "r" (i));
-		printf("%02d %016lx ", i, tmp);
-
-		asm volatile("slbmfev  %0,%1" : "=r" (tmp) : "r" (i));
-		printf("%016lx\n", tmp);
+	for (i = 0; i < mmu_slb_size; i++) {
+		asm volatile("slbmfee  %0,%1" : "=r" (esid) : "r" (i));
+		asm volatile("slbmfev  %0,%1" : "=r" (vsid) : "r" (i));
+		valid = (esid & SLB_ESID_V);
+		if (valid | esid | vsid) {
+			printf("%02d %016lx %016lx", i, esid, vsid);
+			if (valid) {
+				llp = vsid & SLB_VSID_LLP;
+				if (vsid & SLB_VSID_B_1T) {
+					printf("  1T  ESID=%9lx  VSID=%13lx LLP:%3lx \n",
+						GET_ESID_1T(esid),
+						(vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T,
+						llp);
+				} else {
+					printf(" 256M ESID=%9lx  VSID=%13lx LLP:%3lx \n",
+						GET_ESID(esid),
+						(vsid & ~SLB_VSID_B) >> SLB_VSID_SHIFT,
+						llp);
+				}
+			} else
+				printf("\n");
+		}
 	}
 }
 
@@ -2581,6 +2610,32 @@
 }
 #endif
 
+#ifdef CONFIG_44x
+static void dump_tlb_44x(void)
+{
+	int i;
+
+	for (i = 0; i < PPC44x_TLB_SIZE; i++) {
+		unsigned long w0,w1,w2;
+		asm volatile("tlbre  %0,%1,0" : "=r" (w0) : "r" (i));
+		asm volatile("tlbre  %0,%1,1" : "=r" (w1) : "r" (i));
+		asm volatile("tlbre  %0,%1,2" : "=r" (w2) : "r" (i));
+		printf("[%02x] %08x %08x %08x ", i, w0, w1, w2);
+		if (w0 & PPC44x_TLB_VALID) {
+			printf("V %08x -> %01x%08x %c%c%c%c%c",
+			       w0 & PPC44x_TLB_EPN_MASK,
+			       w1 & PPC44x_TLB_ERPN_MASK,
+			       w1 & PPC44x_TLB_RPN_MASK,
+			       (w2 & PPC44x_TLB_W) ? 'W' : 'w',
+			       (w2 & PPC44x_TLB_I) ? 'I' : 'i',
+			       (w2 & PPC44x_TLB_M) ? 'M' : 'm',
+			       (w2 & PPC44x_TLB_G) ? 'G' : 'g',
+			       (w2 & PPC44x_TLB_E) ? 'E' : 'e');
+		}
+		printf("\n");
+	}
+}
+#endif /* CONFIG_44x */
 void xmon_init(int enable)
 {
 #ifdef CONFIG_PPC_ISERIES
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 5255bd8..3c45302 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -37,7 +37,6 @@
 #include <asm/nvram.h>
 #include <asm/xmon.h>
 #include <asm/ocp.h>
-#include <asm/prom.h>
 
 #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \
 		      defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index b1f5b73..731b40e 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -50,7 +50,6 @@
 #include <asm/irq.h>
 #include <asm/immap_85xx.h>
 #include <asm/cpm2.h>
-#include <asm/mpc85xx.h>
 #include <asm/ppc_sys.h>
 
 #include <syslib/cpm2_pic.h>
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
index 976270d..c1f77e1 100644
--- a/arch/ppc/platforms/ev64260.c
+++ b/arch/ppc/platforms/ev64260.c
@@ -336,7 +336,7 @@
 #endif
 
 		if (early_serial_setup(&port) != 0)
-			printk(KERN_WARNING "Early serial init of port 0"
+			printk(KERN_WARNING "Early serial init of port 0 "
 				"failed\n");
 
 		first_time = 0;
@@ -388,7 +388,7 @@
 	ev64260_early_serial_map();
 #endif
 
-	printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc."
+	printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc. "
 		"(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
 
 	if (ppc_md.progress)
diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
index 1df3150..8ed433e 100644
--- a/arch/ppc/platforms/prep_pci.c
+++ b/arch/ppc/platforms/prep_pci.c
@@ -1099,7 +1099,6 @@
 				pci_write_config_byte(dev, 0x43, reg);
 			}
 		}
-		pci_dev_put(dev);
 	}
 
 	if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
diff --git a/arch/ppc/syslib/gt64260_pic.c b/arch/ppc/syslib/gt64260_pic.c
index e84d432..3b4fcca 100644
--- a/arch/ppc/syslib/gt64260_pic.c
+++ b/arch/ppc/syslib/gt64260_pic.c
@@ -35,7 +35,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index af35a31..f58149c 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 
diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
index 4b7a333..2dd2dc5 100644
--- a/arch/ppc/syslib/mv64360_pic.c
+++ b/arch/ppc/syslib/mv64360_pic.c
@@ -36,7 +36,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index 3f5be2c..d42d408 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -376,7 +376,7 @@
 
 	down_write(&ocp_devices_sem);
 	dev = __ocp_find_device(vendor, function, index);
-	list_del((struct list_head *)dev);
+	list_del(&dev->link);
 	up_write(&ocp_devices_sem);
 
 	DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index ec466db..ea37291 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -41,7 +41,6 @@
 
 #include <syslib/ppc83xx_setup.h>
 #if defined(CONFIG_PCI)
-#include <asm/delay.h>
 #include <syslib/ppc83xx_pci.h>
 #endif
 
diff --git a/arch/ppc/syslib/ppc8xx_pic.c b/arch/ppc/syslib/ppc8xx_pic.c
index e8619c75..bce9a75 100644
--- a/arch/ppc/syslib/ppc8xx_pic.c
+++ b/arch/ppc/syslib/ppc8xx_pic.c
@@ -16,7 +16,7 @@
  * the only interrupt controller.  Some boards, like the MBX and
  * Sandpoint have the 8259 as a secondary controller.  Depending
  * upon the processor type, the internal controller can have as
- * few as 16 interrups or as many as 64.  We could use  the
+ * few as 16 interrupts or as many as 64.  We could use  the
  * "clear_bit()" and "set_bit()" functions like other platforms,
  * but they are overkill for us.
  */
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 2d48018..837183c 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -185,7 +185,7 @@
  */
 
 /*
-   Here we'll replace .name pointers with fixed-lenght strings
+   Here we'll replace .name pointers with fixed-length strings
    Hereby, this should be called *before* any func stuff triggeded.
  */
 void ppc_sys_device_initfunc(void)
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index 8f0b953..9056fe5 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -10,7 +10,6 @@
 #include <linux/sysrq.h>
 #include <linux/bitops.h>
 #include <asm/xmon.h>
-#include <asm/machdep.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
 #include <asm/delay.h>
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 2d7cd48..6bbd4fa 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -98,7 +98,7 @@
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on PA6T-1682M processor.
+	  Generator hardware found on PA Semi PWRficient SoCs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pasemi-rng.
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index fa6040b..24ae307 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -126,10 +126,9 @@
 }
 
 static struct of_device_id rng_match[] = {
-	{
-		.compatible      = "1682m-rng",
-	},
-	{},
+	{ .compatible      = "1682m-rng", },
+	{ .compatible      = "pasemi,pwrficient-rng", },
+	{ },
 };
 
 static struct of_platform_driver rng_driver = {
diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c
index 9007d06..9032091 100644
--- a/drivers/edac/pasemi_edac.c
+++ b/drivers/edac/pasemi_edac.c
@@ -225,7 +225,7 @@
 		EDAC_FLAG_NONE;
 	mci->mod_name = MODULE_NAME;
 	mci->dev_name = pci_name(pdev);
-	mci->ctl_name = "pasemi,1682m-mc";
+	mci->ctl_name = "pasemi,pwrficient-mc";
 	mci->edac_check = pasemi_edac_check;
 	mci->ctl_page_to_phys = NULL;
 	pci_read_config_dword(pdev, MCCFG_SCRUB, &scrub);
@@ -297,4 +297,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
-MODULE_DESCRIPTION("MC support for PA Semi PA6T-1682M memory controller");
+MODULE_DESCRIPTION("MC support for PA Semi PWRficient memory controller");
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 5c742a5..5ae28f0 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/device.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
@@ -82,21 +83,11 @@
 BLOCKING_NOTIFIER_HEAD(adb_client_list);
 static int adb_got_sleep;
 static int adb_inited;
-static pid_t adb_probe_task_pid;
 static DECLARE_MUTEX(adb_probe_mutex);
-static struct completion adb_probe_task_comp;
 static int sleepy_trackpad;
 static int autopoll_devs;
 int __adb_probe_sync;
 
-#ifdef CONFIG_PM_SLEEP
-static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier adb_sleep_notifier = {
-	adb_notify_sleep,
-	SLEEP_LEVEL_ADB,
-};
-#endif
-
 static int adb_scan_bus(void);
 static int do_adb_reset_bus(void);
 static void adbdev_init(void);
@@ -134,16 +125,6 @@
 }
 #endif
 
-
-static __inline__ void adb_wait_ms(unsigned int ms)
-{
-	if (current->pid && adb_probe_task_pid &&
-	  adb_probe_task_pid == current->pid)
-		msleep(ms);
-	else
-		mdelay(ms);
-}
-
 static int adb_scan_bus(void)
 {
 	int i, highFree=0, noMovement;
@@ -248,13 +229,10 @@
 static int
 adb_probe_task(void *x)
 {
-	strcpy(current->comm, "kadbprobe");
-
 	printk(KERN_INFO "adb: starting probe task...\n");
 	do_adb_reset_bus();
 	printk(KERN_INFO "adb: finished probe task...\n");
 
-	adb_probe_task_pid = 0;
 	up(&adb_probe_mutex);
 
 	return 0;
@@ -263,7 +241,7 @@
 static void
 __adb_probe_task(struct work_struct *bullshit)
 {
-	adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL);
+	kthread_run(adb_probe_task, NULL, "kadbprobe");
 }
 
 static DECLARE_WORK(adb_reset_work, __adb_probe_task);
@@ -281,6 +259,36 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+/*
+ * notify clients before sleep
+ */
+static int adb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	adb_got_sleep = 1;
+	/* We need to get a lock on the probe thread */
+	down(&adb_probe_mutex);
+	/* Stop autopoll */
+	if (adb_controller->autopoll)
+		adb_controller->autopoll(0);
+	blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
+
+	return 0;
+}
+
+/*
+ * reset bus after sleep
+ */
+static int adb_resume(struct platform_device *dev)
+{
+	adb_got_sleep = 0;
+	up(&adb_probe_mutex);
+	adb_reset_bus();
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 int __init adb_init(void)
 {
 	struct adb_driver *driver;
@@ -313,15 +321,12 @@
 		printk(KERN_WARNING "Warning: no ADB interface detected\n");
 		adb_controller = NULL;
 	} else {
-#ifdef CONFIG_PM_SLEEP
-		pmu_register_sleep_notifier(&adb_sleep_notifier);
-#endif /* CONFIG_PM */
 #ifdef CONFIG_PPC
 		if (machine_is_compatible("AAPL,PowerBook1998") ||
 			machine_is_compatible("PowerBook1,1"))
 			sleepy_trackpad = 1;
 #endif /* CONFIG_PPC */
-		init_completion(&adb_probe_task_comp);
+
 		adbdev_init();
 		adb_reset_bus();
 	}
@@ -330,33 +335,6 @@
 
 __initcall(adb_init);
 
-#ifdef CONFIG_PM
-/*
- * notify clients before sleep and reset bus afterwards
- */
-void
-adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
-{
-	switch (when) {
-	case PBOOK_SLEEP_REQUEST:
-		adb_got_sleep = 1;
-		/* We need to get a lock on the probe thread */
-		down(&adb_probe_mutex);
-		/* Stop autopoll */
-		if (adb_controller->autopoll)
-			adb_controller->autopoll(0);
-		blocking_notifier_call_chain(&adb_client_list,
-			ADB_MSG_POWERDOWN, NULL);
-		break;
-	case PBOOK_WAKE:
-		adb_got_sleep = 0;
-		up(&adb_probe_mutex);
-		adb_reset_bus();
-		break;
-	}
-}
-#endif /* CONFIG_PM */
-
 static int
 do_adb_reset_bus(void)
 {
@@ -373,7 +351,7 @@
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
-		adb_wait_ms(500);
+		msleep(500);
 	}
 
 	down(&adb_handler_sem);
@@ -389,7 +367,7 @@
 
 	if (sleepy_trackpad) {
 		/* Let the trackpad settle down */
-		adb_wait_ms(1500);
+		msleep(1500);
 	}
 
 	if (!ret) {
@@ -413,41 +391,27 @@
 	adb_controller->poll();
 }
 
-static void
-adb_probe_wakeup(struct adb_request *req)
+static void adb_sync_req_done(struct adb_request *req)
 {
-	complete(&adb_probe_task_comp);
-}
+	struct completion *comp = req->arg;
 
-/* Static request used during probe */
-static struct adb_request adb_sreq;
-static unsigned long adb_sreq_lock; // Use semaphore ! */ 
+	complete(comp);
+}
 
 int
 adb_request(struct adb_request *req, void (*done)(struct adb_request *),
 	    int flags, int nbytes, ...)
 {
 	va_list list;
-	int i, use_sreq;
+	int i;
 	int rc;
+	struct completion comp;
 
 	if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
 		return -ENXIO;
 	if (nbytes < 1)
 		return -EINVAL;
-	if (req == NULL && (flags & ADBREQ_NOSEND))
-		return -EINVAL;
-	
-	if (req == NULL) {
-		if (test_and_set_bit(0,&adb_sreq_lock)) {
-			printk("adb.c: Warning: contention on static request !\n");
-			return -EPERM;
-		}
-		req = &adb_sreq;
-		flags |= ADBREQ_SYNC;
-		use_sreq = 1;
-	} else
-		use_sreq = 0;
+
 	req->nbytes = nbytes+1;
 	req->done = done;
 	req->reply_expected = flags & ADBREQ_REPLY;
@@ -460,25 +424,18 @@
 	if (flags & ADBREQ_NOSEND)
 		return 0;
 
-	/* Synchronous requests send from the probe thread cause it to
-	 * block. Beware that the "done" callback will be overriden !
-	 */
-	if ((flags & ADBREQ_SYNC) &&
-	    (current->pid && adb_probe_task_pid &&
-	    adb_probe_task_pid == current->pid)) {
-		req->done = adb_probe_wakeup;
-		rc = adb_controller->send_request(req, 0);
-		if (rc || req->complete)
-			goto bail;
-		wait_for_completion(&adb_probe_task_comp);
-		rc = 0;
-		goto bail;
+	/* Synchronous requests block using an on-stack completion */
+	if (flags & ADBREQ_SYNC) {
+		WARN_ON(done);
+		req->done = adb_sync_req_done;
+		req->arg = &comp;
+		init_completion(&comp);
 	}
 
-	rc = adb_controller->send_request(req, flags & ADBREQ_SYNC);
-bail:
-	if (use_sreq)
-		clear_bit(0, &adb_sreq_lock);
+	rc = adb_controller->send_request(req, 0);
+
+	if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
+		wait_for_completion(&comp);
 
 	return rc;
 }
@@ -864,7 +821,29 @@
 	.release	= adb_release,
 };
 
-static void
+static struct platform_driver adb_pfdrv = {
+	.driver = {
+		.name = "adb",
+	},
+#ifdef CONFIG_PM
+	.suspend = adb_suspend,
+	.resume = adb_resume,
+#endif
+};
+
+static struct platform_device adb_pfdev = {
+	.name = "adb",
+};
+
+static int __init
+adb_dummy_probe(struct platform_device *dev)
+{
+	if (dev == &adb_pfdev)
+		return 0;
+	return -ENODEV;
+}
+
+static void __init
 adbdev_init(void)
 {
 	if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
@@ -876,4 +855,7 @@
 	if (IS_ERR(adb_dev_class))
 		return;
 	class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+
+	platform_device_register(&adb_pfdev);
+	platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
 }
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 48d647a..192bef5 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -20,6 +20,7 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/ide.h>
+#include <linux/kthread.h>
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -35,7 +36,6 @@
 
 
 #define MB_DEBUG
-#define MB_IGNORE_SIGNALS
 
 #ifdef MB_DEBUG
 #define MBDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
@@ -622,12 +622,7 @@
 {
 	int	i;
 
-	strcpy(current->comm, "media-bay");
-#ifdef MB_IGNORE_SIGNALS
-	sigfillset(&current->blocked);
-#endif
-
-	for (;;) {
+	while (!kthread_should_stop()) {
 		for (i = 0; i < media_bay_count; ++i) {
 			down(&media_bays[i].lock);
 			if (!media_bays[i].sleeping)
@@ -636,9 +631,8 @@
 		}
 
 		msleep_interruptible(MB_POLL_DELAY);
-		if (signal_pending(current))
-			return 0;
 	}
+	return 0;
 }
 
 static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_device_id *match)
@@ -699,7 +693,7 @@
 
 	/* Startup kernel thread */
 	if (i == 0)
-		kernel_thread(media_bay_task, NULL, CLONE_KERNEL);
+		kthread_run(media_bay_task, NULL, "media-bay");
 
 	return 0;
 
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index e43554e..6fadc9a 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -121,6 +121,7 @@
 #include <linux/reboot.h>
 #include <linux/kmod.h>
 #include <linux/i2c.h>
+#include <linux/kthread.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -161,7 +162,7 @@
 static int				state;
 static int				cpu_count;
 static int				cpu_pid_type;
-static pid_t				ctrl_task;
+static struct task_struct		*ctrl_task;
 static struct completion		ctrl_complete;
 static int				critical_state;
 static int				rackmac;
@@ -1779,8 +1780,6 @@
  */
 static int main_control_loop(void *x)
 {
-	daemonize("kfand");
-
 	DBG("main_control_loop started\n");
 
 	down(&driver_lock);
@@ -1956,7 +1955,7 @@
 {
 	init_completion(&ctrl_complete);
 
-	ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL);
+	ctrl_task = kthread_run(main_control_loop, NULL, "kfand");
 }
 
 /*
@@ -1964,7 +1963,7 @@
  */
 static void stop_control_loops(void)
 {
-	if (ctrl_task != 0)
+	if (ctrl_task)
 		wait_for_completion(&ctrl_complete);
 }
 
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 5452da1..3722402 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -36,6 +36,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/kthread.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
@@ -61,8 +62,7 @@
 
 static struct {
 	volatile int		running;
-	struct completion	completion;
-	pid_t			poll_task;
+	struct task_struct	*poll_task;
 	
 	struct semaphore 	lock;
 	struct of_device	*of_dev;
@@ -282,27 +282,27 @@
 	write_reg( x.fan, 0x00, x.r0, 1 );
 }
 
-static int
-control_loop( void *dummy )
+static int control_loop(void *dummy)
 {
-	daemonize("g4fand");
-
-	down( &x.lock );
+	down(&x.lock);
 	setup_hardware();
+	up(&x.lock);
 
-	while( x.running ) {
-		up( &x.lock );
-
+	for (;;) {
 		msleep_interruptible(8000);
-		
-		down( &x.lock );
+		if (kthread_should_stop())
+			break;
+
+		down(&x.lock);
 		poll_temp();
+		up(&x.lock);
 	}
 
+	down(&x.lock);
 	restore_regs();
-	up( &x.lock );
+	up(&x.lock);
 
-	complete_and_exit( &x.completion, 0 );
+	return 0;
 }
 
 
@@ -322,8 +322,7 @@
 		ret = i2c_probe( adapter, &addr_data, &do_probe );
 		if( x.thermostat && x.fan ) {
 			x.running = 1;
-			init_completion( &x.completion );
-			x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL );
+			x.poll_task = kthread_run(control_loop, NULL, "g4fand");
 		}
 	}
 	return ret;
@@ -339,7 +338,8 @@
 	else {
 		if( x.running ) {
 			x.running = 0;
-			wait_for_completion( &x.completion );
+			kthread_stop(x.poll_task);
+			x.poll_task = NULL;
 		}
 		if( client == x.thermostat )
 			x.thermostat = NULL;
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index 7e27071..741a2e3 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -22,7 +22,7 @@
 
 static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
 {
-	unsigned int i, flat, count, range = (max - min);
+	int i, flat, count, range = (max - min);
 
 	bl_curve[0] = off;
 
@@ -68,17 +68,11 @@
 	return pmulevel;
 }
 
-static int pmu_backlight_update_status(struct backlight_device *bd)
+static int __pmu_backlight_update_status(struct backlight_device *bd)
 {
 	struct adb_request req;
-	unsigned long flags;
 	int level = bd->props.brightness;
 
-	spin_lock_irqsave(&pmu_backlight_lock, flags);
-
-	/* Don't update brightness when sleeping */
-	if (sleeping)
-		goto out;
 
 	if (bd->props.power != FB_BLANK_UNBLANK ||
 	    bd->props.fb_blank != FB_BLANK_UNBLANK)
@@ -99,12 +93,23 @@
 		pmu_wait_complete(&req);
 	}
 
-out:
-	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
-
 	return 0;
 }
 
+static int pmu_backlight_update_status(struct backlight_device *bd)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&pmu_backlight_lock, flags);
+	/* Don't update brightness when sleeping */
+	if (!sleeping)
+		rc = __pmu_backlight_update_status(bd);
+	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+	return rc;
+}
+
+
 static int pmu_backlight_get_brightness(struct backlight_device *bd)
 {
 	return bd->props.brightness;
@@ -123,6 +128,16 @@
 
 	spin_lock_irqsave(&pmu_backlight_lock, flags);
 	sleeping = sleep;
+	if (pmac_backlight) {
+		if (sleep) {
+			struct adb_request req;
+
+			pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+				    PMU_POW_BACKLIGHT | PMU_POW_OFF);
+			pmu_wait_complete(&req);
+		} else
+			__pmu_backlight_update_status(pmac_backlight);
+	}
 	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
 }
 #endif /* CONFIG_PM */
@@ -148,8 +163,8 @@
 
 	bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data);
 	if (IS_ERR(bd)) {
-		printk("pmubl: Backlight registration failed\n");
-		goto error;
+		printk(KERN_ERR "PMU Backlight registration failed\n");
+		return;
 	}
 	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
@@ -171,10 +186,5 @@
 	bd->props.power = FB_BLANK_UNBLANK;
 	backlight_update_status(bd);
 
-	printk("pmubl: Backlight initialized (%s)\n", name);
-
-	return;
-
-error:
-	return;
+	printk(KERN_INFO "PMU Backlight initialized (%s)\n", name);
 }
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 6123c70..82ec12e 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -10,13 +10,11 @@
  *
  * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
  * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ * Copyright (C) 2006-2007 Johannes Berg
  *
  * THIS DRIVER IS BECOMING A TOTAL MESS !
  *  - Cleanup atomically disabling reply to PMU events after
  *    a sleep or a freq. switch
- *  - Move sleep code out of here to pmac_pm, merge into new
- *    common PM infrastructure
- *  - Save/Restore PCI space properly
  *
  */
 #include <stdarg.h>
@@ -33,7 +31,6 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/cuda.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
@@ -65,9 +62,7 @@
 #include "via-pmu-event.h"
 
 /* Some compile options */
-#undef SUSPEND_USES_PMU
-#define DEBUG_SLEEP
-#undef HACKED_PCI_SAVE
+#undef DEBUG_SLEEP
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR		154
@@ -152,12 +147,9 @@
 static u8 pmu_intr_mask;
 static int pmu_version;
 static int drop_interrupts;
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 static int option_lid_wakeup = 1;
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
-#if (defined(CONFIG_PM_SLEEP)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
-static int sleep_in_progress;
-#endif
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
@@ -177,7 +169,6 @@
 
 int __fake_sleep;
 int asleep;
-BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
 
 #ifdef CONFIG_ADB
 static int adb_dev_map;
@@ -224,7 +215,7 @@
 
 #ifdef DEBUG_SLEEP
 int pmu_polled_request(struct adb_request *req);
-int pmu_wink(struct adb_request *req);
+void pmu_blink(int n);
 #endif
 
 /*
@@ -875,7 +866,7 @@
 {
 	char *p = page;
 
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
 		p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
@@ -916,7 +907,7 @@
 	*(val++) = 0;
 	while(*val == ' ')
 		val++;
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
 		if (!strcmp(label, "lid_wakeup"))
@@ -1256,9 +1247,7 @@
 pmu_suspend(void)
 {
 	unsigned long flags;
-#ifdef SUSPEND_USES_PMU
-	struct adb_request *req;
-#endif
+
 	if (!via)
 		return;
 	
@@ -1276,17 +1265,10 @@
 		via_pmu_interrupt(0, NULL);
 		spin_lock_irqsave(&pmu_lock, flags);
 		if (!adb_int_pending && pmu_state == idle && !req_awaiting_reply) {
-#ifdef SUSPEND_USES_PMU
-			pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
-			spin_unlock_irqrestore(&pmu_lock, flags);
-			while(!req.complete)
-				pmu_poll();
-#else /* SUSPEND_USES_PMU */
 			if (gpio_irq >= 0)
 				disable_irq_nosync(gpio_irq);
 			out_8(&via[IER], CB1_INT | IER_CLR);
 			spin_unlock_irqrestore(&pmu_lock, flags);
-#endif /* SUSPEND_USES_PMU */
 			break;
 		}
 	} while (1);
@@ -1307,18 +1289,11 @@
 		return;
 	}
 	adb_int_pending = 1;
-#ifdef SUSPEND_USES_PMU
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
-	spin_unlock_irqrestore(&pmu_lock, flags);
-	while(!req.complete)
-		pmu_poll();
-#else /* SUSPEND_USES_PMU */
 	if (gpio_irq >= 0)
 		enable_irq(gpio_irq);
 	out_8(&via[IER], CB1_INT | IER_SET);
 	spin_unlock_irqrestore(&pmu_lock, flags);
 	pmu_poll();
-#endif /* SUSPEND_USES_PMU */
 }
 
 /* Interrupt data could be the result data from an ADB cmd */
@@ -1738,228 +1713,7 @@
 	return via != 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-
-static LIST_HEAD(sleep_notifiers);
-
-int
-pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
-{
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		if (n->priority > notifier->priority)
-			break;
-	}
-	__list_add(&n->list, list->prev, list);
-	return 0;
-}
-EXPORT_SYMBOL(pmu_register_sleep_notifier);
-
-int
-pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
-{
-	if (n->list.next == 0)
-		return -ENOENT;
-	list_del(&n->list);
-	n->list.next = NULL;
-	return 0;
-}
-EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
-#endif /* CONFIG_PM_SLEEP */
-
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
-
-/* Sleep is broadcast last-to-first */
-static void broadcast_sleep(int when)
-{
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
-	     list = list->prev) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		notifier->notifier_call(notifier, when);
-	}
-}
-
-/* Wake is broadcast first-to-last */
-static void broadcast_wake(void)
-{
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		notifier->notifier_call(notifier, PBOOK_WAKE);
-	}
-}
-
-/*
- * This struct is used to store config register values for
- * PCI devices which may get powered off when we sleep.
- */
-static struct pci_save {
-#ifndef HACKED_PCI_SAVE
-	u16	command;
-	u16	cache_lat;
-	u16	intr;
-	u32	rom_address;
-#else
-	u32	config[16];
-#endif	
-} *pbook_pci_saves;
-static int pbook_npci_saves;
-
-static void
-pbook_alloc_pci_save(void)
-{
-	int npci;
-	struct pci_dev *pd = NULL;
-
-	npci = 0;
-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		++npci;
-	}
-	if (npci == 0)
-		return;
-	pbook_pci_saves = (struct pci_save *)
-		kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
-	pbook_npci_saves = npci;
-}
-
-static void
-pbook_free_pci_save(void)
-{
-	if (pbook_pci_saves == NULL)
-		return;
-	kfree(pbook_pci_saves);
-	pbook_pci_saves = NULL;
-	pbook_npci_saves = 0;
-}
-
-static void
-pbook_pci_save(void)
-{
-	struct pci_save *ps = pbook_pci_saves;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	
-	if (ps == NULL)
-		return;
-
-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		if (npci-- == 0) {
-			pci_dev_put(pd);
-			return;
-		}
-#ifndef HACKED_PCI_SAVE
-		pci_read_config_word(pd, PCI_COMMAND, &ps->command);
-		pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
-		pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
-		pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
-#else
-		int i;
-		for (i=1;i<16;i++)
-			pci_read_config_dword(pd, i<<4, &ps->config[i]);
-#endif
-		++ps;
-	}
-}
-
-/* For this to work, we must take care of a few things: If gmac was enabled
- * during boot, it will be in the pci dev list. If it's disabled at this point
- * (and it will probably be), then you can't access it's config space.
- */
-static void
-pbook_pci_restore(void)
-{
-	u16 cmd;
-	struct pci_save *ps = pbook_pci_saves - 1;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	int j;
-
-	while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-#ifdef HACKED_PCI_SAVE
-		int i;
-		if (npci-- == 0) {
-			pci_dev_put(pd);
-			return;
-		}
-		ps++;
-		for (i=2;i<16;i++)
-			pci_write_config_dword(pd, i<<4, ps->config[i]);
-		pci_write_config_dword(pd, 4, ps->config[1]);
-#else
-		if (npci-- == 0)
-			return;
-		ps++;
-		if (ps->command == 0)
-			continue;
-		pci_read_config_word(pd, PCI_COMMAND, &cmd);
-		if ((ps->command & ~cmd) == 0)
-			continue;
-		switch (pd->hdr_type) {
-		case PCI_HEADER_TYPE_NORMAL:
-			for (j = 0; j < 6; ++j)
-				pci_write_config_dword(pd,
-					PCI_BASE_ADDRESS_0 + j*4,
-					pd->resource[j].start);
-			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
-				ps->rom_address);
-			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
-				ps->cache_lat);
-			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
-				ps->intr);
-			pci_write_config_word(pd, PCI_COMMAND, ps->command);
-			break;
-		}
-#endif	
-	}
-}
-
-#ifdef DEBUG_SLEEP
-/* N.B. This doesn't work on the 3400 */
-void 
-pmu_blink(int n)
-{
-	struct adb_request req;
-
-	memset(&req, 0, sizeof(req));
-
-	for (; n > 0; --n) {
-		req.nbytes = 4;
-		req.done = NULL;
-		req.data[0] = 0xee;
-		req.data[1] = 4;
-		req.data[2] = 0;
-		req.data[3] = 1;
-		req.reply[0] = ADB_RET_OK;
-		req.reply_len = 1;
-		req.reply_expected = 0;
-		pmu_polled_request(&req);
-		mdelay(50);
-		req.nbytes = 4;
-		req.done = NULL;
-		req.data[0] = 0xee;
-		req.data[1] = 4;
-		req.data[2] = 0;
-		req.data[3] = 0;
-		req.reply[0] = ADB_RET_OK;
-		req.reply_len = 1;
-		req.reply_expected = 0;
-		pmu_polled_request(&req);
-		mdelay(50);
-	}
-	mdelay(50);
-}
-#endif
-
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 /*
  * Put the powerbook to sleep.
  */
@@ -1994,134 +1748,6 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-extern void pmu_backlight_set_sleep(int sleep);
-
-static int
-pmac_suspend_devices(void)
-{
-	int ret;
-
-	pm_prepare_console();
-	
-	/* Notify old-style device drivers */
-	broadcast_sleep(PBOOK_SLEEP_REQUEST);
-
-	/* Sync the disks. */
-	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. That
-	 * could be achieved using the refrigerator for processes
-	 * that swsusp uses
-	 */
-	sys_sync();
-
-	broadcast_sleep(PBOOK_SLEEP_NOW);
-
-	/* Send suspend call to devices, hold the device core's dpm_sem */
-	ret = device_suspend(PMSG_SUSPEND);
-	if (ret) {
-		broadcast_wake();
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code not to muck around with the chip anymore */
-	pmu_backlight_set_sleep(1);
-#endif
-
-	/* Call platform functions marked "on sleep" */
-	pmac_pfunc_i2c_suspend();
-	pmac_pfunc_base_suspend();
-
-	/* Stop preemption */
-	preempt_disable();
-
-	/* Make sure the decrementer won't interrupt us */
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	/* Make sure any pending DEC interrupt occurring while we did
-	 * the above didn't re-enable the DEC */
-	mb();
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-	/* We can now disable MSR_EE. This code of course works properly only
-	 * on UP machines... For SMP, if we ever implement sleep, we'll have to
-	 * stop the "other" CPUs way before we do all that stuff.
-	 */
-	local_irq_disable();
-
-	/* Broadcast power down irq
-	 * This isn't that useful in most cases (only directly wired devices can
-	 * use this but still... This will take care of sysdev's as well, so
-	 * we exit from here with local irqs disabled and PIC off.
-	 */
-	ret = device_power_down(PMSG_SUSPEND);
-	if (ret) {
-		wakeup_decrementer();
-		local_irq_enable();
-		preempt_enable();
-		device_resume();
-		broadcast_wake();
-		printk(KERN_ERR "Driver powerdown failed\n");
-		return -EBUSY;
-	}
-
-	/* Wait for completion of async requests */
-	while (!batt_req.complete)
-		pmu_poll();
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int
-pmac_wakeup_devices(void)
-{
-	mdelay(100);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Tell backlight code it can use the chip again */
-	pmu_backlight_set_sleep(0);
-#endif
-
-	/* Power back up system devices (including the PIC) */
-	device_power_up();
-
-	/* Force a poll of ADB interrupts */
-	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL);
-
-	/* Restart jiffies & scheduling */
-	wakeup_decrementer();
-
-	/* Re-enable local CPU interrupts */
-	local_irq_enable();
-	mdelay(10);
-	preempt_enable();
-
-	/* Call platform functions marked "on wake" */
-	pmac_pfunc_base_resume();
-	pmac_pfunc_i2c_resume();
-
-	/* Resume devices */
-	device_resume();
-
-	/* Notify old style drivers */
-	broadcast_wake();
-
-	pm_restore_console();
-
-	return 0;
-}
-
 #define	GRACKLE_PM	(1<<7)
 #define GRACKLE_DOZE	(1<<5)
 #define	GRACKLE_NAP	(1<<4)
@@ -2132,19 +1758,12 @@
 	unsigned long save_l2cr;
 	unsigned short pmcr1;
 	struct adb_request req;
-	int ret;
 	struct pci_dev *grackle;
 
 	grackle = pci_get_bus_and_slot(0, 0);
 	if (!grackle)
 		return -ENODEV;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-	
 	/* Turn off various things. Darwin does some retry tests here... */
 	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
 	pmu_wait_complete(&req);
@@ -2207,8 +1826,6 @@
 			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
 	pmu_wait_complete(&req);
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
@@ -2218,7 +1835,6 @@
 	unsigned long save_l2cr;
 	unsigned long save_l3cr;
 	struct adb_request req;
-	int ret;
 	
 	if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
 		printk(KERN_ERR "Sleep mode not supported on this machine\n");
@@ -2228,12 +1844,6 @@
 	if (num_online_cpus() > 1 || cpu_is_offline(0))
 		return -EAGAIN;
 
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
 	/* Stop environment and ADB interrupts */
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
 	pmu_wait_complete(&req);
@@ -2304,45 +1914,33 @@
 	/* Restore LPJ, cpufreq will adjust the cpu frequency */
 	loops_per_jiffy /= 2;
 
-	pmac_wakeup_devices();
-
 	return 0;
 }
 
 #define PB3400_MEM_CTRL		0xf8000000
 #define PB3400_MEM_CTRL_SLEEP	0x70
 
-static int
-powerbook_sleep_3400(void)
+static void __iomem *pb3400_mem_ctrl;
+
+static void powerbook_sleep_init_3400(void)
 {
-	int ret, i, x;
+	/* map in the memory controller registers */
+	pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+	if (pb3400_mem_ctrl == NULL)
+		printk(KERN_WARNING "ioremap failed: sleep won't be possible");
+}
+
+static int powerbook_sleep_3400(void)
+{
+	int i, x;
 	unsigned int hid0;
-	unsigned long p;
+	unsigned long msr;
 	struct adb_request sleep_req;
-	void __iomem *mem_ctrl;
 	unsigned int __iomem *mem_ctrl_sleep;
 
-	/* first map in the memory controller registers */
-	mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
-	if (mem_ctrl == NULL) {
-		printk("powerbook_sleep_3400: ioremap failed\n");
+	if (pb3400_mem_ctrl == NULL)
 		return -ENOMEM;
-	}
-	mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
-	/* Allocate room for PCI save */
-	pbook_alloc_pci_save();
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		pbook_free_pci_save();
-		iounmap(mem_ctrl);
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
-	/* Save the state of PCI config space for some slots */
-	pbook_pci_save();
+	mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
 
 	/* Set the memory controller to keep the memory refreshed
 	   while we're asleep */
@@ -2357,41 +1955,34 @@
 
 	/* Ask the PMU to put us to sleep */
 	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-	while (!sleep_req.complete)
-		mb();
+	pmu_wait_complete(&sleep_req);
+	pmu_unlock();
 
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
 
-	/* displacement-flush the L2 cache - necessary? */
-	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
-		i = *(volatile int *)p;
 	asleep = 1;
 
 	/* Put the CPU into sleep mode */
 	hid0 = mfspr(SPRN_HID0);
 	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
 	mtspr(SPRN_HID0, hid0);
-	mtmsr(mfmsr() | MSR_POW | MSR_EE);
-	udelay(10);
+	local_irq_enable();
+	msr = mfmsr() | MSR_POW;
+	while (asleep) {
+		mb();
+		mtmsr(msr);
+		isync();
+	}
+	local_irq_disable();
 
 	/* OK, we're awake again, start restoring things */
 	out_be32(mem_ctrl_sleep, 0x3f);
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-	pbook_pci_restore();
-	pmu_unlock();
-
-	/* wait for the PMU interrupt sequence to complete */
-	while (asleep)
-		mb();
-
-	pmac_wakeup_devices();
-	pbook_free_pci_save();
-	iounmap(mem_ctrl);
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
 
 	return 0;
 }
 
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
 /*
  * Support for /dev/pmu device
@@ -2548,7 +2139,6 @@
 	struct pmu_private *pp = file->private_data;
 	unsigned long flags;
 
-	lock_kernel();
 	if (pp != 0) {
 		file->private_data = NULL;
 		spin_lock_irqsave(&all_pvt_lock, flags);
@@ -2562,10 +2152,96 @@
 
 		kfree(pp);
 	}
-	unlock_kernel();
 	return 0;
 }
 
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
+static void pmac_suspend_disable_irqs(void)
+{
+	/* Call platform functions marked "on sleep" */
+	pmac_pfunc_i2c_suspend();
+	pmac_pfunc_base_suspend();
+}
+
+static int powerbook_sleep(suspend_state_t state)
+{
+	int error = 0;
+
+	/* Wait for completion of async requests */
+	while (!batt_req.complete)
+		pmu_poll();
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	switch (pmu_kind) {
+	case PMU_OHARE_BASED:
+		error = powerbook_sleep_3400();
+		break;
+	case PMU_HEATHROW_BASED:
+	case PMU_PADDINGTON_BASED:
+		error = powerbook_sleep_grackle();
+		break;
+	case PMU_KEYLARGO_BASED:
+		error = powerbook_sleep_Core99();
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	if (error)
+		return error;
+
+	mdelay(100);
+
+	return 0;
+}
+
+static void pmac_suspend_enable_irqs(void)
+{
+	/* Force a poll of ADB interrupts */
+	adb_int_pending = 1;
+	via_pmu_interrupt(0, NULL);
+
+	mdelay(10);
+
+	/* Call platform functions marked "on wake" */
+	pmac_pfunc_base_resume();
+	pmac_pfunc_i2c_resume();
+}
+
+static int pmu_sleep_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM
+		&& (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0);
+}
+
+static struct platform_suspend_ops pmu_pm_ops = {
+	.enter = powerbook_sleep,
+	.valid = pmu_sleep_valid,
+};
+
+static int register_pmu_pm_ops(void)
+{
+	if (pmu_kind == PMU_OHARE_BASED)
+		powerbook_sleep_init_3400();
+	ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs;
+	ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs;
+	suspend_set_ops(&pmu_pm_ops);
+
+	return 0;
+}
+
+device_initcall(register_pmu_pm_ops);
+#endif
+
 static int
 pmu_ioctl(struct inode * inode, struct file *filp,
 		     u_int cmd, u_long arg)
@@ -2574,35 +2250,15 @@
 	int error = -EINVAL;
 
 	switch (cmd) {
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
 	case PMU_IOC_SLEEP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (sleep_in_progress)
-			return -EBUSY;
-		sleep_in_progress = 1;
-		switch (pmu_kind) {
-		case PMU_OHARE_BASED:
-			error = powerbook_sleep_3400();
-			break;
-		case PMU_HEATHROW_BASED:
-		case PMU_PADDINGTON_BASED:
-			error = powerbook_sleep_grackle();
-			break;
-		case PMU_KEYLARGO_BASED:
-			error = powerbook_sleep_Core99();
-			break;
-		default:
-			error = -ENOSYS;
-		}
-		sleep_in_progress = 0;
-		break;
+		return pm_suspend(PM_SUSPEND_MEM);
 	case PMU_IOC_CAN_SLEEP:
-		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) < 0)
 			return put_user(0, argp);
 		else
 			return put_user(1, argp);
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
 
 #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
 	/* Compatibility ioctl's for backlight */
@@ -2610,9 +2266,6 @@
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		brightness = pmac_backlight_get_legacy_brightness();
 		if (brightness < 0)
 			return brightness;
@@ -2624,9 +2277,6 @@
 	{
 		int brightness;
 
-		if (sleep_in_progress)
-			return -EBUSY;
-
 		error = get_user(brightness, argp);
 		if (error)
 			return error;
@@ -2751,15 +2401,43 @@
 	local_irq_restore(flags);
 	return 0;
 }
+
+/* N.B. This doesn't work on the 3400 */
+void pmu_blink(int n)
+{
+	struct adb_request req;
+
+	memset(&req, 0, sizeof(req));
+
+	for (; n > 0; --n) {
+		req.nbytes = 4;
+		req.done = NULL;
+		req.data[0] = 0xee;
+		req.data[1] = 4;
+		req.data[2] = 0;
+		req.data[3] = 1;
+		req.reply[0] = ADB_RET_OK;
+		req.reply_len = 1;
+		req.reply_expected = 0;
+		pmu_polled_request(&req);
+		mdelay(50);
+		req.nbytes = 4;
+		req.done = NULL;
+		req.data[0] = 0xee;
+		req.data[1] = 4;
+		req.data[2] = 0;
+		req.data[3] = 0;
+		req.reply[0] = ADB_RET_OK;
+		req.reply_len = 1;
+		req.reply_expected = 0;
+		pmu_polled_request(&req);
+		mdelay(50);
+	}
+	mdelay(50);
+}
 #endif /* DEBUG_SLEEP */
 
-
-/* FIXME: This is a temporary set of callbacks to enable us
- * to do suspend-to-disk.
- */
-
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
-
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 int pmu_sys_suspended;
 
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
@@ -2767,10 +2445,15 @@
 	if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended)
 		return 0;
 
-	/* Suspend PMU event interrupts */
+	/* Suspend PMU event interrupts */\
 	pmu_suspend();
-
 	pmu_sys_suspended = 1;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code not to muck around with the chip anymore */
+	pmu_backlight_set_sleep(1);
+#endif
+
 	return 0;
 }
 
@@ -2785,15 +2468,18 @@
 	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
 	pmu_wait_complete(&req);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code it can use the chip again */
+	pmu_backlight_set_sleep(0);
+#endif
 	/* Resume PMU event interrupts */
 	pmu_resume();
-
 	pmu_sys_suspended = 0;
 
 	return 0;
 }
 
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
 static struct sysdev_class pmu_sysclass = {
 	set_kset_name("pmu"),
@@ -2804,10 +2490,10 @@
 };
 
 static struct sysdev_driver driver_pmu = {
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 	.suspend	= &pmu_sys_suspend,
 	.resume		= &pmu_sys_resume,
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 };
 
 static int __init init_pmu_sysfs(void)
@@ -2842,10 +2528,10 @@
 EXPORT_SYMBOL(pmu_suspend);
 EXPORT_SYMBOL(pmu_resume);
 EXPORT_SYMBOL(pmu_unlock);
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 EXPORT_SYMBOL(pmu_enable_irled);
 EXPORT_SYMBOL(pmu_battery_count);
 EXPORT_SYMBOL(pmu_batteries);
 EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index da4efbc..e363211 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -81,16 +81,8 @@
 static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
 	const struct fs_platform_info *fpi = fep->fpi;
-	int i;
 
-	W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
-	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
-		if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-			return 0;
-
-	printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-	       __FUNCTION__);
-	return 1;
+	return cpm_command(fpi->cp_command, op);
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index 48f2f30..fe3d8a62 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -89,21 +89,12 @@
  * Delay to wait for SCC reset command to complete (in us)
  */
 #define SCC_RESET_DELAY		50
-#define MAX_CR_CMD_LOOPS	10000
 
 static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
 	const struct fs_platform_info *fpi = fep->fpi;
-	int i;
 
-	W16(cpmp, cp_cpcr, fpi->cp_command | CPM_CR_FLG | (op << 8));
-	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
-		if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-			return 0;
-
-	printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-		__FUNCTION__);
-	return 1;
+	return cpm_command(fpi->cp_command, op);
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index abac7db..8d456e3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3822,6 +3822,7 @@
 	int err, ucc_num, max_speed = 0;
 	const phandle *ph;
 	const unsigned int *prop;
+	const char *sprop;
 	const void *mac_addr;
 	phy_interface_t phy_interface;
 	static const int enet_to_speed[] = {
@@ -3854,10 +3855,56 @@
 
 	ug_info->uf_info.ucc_num = ucc_num;
 
-	prop = of_get_property(np, "rx-clock", NULL);
-	ug_info->uf_info.rx_clock = *prop;
-	prop = of_get_property(np, "tx-clock", NULL);
-	ug_info->uf_info.tx_clock = *prop;
+	sprop = of_get_property(np, "rx-clock-name", NULL);
+	if (sprop) {
+		ug_info->uf_info.rx_clock = qe_clock_source(sprop);
+		if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) ||
+		    (ug_info->uf_info.rx_clock > QE_CLK24)) {
+			printk(KERN_ERR
+				"ucc_geth: invalid rx-clock-name property\n");
+			return -EINVAL;
+		}
+	} else {
+		prop = of_get_property(np, "rx-clock", NULL);
+		if (!prop) {
+			/* If both rx-clock-name and rx-clock are missing,
+			   we want to tell people to use rx-clock-name. */
+			printk(KERN_ERR
+				"ucc_geth: missing rx-clock-name property\n");
+			return -EINVAL;
+		}
+		if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+			printk(KERN_ERR
+				"ucc_geth: invalid rx-clock propperty\n");
+			return -EINVAL;
+		}
+		ug_info->uf_info.rx_clock = *prop;
+	}
+
+	sprop = of_get_property(np, "tx-clock-name", NULL);
+	if (sprop) {
+		ug_info->uf_info.tx_clock = qe_clock_source(sprop);
+		if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) ||
+		    (ug_info->uf_info.tx_clock > QE_CLK24)) {
+			printk(KERN_ERR
+				"ucc_geth: invalid tx-clock-name property\n");
+			return -EINVAL;
+		}
+	} else {
+		prop = of_get_property(np, "rx-clock", NULL);
+		if (!prop) {
+			printk(KERN_ERR
+				"ucc_geth: mising tx-clock-name property\n");
+			return -EINVAL;
+		}
+		if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+			printk(KERN_ERR
+				"ucc_geth: invalid tx-clock property\n");
+			return -EINVAL;
+		}
+		ug_info->uf_info.tx_clock = *prop;
+	}
+
 	err = of_address_to_resource(np, 0, &res);
 	if (err)
 		return -EINVAL;
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index b169b0e..191954b 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -155,7 +155,7 @@
 	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 		of_scan_pci_bridge(dn, dev);
 
-	pcibios_fixup_new_pci_devices(dev->subordinate,0);
+	pcibios_fixup_new_pci_devices(dev->subordinate);
 
 	/* Claim new bus resources */
 	pcibios_claim_one_bus(dev->bus);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 52fb044..6ea0366 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -52,11 +52,7 @@
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
-	u16 __iomem *cpcr = &cpmp->cp_cpcr;
-
-	out_be16(cpcr, port->command | (cmd << 8) | CPM_CR_FLG);
-	while (in_be16(cpcr) & CPM_CR_FLG)
-		;
+	cpm_command(port->command, cmd);
 }
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 882dbc1..def0158 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -52,13 +52,7 @@
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
-	cpm_cpm2_t __iomem *cp = cpm2_map(im_cpm);
-
-	out_be32(&cp->cp_cpcr, port->command | cmd | CPM_CR_FLG);
-	while (in_be32(&cp->cp_cpcr) & CPM_CR_FLG)
-		;
-
-	cpm2_unmap(cp);
+	cpm_command(port->command, cmd);
 }
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
diff --git a/include/asm-powerpc/8xx_immap.h b/include/asm-powerpc/8xx_immap.h
index 1311cef..4b0e152 100644
--- a/include/asm-powerpc/8xx_immap.h
+++ b/include/asm-powerpc/8xx_immap.h
@@ -123,7 +123,7 @@
 #define OR_G5LA		0x00000400	/* Output #GPL5 on #GPL_A5		*/
 #define OR_G5LS		0x00000200	/* Drive #GPL high on falling edge of...*/
 #define OR_BI		0x00000100	/* Burst inhibit			*/
-#define OR_SCY_MSK	0x000000f0	/* Cycle Lenght in Clocks		*/
+#define OR_SCY_MSK	0x000000f0	/* Cycle Length in Clocks		*/
 #define OR_SCY_0_CLK	0x00000000	/* 0 clock cycles wait states		*/
 #define OR_SCY_1_CLK	0x00000010	/* 1 clock cycles wait states		*/
 #define OR_SCY_2_CLK	0x00000020	/* 2 clock cycles wait states		*/
diff --git a/include/asm-powerpc/commproc.h b/include/asm-powerpc/commproc.h
index 2ee59d7..9e3b864 100644
--- a/include/asm-powerpc/commproc.h
+++ b/include/asm-powerpc/commproc.h
@@ -693,7 +693,7 @@
 #define	CICR_SCC_SCC3		((uint)0x00200000)	/* SCC3 @ SCCc */
 #define	CICR_SCB_SCC2		((uint)0x00040000)	/* SCC2 @ SCCb */
 #define	CICR_SCA_SCC1		((uint)0x00000000)	/* SCC1 @ SCCa */
-#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrrupt */
+#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrupt */
 #define CICR_HP_MASK		((uint)0x00001f00)	/* Hi-pri int. */
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h
index 48df9f3..fae83b1 100644
--- a/include/asm-powerpc/cpm.h
+++ b/include/asm-powerpc/cpm.h
@@ -10,5 +10,6 @@
 unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
 void __iomem *cpm_muram_addr(unsigned long offset);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
+int cpm_command(u32 command, u8 opcode);
 
 #endif
diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
new file mode 100644
index 0000000..8485c28
--- /dev/null
+++ b/include/asm-powerpc/cputhreads.h
@@ -0,0 +1,71 @@
+#ifndef _ASM_POWERPC_CPUTHREADS_H
+#define _ASM_POWERPC_CPUTHREADS_H
+
+#include <linux/cpumask.h>
+
+/*
+ * Mapping of threads to cores
+ */
+
+#ifdef CONFIG_SMP
+extern int threads_per_core;
+extern int threads_shift;
+extern cpumask_t threads_core_mask;
+#else
+#define threads_per_core	1
+#define threads_shift		0
+#define threads_core_mask	(CPU_MASK_CPU0)
+#endif
+
+/* cpu_thread_mask_to_cores - Return a cpumask of one per cores
+ *                            hit by the argument
+ *
+ * @threads:	a cpumask of threads
+ *
+ * This function returns a cpumask which will have one "cpu" (or thread)
+ * bit set for each core that has at least one thread set in the argument.
+ *
+ * This can typically be used for things like IPI for tlb invalidations
+ * since those need to be done only once per core/TLB
+ */
+static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
+{
+	cpumask_t	tmp, res;
+	int		i;
+
+	res = CPU_MASK_NONE;
+	for (i = 0; i < NR_CPUS; i += threads_per_core) {
+		cpus_shift_right(tmp, threads_core_mask, i);
+		if (cpus_intersects(threads, tmp))
+			cpu_set(i, res);
+	}
+	return res;
+}
+
+static inline int cpu_nr_cores(void)
+{
+	return NR_CPUS >> threads_shift;
+}
+
+static inline cpumask_t cpu_online_cores_map(void)
+{
+	return cpu_thread_mask_to_cores(cpu_online_map);
+}
+
+static inline int cpu_thread_to_core(int cpu)
+{
+	return cpu >> threads_shift;
+}
+
+static inline int cpu_thread_in_core(int cpu)
+{
+	return cpu & (threads_per_core - 1);
+}
+
+static inline int cpu_first_thread_in_core(int cpu)
+{
+	return cpu & ~(threads_per_core - 1);
+}
+
+#endif /* _ASM_POWERPC_CPUTHREADS_H */
+
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index ff52013..e974876 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -87,6 +87,9 @@
 	return dma_ops->dma_supported(dev, mask);
 }
 
+/* We have our own implementation of pci_set_dma_mask() */
+#define HAVE_ARCH_PCI_SET_DMA_MASK
+
 static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 {
 	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index 3671c12..1e41bd1 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -64,7 +64,7 @@
 	FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1,
 	FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
-	FW_FEATURE_CELLEB_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_BEAT,
+	FW_FEATURE_CELLEB_ALWAYS = 0,
 	FW_FEATURE_NATIVE_POSSIBLE = 0,
 	FW_FEATURE_NATIVE_ALWAYS = 0,
 	FW_FEATURE_POSSIBLE =
diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h
index 0ad4e65..0f165e5 100644
--- a/include/asm-powerpc/immap_86xx.h
+++ b/include/asm-powerpc/immap_86xx.h
@@ -89,14 +89,14 @@
  * them.
  *
  * guts: Pointer to GUTS structure
- * co: The DMA controller (1 or 2)
+ * co: The DMA controller (0 or 1)
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
  */
 static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
 	unsigned int co, unsigned int ch, unsigned int device)
 {
-	unsigned int shift = 16 + (8 * (2 - co) + 2 * (3 - ch));
+	unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
 
 	clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
 }
@@ -118,6 +118,27 @@
 #define CCSR_GUTS_PMUXCR_DMA1_0		0x00000002
 #define CCSR_GUTS_PMUXCR_DMA1_3		0x00000001
 
+/*
+ * Set the DMA external control bits in the GUTS
+ *
+ * The DMA external control bits in the PMUXCR are only meaningful for
+ * channels 0 and 3.  Any other channels are ignored.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * value: the new value for the bit (0 or 1)
+ */
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+	unsigned int co, unsigned int ch, unsigned int value)
+{
+	if ((ch == 0) || (ch == 3)) {
+		unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
+
+		clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
+	}
+}
+
 #define CCSR_GUTS_CLKDVDR_PXCKEN	0x80000000
 #define CCSR_GUTS_CLKDVDR_SSICKEN	0x20000000
 #define CCSR_GUTS_CLKDVDR_PXCKINV	0x10000000
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index e44cdfc..7be26f6 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -50,15 +50,16 @@
 #define PCI_DRAM_OFFSET	pci_dram_offset
 #else
 #define _IO_BASE	pci_io_base
-#define _ISA_MEM_BASE	0
+#define _ISA_MEM_BASE	isa_mem_base
 #define PCI_DRAM_OFFSET	0
 #endif
 
 extern unsigned long isa_io_base;
-extern unsigned long isa_mem_base;
 extern unsigned long pci_io_base;
 extern unsigned long pci_dram_offset;
 
+extern resource_size_t isa_mem_base;
+
 #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO)
 #error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits
 #endif
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 4a82fdc..7a3cef7 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -69,10 +69,9 @@
 };
 
 struct scatterlist;
-struct device_node;
 
 /* Frees table for an individual device node */
-extern void iommu_free_table(struct device_node *dn);
+extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
 
 /* Initializes an iommu_table based in values set in the passed-in
  * structure
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
index edec79d..8ff08be0 100644
--- a/include/asm-powerpc/ipic.h
+++ b/include/asm-powerpc/ipic.h
@@ -20,11 +20,13 @@
 
 /* Flags when we init the IPIC */
 #define IPIC_SPREADMODE_GRP_A	0x00000001
-#define IPIC_SPREADMODE_GRP_D	0x00000002
-#define IPIC_SPREADMODE_MIX_A	0x00000004
-#define IPIC_SPREADMODE_MIX_B	0x00000008
-#define IPIC_DISABLE_MCP_OUT	0x00000010
-#define IPIC_IRQ0_MCP		0x00000020
+#define IPIC_SPREADMODE_GRP_B	0x00000002
+#define IPIC_SPREADMODE_GRP_C	0x00000004
+#define IPIC_SPREADMODE_GRP_D	0x00000008
+#define IPIC_SPREADMODE_MIX_A	0x00000010
+#define IPIC_SPREADMODE_MIX_B	0x00000020
+#define IPIC_DISABLE_MCP_OUT	0x00000040
+#define IPIC_IRQ0_MCP		0x00000080
 
 /* IPIC registers offsets */
 #define IPIC_SICFR	0x00	/* System Global Interrupt Configuration Register */
diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h
index 6ce2ce1..8f5da7d 100644
--- a/include/asm-powerpc/iseries/hv_lp_event.h
+++ b/include/asm-powerpc/iseries/hv_lp_event.h
@@ -78,7 +78,7 @@
 
 /*
  * Close an Lp Event Path for a type and partition
- * returns 0 on sucess
+ * returns 0 on success
  */
 extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 6968f43..0872ec2 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -204,6 +204,13 @@
 	/*
 	 * optional PCI "hooks"
 	 */
+	/* Called in indirect_* to avoid touching devices */
+	int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
+
+	/* Called at then very end of pcibios_init() */
+	void (*pcibios_after_init)(void);
+
+#endif /* CONFIG_PPC32 */
 
 	/* Called after PPC generic resource fixup to perform
 	   machine specific fixups */
@@ -212,18 +219,9 @@
 	/* Called for each PCI bus in the system when it's probed */
 	void (*pcibios_fixup_bus)(struct pci_bus *);
 
-	/* Called when pci_enable_device() is called (initial=0) or
-	 * when a device with no assigned resource is found (initial=1).
-	 * Returns 0 to allow assignment/enabling of the device. */
-	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
-
-	/* Called in indirect_* to avoid touching devices */
-	int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
-
-	/* Called at then very end of pcibios_init() */
-	void (*pcibios_after_init)(void);
-
-#endif /* CONFIG_PPC32 */
+	/* Called when pci_enable_device() is called. Returns 0 to
+	 * allow assignment/enabling of the device. */
+	int  (*pcibios_enable_device_hook)(struct pci_dev *);
 
 	/* Called to shutdown machine specific hardware not already controlled
 	 * by other drivers.
@@ -253,6 +251,16 @@
 	 */
 	void (*machine_kexec)(struct kimage *image);
 #endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_SUSPEND
+	/* These are called to disable and enable, respectively, IRQs when
+	 * entering a suspend state.  If NULL, then the generic versions
+	 * will be called.  The generic versions disable/enable the
+	 * decrementer along with interrupts.
+	 */
+	void (*suspend_disable_irqs)(void);
+	void (*suspend_enable_irqs)(void);
+#endif
 };
 
 extern void power4_idle(void);
@@ -326,5 +334,31 @@
 		ppc_md.log_error(buf, err_type, fatal);
 }
 
+#define __define_machine_initcall(mach,level,fn,id) \
+	static int __init __machine_initcall_##mach##_##fn(void) { \
+		if (machine_is(mach)) return fn(); \
+		return 0; \
+	} \
+	__define_initcall(level,__machine_initcall_##mach##_##fn,id);
+
+#define machine_core_initcall(mach,fn)		__define_machine_initcall(mach,"1",fn,1)
+#define machine_core_initcall_sync(mach,fn)	__define_machine_initcall(mach,"1s",fn,1s)
+#define machine_postcore_initcall(mach,fn)	__define_machine_initcall(mach,"2",fn,2)
+#define machine_postcore_initcall_sync(mach,fn)	__define_machine_initcall(mach,"2s",fn,2s)
+#define machine_arch_initcall(mach,fn)		__define_machine_initcall(mach,"3",fn,3)
+#define machine_arch_initcall_sync(mach,fn)	__define_machine_initcall(mach,"3s",fn,3s)
+#define machine_subsys_initcall(mach,fn)	__define_machine_initcall(mach,"4",fn,4)
+#define machine_subsys_initcall_sync(mach,fn)	__define_machine_initcall(mach,"4s",fn,4s)
+#define machine_fs_initcall(mach,fn)		__define_machine_initcall(mach,"5",fn,5)
+#define machine_fs_initcall_sync(mach,fn)	__define_machine_initcall(mach,"5s",fn,5s)
+#define machine_rootfs_initcall(mach,fn)	__define_machine_initcall(mach,"rootfs",fn,rootfs)
+#define machine_device_initcall(mach,fn)	__define_machine_initcall(mach,"6",fn,6)
+#define machine_device_initcall_sync(mach,fn)	__define_machine_initcall(mach,"6s",fn,6s)
+#define machine_late_initcall(mach,fn)		__define_machine_initcall(mach,"7",fn,7)
+#define machine_late_initcall_sync(mach,fn)	__define_machine_initcall(mach,"7s",fn,7s)
+
+void generic_suspend_disable_irqs(void);
+void generic_suspend_enable_irqs(void);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MACHDEP_H */
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index 82328de..12e5e77 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -180,6 +180,7 @@
 extern int mmu_io_psize;
 extern int mmu_kernel_ssize;
 extern int mmu_highuser_ssize;
+extern u16 mmu_slb_size;
 
 /*
  * If the processor supports 64k normal pages but not 64k cache
diff --git a/include/asm-powerpc/nvram.h b/include/asm-powerpc/nvram.h
index 9877982..4e7059c 100644
--- a/include/asm-powerpc/nvram.h
+++ b/include/asm-powerpc/nvram.h
@@ -10,6 +10,8 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
+#include <linux/errno.h>
+
 #define NVRW_CNT 0x20
 #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
 #define NVRAM_BLOCK_LEN 16
@@ -71,7 +73,16 @@
 extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
 
 extern int pSeries_nvram_init(void);
+
+#ifdef CONFIG_MMIO_NVRAM
 extern int mmio_nvram_init(void);
+#else
+static inline int mmio_nvram_init(void)
+{
+	return -ENODEV;
+}
+#endif
+
 #endif /* __KERNEL__ */
 
 /* PowerMac specific nvram stuffs */
diff --git a/include/asm-powerpc/of_platform.h b/include/asm-powerpc/of_platform.h
index 80e6fad..1bce5ef 100644
--- a/include/asm-powerpc/of_platform.h
+++ b/include/asm-powerpc/of_platform.h
@@ -15,8 +15,14 @@
 #include <linux/of_platform.h>
 
 /* Platform drivers register/unregister */
-extern int of_register_platform_driver(struct of_platform_driver *drv);
-extern void of_unregister_platform_driver(struct of_platform_driver *drv);
+static inline int of_register_platform_driver(struct of_platform_driver *drv)
+{
+	return of_register_driver(drv, &of_platform_bus_type);
+}
+static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+	of_unregister_driver(drv);
+}
 
 /* Platform devices and busses creation */
 extern struct of_device *of_platform_device_create(struct device_node *np,
@@ -26,7 +32,7 @@
 #define OF_NO_DEEP_PROBE ((struct of_device_id *)-1)
 
 extern int of_platform_bus_probe(struct device_node *root,
-				 struct of_device_id *matches,
+				 const struct of_device_id *matches,
 				 struct device *parent);
 
 extern struct of_device *of_find_device_by_phandle(phandle ph);
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index d8bdc79..9b16d3b 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -1,15 +1,42 @@
 #ifndef _ASM_POWERPC_PCI_BRIDGE_H
 #define _ASM_POWERPC_PCI_BRIDGE_H
 #ifdef __KERNEL__
-
+/*
+ * 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.
+ */
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
 
-#ifndef CONFIG_PPC64
-
 struct device_node;
-struct pci_controller;
+
+extern unsigned int ppc_pci_flags;
+enum {
+	/* Force re-assigning all resources (ignore firmware
+	 * setup completely)
+	 */
+	PPC_PCI_REASSIGN_ALL_RSRC	= 0x00000001,
+
+	/* Re-assign all bus numbers */
+	PPC_PCI_REASSIGN_ALL_BUS	= 0x00000002,
+
+	/* Do not try to assign, just use existing setup */
+	PPC_PCI_PROBE_ONLY		= 0x00000004,
+
+	/* Don't bother with ISA alignment unless the bridge has
+	 * ISA forwarding enabled
+	 */
+	PPC_PCI_CAN_SKIP_ISA_ALIGN	= 0x00000008,
+
+	/* Enable domain numbers in /proc */
+	PPC_PCI_ENABLE_PROC_DOMAINS	= 0x00000010,
+	/* ... except for domain 0 */
+	PPC_PCI_COMPAT_DOMAIN_0		= 0x00000020,
+};
+
 
 /*
  * Structure of a PCI controller (host bridge)
@@ -17,26 +44,41 @@
 struct pci_controller {
 	struct pci_bus *bus;
 	char is_dynamic;
-	void *arch_data;
+#ifdef CONFIG_PPC64
+	int node;
+#endif
+	struct device_node *dn;
 	struct list_head list_node;
 	struct device *parent;
 
 	int first_busno;
 	int last_busno;
+#ifndef CONFIG_PPC64
 	int self_busno;
+#endif
 
 	void __iomem *io_base_virt;
+#ifdef CONFIG_PPC64
+	void *io_base_alloc;
+#endif
 	resource_size_t io_base_phys;
+#ifndef CONFIG_PPC64
+	resource_size_t pci_io_size;
+#endif
 
 	/* Some machines (PReP) have a non 1:1 mapping of
 	 * the PCI memory space in the CPU bus space
 	 */
 	resource_size_t pci_mem_offset;
+#ifdef CONFIG_PPC64
+	unsigned long pci_io_size;
+#endif
 
 	struct pci_ops *ops;
-	volatile unsigned int __iomem *cfg_addr;
-	volatile void __iomem *cfg_data;
+	unsigned int __iomem *cfg_addr;
+	void __iomem *cfg_data;
 
+#ifndef CONFIG_PPC64
 	/*
 	 * Used for variants of PCI indirect handling and possible quirks:
 	 *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
@@ -51,21 +93,30 @@
 	 *   set.
 	 *  BIG_ENDIAN - cfg_addr is a big endian register
 	 */
-#define PPC_INDIRECT_TYPE_SET_CFG_TYPE		(0x00000001)
-#define PPC_INDIRECT_TYPE_EXT_REG		(0x00000002)
-#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS	(0x00000004)
-#define PPC_INDIRECT_TYPE_NO_PCIE_LINK		(0x00000008)
-#define PPC_INDIRECT_TYPE_BIG_ENDIAN		(0x00000010)
+#define PPC_INDIRECT_TYPE_SET_CFG_TYPE		0x00000001
+#define PPC_INDIRECT_TYPE_EXT_REG		0x00000002
+#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS	0x00000004
+#define PPC_INDIRECT_TYPE_NO_PCIE_LINK		0x00000008
+#define PPC_INDIRECT_TYPE_BIG_ENDIAN		0x00000010
 	u32 indirect_type;
-
+#endif	/* !CONFIG_PPC64 */
 	/* Currently, we limit ourselves to 1 IO range and 3 mem
 	 * ranges since the common pci_bus structure can't handle more
 	 */
 	struct resource	io_resource;
 	struct resource mem_resources[3];
 	int global_number;		/* PCI domain number */
+#ifdef CONFIG_PPC64
+	unsigned long buid;
+	unsigned long dma_window_base_cur;
+	unsigned long dma_window_size;
+
+	void *private_data;
+#endif	/* CONFIG_PPC64 */
 };
 
+#ifndef CONFIG_PPC64
+
 static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
 {
 	return bus->sysdata;
@@ -81,18 +132,18 @@
 
 /* These are used for config access before all the PCI probing
    has been done. */
-int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
-			   int where, u8 *val);
-int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
-			   int where, u16 *val);
-int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
-			    int where, u32 *val);
-int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
-			    int where, u8 val);
-int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
-			    int where, u16 val);
-int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
-			     int where, u32 val);
+extern int early_read_config_byte(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u8 *val);
+extern int early_read_config_word(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u16 *val);
+extern int early_read_config_dword(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u32 *val);
+extern int early_write_config_byte(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u8 val);
+extern int early_write_config_word(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u16 val);
+extern int early_write_config_dword(struct pci_controller *hose, int bus,
+			int dev_fn, int where, u32 val);
 
 extern int early_find_capability(struct pci_controller *hose, int bus,
 				 int dev_fn, int cap);
@@ -104,62 +155,12 @@
 extern void __init update_bridge_resource(struct pci_dev *dev,
 					  struct resource *res);
 
-#else
-
-
-/*
- * 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.
- */
-
-/*
- * Structure of a PCI controller (host bridge)
- */
-struct pci_controller {
-	struct pci_bus *bus;
-	char is_dynamic;
-	int node;
-	void *arch_data;
-	struct list_head list_node;
-	struct device *parent;
-
-	int first_busno;
-	int last_busno;
-
-	void __iomem *io_base_virt;
-	void *io_base_alloc;
-	resource_size_t io_base_phys;
-
-	/* Some machines have a non 1:1 mapping of
-	 * the PCI memory space in the CPU bus space
-	 */
-	resource_size_t pci_mem_offset;
-	unsigned long pci_io_size;
-
-	struct pci_ops *ops;
-	volatile unsigned int __iomem *cfg_addr;
-	volatile void __iomem *cfg_data;
-
-	/* Currently, we limit ourselves to 1 IO range and 3 mem
-	 * ranges since the common pci_bus structure can't handle more
-	 */
-	struct resource io_resource;
-	struct resource mem_resources[3];
-	int global_number;
-	unsigned long buid;
-	unsigned long dma_window_base_cur;
-	unsigned long dma_window_size;
-
-	void *private_data;
-};
+#else	/* CONFIG_PPC64 */
 
 /*
  * PCI stuff, for nodes representing PCI devices, pointed to
  * by device_node->data.
  */
-struct pci_controller;
 struct iommu_table;
 
 struct pci_dn {
@@ -179,9 +180,9 @@
 	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
 	int	eeh_config_addr;
 	int	eeh_pe_config_addr; /* new-style partition endpoint address */
-	int 	eeh_check_count;	/* # times driver ignored error */
-	int 	eeh_freeze_count;	/* # times this device froze up. */
-	int 	eeh_false_positives;	/* # times this device reported #ff's */
+	int	eeh_check_count;	/* # times driver ignored error */
+	int	eeh_freeze_count;	/* # times this device froze up. */
+	int	eeh_false_positives;	/* # times this device reported #ff's */
 	u32	config_space[16];	/* saved PCI config space */
 #endif
 };
@@ -189,7 +190,7 @@
 /* Get the pointer to a device_node's pci_dn */
 #define PCI_DN(dn)	((struct pci_dn *) (dn)->data)
 
-struct device_node *fetch_dev_dn(struct pci_dev *dev);
+extern struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
 /* Get a device_node from a pci_dev.  This code must be fast except
  * in the case where the sysdata is incorrect and needs to be fixed
@@ -227,14 +228,14 @@
 }
 
 /** Find the bus corresponding to the indicated device node */
-struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
+extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
-void pcibios_remove_pci_devices(struct pci_bus *bus);
+extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
-void pcibios_add_pci_devices(struct pci_bus * bus);
-void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
+extern void pcibios_add_pci_devices(struct pci_bus *bus);
+extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
 
 extern int pcibios_remove_root_bus(struct pci_controller *phb);
 
@@ -270,20 +271,18 @@
 #define PHB_SET_NODE(PHB, NODE)		((PHB)->node = -1)
 #endif
 
-#endif /* CONFIG_PPC64 */
+#endif	/* CONFIG_PPC64 */
 
 /* Get the PCI host controller for an OF device */
-extern struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node* node);
+extern struct pci_controller *pci_find_hose_for_OF_device(
+			struct device_node* node);
 
 /* Fill up host controller resources from the OF node */
-extern void
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
-			   struct device_node *dev, int primary);
+extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			struct device_node *dev, int primary);
 
 /* Allocate & free a PCI host bridge structure */
-extern struct pci_controller *
-pcibios_alloc_controller(struct device_node *dev);
+extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
 
 #ifdef CONFIG_PCI
@@ -298,9 +297,7 @@
 {
 	return 0;
 }
-#endif
+#endif	/* CONFIG_PCI */
 
-
-
-#endif /* __KERNEL__ */
-#endif
+#endif	/* __KERNEL__ */
+#endif	/* _ASM_POWERPC_PCI_BRIDGE_H */
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index 7b11765..a05a942 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -36,11 +36,10 @@
 
 /*
  * Set this to 1 if you want the kernel to re-assign all PCI
- * bus numbers
+ * bus numbers (don't do that on ppc64 yet !)
  */
-extern int pci_assign_all_buses;
-#define pcibios_assign_all_busses()	(pci_assign_all_buses)
-
+#define pcibios_assign_all_busses()    	(ppc_pci_flags & \
+					 PPC_PCI_REASSIGN_ALL_BUS)
 #define pcibios_scan_all_fns(a, b)	0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
@@ -95,9 +94,6 @@
 #define get_pci_dma_ops()	NULL
 #endif
 
-/* Decide whether to display the domain number in /proc */
-extern int pci_proc_domain(struct pci_bus *bus);
-
 #else /* 32-bit */
 
 #ifdef CONFIG_PCI
@@ -109,17 +105,14 @@
 	*strategy_parameter = ~0UL;
 }
 #endif
-
-/* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
-	return 0;
-}
-
 #endif /* CONFIG_PPC64 */
 
 extern int pci_domain_nr(struct pci_bus *bus);
 
+/* Decide whether to display the domain number in /proc */
+extern int pci_proc_domain(struct pci_bus *bus);
+
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -199,13 +192,12 @@
 	return root;
 }
 
-extern void pcibios_fixup_device_resources(struct pci_dev *dev,
-			struct pci_bus *bus);
-
 extern void pcibios_setup_new_device(struct pci_dev *dev);
 
 extern void pcibios_claim_one_bus(struct pci_bus *b);
 
+extern void pcibios_resource_survey(void);
+
 extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
 
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
@@ -229,5 +221,8 @@
 				 const struct resource *rsrc,
 				 resource_size_t *start, resource_size_t *end);
 
+extern void pcibios_do_bus_setup(struct pci_bus *bus);
+extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
+
 #endif	/* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index b847aa1..854ab71 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -22,7 +22,6 @@
 
 
 extern struct list_head hose_list;
-extern int global_phb_number;
 
 extern void find_and_init_phbs(void);
 
@@ -47,9 +46,6 @@
 extern unsigned long get_phb_buid (struct device_node *);
 extern int rtas_setup_phb(struct pci_controller *phb);
 
-/* From iSeries PCI */
-extern void iSeries_pcibios_init(void);
-
 extern unsigned long pci_probe_only;
 
 /* ---- EEH internal-use-only related routines ---- */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 925e2d3..78b7b0d 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -202,6 +202,10 @@
  */
 extern u64 of_translate_address(struct device_node *np, const u32 *addr);
 
+/* Translate a DMA address from device space to CPU space */
+extern u64 of_translate_dma_address(struct device_node *dev,
+				    const u32 *in_addr);
+
 /* Extract an address from a device, returns the region size and
  * the address space flags too. The PCI version uses a BAR number
  * instead of an absolute index
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index 0dabe46..a24b7b1 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -28,6 +28,52 @@
 #define MEM_PART_SECONDARY	1
 #define MEM_PART_MURAM		2
 
+/* Clocks and BRGs */
+enum qe_clock {
+	QE_CLK_NONE = 0,
+	QE_BRG1,		/* Baud Rate Generator 1 */
+	QE_BRG2,		/* Baud Rate Generator 2 */
+	QE_BRG3,		/* Baud Rate Generator 3 */
+	QE_BRG4,		/* Baud Rate Generator 4 */
+	QE_BRG5,		/* Baud Rate Generator 5 */
+	QE_BRG6,		/* Baud Rate Generator 6 */
+	QE_BRG7,		/* Baud Rate Generator 7 */
+	QE_BRG8,		/* Baud Rate Generator 8 */
+	QE_BRG9,		/* Baud Rate Generator 9 */
+	QE_BRG10,		/* Baud Rate Generator 10 */
+	QE_BRG11,		/* Baud Rate Generator 11 */
+	QE_BRG12,		/* Baud Rate Generator 12 */
+	QE_BRG13,		/* Baud Rate Generator 13 */
+	QE_BRG14,		/* Baud Rate Generator 14 */
+	QE_BRG15,		/* Baud Rate Generator 15 */
+	QE_BRG16,		/* Baud Rate Generator 16 */
+	QE_CLK1,		/* Clock 1 */
+	QE_CLK2,		/* Clock 2 */
+	QE_CLK3,		/* Clock 3 */
+	QE_CLK4,		/* Clock 4 */
+	QE_CLK5,		/* Clock 5 */
+	QE_CLK6,		/* Clock 6 */
+	QE_CLK7,		/* Clock 7 */
+	QE_CLK8,		/* Clock 8 */
+	QE_CLK9,		/* Clock 9 */
+	QE_CLK10,		/* Clock 10 */
+	QE_CLK11,		/* Clock 11 */
+	QE_CLK12,		/* Clock 12 */
+	QE_CLK13,		/* Clock 13 */
+	QE_CLK14,		/* Clock 14 */
+	QE_CLK15,		/* Clock 15 */
+	QE_CLK16,		/* Clock 16 */
+	QE_CLK17,		/* Clock 17 */
+	QE_CLK18,		/* Clock 18 */
+	QE_CLK19,		/* Clock 19 */
+	QE_CLK20,		/* Clock 20 */
+	QE_CLK21,		/* Clock 21 */
+	QE_CLK22,		/* Clock 22 */
+	QE_CLK23,		/* Clock 23 */
+	QE_CLK24,		/* Clock 24 */
+	QE_CLK_DUMMY
+};
+
 /* Export QE common operations */
 extern void qe_reset(void);
 extern int par_io_init(struct device_node *np);
@@ -38,7 +84,8 @@
 
 /* QE internal API */
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
+enum qe_clock qe_clock_source(const char *source);
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
 unsigned long qe_muram_alloc(int size, int align);
@@ -129,52 +176,6 @@
 	COMM_DIR_RX_AND_TX = 3
 };
 
-/* Clocks and BRGs */
-enum qe_clock {
-	QE_CLK_NONE = 0,
-	QE_BRG1,		/* Baud Rate Generator 1 */
-	QE_BRG2,		/* Baud Rate Generator 2 */
-	QE_BRG3,		/* Baud Rate Generator 3 */
-	QE_BRG4,		/* Baud Rate Generator 4 */
-	QE_BRG5,		/* Baud Rate Generator 5 */
-	QE_BRG6,		/* Baud Rate Generator 6 */
-	QE_BRG7,		/* Baud Rate Generator 7 */
-	QE_BRG8,		/* Baud Rate Generator 8 */
-	QE_BRG9,		/* Baud Rate Generator 9 */
-	QE_BRG10,		/* Baud Rate Generator 10 */
-	QE_BRG11,		/* Baud Rate Generator 11 */
-	QE_BRG12,		/* Baud Rate Generator 12 */
-	QE_BRG13,		/* Baud Rate Generator 13 */
-	QE_BRG14,		/* Baud Rate Generator 14 */
-	QE_BRG15,		/* Baud Rate Generator 15 */
-	QE_BRG16,		/* Baud Rate Generator 16 */
-	QE_CLK1,		/* Clock 1 */
-	QE_CLK2,		/* Clock 2 */
-	QE_CLK3,		/* Clock 3 */
-	QE_CLK4,		/* Clock 4 */
-	QE_CLK5,		/* Clock 5 */
-	QE_CLK6,		/* Clock 6 */
-	QE_CLK7,		/* Clock 7 */
-	QE_CLK8,		/* Clock 8 */
-	QE_CLK9,		/* Clock 9 */
-	QE_CLK10,		/* Clock 10 */
-	QE_CLK11,		/* Clock 11 */
-	QE_CLK12,		/* Clock 12 */
-	QE_CLK13,		/* Clock 13 */
-	QE_CLK14,		/* Clock 14 */
-	QE_CLK15,		/* Clock 15 */
-	QE_CLK16,		/* Clock 16 */
-	QE_CLK17,		/* Clock 17 */
-	QE_CLK18,		/* Clock 18 */
-	QE_CLK19,		/* Clock 19 */
-	QE_CLK20,		/* Clock 20 */
-	QE_CLK21,		/* Clock 21 */
-	QE_CLK22,		/* Clock 22 */
-	QE_CLK23,		/* Clock 23 */
-	QE_CLK24,		/* Clock 24 */
-	QE_CLK_DUMMY,
-};
-
 /* QE CMXUCR Registers.
  * There are two UCCs represented in each of the four CMXUCR registers.
  * These values are for the UCC in the LSBs
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index e775ff1..1f68504 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -691,12 +691,6 @@
 #define PV_BE		0x0070
 #define PV_PA6T		0x0090
 
-/*
- * Number of entries in the SLB. If this ever changes we should handle
- * it with a use a cpu feature fixup.
- */
-#define SLB_NUM_ENTRIES 64
-
 /* Macros for setting and retrieving special purpose registers */
 #ifndef __ASSEMBLY__
 #define mfmsr()		({unsigned long rval; \
diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h
index 8fdc2b4..d3e8dd0 100644
--- a/include/asm-powerpc/reg_booke.h
+++ b/include/asm-powerpc/reg_booke.h
@@ -123,16 +123,23 @@
 #define SPRN_SPEFSCR	0x200	/* SPE & Embedded FP Status & Control */
 #define SPRN_BBEAR	0x201	/* Branch Buffer Entry Address Register */
 #define SPRN_BBTAR	0x202	/* Branch Buffer Target Address Register */
+#define SPRN_ATB	0x20E	/* Alternate Time Base */
+#define SPRN_ATBL	0x20E	/* Alternate Time Base Lower */
+#define SPRN_ATBU	0x20F	/* Alternate Time Base Upper */
 #define SPRN_IVOR32	0x210	/* Interrupt Vector Offset Register 32 */
 #define SPRN_IVOR33	0x211	/* Interrupt Vector Offset Register 33 */
 #define SPRN_IVOR34	0x212	/* Interrupt Vector Offset Register 34 */
 #define SPRN_IVOR35	0x213	/* Interrupt Vector Offset Register 35 */
+#define SPRN_IVOR36	0x214	/* Interrupt Vector Offset Register 36 */
+#define SPRN_IVOR37	0x215	/* Interrupt Vector Offset Register 37 */
 #define SPRN_MCSRR0	0x23A	/* Machine Check Save and Restore Register 0 */
 #define SPRN_MCSRR1	0x23B	/* Machine Check Save and Restore Register 1 */
 #define SPRN_MCSR	0x23C	/* Machine Check Status Register */
 #define SPRN_MCAR	0x23D	/* Machine Check Address Register */
 #define SPRN_DSRR0	0x23E	/* Debug Save and Restore Register 0 */
 #define SPRN_DSRR1	0x23F	/* Debug Save and Restore Register 1 */
+#define SPRN_SPRG8	0x25C	/* Special Purpose Register General 8 */
+#define SPRN_SPRG9	0x25D	/* Special Purpose Register General 9 */
 #define SPRN_MAS0	0x270	/* MMU Assist Register 0 */
 #define SPRN_MAS1	0x271	/* MMU Assist Register 1 */
 #define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
@@ -140,15 +147,18 @@
 #define SPRN_MAS4	0x274	/* MMU Assist Register 4 */
 #define SPRN_MAS5	0x275	/* MMU Assist Register 5 */
 #define SPRN_MAS6	0x276	/* MMU Assist Register 6 */
-#define SPRN_MAS7	0x3b0	/* MMU Assist Register 7 */
 #define SPRN_PID1	0x279	/* Process ID Register 1 */
 #define SPRN_PID2	0x27A	/* Process ID Register 2 */
 #define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
 #define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
+#define SPRN_EPR	0x2BE	/* External Proxy Register */
 #define SPRN_CCR1	0x378	/* Core Configuration Register 1 */
 #define SPRN_ZPR	0x3B0	/* Zone Protection Register (40x) */
+#define SPRN_MAS7	0x3B0	/* MMU Assist Register 7 */
 #define SPRN_MMUCR	0x3B2	/* MMU Control Register */
 #define SPRN_CCR0	0x3B3	/* Core Configuration Register 0 */
+#define SPRN_EPLC	0x3B3	/* External Process ID Load Context */
+#define SPRN_EPSC	0x3B4	/* External Process ID Store Context */
 #define SPRN_SGR	0x3B9	/* Storage Guarded Register */
 #define SPRN_DCWR	0x3BA	/* Data Cache Write-thru Register */
 #define SPRN_SLER	0x3BB	/* Little-endian real mode */
@@ -159,6 +169,7 @@
 #define SPRN_L1CSR0	0x3F2	/* L1 Cache Control and Status Register 0 */
 #define SPRN_L1CSR1	0x3F3	/* L1 Cache Control and Status Register 1 */
 #define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
+#define SPRN_BUCSR	0x3F5	/* Branch Unit Control and Status */
 #define SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
 #define SPRN_ICCR	0x3FB	/* Instruction Cache Cacheability Register */
 #define SPRN_SVR	0x3FF	/* System Version Register */
@@ -293,7 +304,7 @@
 #define ESR_IMCB	0x20000000	/* Instr. Machine Check - Bus error */
 #define ESR_IMCT	0x10000000	/* Instr. Machine Check - Timeout */
 #define ESR_PIL		0x08000000	/* Program Exception - Illegal */
-#define ESR_PPR		0x04000000	/* Program Exception - Priveleged */
+#define ESR_PPR		0x04000000	/* Program Exception - Privileged */
 #define ESR_PTR		0x02000000	/* Program Exception - Trap */
 #define ESR_FP		0x01000000	/* Floating Point Operation */
 #define ESR_DST		0x00800000	/* Storage Exception - Data miss */
diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h
index e49f644..7ae2753 100644
--- a/include/asm-powerpc/smu.h
+++ b/include/asm-powerpc/smu.h
@@ -22,7 +22,7 @@
  * Partition info commands
  *
  * These commands are used to retrieve the sdb-partition-XX datas from
- * the SMU. The lenght is always 2. First byte is the subcommand code
+ * the SMU. The length is always 2. First byte is the subcommand code
  * and second byte is the partition ID.
  *
  * The reply is 6 bytes:
@@ -173,12 +173,12 @@
  * Power supply control
  *
  * The "sub" command is an ASCII string in the data, the
- * data lenght is that of the string.
+ * data length is that of the string.
  *
  * The VSLEW command can be used to get or set the voltage slewing.
- *  - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
+ *  - length 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
  *    reply at data offset 6, 7 and 8.
- *  - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
+ *  - length 8 ("VSLEWxyz") has 3 additional bytes appended, and is
  *    used to set the voltage slewing point. The SMU replies with "DONE"
  * I yet have to figure out their exact meaning of those 3 bytes in
  * both cases. They seem to be:
@@ -201,20 +201,90 @@
  */
 #define SMU_CMD_READ_ADC			0xd8
 
+
 /* Misc commands
  *
  * This command seem to be a grab bag of various things
+ *
+ * Parameters:
+ *   1: subcommand
  */
 #define SMU_CMD_MISC_df_COMMAND			0xdf
-#define   SMU_CMD_MISC_df_SET_DISPLAY_LIT	0x02 /* i: 1 byte */
+
+/*
+ * Sets "system ready" status
+ *
+ * I did not yet understand how it exactly works or what it does.
+ *
+ * Guessing from OF code, 0x02 activates the display backlight. Apple uses/used
+ * the same codebase for all OF versions. On PowerBooks, this command would
+ * enable the backlight. For the G5s, it only activates the front LED. However,
+ * don't take this for granted.
+ *
+ * Parameters:
+ *   2: status [0x00, 0x01 or 0x02]
+ */
+#define   SMU_CMD_MISC_df_SET_DISPLAY_LIT	0x02
+
+/*
+ * Sets mode of power switch.
+ *
+ * What this actually does is not yet known. Maybe it enables some interrupt.
+ *
+ * Parameters:
+ *   2: enable power switch? [0x00 or 0x01]
+ *   3 (optional): enable nmi? [0x00 or 0x01]
+ *
+ * Returns:
+ *   If parameter 2 is 0x00 and parameter 3 is not specified, returns wether
+ *   NMI is enabled. Otherwise unknown.
+ */
 #define   SMU_CMD_MISC_df_NMI_OPTION		0x04
 
+/* Sets LED dimm offset.
+ *
+ * The front LED dimms itself during sleep. Its brightness (or, well, the PWM
+ * frequency) depends on current time. Therefore, the SMU needs to know the
+ * timezone.
+ *
+ * Parameters:
+ *   2-8: unknown (BCD coding)
+ */
+#define   SMU_CMD_MISC_df_DIMM_OFFSET		0x99
+
+
 /*
  * Version info commands
  *
- * I haven't quite tried to figure out how these work
+ * Parameters:
+ *   1 (optional): Specifies version part to retrieve
+ *
+ * Returns:
+ *   Version value
  */
 #define SMU_CMD_VERSION_COMMAND			0xea
+#define   SMU_VERSION_RUNNING			0x00
+#define   SMU_VERSION_BASE			0x01
+#define   SMU_VERSION_UPDATE			0x02
+
+
+/*
+ * Switches
+ *
+ * These are switches whose status seems to be known to the SMU.
+ *
+ * Parameters:
+ *   none
+ *
+ * Result:
+ *   Switch bits (ORed, see below)
+ */
+#define SMU_CMD_SWITCHES			0xdc
+
+/* Switches bits */
+#define SMU_SWITCH_CASE_CLOSED			0x01
+#define SMU_SWITCH_AC_POWER			0x04
+#define SMU_SWITCH_POWER_SWITCH			0x08
 
 
 /*
@@ -243,10 +313,64 @@
  */
 #define SMU_CMD_MISC_ee_COMMAND			0xee
 #define   SMU_CMD_MISC_ee_GET_DATABLOCK_REC	0x02
-#define	  SMU_CMD_MISC_ee_LEDS_CTRL		0x04 /* i: 00 (00,01) [00] */
+
+/* Retrieves currently used watts.
+ *
+ * Parameters:
+ *   1: 0x03 (Meaning unknown)
+ */
+#define   SMU_CMD_MISC_ee_GET_WATTS		0x03
+
+#define   SMU_CMD_MISC_ee_LEDS_CTRL		0x04 /* i: 00 (00,01) [00] */
 #define   SMU_CMD_MISC_ee_GET_DATA		0x05 /* i: 00 , o: ?? */
 
 
+/*
+ * Power related commands
+ *
+ * Parameters:
+ *   1: subcommand
+ */
+#define SMU_CMD_POWER_EVENTS_COMMAND		0x8f
+
+/* SMU_POWER_EVENTS subcommands */
+enum {
+	SMU_PWR_GET_POWERUP_EVENTS      = 0x00,
+	SMU_PWR_SET_POWERUP_EVENTS      = 0x01,
+	SMU_PWR_CLR_POWERUP_EVENTS      = 0x02,
+	SMU_PWR_GET_WAKEUP_EVENTS       = 0x03,
+	SMU_PWR_SET_WAKEUP_EVENTS       = 0x04,
+	SMU_PWR_CLR_WAKEUP_EVENTS       = 0x05,
+
+	/*
+	 * Get last shutdown cause
+	 *
+	 * Returns:
+	 *   1 byte (signed char): Last shutdown cause. Exact meaning unknown.
+	 */
+	SMU_PWR_LAST_SHUTDOWN_CAUSE	= 0x07,
+
+	/*
+	 * Sets or gets server ID. Meaning or use is unknown.
+	 *
+	 * Parameters:
+	 *   2 (optional): Set server ID (1 byte)
+	 *
+	 * Returns:
+	 *   1 byte (server ID?)
+	 */
+	SMU_PWR_SERVER_ID		= 0x08,
+};
+
+/* Power events wakeup bits */
+enum {
+	SMU_PWR_WAKEUP_KEY              = 0x01, /* Wake on key press */
+	SMU_PWR_WAKEUP_AC_INSERT        = 0x02, /* Wake on AC adapter plug */
+	SMU_PWR_WAKEUP_AC_CHANGE        = 0x04,
+	SMU_PWR_WAKEUP_LID_OPEN         = 0x08,
+	SMU_PWR_WAKEUP_RING             = 0x10,
+};
+
 
 /*
  * - Kernel side interface -
@@ -564,13 +688,13 @@
 
 	__u8		cmd;			/* SMU command byte */
 	__u8		pad[3];			/* padding */
-	__u32		data_len;		/* Lenght of data following */
+	__u32		data_len;		/* Length of data following */
 };
 
 struct smu_user_reply_hdr
 {
 	__u32		status;			/* Command status */
-	__u32		reply_len;		/* Lenght of data follwing */
+	__u32		reply_len;		/* Length of data follwing */
 };
 
 #endif /*  _SMU_H */
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index b1accce..5ca30e2e 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -104,6 +104,7 @@
 
 struct spu_context;
 struct spu_runqueue;
+struct spu_lscsa;
 struct device_node;
 
 enum spu_utilization_state {
@@ -145,7 +146,6 @@
 	void (* ibox_callback)(struct spu *spu);
 	void (* stop_callback)(struct spu *spu);
 	void (* mfc_callback)(struct spu *spu);
-	void (* dma_callback)(struct spu *spu, int type);
 
 	char irq_c0[8];
 	char irq_c1[8];
@@ -196,10 +196,11 @@
 extern struct cbe_spu_info cbe_spu_info[];
 
 void spu_init_channels(struct spu *spu);
-int spu_irq_class_0_bottom(struct spu *spu);
-int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size);
+
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);
 #else
@@ -210,6 +211,7 @@
 
 extern void spu_invalidate_slbs(struct spu *spu);
 extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm);
+int spu_64k_pages_available(void);
 
 /* Calls from the memory management to the SPU */
 struct mm_struct;
@@ -278,6 +280,8 @@
 int spu_add_sysdev_attr_group(struct attribute_group *attrs);
 void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
 
+int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+		unsigned long dsisr, unsigned *flt);
 
 /*
  * Notifier blocks:
@@ -299,7 +303,7 @@
 int spu_switch_event_unregister(struct notifier_block * n);
 
 /*
- * This defines the Local Store, Problem Area and Privlege Area of an SPU.
+ * This defines the Local Store, Problem Area and Privilege Area of an SPU.
  */
 
 union mfc_tag_size_class_cmd {
@@ -520,8 +524,24 @@
 #define CLASS2_ENABLE_SPU_STOP_INTR			0x2L
 #define CLASS2_ENABLE_SPU_HALT_INTR			0x4L
 #define CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR	0x8L
+#define CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR		0x10L
 	u8  pad_0x118_0x140[0x28];				/* 0x118 */
 	u64 int_stat_RW[3];					/* 0x140 */
+#define CLASS0_DMA_ALIGNMENT_INTR			0x1L
+#define CLASS0_INVALID_DMA_COMMAND_INTR			0x2L
+#define CLASS0_SPU_ERROR_INTR				0x4L
+#define CLASS0_INTR_MASK				0x7L
+#define CLASS1_SEGMENT_FAULT_INTR			0x1L
+#define CLASS1_STORAGE_FAULT_INTR			0x2L
+#define CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR		0x4L
+#define CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR		0x8L
+#define CLASS1_INTR_MASK				0xfL
+#define CLASS2_MAILBOX_INTR				0x1L
+#define CLASS2_SPU_STOP_INTR				0x2L
+#define CLASS2_SPU_HALT_INTR				0x4L
+#define CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR		0x8L
+#define CLASS2_MAILBOX_THRESHOLD_INTR			0x10L
+#define CLASS2_INTR_MASK				0x1fL
 	u8  pad_0x158_0x180[0x28];				/* 0x158 */
 	u64 int_route_RW;					/* 0x180 */
 
diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h
index e87794d..0ab6bff 100644
--- a/include/asm-powerpc/spu_csa.h
+++ b/include/asm-powerpc/spu_csa.h
@@ -194,7 +194,7 @@
 };
 
 /*
- * struct spu_priv2_collapsed - condensed priviliged 2 area, w/o pads.
+ * struct spu_priv2_collapsed - condensed privileged 2 area, w/o pads.
  */
 struct spu_priv2_collapsed {
 	u64 slb_index_W;
@@ -254,20 +254,11 @@
 	u64 spu_chnldata_RW[32];
 	u32 spu_mailbox_data[4];
 	u32 pu_mailbox_data[1];
-	u64 dar, dsisr;
+	u64 dar, dsisr, class_0_pending;
 	unsigned long suspend_time;
 	spinlock_t register_lock;
 };
 
-extern int spu_init_csa(struct spu_state *csa);
-extern void spu_fini_csa(struct spu_state *csa);
-extern int spu_save(struct spu_state *prev, struct spu *spu);
-extern int spu_restore(struct spu_state *new, struct spu *spu);
-extern int spu_switch(struct spu_state *prev, struct spu_state *new,
-		      struct spu *spu);
-extern int spu_alloc_lscsa(struct spu_state *csa);
-extern void spu_free_lscsa(struct spu_state *csa);
-
 #endif /* !__SPU__ */
 #endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h
index 0f37c7c..25020a3 100644
--- a/include/asm-powerpc/spu_priv1.h
+++ b/include/asm-powerpc/spu_priv1.h
@@ -24,6 +24,7 @@
 #include <linux/types.h>
 
 struct spu;
+struct spu_context;
 
 /* access to priv1 registers */
 
@@ -178,6 +179,8 @@
 	int (*enumerate_spus)(int (*fn)(void *data));
 	int (*create_spu)(struct spu *spu, void *data);
 	int (*destroy_spu)(struct spu *spu);
+	void (*enable_spu)(struct spu_context *ctx);
+	void (*disable_spu)(struct spu_context *ctx);
 	int (*init_affinity)(void);
 };
 
@@ -207,6 +210,18 @@
 	return spu_management_ops->init_affinity();
 }
 
+static inline void
+spu_enable_spu (struct spu_context *ctx)
+{
+	spu_management_ops->enable_spu(ctx);
+}
+
+static inline void
+spu_disable_spu (struct spu_context *ctx)
+{
+	spu_management_ops->disable_spu(ctx);
+}
+
 /*
  * The declarations folowing are put here for convenience
  * and only intended to be used by the platform setup code.
diff --git a/include/asm-ppc/8xx_immap.h b/include/asm-ppc/8xx_immap.h
index 1311cef..4b0e152 100644
--- a/include/asm-ppc/8xx_immap.h
+++ b/include/asm-ppc/8xx_immap.h
@@ -123,7 +123,7 @@
 #define OR_G5LA		0x00000400	/* Output #GPL5 on #GPL_A5		*/
 #define OR_G5LS		0x00000200	/* Drive #GPL high on falling edge of...*/
 #define OR_BI		0x00000100	/* Burst inhibit			*/
-#define OR_SCY_MSK	0x000000f0	/* Cycle Lenght in Clocks		*/
+#define OR_SCY_MSK	0x000000f0	/* Cycle Length in Clocks		*/
 #define OR_SCY_0_CLK	0x00000000	/* 0 clock cycles wait states		*/
 #define OR_SCY_1_CLK	0x00000010	/* 1 clock cycles wait states		*/
 #define OR_SCY_2_CLK	0x00000020	/* 2 clock cycles wait states		*/
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 3972487..462abb1 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -681,7 +681,7 @@
 #define	CICR_SCC_SCC3		((uint)0x00200000)	/* SCC3 @ SCCc */
 #define	CICR_SCB_SCC2		((uint)0x00040000)	/* SCC2 @ SCCb */
 #define	CICR_SCA_SCC1		((uint)0x00000000)	/* SCC1 @ SCCa */
-#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrrupt */
+#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrupt */
 #define CICR_HP_MASK		((uint)0x00001f00)	/* Hi-pri int. */
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 82948ed..4cad45a 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -283,7 +283,7 @@
 #define ESR_IMCB	0x20000000	/* Instr. Machine Check - Bus error */
 #define ESR_IMCT	0x10000000	/* Instr. Machine Check - Timeout */
 #define ESR_PIL		0x08000000	/* Program Exception - Illegal */
-#define ESR_PPR		0x04000000	/* Program Exception - Priveleged */
+#define ESR_PPR		0x04000000	/* Program Exception - Privileged */
 #define ESR_PTR		0x02000000	/* Program Exception - Trap */
 #define ESR_FP		0x01000000	/* Floating Point Operation */
 #define ESR_DST		0x00800000	/* Storage Exception - Data miss */
diff --git a/include/linux/of.h b/include/linux/of.h
index 5c39b92..c65af7b 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -46,6 +46,10 @@
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
 					     struct device_node *prev);
+#define for_each_child_of_node(parent, child) \
+	for (child = of_get_next_child(parent, NULL); child != NULL; \
+	     child = of_get_next_child(parent, child))
+
 extern struct property *of_find_property(const struct device_node *np,
 					 const char *name,
 					 int *lenp);
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index b7824c2..4c5f653 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -159,41 +159,7 @@
 extern int pmu_present(void);
 extern int pmu_get_model(void);
 
-#ifdef CONFIG_PM
-/*
- * Stuff for putting the powerbook to sleep and waking it again.
- *
- */
-#include <linux/list.h>
-
-struct pmu_sleep_notifier
-{
-	void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
-	int priority;
-	struct list_head list;
-};
-
-/* Code values for calling sleep/wakeup handlers
- */
-#define PBOOK_SLEEP_REQUEST	1
-#define PBOOK_SLEEP_NOW		2
-#define PBOOK_WAKE		3
-
-/* priority levels in notifiers */
-#define SLEEP_LEVEL_VIDEO	100	/* Video driver (first wake) */
-#define SLEEP_LEVEL_MEDIABAY	90	/* Media bay driver */
-#define SLEEP_LEVEL_BLOCK	80	/* IDE, SCSI */
-#define SLEEP_LEVEL_NET		70	/* bmac, gmac */
-#define SLEEP_LEVEL_MISC	60	/* Anything else */
-#define SLEEP_LEVEL_USERLAND	55	/* Reserved for apm_emu */
-#define SLEEP_LEVEL_ADB		50	/* ADB (async) */
-#define SLEEP_LEVEL_SOUND	40	/* Sound driver (blocking) */
-
-/* special register notifier functions */
-int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier);
-int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier);
-
-#endif /* CONFIG_PM */
+extern void pmu_backlight_set_sleep(int sleep);
 
 #define PMU_MAX_BATTERIES	2