]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'linux-2.6' into for-2.6.25
authorPaul Mackerras <paulus@samba.org>
Tue, 11 Dec 2007 04:30:27 +0000 (15:30 +1100)
committerPaul Mackerras <paulus@samba.org>
Tue, 11 Dec 2007 04:30:27 +0000 (15:30 +1100)
111 files changed:
Documentation/powerpc/booting-without-of.txt
arch/powerpc/Makefile
arch/powerpc/boot/Makefile
arch/powerpc/boot/bamboo.c
arch/powerpc/boot/cuboot-52xx.c
arch/powerpc/boot/cuboot-83xx.c
arch/powerpc/boot/cuboot-85xx.c
arch/powerpc/boot/cuboot-8xx.c
arch/powerpc/boot/cuboot-hpc2.c
arch/powerpc/boot/cuboot-pq2.c
arch/powerpc/boot/cuboot-sequoia.c
arch/powerpc/boot/ebony.c
arch/powerpc/boot/ep88xc.c
arch/powerpc/boot/flatdevtree.c [deleted file]
arch/powerpc/boot/flatdevtree.h [deleted file]
arch/powerpc/boot/flatdevtree_misc.c [deleted file]
arch/powerpc/boot/holly.c
arch/powerpc/boot/libfdt-wrapper.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/Makefile.libfdt [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt.h [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt_ro.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt_rw.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt_strerror.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt_sw.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/fdt_wip.c [new file with mode: 0644]
arch/powerpc/boot/libfdt/libfdt.h [new file with mode: 0644]
arch/powerpc/boot/libfdt/libfdt_internal.h [new file with mode: 0644]
arch/powerpc/boot/libfdt_env.h [new file with mode: 0644]
arch/powerpc/boot/main.c
arch/powerpc/boot/ops.h
arch/powerpc/boot/prpmc2800.c
arch/powerpc/boot/ps3.c
arch/powerpc/boot/treeboot-walnut.c
arch/powerpc/boot/wrapper
arch/powerpc/configs/celleb_defconfig
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/isa-bridge.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/slb.c
arch/powerpc/mm/slb_low.S
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/cell/io-workarounds.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/celleb/Kconfig
arch/powerpc/platforms/celleb/io-workarounds.c
arch/powerpc/platforms/celleb/iommu.c
arch/powerpc/platforms/celleb/pci.c
arch/powerpc/platforms/celleb/scc_epci.c
arch/powerpc/platforms/celleb/setup.c
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/iseries/Makefile
arch/powerpc/platforms/iseries/pci.c
arch/powerpc/platforms/iseries/pci.h
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/platforms/iseries/setup.h
arch/powerpc/platforms/iseries/vpdinfo.c [deleted file]
arch/powerpc/platforms/maple/pci.c
arch/powerpc/platforms/pasemi/Kconfig
arch/powerpc/platforms/pasemi/cpufreq.c
arch/powerpc/platforms/pasemi/gpio_mdio.c
arch/powerpc/platforms/pasemi/pasemi.h
arch/powerpc/platforms/pasemi/powersave.S
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/time.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/plpar_wrappers.h
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/axonram.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/pmi.c
arch/powerpc/xmon/xmon.c
arch/ppc/platforms/ev64260.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/pasemi-rng.c
drivers/edac/pasemi_edac.c
drivers/macintosh/via-pmu.c
include/asm-powerpc/cputhreads.h [new file with mode: 0644]
include/asm-powerpc/firmware.h
include/asm-powerpc/iommu.h
include/asm-powerpc/mmu-hash64.h
include/asm-powerpc/of_platform.h
include/asm-powerpc/pci-bridge.h
include/asm-powerpc/ppc-pci.h
include/asm-powerpc/reg.h
include/asm-powerpc/smu.h
include/linux/of.h

index e9a3cb1d6b06b18a3e0bba0d5a0bf85dc3fde77f..7327f37d78f3a57fbe4404508960b4def68fbe84 100644 (file)
@@ -711,13 +711,14 @@ define a bus type with a more complex address format, including things
 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 @@ fit in a single 32-bit word.   New 32-bit powerpc boards should use a
 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
 -------------------------------------
index bd87626c1f6041664ed777fcd4349116bb32ea32..f70df9b64f8f601c420e857d0fba4a4f9b85276d 100644 (file)
@@ -167,6 +167,9 @@ boot := arch/$(ARCH)/boot
 $(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'
index 18e32719d0ed4544202bae47cc9c1361e6116649..af01b4f8ade08a6629ca2f53ca7ae6759f6d756d 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(call cc-option-yn, -fstack-protector),y)
 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 @@ zliblinuxheader := zlib.h zconf.h zutil.h
 $(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,8 +103,10 @@ quiet_cmd_bootar = BOOTAR  $@
       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
@@ -243,3 +247,51 @@ clean-kernel := vmlinux.strip vmlinux.bin
 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)
+
index f61fcdab1c7c59bf0f649f1e0e434a06431b6612..e634359d98e9375ce66570f2d7b2c4daff2be2fc 100644 (file)
@@ -42,6 +42,6 @@ void bamboo_init(void *mac0, void *mac1)
        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();
 }
index 9256a26d40e4c8f1033d72f976bd961f619e77ea..a8611546a656338820ffb2d83448c03954f331cb 100644 (file)
@@ -53,7 +53,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    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;
 }
index a0505509abcc40ed3eff8121e8a8b56f4e40bdf0..acd860ed7393222fbcbbe469d5ce39ec55d55140 100644 (file)
@@ -52,7 +52,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    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;
 }
index 345dcbecef0fc81d14a41e1d14bf85bec2410afb..943779ed19be08f3988559ad305fe4125f3b3f26 100644 (file)
@@ -53,7 +53,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    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;
 }
index 0e82015a5f95d42add314aa7e5c6fb3cbaa0b0aa..c202c8868bd6df3b3ad5e448e0d983dc0036098f 100644 (file)
@@ -41,7 +41,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    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;
 }
index d333898bca308fa41985537f1491a99f1b296edc..1b8953259d75d39ad6d464c47f977c05bb47b293 100644 (file)
@@ -42,7 +42,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                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;
 }
index 61574f3272ddb9f8429f30b6c533e91e5c408de0..f56ac6cae9f3b291c1744a21958dc27d2e487a28 100644 (file)
@@ -255,7 +255,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                    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;
 }
index ec635e0bd4ec240630a585421aa04759a92f8d74..cf78260fcf3f584e50787bb03d4423926691c58e 100644 (file)
@@ -51,6 +51,6 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
        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();
 }
index 86c0f5df0a86358925d3d0b8c19b91c79a3fa5e5..ee31be5e633e108a4d0d20e207d340ddcee84214 100644 (file)
@@ -146,6 +146,6 @@ void ebony_init(void *mac0, void *mac1)
        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();
 }
index 6b87cdce3fe7312cc6d3e45ac55d4136e23a66c1..a400f540715541ba550a973febe007e9e0a57712 100644 (file)
@@ -45,7 +45,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
        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 (file)
index cf30675..0000000
+++ /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 (file)
index b0957a2..0000000
+++ /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 (file)
index b367009..0000000
+++ /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);
-}
index 199e783aea4d3c3fa4a71ef995203f86174a88ed..58013b923178e38b8675121c1f48c34395d73a95 100644 (file)
@@ -28,6 +28,6 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
        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 (file)
index 0000000..002da16
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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(devp)      (((int)(devp))-1)
+
+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)
+{
+       return offset_devp(fdt_node_offset_by_prop_value(fdt, devp_offset(prev),
+                                                        name, val, len));
+}
+
+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 (file)
index 0000000..82f9c6a
--- /dev/null
@@ -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 (file)
index 0000000..586a361
--- /dev/null
@@ -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 (file)
index 0000000..48ccfd9
--- /dev/null
@@ -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 (file)
index 0000000..12a37d5
--- /dev/null
@@ -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 (file)
index 0000000..6673f8e
--- /dev/null
@@ -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 (file)
index 0000000..f9d32ef
--- /dev/null
@@ -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 (file)
index 0000000..dda2de3
--- /dev/null
@@ -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 (file)
index 0000000..88e24b8
--- /dev/null
@@ -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 (file)
index 0000000..6b2fb92
--- /dev/null
@@ -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 (file)
index 0000000..1e60936
--- /dev/null
@@ -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 (file)
index 0000000..a4b0fc9
--- /dev/null
@@ -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 */
index 1b496b37eca0b8efc1230e20f02ea2344d530b28..9e7f3ddd99131523c275f468ea26cc3f974a2e83 100644 (file)
@@ -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;
index a180b6505f477c8e1422be0ba64eadeeed1d5ff5..6036a98e646afa1aca3ff90db53396d84e158fe0 100644 (file)
@@ -79,7 +79,7 @@ struct loader_info {
 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);
index 9614e1db9daec7fca76586d8fd252ce556bd86ed..05c3245b30d7472aa9e995b4919e06f3b75aabe0 100644 (file)
@@ -547,8 +547,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
        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();
 
index d6661151b49426b86256e6d932b051f0129a27a1..3b0ac4d006ec857385e04e873487577b549ac6e5 100644 (file)
@@ -131,7 +131,7 @@ void platform_init(void)
        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");
 
index bb2c309d70fcdafaf7b32c1495afe67daf6c7ea7..70ffce343c0a651e1f339e5e3c7548bed078e444 100644 (file)
@@ -128,6 +128,6 @@ void platform_init(void)
        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();
 }
index 31147a0377283e179b473aa4fa4c9f720ce8ed48..a591ced478758f00b38cf4f7d0ee24f6cc931ab7 100755 (executable)
@@ -45,6 +45,7 @@ CROSS=
 
 # 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 @@ while [ "$#" -gt 0 ]; do
        shift
        [ "$#" -gt 0 ] || usage
        object="$1"
+       objbin="$1"
        ;;
     -W)
        shift
@@ -116,6 +118,9 @@ while [ "$#" -gt 0 ]; do
 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
@@ -246,11 +251,11 @@ fi
 # 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 @@ cuboot*)
     ;;
 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 @@ ps3)
     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 @@ ps3)
         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
index 421e08ee857a5c98bc84d96357fd352c74f18886..9ed2e098f96ff8b757a550e3225fdbca366b634e 100644 (file)
@@ -50,7 +50,8 @@ CONFIG_AUDIT_ARCH=y
 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_MULTIPLATFORM=y
 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_PPC_CELL=y
 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_MII=y
 # 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_SERIAL_TXX9_CONSOLE=y
 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 @@ CONFIG_WATCHDOG=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_WATCHDOG_RTAS is not set
 
 #
 # PCI-based Watchdog Cards
@@ -1245,17 +1255,7 @@ CONFIG_XMON_DISASSEMBLY=y
 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
index 2d0c9ef555e9e4578d9df93ff91e025697069c4e..47c3fe55242faa388703bb4ac7a59e7884ba4e04 100644 (file)
@@ -526,16 +526,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        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 @@ void iommu_free_table(struct device_node *dn)
        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;
                }
        }
index f0f49d1be3d5e156d8327b3783cf69541e77335a..ee172aa42aa7713abba98220903b826ab5d8cadf 100644 (file)
@@ -108,7 +108,7 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
        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 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
        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 @@ void __init isa_bridge_find_early(struct pci_controller *hose)
        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;
                        }
index ff781b2eddece571238831c081deee383d3092b2..dcb89a88df46d75102c2aaa23bc6641aa34a041c 100644 (file)
@@ -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 @@ int __init lparcfg_init(void)
        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 @@ int __init lparcfg_init(void)
 
 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);
index 330c9dc7db8615f517863a5de438ad1623abe566..74ce0c7a7b1e7f481828f451ef478719d611c0b8 100644 (file)
@@ -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 @@ _GLOBAL(add_reloc_offset)
        add     r3,r3,r5
        mtlr    r0
        blr
+
+_GLOBAL(kernel_execve)
+       li      r0,__NR_execve
+       sc
+       bnslr
+       neg     r3,r3
+       blr
index 8b642ab26d3767c23205125b1022dcad45964efd..ea1137851a4adc4a6ae7adfcba8aa74ed303340c 100644 (file)
@@ -793,13 +793,6 @@ _GLOBAL(kernel_thread)
        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...
  */
index bbb3ba54c51c7b331c7ce2469361b4991a02cd1e..a3c491e88a72853a34b56121d31818002aeee882 100644 (file)
@@ -518,13 +518,6 @@ _GLOBAL(giveup_altivec)
 
 #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
index aeaa20268ce2deef9b93d137b5d8148f334327f3..79c04d151ddbf52631199d0aa0baa328afed1d73 100644 (file)
@@ -64,26 +64,6 @@ static int __init of_bus_driver_init(void)
 
 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)
index 2ae3b6f778a3c4e5cff5922c10c96a705d44c2de..2f3f30efffed67e266663337e165f3d3e111dfc6 100644 (file)
 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;
 
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-       memset(hose, 0, sizeof(struct pci_controller));
-
-       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 +115,10 @@ int pcibios_vaddr_is_ioport(void __iomem *address)
  */
 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 +137,7 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
        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;
        }
index 0e2bee46304c51fc109d0e2b899a6ce6a559f841..096c97e03aa655d1e723cc579da9252929e7cad6 100644 (file)
@@ -662,8 +662,8 @@ pcibios_make_OF_bus_map(void)
 
        /* 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 +742,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus)
                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 +812,9 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
                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);
index 9f63bdcb0bdf88f0cdabe6de30b8276070ecebaf..6b9a8564e73513d14ec41c8c6dd8d5e7ef653155 100644 (file)
@@ -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>
@@ -197,9 +196,6 @@ 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);
 }
@@ -462,7 +458,7 @@ EXPORT_SYMBOL(of_scan_pci_bridge);
 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;
 
@@ -477,8 +473,7 @@ void __devinit scan_phb(struct pci_controller *hose)
        bus->secondary = hose->first_busno;
        hose->bus = bus;
 
-       if (!firmware_has_feature(FW_FEATURE_ISERIES))
-               pcibios_map_io_space(bus);
+       pcibios_map_io_space(bus);
 
        bus->resource[0] = res = &hose->io_resource;
        if (res->flags && request_resource(&ioport_resource, res)) {
@@ -519,9 +514,6 @@ static int __init pcibios_init(void)
         */
        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");
 
        /* Scan all of the recorded PCI controllers.  */
@@ -530,15 +522,13 @@ static int __init pcibios_init(void)
                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();
-       }
+       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)
@@ -584,12 +574,8 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 /* 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;
-       }
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       return hose->buid != 0;
 }
 
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
@@ -719,8 +705,7 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
        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 +764,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
        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",
index b4839038613d2232c8a2c7cc2ba9a56c95795969..85d4d8924b5ca1628cde9eee99088f53b5885098 100644 (file)
@@ -133,7 +133,7 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
  */
 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 */
index acc0d247d3c3a83920c92cb11f33639a86e8da1b..6c2d8836f77dcf9b87c80db13b738449ca1bcdeb 100644 (file)
@@ -583,6 +583,20 @@ static void __init check_cpu_pa_features(unsigned long node)
                      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 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 
        check_cpu_feature_properties(node);
        check_cpu_pa_features(node);
+       check_cpu_slb_size(node);
 
 #ifdef CONFIG_PPC_PSERIES
        if (nthreads > 1)
index b5c96af955c639ce43ea1532423bebebf0a6b177..6bdfaf3f99eaa0151d80ccee0e8704e0f5e1f8c5 100644 (file)
@@ -273,7 +273,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 #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)
index 21f14e57d1f3d848d9d7d375abf96c2a83ae1b27..3650eb50c27d2c910fd072e875244bc43ef83469 100644 (file)
@@ -260,7 +260,7 @@ static int phb_set_bus_ranges(struct device_node *dev,
 
 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);
index 2de00f870edc34438352ae71ed54c7013228b7fa..6adb5a1e98bb8f2a46eac766b03288ac8e4b1f7e 100644 (file)
@@ -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 @@ void __init check_for_initrd(void)
 
 #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 @@ void __init smp_setup_cpu_maps(void)
 {
        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 @@ void __init smp_setup_cpu_maps(void)
                }
        }
 
+       /* 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 @@ void __init smp_setup_cpu_maps(void)
 
                /* 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 @@ void __init smp_setup_cpu_maps(void)
        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_maps(void)
  */
 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 */
index 8135da06e0a44e4e320e7157e3b9fec364e67793..10dda224a3611128913cca2357affd92ca7ff48a 100644 (file)
@@ -189,7 +189,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
                        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);
index f09730bf3a335bc20de567bd5e596b727317faca..cbbd8b0bc8f4070d37243491be3e3a0025be88d6 100644 (file)
@@ -96,6 +96,7 @@ int mmu_vmalloc_psize = MMU_PAGE_4K;
 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;
index 27922dff8b94e34614890f7764ce10c014b6fb65..3cf0802cd2b6b23078dc3d12aeb254480a563771 100644 (file)
@@ -256,6 +256,7 @@ void slb_initialize(void)
        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 @@ void slb_initialize(void)
                                   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);
index 1328a81a84aa16d46bb11cb9ba207a6848354f07..657f6b37e9df58892fe4ece4a2a02eef51fe7d44 100644 (file)
@@ -227,8 +227,9 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 
 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
index a497cbaa1ac5ad7ba76db0d2a0890fe47b2171d9..11d1db8bb09154b3742226aef0d3b4094d6f11df 100644 (file)
@@ -59,7 +59,7 @@ static void __init pq2_pci_add_bridge(struct device_node *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);
index 59c121a97ac7c60a0069e4b0dc91ee46c245814f..bdb3d0b38cd2789b1cde4d63f7ffcad2a9af6336 100644 (file)
@@ -123,7 +123,7 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
        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) {
index 6390895e5e9258ae03c07512180c1a94f3dc3224..c6d2f48f8f3d2ef44f1bf1c95e2014074ba58cad 100644 (file)
@@ -124,7 +124,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev)
 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];
index 32a531aebcb78458ca1998387c29ad9441337213..14f4e527e7ac0245224819e578ae73506a6ad530 100644 (file)
@@ -116,7 +116,7 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
        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) {
index d35eda80e9e62376ae882636cf0159ec19bce8a1..ba645c2b63f62f61677eecb85a9abacbcf79b329 100644 (file)
@@ -120,7 +120,7 @@ void __init mpc8xx_calibrate_decr(void)
        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);
index 9d7c2ef940a818fff1406e7b6523174499451da9..b86076e3c09e402a6e74b880a8d23a8160143b33 100644 (file)
@@ -238,7 +238,7 @@ static void __init spider_pci_setup_chip(struct spider_pci_bus *bus)
 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 @@ static int __init spider_pci_workaround_init(void)
         * 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 */
index faabc3fdc130220ff7aeb8bd3ddc139e20157654..b465494cc24c2f6eb428f85892db6931538b5a6d 100644 (file)
@@ -34,6 +34,7 @@
 #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 @@ static int __init cell_iommu_init(void)
 {
        struct device_node *np;
 
-       if (!machine_is(cell))
+       if ((!machine_is(cell) && !machine_is(celleb)) ||
+           firmware_has_feature(FW_FEATURE_LPAR))
                return -ENODEV;
 
        /* If IOMMU is disabled or we have little enough RAM to not need
index 98e7ef8e6fc66a5becd6c3cd18a676bd6ef96fdb..6a56b6474f523820b135d7f2293ab8e71e983fc3 100644 (file)
@@ -179,7 +179,9 @@ static void __init cell_setup_arch(void)
        conswitchp = &dummy_con;
 #endif
 
+#ifdef CONFIG_MMIO_NVRAM
        mmio_nvram_init();
+#endif
 }
 
 static int __init cell_probe(void)
index e4438456c8675c8917052ba9e95cdd8a9e828809..efb3964457b1db4451c1c75d97dbf03e2c40ca0b 100644 (file)
@@ -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 @@ static int smp_cell_cpu_bootable(unsigned int nr)
         */
        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;
index 04748d410fc99c782f8fc0a33a8024c1b82b2196..372891edcdd2dda7779935ed4bd4d96d2e84b0d2 100644 (file)
@@ -2,6 +2,8 @@ config PPC_CELLEB
        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
index 2b912140bcbb6feee382aead23826adfcde27d5b..b939c0e98af8eaf018acb3afce1621f32a87172d 100644 (file)
@@ -222,7 +222,7 @@ void __init celleb_pci_add_one(struct pci_controller *phb,
                               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 @@ int __init celleb_pci_workaround_init(void)
 
        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) {
index 755d869d8553c424b978c21a6da7978f438dd03b..287450a07c41c21c0588c297c9c9c0b803fd7e66 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/pci.h>
 
 #include <asm/of_platform.h>
+#include <asm/firmware.h>
 
 #include "beat_wrapper.h"
 
@@ -91,7 +92,7 @@ static struct notifier_block celleb_of_bus_notifier = {
 
 static int __init celleb_init_iommu(void)
 {
-       if (!machine_is(celleb))
+       if (!firmware_has_feature(FW_FEATURE_BEAT))
                return -ENODEV;
 
        celleb_init_direct_mapping();
index 6bc32fda7a6b3e51716b2d01f40b29aaf19ad695..5d399e038c2326954002f956e89199d97f333f10 100644 (file)
@@ -138,8 +138,6 @@ static void celleb_config_read_fake(unsigned char *config, int where,
                *val = celleb_fake_config_readl(p);
                break;
        }
-
-       return;
 }
 
 static void celleb_config_write_fake(unsigned char *config, int where,
@@ -158,7 +156,6 @@ static void celleb_config_write_fake(unsigned char *config, int where,
                celleb_fake_config_writel(val, p);
                break;
        }
-       return;
 }
 
 static int celleb_fake_pci_read_config(struct pci_bus *bus,
@@ -351,6 +348,10 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
        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 @@ static int __init celleb_setup_fake_pci_device(struct device_node *node,
        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 @@ static struct of_device_id celleb_phb_match[] __initdata = {
 
 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 *);
 
index 9d076426676c696874375f8474f11f9a502f6819..a3c7cfbcb323049da70590529d8e20dea251fda5 100644 (file)
@@ -95,7 +95,7 @@ void __init epci_workaround_init(struct pci_controller *hose)
        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;
        }
index ddfb35ae741ff2abbdea105a79a2609623f67d07..5a3f73478f4b9489859ce045f52a34a1752c6bf9 100644 (file)
 #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,16 +93,74 @@ static void celleb_progress(char *s, unsigned short hex)
        printk("*** %04x : %s\n", hex, s ? s : "");
 }
 
-static void __init celleb_setup_arch(void)
+static void __init celleb_init_IRQ_native(void)
+{
+       iic_init_IRQ();
+       spider_init_IRQ();
+}
+
+static void __init celleb_setup_arch_beat(void)
 {
+       ppc_md.restart          = beat_restart;
+       ppc_md.power_off        = beat_power_off;
+       ppc_md.halt             = beat_halt;
+       ppc_md.get_rtc_time     = beat_get_rtc_time;
+       ppc_md.set_rtc_time     = beat_set_rtc_time;
+       ppc_md.power_save       = beat_power_save;
+       ppc_md.nvram_size       = beat_nvram_get_size;
+       ppc_md.nvram_read       = beat_nvram_read;
+       ppc_md.nvram_write      = beat_nvram_write;
+       ppc_md.set_dabr         = beat_set_xdabr;
+       ppc_md.init_IRQ         = beatic_init_IRQ;
+       ppc_md.get_irq          = beatic_get_irq;
+#ifdef CONFIG_KEXEC
+       ppc_md.kexec_cpu_down   = beat_kexec_cpu_down;
+#endif
+
 #ifdef CONFIG_SPU_BASE
-       spu_priv1_ops = &spu_priv1_beat_ops;
-       spu_management_ops = &spu_management_of_ops;
+       spu_priv1_ops           = &spu_priv1_beat_ops;
+       spu_management_ops      = &spu_management_of_ops;
 #endif
 
 #ifdef CONFIG_SMP
        smp_init_celleb();
 #endif
+}
+
+static void __init celleb_setup_arch_native(void)
+{
+       ppc_md.restart          = rtas_restart;
+       ppc_md.power_off        = rtas_power_off;
+       ppc_md.halt             = rtas_halt;
+       ppc_md.get_boot_time    = rtas_get_boot_time;
+       ppc_md.get_rtc_time     = rtas_get_rtc_time;
+       ppc_md.set_rtc_time     = rtas_set_rtc_time;
+       ppc_md.init_IRQ         = celleb_init_IRQ_native;
+
+#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();
+}
+
+static void __init celleb_setup_arch(void)
+{
+       if (firmware_has_feature(FW_FEATURE_BEAT))
+               celleb_setup_arch_beat();
+       else
+               celleb_setup_arch_native();
 
        /* init to some ~sane value until calibrate_delay() runs */
        loops_per_jiffy = 50000000;
@@ -111,12 +174,19 @@ static int __init celleb_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (!of_flat_dt_is_compatible(root, "Beat"))
-               return 0;
+       if (of_flat_dt_is_compatible(root, "Beat")) {
+               powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+                       | FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+               hpte_init_beat_v3();
+               return 1;
+       }
+       if (of_flat_dt_is_compatible(root, "TOSHIBA,Celleb")) {
+               powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+               hpte_init_native();
+               return 1;
+       }
 
-       powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
-       hpte_init_beat_v3();
-       return 1;
+       return 0;
 }
 
 static struct of_device_id celleb_bus_ids[] __initdata = {
@@ -144,24 +214,11 @@ define_machine(celleb) {
        .probe                  = celleb_probe,
        .setup_arch             = celleb_setup_arch,
        .show_cpuinfo           = celleb_show_cpuinfo,
-       .restart                = beat_restart,
-       .power_off              = beat_power_off,
-       .halt                   = beat_halt,
-       .get_rtc_time           = beat_get_rtc_time,
-       .set_rtc_time           = beat_set_rtc_time,
        .calibrate_decr         = generic_calibrate_decr,
        .progress               = celleb_progress,
-       .power_save             = beat_power_save,
-       .nvram_size             = beat_nvram_get_size,
-       .nvram_read             = beat_nvram_read,
-       .nvram_write            = beat_nvram_write,
-       .set_dabr               = beat_set_xdabr,
-       .init_IRQ               = beatic_init_IRQ,
-       .get_irq                = beatic_get_irq,
        .pci_probe_mode         = celleb_pci_probe_mode,
        .pci_setup_phb          = celleb_setup_phb,
 #ifdef CONFIG_KEXEC
-       .kexec_cpu_down         = beat_kexec_cpu_down,
        .machine_kexec          = default_machine_kexec,
        .machine_kexec_prepare  = default_machine_kexec_prepare,
        .machine_crash_shutdown = default_machine_crash_shutdown,
index b6de2b5223dd4682b61d9c9708b68c978c782059..ce91787f3c7c39789e094e31219a6079040e9367 100644 (file)
@@ -26,6 +26,7 @@
 #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 +40,6 @@
 #include <asm/tsi108_irq.h>
 #include <asm/tsi108_pci.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 
 #undef DEBUG
 
index a65f1b44abf85f139b93ff337445fe0de8949e73..cc7161ff166665ea120614c846f8ecd8082a6069 100644 (file)
@@ -5,7 +5,7 @@ extra-y += dt.o
 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
index da87162000f0b25aa38c9189622a7105412b1272..68f248b4c6960ca771b610c6c2d9a5e633fe69bf 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2001 Allan Trautman, IBM Corporation
+ * Copyright (C) 2005,2007  Stephen Rothwell, IBM Corp
  *
  * iSeries specific routines for PCI.
  *
@@ -26,6 +27,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 +37,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>
 #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
@@ -75,6 +71,232 @@ 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, int count,
+               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("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
+                       "Card %4s  0x%04X\n", count, bus,
+                       PCI_SLOT(pdev->devfn), pdev->vendor, frame,
+                       card, (int)(pdev->class >> 8));
+       }
+}
+
 /*
  * iomm_table_allocate_entry
  *
@@ -87,7 +309,7 @@ static DEFINE_SPINLOCK(iomm_table_lock);
  * - 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);
@@ -130,7 +352,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
  * - 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 +367,19 @@ static void allocate_device_bars(struct pci_dev *dev)
  * 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 +392,65 @@ static struct device_node *find_Device_Node(int bus, int devfn)
        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_pci_final_fixup(void)
  */
-static struct device_node *get_Device_Node(struct pci_dev *pdev)
+void __init iSeries_pci_final_fixup(void)
 {
+       struct pci_dev *pdev = NULL;
        struct device_node *node;
+       int num_dev = 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) {
+               const u32 *agent;
+               const u32 *sub_bus;
+               unsigned char bus = pdev->bus->number;
+
+               node = find_device_node(bus, pdev->devfn);
+               printk("pci dev %p (%x.%x), node %p\n", pdev, bus,
+                       pdev->devfn, node);
+               if (!node) {
+                       printk("PCI: Device Tree not found for 0x%016lX\n",
+                                       (unsigned long)pdev);
+                       continue;
+               }
+
+               agent = of_get_property(node, "linux,agent-id", NULL);
+               sub_bus = of_get_property(node, "linux,subbus", 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;
+                       }
+               }
 
-       node = pdev->sysdata;
-       if (node == NULL || PCI_DN(node)->pcidev != pdev)
-               node = find_Device_Node(pdev->bus->number, pdev->devfn);
-       return node;
+               num_dev++;
+               pdev->sysdata = node;
+               PCI_DN(node)->pcidev = pdev;
+               allocate_device_bars(pdev);
+               iseries_device_information(pdev, num_dev, bus, *sub_bus);
+               iommu_devnode_init_iSeries(pdev, node);
+       }
+       iSeries_activate_IRQs();
+       mf_display_src(0xC9000200);
 }
-#endif
 
 /*
  * Config space read and write functions.
@@ -269,7 +474,7 @@ static u64 hv_cfg_write_func[4] = {
 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 +504,7 @@ static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
 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 +536,22 @@ static struct pci_ops iSeries_pci_ops = {
  * 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 +568,40 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
  * 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;
+
+       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;
 
-       OrigIoAddr = (unsigned long __force)IoAddress;
-       if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
+               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];
-
-       if (DevNode != NULL) {
-               int barnum = iobar_table[TableIndex];
-               *dsaptr = iseries_ds_addr(DevNode) | (barnum << 24);
-               *BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE;
+       }
+       base_addr = orig_addr - BASE_IO_MEMORY;
+       ind = base_addr / IOMM_TABLE_ENTRY_SIZE;
+       dn = iomm_table[ind];
+
+       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 +609,58 @@ static inline struct device_node *xlate_iomm_address(
  * 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);
-
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
 
-               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);
-
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_long");
 
-               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 +669,72 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
  * Write MM I/O Instructions for the iSeries
  *
  */
-static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
+static void iseries_writeb(u8 data, volatile void __iomem *addr)
 {
-       u64 BarOffset;
+       u64 bar_offset;
        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;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_byte");
 
-               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);
+       if (dn == NULL)
                return;
-       }
        do {
-               rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
-       } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
+               rc = HvCall4(HvCallPciBarStore8, dsa, bar_offset, data, 0);
+       } while (check_return_code("WWB", dn, &retry, rc) != 0);
 }
 
-static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
+static void iseries_writew_be(u16 data, volatile void __iomem *addr)
 {
-       u64 BarOffset;
+       u64 bar_offset;
        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;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
 
-               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);
+       if (dn == NULL)
                return;
-       }
        do {
-               rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0);
-       } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
+               rc = HvCall4(HvCallPciBarStore16, dsa, bar_offset, data, 0);
+       } while (check_return_code("WWW", dn, &retry, rc) != 0);
 }
 
-static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
+static void iseries_writel_be(u32 data, volatile void __iomem *addr)
 {
-       u64 BarOffset;
+       u64 bar_offset;
        u64 dsa;
        int retry = 0;
        u64 rc;
-       struct device_node *DevNode =
-               xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_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_Write_Long: invalid access at IO address %p\n",
-                              IoAddress);
+       if (dn == NULL)
                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);
+               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_Read_Word(addr));
+       return le16_to_cpu(iseries_readw_be(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);
+       return le32_to_cpu(iseries_readl_be(addr));
 }
 
 static void iseries_writew(u16 data, volatile void __iomem *addr)
 {
-       iSeries_Write_Word(cpu_to_le16(data), addr);
+       iseries_writew_be(cpu_to_le16(data), addr);
 }
 
 static void iseries_writel(u32 data, volatile void __iomem *addr)
 {
-       iSeries_Write_Long(cpu_to_le32(data), addr);
-}
-
-static void iseries_writew_be(u16 data, volatile void __iomem *addr)
-{
-       iSeries_Write_Word(data, addr);
-}
-
-static void iseries_writel_be(u32 data, volatile void __iomem *addr)
-{
-       iSeries_Write_Long(data, addr);
+       iseries_writel(cpu_to_le32(data), addr);
 }
 
 static void iseries_readsb(const volatile void __iomem *addr, void *buf,
@@ -620,7 +742,7 @@ static void iseries_readsb(const volatile void __iomem *addr, void *buf,
 {
        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 +750,7 @@ static void iseries_readsw(const volatile void __iomem *addr, void *buf,
 {
        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 +758,7 @@ static void iseries_readsl(const volatile void __iomem *addr, void *buf,
 {
        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 +766,7 @@ static void iseries_writesb(volatile void __iomem *addr, const void *buf,
 {
        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 +774,7 @@ static void iseries_writesw(volatile void __iomem *addr, const void *buf,
 {
        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 +782,7 @@ static void iseries_writesl(volatile void __iomem *addr, const void *buf,
 {
        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 +791,7 @@ static void iseries_memset_io(volatile void __iomem *addr, int c,
        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 +801,7 @@ static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
        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 +811,7 @@ static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
        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 +864,8 @@ void __init iSeries_pcibios_init(void)
        /* 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,6 +891,8 @@ void __init iSeries_pcibios_init(void)
                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;
index 33a8489fde54c636260781a944aa82b2549348e7..180aa74afb2d974ab3cf6c9dd22bba8448fe27af 100644 (file)
  * 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,12 @@ struct pci_dev;                             /* For Forward Reference */
 #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);
-
-       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);
+#else
+static inline void     iSeries_pcibios_init(void) { }
+static inline void     iSeries_pci_final_fixup(void) { }
+#endif
 
 #endif /* _PLATFORMS_ISERIES_PCI_H */
index 0877a88341100e7cdf25a49c3167f0c3a94fdffc..5616219a20d5d3ee2d3f6484081378a19f1671ac 100644 (file)
@@ -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)
 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 @@ static unsigned long iSeries_process_Condor_mainstore_vpd(
         * 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 @@ static unsigned long iSeries_process_Condor_mainstore_vpd(
                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 @@ static unsigned long iSeries_process_Regatta_mainstore_vpd(
                                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 @@ struct mschunks_map mschunks_map = {
 };
 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 @@ static void __init iSeries_setup_arch(void)
                        itVpdAreas.xSlicMaxLogicalProcs);
        printk("Max physical processors = %d\n",
                        itVpdAreas.xSlicMaxPhysicalProcs);
+
+       iSeries_pcibios_init();
 }
 
 static void iSeries_show_cpuinfo(struct seq_file *m)
index 0a47ac53c95970a0fbf958410829c0a2cc97d9e3..729754bbb0189054f1fc28311ce13f66c6e341af 100644 (file)
@@ -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 (file)
index 9f83878..0000000
+++ /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));
-       }
-}
index 771ed0cf29a5d8c0c5f8d7858ddf223913d19f5a..3ffa0ac170eeefc84ff28bba853b485156ebc66e 100644 (file)
@@ -558,7 +558,7 @@ void __init maple_pci_init(void)
         * 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;
index 735e1536cbfc15dc93a01d517d55245190694ab6..2f4dd6e4aac112b44d57cdbbcad734c4adac901e 100644 (file)
@@ -17,7 +17,7 @@ config PPC_PASEMI_IOMMU
        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"
index 1cfb8b0c8fecd512f6b26564138a9df52b148c17..58556b028a4c142b9886fe78c48b69a752c8fd2c 100644 (file)
@@ -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 @@ static void set_astate(int cpu, unsigned int astate)
        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 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
        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 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
                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 struct cpufreq_driver pas_cpufreq_driver = {
 
 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);
index dae9f658122e4ef47dffa02ba5877cd73bac2c52..b46542990cf8288338c34c80a169d8364e942a56 100644 (file)
@@ -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 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
                                     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 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
        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 @@ static int __devinit gpio_mdio_probe(struct of_device *ofdev,
 
        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 @@ static struct of_device_id gpio_mdio_match[] =
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, gpio_mdio_match);
 
 static struct of_platform_driver gpio_mdio_driver =
 {
@@ -330,12 +332,32 @@ static struct of_platform_driver gpio_mdio_driver =
 
 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");
index 516acabb4e96a4151b42e2833e907feb633c6ae2..c96127b029b653c4dd8e7d7c7e23864323d30152 100644 (file)
@@ -16,8 +16,14 @@ extern void idle_doze(void);
 
 /* 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)
 {
 }
index 6d0fba6aab174fbaf52bc2136f7983048fce91b4..56f45adcd0895aceb35f7be4ef800b2c39e60b77 100644 (file)
@@ -62,7 +62,16 @@ sleep_common:
        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 @@ sleep_common:
 
        mtmsrd  r4,0
 
-       addi    r1,r1,64
+1:     addi    r1,r1,64
        ld      r0,16(r1)
        mtlr    r0
        blr
index 3d62060498b4256151a3e63aa28e94350552fcec..6d7d068ceba099be37ea5ec6c2542a2838991ffc 100644 (file)
@@ -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>
 
 #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 int num_mce_regs;
 
 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);
@@ -295,7 +303,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
                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 inline void pasemi_pcmcia_init(void)
 
 
 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 @@ static int __init pas_probe(void)
 {
        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 @@ static int __init pas_probe(void)
 }
 
 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,
index f852ae3e0ee42a016adc6155b2f5c37942f6dbc5..589c613bcd3c290b887b01d3da3c6e59d5a155c4 100644 (file)
@@ -319,7 +319,7 @@ static int u3_ht_skip_device(struct pci_controller *hose,
        if (bus->self)
                busdn = pci_device_to_OF_node(bus->self);
        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;
@@ -778,7 +778,7 @@ static void __init setup_u4_pcie(struct pci_controller* hose)
 
 static void __init setup_u3_ht(struct pci_controller* hose)
 {
-       struct device_node *np = (struct device_node *)hose->arch_data;
+       struct device_node *np = hose->dn;
        struct pci_controller *other = NULL;
        int i, cur;
 
@@ -1032,7 +1032,7 @@ void __init pmac_pci_init(void)
         * 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;
index 02c533096627851363c3864232b53d130659ed8b..3acb59d5cdf56c9c260dd0952b2fe866ec7daf29 100644 (file)
@@ -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>
index bf9da56942e8df6bbfdaeea285d7584961970000..bbbefd64ab5991f3c30c5e7d34a074a3e224d326 100644 (file)
@@ -84,12 +84,14 @@ long __init pmac_time_init(void)
        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)
 {
index fb3d636e088be7eaf049d5af89dcf8e72add7cee..aa14a8559edb99480cd65b63c15b27546b4ba50a 100644 (file)
@@ -480,6 +480,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
                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 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 
        /* 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;
index 57e025e84ab4ae0132b3145c96689730989ef6f9..68ea5eee39a832ddd054b9fe36d78d301f884f67 100644 (file)
@@ -310,8 +310,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
        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 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
                        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 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
        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 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
         */
        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.
index be17d2395072c02a67abd37565c956a1221f2699..a65c763082010c8c1ff7d6fd0a8b458974fef085 100644 (file)
@@ -251,7 +251,7 @@ static void iommu_table_setparms(struct pci_controller *phb,
        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(struct pci_controller *phb,
 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 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
            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 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 
        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 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
        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;
index d003c80fa31d2b4369f0021fd3a9b38ab99dd4ae..d8680b589dc96c325afb09725c47f5c6a008a3e6 100644 (file)
@@ -8,11 +8,6 @@ static inline long poll_pending(void)
        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);
index 116305b22a2bf209721e12bfca19666e6a293432..ea4c65917a648c5e4795a99a23ba87c4efaf3351 100644 (file)
@@ -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 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
         */
        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;
index 5eaf3e3f4b8b01dda9b99e59afa7fe39dccaccac..d359d6e929752f5cd7258a127b8845f13e3a2791 100644 (file)
@@ -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>
 
index 33df4c347ca7cb69cae3d8f945afb168695c011f..87e58e09b500b7b78ae22c4c210ce23c605f504d 100644 (file)
@@ -222,7 +222,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
                        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);
index 20edd1e94eff7111927fef861236f8827e002b4d..c858749263e019e0641af6475341740993077741 100644 (file)
@@ -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>
index 121b04d165d1937b2805a5a1dabaaa30c0467f6f..865e36751f21c434d107e8d4b2dbadcce232e56d 100644 (file)
@@ -153,6 +153,10 @@ static const char *getvecname(unsigned long vec);
 
 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 @@ Commands:\n\
 #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"
@@ -855,6 +862,11 @@ cmds(struct pt_regs *excp)
                case 'u':
                        dump_segments();
                        break;
+#endif
+#ifdef CONFIG_4xx
+               case 'u':
+                       dump_tlb_44x();
+                       break;
 #endif
                default:
                        printf("Unrecognized command: ");
@@ -2527,16 +2539,33 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
 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 @@ void dump_segments(void)
 }
 #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
index 976270d537c1947480f3d8e573d5c4b2fae7d089..c1f77e1d368e7965c0fa062226df4f6562c81f33 100644 (file)
@@ -336,7 +336,7 @@ ev64260_early_serial_map(void)
 #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_setup_arch(void)
        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)
index 2d7cd486e025b45015868f2a5e51f61f36e48ed0..6bbd4fa50f3b87458a56dbc155288f1e21b5a64d 100644 (file)
@@ -98,7 +98,7 @@ config HW_RANDOM_PASEMI
        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.
index fa6040b6c8f2a4f0483d830aa97abe48ae2f7f60..24ae3073991fee365fe0533863adb2e097dc8b97 100644 (file)
@@ -126,10 +126,9 @@ static int __devexit rng_remove(struct of_device *dev)
 }
 
 static struct of_device_id rng_match[] = {
-       {
-               .compatible      = "1682m-rng",
-       },
-       {},
+       { .compatible      = "1682m-rng", },
+       { .compatible      = "pasemi,pwrficient-rng", },
+       { },
 };
 
 static struct of_platform_driver rng_driver = {
index 9007d0677220cf3aef8a524608d345452820ba6b..90320917be2875a6a0fc77361fd59e254f7670f6 100644 (file)
@@ -225,7 +225,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev,
                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_exit(pasemi_edac_exit);
 
 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");
index dc741d3a4531cbe365aa8b89256a0337782b5b00..35e1f22089d621619ea28f9304f729ae25d8e068 100644 (file)
@@ -33,7 +33,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 +64,7 @@
 #include "via-pmu-event.h"
 
 /* Some compile options */
-#undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
-#undef HACKED_PCI_SAVE
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR              154
@@ -1256,9 +1253,7 @@ void
 pmu_suspend(void)
 {
        unsigned long flags;
-#ifdef SUSPEND_USES_PMU
-       struct adb_request *req;
-#endif
+
        if (!via)
                return;
        
@@ -1276,17 +1271,10 @@ pmu_suspend(void)
                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 +1295,11 @@ pmu_resume(void)
                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 */
@@ -1804,14 +1785,10 @@ static void broadcast_wake(void)
  * 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;
 
@@ -1857,16 +1834,10 @@ pbook_pci_save(void)
                        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;
        }
 }
@@ -1885,17 +1856,6 @@ pbook_pci_restore(void)
        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++;
@@ -1919,7 +1879,6 @@ pbook_pci_restore(void)
                        pci_write_config_word(pd, PCI_COMMAND, ps->command);
                        break;
                }
-#endif 
        }
 }
 
@@ -2547,7 +2506,6 @@ pmu_release(struct inode *inode, struct file *file)
        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);
@@ -2561,7 +2519,6 @@ pmu_release(struct inode *inode, struct file *file)
 
                kfree(pp);
        }
-       unlock_kernel();
        return 0;
 }
 
diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
new file mode 100644 (file)
index 0000000..8485c28
--- /dev/null
@@ -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 */
+
index 3671c128f271eae3806930d50bb54387b7cc0e6f..1e41bd1c85029de00f0ca7767e8c91ed19610ec8 100644 (file)
@@ -64,7 +64,7 @@ enum {
        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 =
index 4a82fdccee92a8fd57e5bde18439a05c5e48c02e..7a3cef785abdee2aa52b2cdc6716bdf04348b291 100644 (file)
@@ -69,10 +69,9 @@ struct iommu_table {
 };
 
 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
index 82328dec2b527d2ecdd05b0694ca2d8562c0558d..12e5e773c67e765b6c1efbc1bae9e2a44fba8641 100644 (file)
@@ -180,6 +180,7 @@ extern int mmu_vmalloc_psize;
 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
index 80e6fad28b4fdb7762d93cef14296c59b875a149..d20a4cd08fa1a928fca2e4307552c0e6031c2bb9 100644 (file)
 #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,
index d8bdc79db12e2767b1dec66cf74a530975fb8f49..f139f2a44b19b0d7cf7bfa9033315ea1261b251f 100644 (file)
@@ -1,15 +1,17 @@
 #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;
 
 /*
  * Structure of a PCI controller (host bridge)
@@ -17,26 +19,38 @@ struct pci_controller;
 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;
 
        /* 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;
 
+#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 +65,30 @@ struct pci_controller {
         *   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 +104,18 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
 
 /* 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 +127,12 @@ extern void setup_grackle(struct pci_controller *hose);
 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 +152,9 @@ struct pci_dn {
        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 +162,7 @@ struct pci_dn {
 /* 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 +200,14 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
 }
 
 /** 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, int fix_bus);
 
 extern int pcibios_remove_root_bus(struct pci_controller *phb);
 
@@ -270,20 +243,18 @@ extern int pcibios_map_io_space(struct pci_bus *bus);
 #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 +269,7 @@ static inline int pcibios_vaddr_is_ioport(void __iomem *address)
 {
        return 0;
 }
-#endif
-
+#endif /* CONFIG_PCI */
 
-
-#endif /* __KERNEL__ */
-#endif
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_PCI_BRIDGE_H */
index b847aa10074be1d87878a40acbece6bb204644eb..854ab713f56cb62b857216285d3b343c13e9ea66 100644 (file)
@@ -22,7 +22,6 @@ extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
 
 
 extern struct list_head hose_list;
-extern int global_phb_number;
 
 extern void find_and_init_phbs(void);
 
@@ -47,9 +46,6 @@ extern void init_pci_config_tokens (void);
 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 ---- */
index e775ff1ca413e96ff5cf8b926f1b08c6105f58bf..1f685047c6ffe80c983a5bff36e53777206ff7bb 100644 (file)
 #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; \
index e49f644ca63a18e9bfc491ff326a7d5b5b61d501..76329f451aba063127377777b8093d6c4e92a45d 100644 (file)
  * 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
  */
 #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
 
 
 /*
  */
 #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 -
index 5c39b9270ff7007b359df90a7cfc407607ddb7ab..c65af7bd1e9c6369757dfaeeecf74feccea83f97 100644 (file)
@@ -46,6 +46,10 @@ extern struct device_node *of_find_node_by_phandle(phandle handle);
 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);