]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'linux-2.6'
authorPaul Mackerras <paulus@samba.org>
Fri, 21 Dec 2007 11:21:08 +0000 (22:21 +1100)
committerPaul Mackerras <paulus@samba.org>
Fri, 21 Dec 2007 11:21:08 +0000 (22:21 +1100)
270 files changed:
Documentation/powerpc/booting-without-of.txt
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/4xx.c
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/dtc-src/Makefile.dtc [new file with mode: 0644]
arch/powerpc/boot/dtc-src/checks.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/data.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc-lexer.l [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc-parser.y [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/dtc.h [new file with mode: 0644]
arch/powerpc/boot/dtc-src/flattree.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/fstree.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/livetree.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/srcpos.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/srcpos.h [new file with mode: 0644]
arch/powerpc/boot/dtc-src/treesource.c [new file with mode: 0644]
arch/powerpc/boot/dtc-src/version_gen.h [new file with mode: 0644]
arch/powerpc/boot/dts/kuroboxHD.dts
arch/powerpc/boot/dts/kuroboxHG.dts
arch/powerpc/boot/dts/lite5200.dts
arch/powerpc/boot/dts/lite5200b.dts
arch/powerpc/boot/dts/mpc8313erdb.dts
arch/powerpc/boot/dts/mpc832x_mds.dts
arch/powerpc/boot/dts/mpc832x_rdb.dts
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/mpc8349emitxgp.dts
arch/powerpc/boot/dts/mpc834x_mds.dts
arch/powerpc/boot/dts/mpc836x_mds.dts
arch/powerpc/boot/dts/mpc8540ads.dts
arch/powerpc/boot/dts/mpc8541cds.dts
arch/powerpc/boot/dts/mpc8544ds.dts
arch/powerpc/boot/dts/mpc8548cds.dts
arch/powerpc/boot/dts/mpc8555cds.dts
arch/powerpc/boot/dts/mpc8560ads.dts
arch/powerpc/boot/dts/mpc8568mds.dts
arch/powerpc/boot/dts/mpc8572ds.dts
arch/powerpc/boot/dts/mpc8610_hpcd.dts
arch/powerpc/boot/dts/mpc8641_hpcn.dts
arch/powerpc/boot/dts/mpc866ads.dts
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/configs/mpc837x_mds_defconfig [new file with mode: 0644]
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/isa-bridge.c
arch/powerpc/kernel/legacy_serial.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/module_32.c
arch/powerpc/kernel/module_64.c
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/kernel/signal_32.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/udbg.c
arch/powerpc/kernel/udbg_16550.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/slb.c
arch/powerpc/mm/slb_low.S
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/82xx/pq2fads.c
arch/powerpc/platforms/83xx/Kconfig
arch/powerpc/platforms/83xx/Makefile
arch/powerpc/platforms/83xx/mpc8313_rdb.c
arch/powerpc/platforms/83xx/mpc832x_mds.c
arch/powerpc/platforms/83xx/mpc832x_rdb.c
arch/powerpc/platforms/83xx/mpc834x_mds.c
arch/powerpc/platforms/83xx/mpc836x_mds.c
arch/powerpc/platforms/83xx/mpc837x_mds.c [new file with mode: 0644]
arch/powerpc/platforms/83xx/pci.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/86xx/mpc8610_hpcd.c
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/8xx/Kconfig
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/8xx/mpc86xads.h
arch/powerpc/platforms/8xx/mpc86xads_setup.c
arch/powerpc/platforms/cell/Makefile
arch/powerpc/platforms/cell/cbe_cpufreq.c
arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
arch/powerpc/platforms/cell/cbe_regs.c
arch/powerpc/platforms/cell/io-workarounds.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/pmu.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spu_fault.c [new file with mode: 0644]
arch/powerpc/platforms/cell/spu_manage.c
arch/powerpc/platforms/cell/spufs/Makefile
arch/powerpc/platforms/cell/spufs/backing_ops.c
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/cell/spufs/fault.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/hw_ops.c
arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spufs.h
arch/powerpc/platforms/cell/spufs/switch.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/scc_uhc.c
arch/powerpc/platforms/celleb/setup.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/embedded6xx/holly.c
arch/powerpc/platforms/iseries/Makefile
arch/powerpc/platforms/iseries/iommu.c
arch/powerpc/platforms/iseries/lpevents.c
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/Kconfig
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/pmac.h
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/time.c
arch/powerpc/platforms/ps3/spu.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/eeh_driver.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/plpar_wrappers.h
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/platforms/pseries/xics.h
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/axonram.c
arch/powerpc/sysdev/bestcomm/bestcomm.h
arch/powerpc/sysdev/commproc.c
arch/powerpc/sysdev/cpm2_common.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_soc.c
arch/powerpc/sysdev/grackle.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/ipic.h
arch/powerpc/sysdev/mmio_nvram.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic.h
arch/powerpc/sysdev/mpic_pasemi_msi.c [new file with mode: 0644]
arch/powerpc/sysdev/pmi.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/xmon/xmon.c
arch/ppc/kernel/setup.c
arch/ppc/platforms/85xx/stx_gp3.c
arch/ppc/platforms/ev64260.c
arch/ppc/platforms/prep_pci.c
arch/ppc/syslib/gt64260_pic.c
arch/ppc/syslib/mpc52xx_pic.c
arch/ppc/syslib/mv64360_pic.c
arch/ppc/syslib/ocp.c
arch/ppc/syslib/ppc83xx_setup.c
arch/ppc/syslib/ppc8xx_pic.c
arch/ppc/syslib/ppc_sys.c
arch/ppc/xmon/start.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/pasemi-rng.c
drivers/edac/pasemi_edac.c
drivers/macintosh/adb.c
drivers/macintosh/mediabay.c
drivers/macintosh/therm_pm72.c
drivers/macintosh/therm_windtunnel.c
drivers/macintosh/via-pmu-backlight.c
drivers/macintosh/via-pmu.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/fs_enet/mac-scc.c
drivers/net/ucc_geth.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/serial/cpm_uart/cpm_uart_cpm1.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c
include/asm-powerpc/8xx_immap.h
include/asm-powerpc/commproc.h
include/asm-powerpc/cpm.h
include/asm-powerpc/cputhreads.h [new file with mode: 0644]
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/firmware.h
include/asm-powerpc/immap_86xx.h
include/asm-powerpc/io.h
include/asm-powerpc/iommu.h
include/asm-powerpc/ipic.h
include/asm-powerpc/iseries/hv_lp_event.h
include/asm-powerpc/machdep.h
include/asm-powerpc/mmu-hash64.h
include/asm-powerpc/nvram.h
include/asm-powerpc/of_platform.h
include/asm-powerpc/pci-bridge.h
include/asm-powerpc/pci.h
include/asm-powerpc/ppc-pci.h
include/asm-powerpc/prom.h
include/asm-powerpc/qe.h
include/asm-powerpc/reg.h
include/asm-powerpc/reg_booke.h
include/asm-powerpc/smu.h
include/asm-powerpc/spu.h
include/asm-powerpc/spu_csa.h
include/asm-powerpc/spu_priv1.h
include/asm-ppc/8xx_immap.h
include/asm-ppc/commproc.h
include/asm-ppc/reg_booke.h
include/linux/of.h
include/linux/pmu.h

index e9a3cb1d6b06b18a3e0bba0d5a0bf85dc3fde77f..ee0209a7de3ee62d810c060e72ec69ad17f2d4c1 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
 -------------------------------------
@@ -1218,16 +1223,14 @@ platforms are moved over to use the flattened-device-tree model.
 
   Required properties:
     - reg : Offset and length of the register set for the device
-    - device_type : Should be "mdio"
     - compatible : Should define the compatible device type for the
-      mdio.  Currently, this is most likely to be "gianfar"
+      mdio.  Currently, this is most likely to be "fsl,gianfar-mdio"
 
   Example:
 
        mdio@24520 {
                reg = <24520 20>;
-               device_type = "mdio"; 
-               compatible = "gianfar";
+               compatible = "fsl,gianfar-mdio";
 
                ethernet-phy@0 {
                        ......
@@ -1626,6 +1629,19 @@ platforms are moved over to use the flattened-device-tree model.
    - interrupt-parent : the phandle for the interrupt controller that
      services interrupts for this device.
    - pio-handle : The phandle for the Parallel I/O port configuration.
+   - rx-clock-name: the UCC receive clock source
+     "none": clock source is disabled
+     "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+     "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+   - tx-clock-name: the UCC transmit clock source
+     "none": clock source is disabled
+     "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+     "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+   The following two properties are deprecated.  rx-clock has been replaced
+   with rx-clock-name, and tx-clock has been replaced with tx-clock-name.
+   Drivers that currently use the deprecated properties should continue to
+   do so, in order to support older device trees, but they should be updated
+   to check for the new properties first.
    - rx-clock : represents the UCC receive clock source.
      0x00 : clock source is disabled;
      0x1~0x10 : clock source is BRG1~BRG16 respectively;
index 232c298c933fa3601b9fa9099b3eeee26e40d514..d40844f9b047da2e512de8b2c9ded9b00ca094ce 100644 (file)
@@ -160,6 +160,7 @@ config PPC_DCR
 
 config PPC_OF_PLATFORM_PCI
        bool
+       depends on PCI
        depends on PPC64 # not supported on 32 bits yet
        default n
 
@@ -417,7 +418,7 @@ endmenu
 
 config ISA_DMA_API
        bool
-       default y
+       default !PPC_ISERIES || PCI
 
 menu "Bus options"
 
index 6a79fe43e229e9036a25b8792eb45246f44db30c..d20ccf5f2ca99cc1f06ab37e809a4984a547f596 100644 (file)
@@ -151,6 +151,13 @@ config BOOTX_TEXT
 
 config PPC_EARLY_DEBUG
        bool "Early debugging (dangerous)"
+       help
+         Say Y to enable some early debugging facilities that may be available
+         for your processor/board combination. Those facilities are hacks
+         intended to debug problems early during boot, this should not be
+         enabled in a production kernel.
+         Note that enabling this will also cause the kernel default log level
+         to be pushed to max automatically very early during boot
 
 choice
        prompt "Early debugging console"
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 ebf9e217612d65bee7d489ed55b7a77b2bd0d6da..3d0e4f921f1d3964f3cb9a881abccd04524819ff 100644 (file)
@@ -122,7 +122,7 @@ void ibm4xx_denali_fixup_memsize(void)
        else
                dpath = 4; /* 32 bits */
 
-       /* get adress pins (rows) */
+       /* get address pins (rows) */
        val = mfdcr_sdram0(DDR0_42);
 
        row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
index 18e32719d0ed4544202bae47cc9c1361e6116649..9149bb8ed03c9fbfd3f472fca3eac62f44d34bc3 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,23 +103,60 @@ 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
        $(call if_changed,bootar)
 
-hostprogs-y    := addnote addRamDisk hack-coff mktree
+hostprogs-y    := addnote addRamDisk hack-coff mktree dtc
 
 targets                += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
 extra-y                := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
                   $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds
 
 wrapper                :=$(srctree)/$(src)/wrapper
-wrapperbits    := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
+wrapperbits    := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
                        $(wrapper) FORCE
 
+#############
+# Bits for building dtc
+# DTC_GENPARSER      := 1    # Uncomment to rebuild flex/bison output
+
+dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o
+dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+dtc-objs := $(addprefix dtc-src/, $(dtc-objs))
+
+# prerequisites on generated files needs to be explicit
+$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h
+$(obj)/dtc-src/dtc-lexer.lex.o:  $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h
+
+HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/
+
+targets += dtc-src/dtc-parser.tab.c
+targets += dtc-src/dtc-lexer.lex.c
+
+ifdef DTC_GENPARSER
+BISON = bison
+FLEX = flex
+
+quiet_cmd_bison = BISON   $@
+      cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
+quiet_cmd_flex = FLEX    $@
+      cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
+
+$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
+     $(call if_changed,bison)
+
+$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
+
+$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
+     $(call if_changed,flex)
+endif
+
 #############
 # Bits for building various flavours of zImage
 
@@ -243,3 +282,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();
 }
diff --git a/arch/powerpc/boot/dtc-src/Makefile.dtc b/arch/powerpc/boot/dtc-src/Makefile.dtc
new file mode 100644 (file)
index 0000000..d607fdb
--- /dev/null
@@ -0,0 +1,25 @@
+# Makefile.dtc
+#
+# This is not a complete Makefile of itself.  Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
+       checks.c
+DTC_EXTRA = dtc.h srcpos.h
+DTC_LEXFILES = dtc-lexer.l
+DTC_BISONFILES = dtc-parser.y
+
+DTC_LEX_SRCS = $(DTC_LEXFILES:%.l=%.lex.c)
+DTC_BISON_SRCS = $(DTC_BISONFILES:%.y=%.tab.c)
+DTC_BISON_INCLUDES = $(DTC_BISONFILES:%.y=%.tab.h)
+
+DTC_GEN_SRCS = $(DTC_LEX_SRCS) $(DTC_BISON_SRCS)
+DTC_GEN_ALL = $(DTC_GEN_SRCS) $(DTC_BISON_INCLUDES)
+DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
+
+DTC_CLEANFILES = $(DTC_GEN_ALL)
+
+# We assume the containing Makefile system can do auto-dependencies for most
+# things, but we supply the dependencies on generated header files explicitly
+
+$(addprefix $(DTC_objdir)/,$(DTC_GEN_SRCS:%.c=%.o)): $(addprefix $(DTC_objdir)/,$(DTC_BISON_INCLUDES))
diff --git a/arch/powerpc/boot/dtc-src/checks.c b/arch/powerpc/boot/dtc-src/checks.c
new file mode 100644 (file)
index 0000000..2ce961c
--- /dev/null
@@ -0,0 +1,750 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2007.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+#ifdef TRACE_CHECKS
+#define TRACE(c, ...) \
+       do { \
+               fprintf(stderr, "=== %s: ", (c)->name); \
+               fprintf(stderr, __VA_ARGS__); \
+               fprintf(stderr, "\n"); \
+       } while (0)
+#else
+#define TRACE(c, fmt, ...)     do { } while (0)
+#endif
+
+enum checklevel {
+       IGNORE = 0,
+       WARN = 1,
+       ERROR = 2,
+};
+
+enum checkstatus {
+       UNCHECKED = 0,
+       PREREQ,
+       PASSED,
+       FAILED,
+};
+
+struct check;
+
+typedef void (*tree_check_fn)(struct check *c, struct node *dt);
+typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*prop_check_fn)(struct check *c, struct node *dt,
+                             struct node *node, struct property *prop);
+
+struct check {
+       const char *name;
+       tree_check_fn tree_fn;
+       node_check_fn node_fn;
+       prop_check_fn prop_fn;
+       void *data;
+       enum checklevel level;
+       enum checkstatus status;
+       int inprogress;
+       int num_prereqs;
+       struct check **prereq;
+};
+
+#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+       static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
+       static struct check nm = { \
+               .name = #nm, \
+               .tree_fn = (tfn), \
+               .node_fn = (nfn), \
+               .prop_fn = (pfn), \
+               .data = (d), \
+               .level = (lvl), \
+               .status = UNCHECKED, \
+               .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
+               .prereq = nm##_prereqs, \
+       };
+
+#define TREE_CHECK(nm, d, lvl, ...) \
+       CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
+#define NODE_CHECK(nm, d, lvl, ...) \
+       CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
+#define PROP_CHECK(nm, d, lvl, ...) \
+       CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
+#define BATCH_CHECK(nm, lvl, ...) \
+       CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+
+#ifdef __GNUC__
+static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
+#endif
+static inline void check_msg(struct check *c, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+
+       if ((c->level < WARN) || (c->level <= quiet))
+               return; /* Suppress message */
+
+       fprintf(stderr, "%s (%s): ",
+               (c->level == ERROR) ? "ERROR" : "Warning", c->name);
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, "\n");
+}
+
+#define FAIL(c, ...) \
+       do { \
+               TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+               (c)->status = FAILED; \
+               check_msg((c), __VA_ARGS__); \
+       } while (0)
+
+static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+{
+       struct node *child;
+       struct property *prop;
+
+       TRACE(c, "%s", node->fullpath);
+       if (c->node_fn)
+               c->node_fn(c, dt, node);
+
+       if (c->prop_fn)
+               for_each_property(node, prop) {
+                       TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
+                       c->prop_fn(c, dt, node, prop);
+               }
+
+       for_each_child(node, child)
+               check_nodes_props(c, dt, child);
+}
+
+static int run_check(struct check *c, struct node *dt)
+{
+       int error = 0;
+       int i;
+
+       assert(!c->inprogress);
+
+       if (c->status != UNCHECKED)
+               goto out;
+
+       c->inprogress = 1;
+
+       for (i = 0; i < c->num_prereqs; i++) {
+               struct check *prq = c->prereq[i];
+               error |= run_check(prq, dt);
+               if (prq->status != PASSED) {
+                       c->status = PREREQ;
+                       check_msg(c, "Failed prerequisite '%s'",
+                                 c->prereq[i]->name);
+               }
+       }
+
+       if (c->status != UNCHECKED)
+               goto out;
+
+       if (c->node_fn || c->prop_fn)
+               check_nodes_props(c, dt, dt);
+
+       if (c->tree_fn)
+               c->tree_fn(c, dt);
+       if (c->status == UNCHECKED)
+               c->status = PASSED;
+
+       TRACE(c, "\tCompleted, status %d", c->status);
+
+out:
+       c->inprogress = 0;
+       if ((c->status != PASSED) && (c->level == ERROR))
+               error = 1;
+       return error;
+}
+
+/*
+ * Utility check functions
+ */
+
+static void check_is_string(struct check *c, struct node *root,
+                           struct node *node)
+{
+       struct property *prop;
+       char *propname = c->data;
+
+       prop = get_property(node, propname);
+       if (!prop)
+               return; /* Not present, assumed ok */
+
+       if (!data_is_one_string(prop->val))
+               FAIL(c, "\"%s\" property in %s is not a string",
+                    propname, node->fullpath);
+}
+#define CHECK_IS_STRING(nm, propname, lvl) \
+       CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+
+static void check_is_cell(struct check *c, struct node *root,
+                         struct node *node)
+{
+       struct property *prop;
+       char *propname = c->data;
+
+       prop = get_property(node, propname);
+       if (!prop)
+               return; /* Not present, assumed ok */
+
+       if (prop->val.len != sizeof(cell_t))
+               FAIL(c, "\"%s\" property in %s is not a single cell",
+                    propname, node->fullpath);
+}
+#define CHECK_IS_CELL(nm, propname, lvl) \
+       CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+
+/*
+ * Structural check functions
+ */
+
+static void check_duplicate_node_names(struct check *c, struct node *dt,
+                                      struct node *node)
+{
+       struct node *child, *child2;
+
+       for_each_child(node, child)
+               for (child2 = child->next_sibling;
+                    child2;
+                    child2 = child2->next_sibling)
+                       if (streq(child->name, child2->name))
+                               FAIL(c, "Duplicate node name %s",
+                                    child->fullpath);
+}
+NODE_CHECK(duplicate_node_names, NULL, ERROR);
+
+static void check_duplicate_property_names(struct check *c, struct node *dt,
+                                          struct node *node)
+{
+       struct property *prop, *prop2;
+
+       for_each_property(node, prop)
+               for (prop2 = prop->next; prop2; prop2 = prop2->next)
+                       if (streq(prop->name, prop2->name))
+                               FAIL(c, "Duplicate property name %s in %s",
+                                    prop->name, node->fullpath);
+}
+NODE_CHECK(duplicate_property_names, NULL, ERROR);
+
+static void check_explicit_phandles(struct check *c, struct node *root,
+                                         struct node *node)
+{
+       struct property *prop;
+       struct node *other;
+       cell_t phandle;
+
+       prop = get_property(node, "linux,phandle");
+       if (! prop)
+               return; /* No phandle, that's fine */
+
+       if (prop->val.len != sizeof(cell_t)) {
+               FAIL(c, "%s has bad length (%d) linux,phandle property",
+                    node->fullpath, prop->val.len);
+               return;
+       }
+
+       phandle = propval_cell(prop);
+       if ((phandle == 0) || (phandle == -1)) {
+               FAIL(c, "%s has invalid linux,phandle value 0x%x",
+                    node->fullpath, phandle);
+               return;
+       }
+
+       other = get_node_by_phandle(root, phandle);
+       if (other) {
+               FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+                    node->fullpath, phandle, other->fullpath);
+               return;
+       }
+
+       node->phandle = phandle;
+}
+NODE_CHECK(explicit_phandles, NULL, ERROR);
+
+static void check_name_properties(struct check *c, struct node *root,
+                                 struct node *node)
+{
+       struct property *prop;
+
+       prop = get_property(node, "name");
+       if (!prop)
+               return; /* No name property, that's fine */
+
+       if ((prop->val.len != node->basenamelen+1)
+           || (memcmp(prop->val.val, node->name, node->basenamelen) != 0))
+               FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
+                    " of base node name)", node->fullpath, prop->val.val);
+}
+CHECK_IS_STRING(name_is_string, "name", ERROR);
+NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+
+/*
+ * Reference fixup functions
+ */
+
+static void fixup_phandle_references(struct check *c, struct node *dt,
+                                    struct node *node, struct property *prop)
+{
+      struct marker *m = prop->val.markers;
+      struct node *refnode;
+      cell_t phandle;
+
+      for_each_marker_of_type(m, REF_PHANDLE) {
+             assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+             refnode = get_node_by_ref(dt, m->ref);
+             if (! refnode) {
+                     FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+                          m->ref);
+                     continue;
+             }
+
+             phandle = get_node_phandle(dt, refnode);
+             *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle);
+      }
+}
+CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+      &duplicate_node_names, &explicit_phandles);
+
+static void fixup_path_references(struct check *c, struct node *dt,
+                                 struct node *node, struct property *prop)
+{
+       struct marker *m = prop->val.markers;
+       struct node *refnode;
+       char *path;
+
+       for_each_marker_of_type(m, REF_PATH) {
+               assert(m->offset <= prop->val.len);
+
+               refnode = get_node_by_ref(dt, m->ref);
+               if (!refnode) {
+                       FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+                            m->ref);
+                       continue;
+               }
+
+               path = refnode->fullpath;
+               prop->val = data_insert_at_marker(prop->val, m, path,
+                                                 strlen(path) + 1);
+       }
+}
+CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+      &duplicate_node_names);
+
+/*
+ * Semantic checks
+ */
+CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
+CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
+CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+
+CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
+CHECK_IS_STRING(model_is_string, "model", WARN);
+CHECK_IS_STRING(status_is_string, "status", WARN);
+
+static void fixup_addr_size_cells(struct check *c, struct node *dt,
+                                 struct node *node)
+{
+       struct property *prop;
+
+       node->addr_cells = -1;
+       node->size_cells = -1;
+
+       prop = get_property(node, "#address-cells");
+       if (prop)
+               node->addr_cells = propval_cell(prop);
+
+       prop = get_property(node, "#size-cells");
+       if (prop)
+               node->size_cells = propval_cell(prop);
+}
+CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
+      &address_cells_is_cell, &size_cells_is_cell);
+
+#define node_addr_cells(n) \
+       (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
+#define node_size_cells(n) \
+       (((n)->size_cells == -1) ? 1 : (n)->size_cells)
+
+static void check_reg_format(struct check *c, struct node *dt,
+                            struct node *node)
+{
+       struct property *prop;
+       int addr_cells, size_cells, entrylen;
+
+       prop = get_property(node, "reg");
+       if (!prop)
+               return; /* No "reg", that's fine */
+
+       if (!node->parent) {
+               FAIL(c, "Root node has a \"reg\" property");
+               return;
+       }
+
+       if (prop->val.len == 0)
+               FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
+
+       addr_cells = node_addr_cells(node->parent);
+       size_cells = node_size_cells(node->parent);
+       entrylen = (addr_cells + size_cells) * sizeof(cell_t);
+
+       if ((prop->val.len % entrylen) != 0)
+               FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
+                    "(#address-cells == %d, #size-cells == %d)",
+                    node->fullpath, prop->val.len, addr_cells, size_cells);
+}
+NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+
+static void check_ranges_format(struct check *c, struct node *dt,
+                               struct node *node)
+{
+       struct property *prop;
+       int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
+
+       prop = get_property(node, "ranges");
+       if (!prop)
+               return;
+
+       if (!node->parent) {
+               FAIL(c, "Root node has a \"ranges\" property");
+               return;
+       }
+
+       p_addr_cells = node_addr_cells(node->parent);
+       p_size_cells = node_size_cells(node->parent);
+       c_addr_cells = node_addr_cells(node);
+       c_size_cells = node_size_cells(node);
+       entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
+
+       if (prop->val.len == 0) {
+               if (p_addr_cells != c_addr_cells)
+                       FAIL(c, "%s has empty \"ranges\" property but its "
+                            "#address-cells (%d) differs from %s (%d)",
+                            node->fullpath, c_addr_cells, node->parent->fullpath,
+                            p_addr_cells);
+               if (p_size_cells != c_size_cells)
+                       FAIL(c, "%s has empty \"ranges\" property but its "
+                            "#size-cells (%d) differs from %s (%d)",
+                            node->fullpath, c_size_cells, node->parent->fullpath,
+                            p_size_cells);
+       } else if ((prop->val.len % entrylen) != 0) {
+               FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
+                    "(parent #address-cells == %d, child #address-cells == %d, "
+                    "#size-cells == %d)", node->fullpath, prop->val.len,
+                    p_addr_cells, c_addr_cells, c_size_cells);
+       }
+}
+NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+
+/*
+ * Style checks
+ */
+static void check_avoid_default_addr_size(struct check *c, struct node *dt,
+                                         struct node *node)
+{
+       struct property *reg, *ranges;
+
+       if (!node->parent)
+               return; /* Ignore root node */
+
+       reg = get_property(node, "reg");
+       ranges = get_property(node, "ranges");
+
+       if (!reg && !ranges)
+               return;
+
+       if ((node->parent->addr_cells == -1))
+               FAIL(c, "Relying on default #address-cells value for %s",
+                    node->fullpath);
+
+       if ((node->parent->size_cells == -1))
+               FAIL(c, "Relying on default #size-cells value for %s",
+                    node->fullpath);
+}
+NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+
+static void check_obsolete_chosen_interrupt_controller(struct check *c,
+                                                      struct node *dt)
+{
+       struct node *chosen;
+       struct property *prop;
+
+       chosen = get_node_by_path(dt, "/chosen");
+       if (!chosen)
+               return;
+
+       prop = get_property(chosen, "interrupt-controller");
+       if (prop)
+               FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
+                    "property");
+}
+TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+
+static struct check *check_table[] = {
+       &duplicate_node_names, &duplicate_property_names,
+       &name_is_string, &name_properties,
+       &explicit_phandles,
+       &phandle_references, &path_references,
+
+       &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+       &device_type_is_string, &model_is_string, &status_is_string,
+
+       &addr_size_cells, &reg_format, &ranges_format,
+
+       &avoid_default_addr_size,
+       &obsolete_chosen_interrupt_controller,
+};
+
+int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys);
+
+void process_checks(int force, struct boot_info *bi,
+                   int checkflag, int outversion, int boot_cpuid_phys)
+{
+       struct node *dt = bi->dt;
+       int i;
+       int error = 0;
+
+       for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+               struct check *c = check_table[i];
+
+               if (c->level != IGNORE)
+                       error = error || run_check(c, dt);
+       }
+
+       if (error) {
+               if (!force) {
+                       fprintf(stderr, "ERROR: Input tree has errors, aborting "
+                               "(use -f to force output)\n");
+                       exit(2);
+               } else if (quiet < 3) {
+                       fprintf(stderr, "Warning: Input tree has errors, "
+                               "output forced\n");
+               }
+       }
+
+       if (checkflag) {
+               if (error) {
+                       fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
+               } else {
+                       if (!check_semantics(bi->dt, outversion,
+                                            boot_cpuid_phys))
+                               fprintf(stderr, "Warning: Input tree has semantic errors\n");
+               }
+       }
+}
+
+/*
+ * Semantic check functions
+ */
+
+#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
+#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
+
+#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
+
+#define CHECK_HAVE(node, propname) \
+       do { \
+               if (! (prop = get_property((node), (propname)))) \
+                       DO_ERR("Missing \"%s\" property in %s\n", (propname), \
+                               (node)->fullpath); \
+       } while (0);
+
+#define CHECK_HAVE_WARN(node, propname) \
+       do { \
+               if (! (prop  = get_property((node), (propname)))) \
+                       WARNMSG("%s has no \"%s\" property\n", \
+                               (node)->fullpath, (propname)); \
+       } while (0)
+
+#define CHECK_HAVE_STRING(node, propname) \
+       do { \
+               CHECK_HAVE((node), (propname)); \
+               if (prop && !data_is_one_string(prop->val)) \
+                       DO_ERR("\"%s\" property in %s is not a string\n", \
+                               (propname), (node)->fullpath); \
+       } while (0)
+
+#define CHECK_HAVE_STREQ(node, propname, value) \
+       do { \
+               CHECK_HAVE_STRING((node), (propname)); \
+               if (prop && !streq(prop->val.val, (value))) \
+                       DO_ERR("%s has wrong %s, %s (should be %s\n", \
+                               (node)->fullpath, (propname), \
+                               prop->val.val, (value)); \
+       } while (0)
+
+#define CHECK_HAVE_ONECELL(node, propname) \
+       do { \
+               CHECK_HAVE((node), (propname)); \
+               if (prop && (prop->val.len != sizeof(cell_t))) \
+                       DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
+       } while (0)
+
+#define CHECK_HAVE_WARN_ONECELL(node, propname) \
+       do { \
+               CHECK_HAVE_WARN((node), (propname)); \
+               if (prop && (prop->val.len != sizeof(cell_t))) \
+                       DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
+       } while (0)
+
+#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
+       do { \
+               struct node *ref; \
+               CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
+               if (prop) {\
+                       cell_t phandle = propval_cell(prop); \
+                       if ((phandle == 0) || (phandle == -1)) { \
+                               DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
+                       } else { \
+                               ref = get_node_by_phandle((root), propval_cell(prop)); \
+                               if (! ref) \
+                                       DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
+                       } \
+               } \
+       } while (0)
+
+#define CHECK_HAVE_WARN_STRING(node, propname) \
+       do { \
+               CHECK_HAVE_WARN((node), (propname)); \
+               if (prop && !data_is_one_string(prop->val)) \
+                       DO_ERR("\"%s\" property in %s is not a string\n", \
+                               (propname), (node)->fullpath); \
+       } while (0)
+
+static int check_root(struct node *root)
+{
+       struct property *prop;
+       int ok = 1;
+
+       CHECK_HAVE_STRING(root, "model");
+       CHECK_HAVE_WARN(root, "compatible");
+
+       return ok;
+}
+
+static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
+{
+       struct node *cpus, *cpu;
+       struct property *prop;
+       struct node *bootcpu = NULL;
+       int ok = 1;
+
+       cpus = get_subnode(root, "cpus");
+       if (! cpus) {
+               ERRMSG("Missing /cpus node\n");
+               return 0;
+       }
+
+       if (cpus->addr_cells != 1)
+               DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
+                      cpus->fullpath, cpus->addr_cells);
+       if (cpus->size_cells != 0)
+               DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
+                      cpus->fullpath, cpus->size_cells);
+
+       for_each_child(cpus, cpu) {
+               CHECK_HAVE_STREQ(cpu, "device_type", "cpu");
+
+               CHECK_HAVE_ONECELL(cpu, "reg");
+               if (prop) {
+                       cell_t unitnum;
+                       char *eptr;
+
+                       unitnum = strtol(get_unitname(cpu), &eptr, 16);
+                       if (*eptr) {
+                               WARNMSG("%s has bad format unit name %s (should be CPU number\n",
+                                       cpu->fullpath, get_unitname(cpu));
+                       } else if (unitnum != propval_cell(prop)) {
+                               WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
+                                      cpu->fullpath, get_unitname(cpu),
+                                      propval_cell(prop));
+                       }
+               }
+
+/*             CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
+/*             CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
+               CHECK_HAVE_ONECELL(cpu, "d-cache-size");
+               CHECK_HAVE_ONECELL(cpu, "i-cache-size");
+
+               CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
+               CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");
+
+               prop = get_property(cpu, "linux,boot-cpu");
+               if (prop) {
+                       if (prop->val.len)
+                               WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
+                                       cpu->fullpath);
+                       if (bootcpu)
+                               DO_ERR("Multiple boot cpus (%s and %s)\n",
+                                      bootcpu->fullpath, cpu->fullpath);
+                       else
+                               bootcpu = cpu;
+               }
+       }
+
+       if (outversion < 2) {
+               if (! bootcpu)
+                       WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
+       } else {
+               if (bootcpu)
+                       WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
+               if (boot_cpuid_phys == 0xfeedbeef)
+                       WARNMSG("physical boot CPU not set.  Use -b option to set\n");
+       }
+
+       return ok;
+}
+
+static int check_memory(struct node *root)
+{
+       struct node *mem;
+       struct property *prop;
+       int nnodes = 0;
+       int ok = 1;
+
+       for_each_child(root, mem) {
+               if (! strneq(mem->name, "memory", mem->basenamelen))
+                       continue;
+
+               nnodes++;
+
+               CHECK_HAVE_STREQ(mem, "device_type", "memory");
+               CHECK_HAVE(mem, "reg");
+       }
+
+       if (nnodes == 0) {
+               ERRMSG("No memory nodes\n");
+               return 0;
+       }
+
+       return ok;
+}
+
+int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
+{
+       int ok = 1;
+
+       ok = ok && check_root(dt);
+       ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
+       ok = ok && check_memory(dt);
+       if (! ok)
+               return 0;
+
+       return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/data.c b/arch/powerpc/boot/dtc-src/data.c
new file mode 100644 (file)
index 0000000..a94718c
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+void data_free(struct data d)
+{
+       struct marker *m, *nm;
+
+       m = d.markers;
+       while (m) {
+               nm = m->next;
+               free(m->ref);
+               free(m);
+               m = nm;
+       }
+
+       assert(!d.val || d.asize);
+
+       if (d.val)
+               free(d.val);
+}
+
+struct data data_grow_for(struct data d, int xlen)
+{
+       struct data nd;
+       int newsize;
+
+       /* we must start with an allocated datum */
+       assert(!d.val || d.asize);
+
+       if (xlen == 0)
+               return d;
+
+       nd = d;
+
+       newsize = xlen;
+
+       while ((d.len + xlen) > newsize)
+               newsize *= 2;
+
+       nd.asize = newsize;
+       nd.val = xrealloc(d.val, newsize);
+
+       assert(nd.asize >= (d.len + xlen));
+
+       return nd;
+}
+
+struct data data_copy_mem(const char *mem, int len)
+{
+       struct data d;
+
+       d = data_grow_for(empty_data, len);
+
+       d.len = len;
+       memcpy(d.val, mem, len);
+
+       return d;
+}
+
+static char get_oct_char(const char *s, int *i)
+{
+       char x[4];
+       char *endx;
+       long val;
+
+       x[3] = '\0';
+       x[0] = s[(*i)];
+       if (x[0]) {
+               x[1] = s[(*i)+1];
+               if (x[1])
+                       x[2] = s[(*i)+2];
+       }
+
+       val = strtol(x, &endx, 8);
+       if ((endx - x) == 0)
+               fprintf(stderr, "Empty \\nnn escape\n");
+
+       (*i) += endx - x;
+       return val;
+}
+
+static char get_hex_char(const char *s, int *i)
+{
+       char x[3];
+       char *endx;
+       long val;
+
+       x[2] = '\0';
+       x[0] = s[(*i)];
+       if (x[0])
+               x[1] = s[(*i)+1];
+
+       val = strtol(x, &endx, 16);
+       if ((endx - x) == 0)
+               fprintf(stderr, "Empty \\x escape\n");
+
+       (*i) += endx - x;
+       return val;
+}
+
+struct data data_copy_escape_string(const char *s, int len)
+{
+       int i = 0;
+       struct data d;
+       char *q;
+
+       d = data_grow_for(empty_data, strlen(s)+1);
+
+       q = d.val;
+       while (i < len) {
+               char c = s[i++];
+
+               if (c != '\\') {
+                       q[d.len++] = c;
+                       continue;
+               }
+
+               c = s[i++];
+               assert(c);
+               switch (c) {
+               case 'a':
+                       q[d.len++] = '\a';
+                       break;
+               case 'b':
+                       q[d.len++] = '\b';
+                       break;
+               case 't':
+                       q[d.len++] = '\t';
+                       break;
+               case 'n':
+                       q[d.len++] = '\n';
+                       break;
+               case 'v':
+                       q[d.len++] = '\v';
+                       break;
+               case 'f':
+                       q[d.len++] = '\f';
+                       break;
+               case 'r':
+                       q[d.len++] = '\r';
+                       break;
+               case '0':
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+                       i--; /* need to re-read the first digit as
+                             * part of the octal value */
+                       q[d.len++] = get_oct_char(s, &i);
+                       break;
+               case 'x':
+                       q[d.len++] = get_hex_char(s, &i);
+                       break;
+               default:
+                       q[d.len++] = c;
+               }
+       }
+
+       q[d.len++] = '\0';
+       return d;
+}
+
+struct data data_copy_file(FILE *f, size_t len)
+{
+       struct data d;
+
+       d = data_grow_for(empty_data, len);
+
+       d.len = len;
+       fread(d.val, len, 1, f);
+
+       return d;
+}
+
+struct data data_append_data(struct data d, const void *p, int len)
+{
+       d = data_grow_for(d, len);
+       memcpy(d.val + d.len, p, len);
+       d.len += len;
+       return d;
+}
+
+struct data data_insert_at_marker(struct data d, struct marker *m,
+                                 const void *p, int len)
+{
+       d = data_grow_for(d, len);
+       memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
+       memcpy(d.val + m->offset, p, len);
+       d.len += len;
+
+       /* Adjust all markers after the one we're inserting at */
+       m = m->next;
+       for_each_marker(m)
+               m->offset += len;
+       return d;
+}
+
+struct data data_append_markers(struct data d, struct marker *m)
+{
+       struct marker **mp = &d.markers;
+
+       /* Find the end of the markerlist */
+       while (*mp)
+               mp = &((*mp)->next);
+       *mp = m;
+       return d;
+}
+
+struct data data_merge(struct data d1, struct data d2)
+{
+       struct data d;
+       struct marker *m2 = d2.markers;
+
+       d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
+
+       /* Adjust for the length of d1 */
+       for_each_marker(m2)
+               m2->offset += d1.len;
+
+       d2.markers = NULL; /* So data_free() doesn't clobber them */
+       data_free(d2);
+
+       return d;
+}
+
+struct data data_append_cell(struct data d, cell_t word)
+{
+       cell_t beword = cpu_to_be32(word);
+
+       return data_append_data(d, &beword, sizeof(beword));
+}
+
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+{
+       struct fdt_reserve_entry bere;
+
+       bere.address = cpu_to_be64(re->address);
+       bere.size = cpu_to_be64(re->size);
+
+       return data_append_data(d, &bere, sizeof(bere));
+}
+
+struct data data_append_addr(struct data d, u64 addr)
+{
+       u64 beaddr = cpu_to_be64(addr);
+
+       return data_append_data(d, &beaddr, sizeof(beaddr));
+}
+
+struct data data_append_byte(struct data d, uint8_t byte)
+{
+       return data_append_data(d, &byte, 1);
+}
+
+struct data data_append_zeroes(struct data d, int len)
+{
+       d = data_grow_for(d, len);
+
+       memset(d.val + d.len, 0, len);
+       d.len += len;
+       return d;
+}
+
+struct data data_append_align(struct data d, int align)
+{
+       int newlen = ALIGN(d.len, align);
+       return data_append_zeroes(d, newlen - d.len);
+}
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref)
+{
+       struct marker *m;
+
+       m = xmalloc(sizeof(*m));
+       m->offset = d.len;
+       m->type = type;
+       m->ref = ref;
+       m->next = NULL;
+
+       return data_append_markers(d, m);
+}
+
+int data_is_one_string(struct data d)
+{
+       int i;
+       int len = d.len;
+
+       if (len == 0)
+               return 0;
+
+       for (i = 0; i < len-1; i++)
+               if (d.val[i] == '\0')
+                       return 0;
+
+       if (d.val[len-1] != '\0')
+               return 0;
+
+       return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.l b/arch/powerpc/boot/dtc-src/dtc-lexer.l
new file mode 100644 (file)
index 0000000..c811b22
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+%option noyywrap nounput yylineno
+
+%x INCLUDE
+%x BYTESTRING
+%x PROPNODENAME
+%s V1
+
+PROPNODECHAR   [a-zA-Z0-9,._+*#?@-]
+PATHCHAR       ({PROPNODECHAR}|[/])
+LABEL          [a-zA-Z_][a-zA-Z0-9_]*
+
+%{
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG     1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...)       fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...)       do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT()        if (dts_version == 0) { \
+                               DPRINT("<INITIAL>\n"); \
+                               BEGIN(INITIAL); \
+                       } else { \
+                               DPRINT("<V1>\n"); \
+                               BEGIN(V1); \
+                       }
+%}
+
+%%
+<*>"/include/"         BEGIN(INCLUDE);
+
+<INCLUDE>\"[^"\n]*\"   {
+                       yytext[strlen(yytext) - 1] = 0;
+                       if (!push_input_file(yytext + 1)) {
+                               /* Some unrecoverable error.*/
+                               exit(1);
+                       }
+                       BEGIN_DEFAULT();
+               }
+
+
+<*><<EOF>>             {
+                       if (!pop_input_file()) {
+                               yyterminate();
+                       }
+               }
+
+<*>\"([^\\"]|\\.)*\"   {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("String: %s\n", yytext);
+                       yylval.data = data_copy_escape_string(yytext+1,
+                                       yyleng-2);
+                       yylloc.first_line = yylineno;
+                       return DT_STRING;
+               }
+
+<*>"/dts-v1/"  {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Keyword: /dts-v1/\n");
+                       dts_version = 1;
+                       BEGIN_DEFAULT();
+                       return DT_V1;
+               }
+
+<*>"/memreserve/"      {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Keyword: /memreserve/\n");
+                       BEGIN_DEFAULT();
+                       return DT_MEMRESERVE;
+               }
+
+<*>{LABEL}:    {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Label: %s\n", yytext);
+                       yylval.labelref = strdup(yytext);
+                       yylval.labelref[yyleng-1] = '\0';
+                       return DT_LABEL;
+               }
+
+<INITIAL>[bodh]# {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       if (*yytext == 'b')
+                               yylval.cbase = 2;
+                       else if (*yytext == 'o')
+                               yylval.cbase = 8;
+                       else if (*yytext == 'd')
+                               yylval.cbase = 10;
+                       else
+                               yylval.cbase = 16;
+                       DPRINT("Base: %d\n", yylval.cbase);
+                       return DT_BASE;
+               }
+
+<INITIAL>[0-9a-fA-F]+  {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.literal = strdup(yytext);
+                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       return DT_LEGACYLITERAL;
+               }
+
+<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.literal = strdup(yytext);
+                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       return DT_LITERAL;
+               }
+
+\&{LABEL}      {       /* label reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Ref: %s\n", yytext+1);
+                       yylval.labelref = strdup(yytext+1);
+                       return DT_REF;
+               }
+
+"&{/"{PATHCHAR}+\}     {       /* new-style path reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yytext[yyleng-1] = '\0';
+                       DPRINT("Ref: %s\n", yytext+2);
+                       yylval.labelref = strdup(yytext+2);
+                       return DT_REF;
+               }
+
+<INITIAL>"&/"{PATHCHAR}+ {     /* old-style path reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Ref: %s\n", yytext+1);
+                       yylval.labelref = strdup(yytext+1);
+                       return DT_REF;
+               }
+
+<BYTESTRING>[0-9a-fA-F]{2} {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.byte = strtol(yytext, NULL, 16);
+                       DPRINT("Byte: %02x\n", (int)yylval.byte);
+                       return DT_BYTE;
+               }
+
+<BYTESTRING>"]"        {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("/BYTESTRING\n");
+                       BEGIN_DEFAULT();
+                       return ']';
+               }
+
+<PROPNODENAME>{PROPNODECHAR}+ {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("PropNodeName: %s\n", yytext);
+                       yylval.propnodename = strdup(yytext);
+                       BEGIN_DEFAULT();
+                       return DT_PROPNODENAME;
+               }
+
+
+<*>[[:space:]]+        /* eat whitespace */
+
+<*>"/*"([^*]|\*+[^*/])*\*+"/"  {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Comment: %s\n", yytext);
+                       /* eat comments */
+               }
+
+<*>"//".*\n    /* eat line comments */
+
+<*>.           {
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+                               (unsigned)yytext[0]);
+                       if (yytext[0] == '[') {
+                               DPRINT("<BYTESTRING>\n");
+                               BEGIN(BYTESTRING);
+                       }
+                       if ((yytext[0] == '{')
+                           || (yytext[0] == ';')) {
+                               DPRINT("<PROPNODENAME>\n");
+                               BEGIN(PROPNODENAME);
+                       }
+                       return yytext[0];
+               }
+
+%%
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+       int filenum;
+       FILE *file;
+       YY_BUFFER_STATE yy_prev_buf;
+       int yy_prev_lineno;
+       struct incl_file *prev;
+};
+
+struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH      (100)
+
+static int incl_depth = 0;
+
+
+int push_input_file(const char *filename)
+{
+       FILE *f;
+       struct incl_file *incl_file;
+
+       if (!filename) {
+               yyerror("No include file name given.");
+               return 0;
+       }
+
+       if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
+               yyerror("Includes nested too deeply");
+               return 0;
+       }
+
+       f = dtc_open_file(filename);
+
+       incl_file = malloc(sizeof(struct incl_file));
+       if (!incl_file) {
+               yyerror("Can not allocate include file space.");
+               return 0;
+       }
+
+       /*
+        * Save current context.
+        */
+       incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+       incl_file->yy_prev_lineno = yylineno;
+       incl_file->filenum = srcpos_filenum;
+       incl_file->file = yyin;
+       incl_file->prev = incl_file_stack;
+
+       incl_file_stack = incl_file;
+
+       /*
+        * Establish new context.
+        */
+       srcpos_filenum = lookup_file_name(filename, 0);
+       yylineno = 1;
+       yyin = f;
+       yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+
+       return 1;
+}
+
+
+int pop_input_file(void)
+{
+       struct incl_file *incl_file;
+
+       if (incl_file_stack == 0)
+               return 0;
+
+       fclose(yyin);
+
+       /*
+        * Pop.
+        */
+       --incl_depth;
+       incl_file = incl_file_stack;
+       incl_file_stack = incl_file->prev;
+
+       /*
+        * Recover old context.
+        */
+       yy_delete_buffer(YY_CURRENT_BUFFER);
+       yy_switch_to_buffer(incl_file->yy_prev_buf);
+       yylineno = incl_file->yy_prev_lineno;
+       srcpos_filenum = incl_file->filenum;
+       yyin = incl_file->file;
+
+       /*
+        * Free old state.
+        */
+       free(incl_file);
+
+       if (YY_CURRENT_BUFFER == 0)
+               return 0;
+
+       return 1;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped b/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped
new file mode 100644 (file)
index 0000000..d0f7424
--- /dev/null
@@ -0,0 +1,2174 @@
+#line 2 "dtc-lexer.lex.c"
+
+#line 4 "dtc-lexer.lex.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = (yy_hold_char); \
+               YY_RESTORE_YY_MORE_OFFSET \
+               (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       (yytext_ptr) = yy_bp; \
+       yyleng = (size_t) (yy_cp - yy_bp); \
+       (yy_hold_char) = *yy_cp; \
+       *yy_cp = '\0'; \
+       (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 20
+#define YY_END_OF_BUFFER 21
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static yyconst flex_int16_t yy_accept[94] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       21,   19,   16,   16,   19,   19,   19,    8,    8,   19,
+        8,   19,   19,   19,   19,   14,   15,   15,   19,    9,
+        9,   16,    0,    3,    0,    0,   10,    0,    0,    0,
+        0,    0,    0,    8,    8,    6,    0,    7,    0,    2,
+        0,   13,   13,   15,   15,    9,    0,   12,   10,    0,
+        0,    0,    0,   18,    0,    0,    0,    2,    9,    0,
+       17,    0,    0,    0,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    4,    0,    0,    1,    0,    0,
+        0,    5,    0
+
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        2,    2,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    6,    1,    1,
+        1,    7,    8,    8,    9,    8,   10,   11,   12,   13,
+       13,   13,   13,   13,   13,   13,   13,   14,    1,    1,
+        1,    1,    8,    8,   15,   15,   15,   15,   15,   15,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16,   16,   16,   16,   16,   16,   16,   17,   16,   16,
+        1,   18,   19,    1,   16,    1,   15,   20,   21,   22,
+
+       23,   15,   16,   24,   25,   16,   16,   26,   27,   28,
+       24,   16,   16,   29,   30,   31,   32,   33,   16,   17,
+       16,   16,   34,    1,   35,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[36] =
+    {   0,
+        1,    1,    1,    1,    2,    1,    2,    2,    2,    3,
+        4,    4,    4,    5,    6,    7,    7,    1,    1,    6,
+        6,    6,    6,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    8,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[107] =
+    {   0,
+        0,    0,   32,    0,   53,    0,   76,    0,  108,  111,
+      280,  288,   37,   39,   33,   36,  106,    0,  123,  146,
+      255,  251,   45,    0,  159,  288,    0,   53,  108,  172,
+      114,  127,  158,  288,  245,    0,    0,  234,  235,  236,
+      197,  195,  199,    0,    0,  288,    0,  288,  160,  288,
+      183,  288,    0,    0,  183,  182,    0,    0,    0,    0,
+      204,  189,  207,  288,  179,  187,  180,  194,    0,  171,
+      288,  196,  178,  174,  288,  169,  169,  177,  165,  153,
+      143,  155,  137,  118,  288,  122,   42,  288,   36,   36,
+       40,  288,  288,  212,  218,  223,  229,  234,  239,  245,
+
+      251,  255,  262,  270,  275,  280
+    } ;
+
+static yyconst flex_int16_t yy_def[107] =
+    {   0,
+       93,    1,    1,    3,    3,    5,   93,    7,    3,    3,
+       93,   93,   93,   93,   94,   95,   93,   96,   93,   19,
+       19,   20,   97,   98,   20,   93,   99,  100,   95,   93,
+       93,   93,   94,   93,   94,  101,  102,   93,  103,  104,
+       93,   93,   93,   96,   19,   93,   20,   93,   97,   93,
+       97,   93,   20,   99,  100,   93,  105,  101,  102,  106,
+      103,  103,  104,   93,   93,   93,   93,   94,  105,  106,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,    0,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93
+    } ;
+
+static yyconst flex_int16_t yy_nxt[324] =
+    {   0,
+       12,   13,   14,   15,   12,   16,   12,   12,   12,   17,
+       18,   18,   18,   12,   19,   20,   20,   12,   12,   21,
+       19,   21,   19,   22,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   12,   12,   23,   34,   12,   32,   32,
+       32,   32,   12,   12,   12,   36,   20,   33,   50,   92,
+       35,   20,   20,   20,   20,   20,   15,   54,   91,   54,
+       54,   54,   51,   24,   24,   24,   46,   25,   90,   38,
+       89,   26,   25,   25,   25,   25,   12,   13,   14,   15,
+       27,   12,   27,   27,   27,   17,   27,   27,   27,   12,
+       28,   28,   28,   12,   12,   28,   28,   28,   28,   28,
+
+       28,   28,   28,   28,   28,   28,   28,   28,   28,   12,
+       12,   15,   39,   29,   15,   40,   29,   93,   30,   31,
+       31,   30,   31,   31,   56,   56,   56,   41,   32,   32,
+       42,   88,   43,   45,   45,   45,   46,   45,   47,   47,
+       87,   38,   45,   45,   45,   45,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   86,
+       47,   34,   33,   50,   85,   47,   47,   47,   47,   53,
+       53,   53,   84,   53,   83,   35,   82,   51,   53,   53,
+       53,   53,   56,   56,   56,   93,   68,   54,   57,   54,
+       54,   54,   56,   56,   56,   62,   46,   34,   71,   81,
+
+       80,   79,   78,   77,   76,   75,   74,   73,   72,   64,
+       62,   35,   33,   33,   33,   33,   33,   33,   33,   33,
+       37,   67,   66,   37,   37,   37,   44,   65,   44,   49,
+       49,   49,   49,   49,   49,   49,   49,   52,   64,   52,
+       54,   62,   54,   60,   54,   54,   55,   93,   55,   55,
+       55,   55,   58,   58,   58,   48,   58,   58,   59,   48,
+       59,   59,   61,   61,   61,   61,   61,   61,   61,   61,
+       63,   63,   63,   63,   63,   63,   63,   63,   69,   93,
+       69,   70,   70,   70,   93,   70,   70,   11,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93
+    } ;
+
+static yyconst flex_int16_t yy_chk[324] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    3,   15,    3,   13,   13,
+       14,   14,    3,    3,    3,   16,    3,   23,   23,   91,
+       15,    3,    3,    3,    3,    3,    5,   28,   90,   28,
+       28,   28,   23,    5,    5,    5,   28,    5,   89,   16,
+       87,    5,    5,    5,    5,    5,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+
+        7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        7,    9,   17,    9,   10,   17,   10,   29,    9,    9,
+        9,   10,   10,   10,   31,   31,   31,   17,   32,   32,
+       17,   86,   17,   19,   19,   19,   19,   19,   19,   19,
+       84,   29,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   20,   20,   20,   83,
+       20,   33,   49,   49,   82,   20,   20,   20,   20,   25,
+       25,   25,   81,   25,   80,   33,   79,   49,   25,   25,
+       25,   25,   30,   30,   30,   51,   51,   55,   30,   55,
+       55,   55,   56,   56,   56,   62,   55,   68,   62,   78,
+
+       77,   76,   74,   73,   72,   70,   67,   66,   65,   63,
+       61,   68,   94,   94,   94,   94,   94,   94,   94,   94,
+       95,   43,   42,   95,   95,   95,   96,   41,   96,   97,
+       97,   97,   97,   97,   97,   97,   97,   98,   40,   98,
+       99,   39,   99,   38,   99,   99,  100,   35,  100,  100,
+      100,  100,  101,  101,  101,   22,  101,  101,  102,   21,
+      102,  102,  103,  103,  103,  103,  103,  103,  103,  103,
+      104,  104,  104,  104,  104,  104,  104,  104,  105,   11,
+      105,  106,  106,  106,    0,  106,  106,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93,   93,   93,   93,   93,   93,   93,   93,
+       93,   93,   93
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[21] =
+    {   0,
+0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 
+    0,     };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "dtc-lexer.l"
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+
+
+
+#line 33 "dtc-lexer.l"
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG     1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...)       fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...)       do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT()        if (dts_version == 0) { \
+                               DPRINT("<INITIAL>\n"); \
+                               BEGIN(INITIAL); \
+                       } else { \
+                               DPRINT("<V1>\n"); \
+                               BEGIN(V1); \
+                       }
+#line 627 "dtc-lexer.lex.c"
+
+#define INITIAL 0
+#define INCLUDE 1
+#define BYTESTRING 2
+#define PROPNODENAME 3
+#define V1 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               size_t n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+    
+#line 57 "dtc-lexer.l"
+
+#line 784 "dtc-lexer.lex.c"
+
+       if ( !(yy_init) )
+               {
+               (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! (yy_start) )
+                       (yy_start) = 1; /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       yyensure_buffer_stack ();
+                       YY_CURRENT_BUFFER_LVALUE =
+                               yy_create_buffer(yyin,YY_BUF_SIZE );
+               }
+
+               yy_load_buffer_state( );
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = (yy_c_buf_p);
+
+               /* Support of yytext. */
+               *yy_cp = (yy_hold_char);
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = (yy_start);
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               (yy_last_accepting_state) = yy_current_state;
+                               (yy_last_accepting_cpos) = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 94 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 288 );
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+               if ( yy_act == 0 )
+                       { /* have to back up */
+                       yy_cp = (yy_last_accepting_cpos);
+                       yy_current_state = (yy_last_accepting_state);
+                       yy_act = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+               if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+                       {
+                       int yyl;
+                       for ( yyl = 0; yyl < yyleng; ++yyl )
+                               if ( yytext[yyl] == '\n' )
+                                          
+    yylineno++;
+;
+                       }
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = (yy_hold_char);
+                       yy_cp = (yy_last_accepting_cpos);
+                       yy_current_state = (yy_last_accepting_state);
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 58 "dtc-lexer.l"
+BEGIN(INCLUDE);
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 60 "dtc-lexer.l"
+{
+                       yytext[strlen(yytext) - 1] = 0;
+                       if (!push_input_file(yytext + 1)) {
+                               /* Some unrecoverable error.*/
+                               exit(1);
+                       }
+                       BEGIN_DEFAULT();
+               }
+       YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(INCLUDE):
+case YY_STATE_EOF(BYTESTRING):
+case YY_STATE_EOF(PROPNODENAME):
+case YY_STATE_EOF(V1):
+#line 70 "dtc-lexer.l"
+{
+                       if (!pop_input_file()) {
+                               yyterminate();
+                       }
+               }
+       YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 76 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("String: %s\n", yytext);
+                       yylval.data = data_copy_escape_string(yytext+1,
+                                       yyleng-2);
+                       yylloc.first_line = yylineno;
+                       return DT_STRING;
+               }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 86 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Keyword: /dts-v1/\n");
+                       dts_version = 1;
+                       BEGIN_DEFAULT();
+                       return DT_V1;
+               }
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 95 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Keyword: /memreserve/\n");
+                       BEGIN_DEFAULT();
+                       return DT_MEMRESERVE;
+               }
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 103 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Label: %s\n", yytext);
+                       yylval.labelref = strdup(yytext);
+                       yylval.labelref[yyleng-1] = '\0';
+                       return DT_LABEL;
+               }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 112 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       if (*yytext == 'b')
+                               yylval.cbase = 2;
+                       else if (*yytext == 'o')
+                               yylval.cbase = 8;
+                       else if (*yytext == 'd')
+                               yylval.cbase = 10;
+                       else
+                               yylval.cbase = 16;
+                       DPRINT("Base: %d\n", yylval.cbase);
+                       return DT_BASE;
+               }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.literal = strdup(yytext);
+                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       return DT_LEGACYLITERAL;
+               }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 135 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.literal = strdup(yytext);
+                       DPRINT("Literal: '%s'\n", yylval.literal);
+                       return DT_LITERAL;
+               }
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 143 "dtc-lexer.l"
+{      /* label reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Ref: %s\n", yytext+1);
+                       yylval.labelref = strdup(yytext+1);
+                       return DT_REF;
+               }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 151 "dtc-lexer.l"
+{      /* new-style path reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yytext[yyleng-1] = '\0';
+                       DPRINT("Ref: %s\n", yytext+2);
+                       yylval.labelref = strdup(yytext+2);
+                       return DT_REF;
+               }
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 160 "dtc-lexer.l"
+{      /* old-style path reference */
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Ref: %s\n", yytext+1);
+                       yylval.labelref = strdup(yytext+1);
+                       return DT_REF;
+               }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 168 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       yylval.byte = strtol(yytext, NULL, 16);
+                       DPRINT("Byte: %02x\n", (int)yylval.byte);
+                       return DT_BYTE;
+               }
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 176 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("/BYTESTRING\n");
+                       BEGIN_DEFAULT();
+                       return ']';
+               }
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 184 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("PropNodeName: %s\n", yytext);
+                       yylval.propnodename = strdup(yytext);
+                       BEGIN_DEFAULT();
+                       return DT_PROPNODENAME;
+               }
+       YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
+/* eat whitespace */
+       YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 196 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Comment: %s\n", yytext);
+                       /* eat comments */
+               }
+       YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+/* eat line comments */
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{
+                       yylloc.filenum = srcpos_filenum;
+                       yylloc.first_line = yylineno;
+                       DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+                               (unsigned)yytext[0]);
+                       if (yytext[0] == '[') {
+                               DPRINT("<BYTESTRING>\n");
+                               BEGIN(BYTESTRING);
+                       }
+                       if ((yytext[0] == '{')
+                           || (yytext[0] == ';')) {
+                               DPRINT("<PROPNODENAME>\n");
+                               BEGIN(PROPNODENAME);
+                       }
+                       return yytext[0];
+               }
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 222 "dtc-lexer.l"
+ECHO;
+       YY_BREAK
+#line 1111 "dtc-lexer.lex.c"
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = (yy_hold_char);
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state(  );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++(yy_c_buf_p);
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = (yy_c_buf_p);
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer(  ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               (yy_did_buffer_switch_on_eof) = 0;
+
+                               if ( yywrap( ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! (yy_did_buffer_switch_on_eof) )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               (yy_c_buf_p) =
+                                       (yytext_ptr) + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state(  );
+
+                               yy_cp = (yy_c_buf_p);
+                               yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               (yy_c_buf_p) =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+                               yy_current_state = yy_get_previous_state(  );
+
+                               yy_cp = (yy_c_buf_p);
+                               yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       register char *source = (yytext_ptr);
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+       else
+               {
+                       int num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+                       int yy_c_buf_p_offset =
+                               (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+                                               number_to_move - 1;
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       (yy_n_chars), (size_t) num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       if ( (yy_n_chars) == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart(yyin  );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       (yy_n_chars) += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+       (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+    
+       yy_current_state = (yy_start);
+
+       for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       (yy_last_accepting_state) = yy_current_state;
+                       (yy_last_accepting_cpos) = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 94 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+       register int yy_is_jam;
+       register char *yy_cp = (yy_c_buf_p);
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               (yy_last_accepting_state) = yy_current_state;
+               (yy_last_accepting_cpos) = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 94 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 93);
+
+       return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+       int c;
+    
+       *(yy_c_buf_p) = (yy_hold_char);
+
+       if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+                       /* This was really a NUL. */
+                       *(yy_c_buf_p) = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = (yy_c_buf_p) - (yytext_ptr);
+                       ++(yy_c_buf_p);
+
+                       switch ( yy_get_next_buffer(  ) )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart(yyin );
+
+                                       /*FALLTHROUGH*/
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap( ) )
+                                               return EOF;
+
+                                       if ( ! (yy_did_buffer_switch_on_eof) )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       (yy_c_buf_p) = (yytext_ptr) + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) (yy_c_buf_p);    /* cast for 8-bit char's */
+       *(yy_c_buf_p) = '\0';   /* preserve yytext */
+       (yy_hold_char) = *++(yy_c_buf_p);
+
+       if ( c == '\n' )
+                  
+    yylineno++;
+;
+
+       return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+       if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+               YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+       }
+
+       yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+       yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+       /* TODO. We should be able to replace this entire function body
+        * with
+        *              yypop_buffer_state();
+        *              yypush_buffer_state(new_buffer);
+     */
+       yyensure_buffer_stack ();
+       if ( YY_CURRENT_BUFFER == new_buffer )
+               return;
+
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *(yy_c_buf_p) = (yy_hold_char);
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+       yy_load_buffer_state( );
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+       (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+       (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+       (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+       YY_BUFFER_STATE b;
+    
+       b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer(b,file );
+
+       return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+       if ( ! b )
+               return;
+
+       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yyfree((void *) b->yy_ch_buf  );
+
+       yyfree((void *) b  );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+       int oerrno = errno;
+    
+       yy_flush_buffer(b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+       errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == YY_CURRENT_BUFFER )
+               yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+       if (new_buffer == NULL)
+               return;
+
+       yyensure_buffer_stack();
+
+       /* This block is copied from yy_switch_to_buffer. */
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *(yy_c_buf_p) = (yy_hold_char);
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       /* Only push if top exists. Otherwise, replace top. */
+       if (YY_CURRENT_BUFFER)
+               (yy_buffer_stack_top)++;
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+       /* copied from yy_switch_to_buffer. */
+       yy_load_buffer_state( );
+       (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+       if (!YY_CURRENT_BUFFER)
+               return;
+
+       yy_delete_buffer(YY_CURRENT_BUFFER );
+       YY_CURRENT_BUFFER_LVALUE = NULL;
+       if ((yy_buffer_stack_top) > 0)
+               --(yy_buffer_stack_top);
+
+       if (YY_CURRENT_BUFFER) {
+               yy_load_buffer_state( );
+               (yy_did_buffer_switch_on_eof) = 1;
+       }
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+       int num_to_alloc;
+    
+       if (!(yy_buffer_stack)) {
+
+               /* First allocation is just for 2 elements, since we don't know if this
+                * scanner will even need a stack. We use 2 instead of 1 to avoid an
+                * immediate realloc on the next call.
+         */
+               num_to_alloc = 1;
+               (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               );
+               
+               memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+                               
+               (yy_buffer_stack_max) = num_to_alloc;
+               (yy_buffer_stack_top) = 0;
+               return;
+       }
+
+       if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+               /* Increase the buffer to prepare for a possible push. */
+               int grow_size = 8 /* arbitrary grow size */;
+
+               num_to_alloc = (yy_buffer_stack_max) + grow_size;
+               (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+                                                               ((yy_buffer_stack),
+                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               );
+
+               /* zero only the new slots.*/
+               memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+               (yy_buffer_stack_max) = num_to_alloc;
+       }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+       YY_BUFFER_STATE b;
+    
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer(b  );
+
+       return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+       return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+{
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+    
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = _yybytes_len + 2;
+       buf = (char *) yyalloc(n  );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < _yybytes_len; ++i )
+               buf[i] = yybytes[i];
+
+       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer(buf,n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               yytext[yyleng] = (yy_hold_char); \
+               (yy_c_buf_p) = yytext + yyless_macro_arg; \
+               (yy_hold_char) = *(yy_c_buf_p); \
+               *(yy_c_buf_p) = '\0'; \
+               yyleng = yyless_macro_arg; \
+               } \
+       while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+int yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    /* We do not touch yylineno unless the option is enabled. */
+    yylineno =  1;
+    
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+       while(YY_CURRENT_BUFFER){
+               yy_delete_buffer(YY_CURRENT_BUFFER  );
+               YY_CURRENT_BUFFER_LVALUE = NULL;
+               yypop_buffer_state();
+       }
+
+       /* Destroy the stack itself. */
+       yyfree((yy_buffer_stack) );
+       (yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+       return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+       free( (char *) ptr );   /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 222 "dtc-lexer.l"
+
+
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+       int filenum;
+       FILE *file;
+       YY_BUFFER_STATE yy_prev_buf;
+       int yy_prev_lineno;
+       struct incl_file *prev;
+};
+
+struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH      (100)
+
+static int incl_depth = 0;
+
+
+int push_input_file(const char *filename)
+{
+       FILE *f;
+       struct incl_file *incl_file;
+
+       if (!filename) {
+               yyerror("No include file name given.");
+               return 0;
+       }
+
+       if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
+               yyerror("Includes nested too deeply");
+               return 0;
+       }
+
+       f = dtc_open_file(filename);
+
+       incl_file = malloc(sizeof(struct incl_file));
+       if (!incl_file) {
+               yyerror("Can not allocate include file space.");
+               return 0;
+       }
+
+       /*
+        * Save current context.
+        */
+       incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+       incl_file->yy_prev_lineno = yylineno;
+       incl_file->filenum = srcpos_filenum;
+       incl_file->file = yyin;
+       incl_file->prev = incl_file_stack;
+
+       incl_file_stack = incl_file;
+
+       /*
+        * Establish new context.
+        */
+       srcpos_filenum = lookup_file_name(filename, 0);
+       yylineno = 1;
+       yyin = f;
+       yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+
+       return 1;
+}
+
+
+int pop_input_file(void)
+{
+       struct incl_file *incl_file;
+
+       if (incl_file_stack == 0)
+               return 0;
+
+       fclose(yyin);
+
+       /*
+        * Pop.
+        */
+       --incl_depth;
+       incl_file = incl_file_stack;
+       incl_file_stack = incl_file->prev;
+
+       /*
+        * Recover old context.
+        */
+       yy_delete_buffer(YY_CURRENT_BUFFER);
+       yy_switch_to_buffer(incl_file->yy_prev_buf);
+       yylineno = incl_file->yy_prev_lineno;
+       srcpos_filenum = incl_file->filenum;
+       yyin = incl_file->file;
+
+       /*
+        * Free old state.
+        */
+       free(incl_file);
+
+       if (YY_CURRENT_BUFFER == 0)
+               return 0;
+
+       return 1;
+}
+
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped b/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped
new file mode 100644 (file)
index 0000000..28e6ec0
--- /dev/null
@@ -0,0 +1,1983 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Using locations.  */
+#define YYLSP_NEEDED 1
+
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DT_V1 = 258,
+     DT_MEMRESERVE = 259,
+     DT_PROPNODENAME = 260,
+     DT_LITERAL = 261,
+     DT_LEGACYLITERAL = 262,
+     DT_BASE = 263,
+     DT_BYTE = 264,
+     DT_STRING = 265,
+     DT_LABEL = 266,
+     DT_REF = 267
+   };
+#endif
+/* Tokens.  */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 23 "dtc-parser.y"
+
+#include "dtc.h"
+#include "srcpos.h"
+
+int yylex(void);
+unsigned long long eval_literal(const char *s, int base, int bits);
+
+extern struct boot_info *the_boot_info;
+
+
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 34 "dtc-parser.y"
+{
+       char *propnodename;
+       char *literal;
+       char *labelref;
+       unsigned int cbase;
+       u8 byte;
+       struct data data;
+
+       u64 addr;
+       cell_t cell;
+       struct property *prop;
+       struct property *proplist;
+       struct node *node;
+       struct node *nodelist;
+       struct reserve_info *re;
+}
+/* Line 187 of yacc.c.  */
+#line 148 "dtc-parser.tab.c"
+       YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 216 of yacc.c.  */
+#line 173 "dtc-parser.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+    int i;
+#endif
+{
+  return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+            && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+        || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+            && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss;
+  YYSTYPE yyvs;
+    YYLTYPE yyls;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+      + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         YYSIZE_T yyi;                         \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  9
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   60
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  24
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  20
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  43
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  67
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   267
+
+#define YYTRANSLATE(YYX)                                               \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    23,    14,     2,    15,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    13,
+      19,    18,    20,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    21,     2,    22,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    16,     2,    17,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint8 yyprhs[] =
+{
+       0,     0,     3,     8,    11,    12,    15,    21,    22,    25,
+      27,    34,    36,    38,    41,    47,    48,    51,    57,    61,
+      64,    69,    74,    77,    80,    81,    84,    87,    88,    91,
+      94,    97,    98,   100,   102,   105,   106,   109,   112,   113,
+     116,   119,   123,   124
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      25,     0,    -1,     3,    13,    26,    31,    -1,    28,    31,
+      -1,    -1,    27,    26,    -1,    43,     4,    30,    30,    13,
+      -1,    -1,    29,    28,    -1,    27,    -1,    43,     4,    30,
+      14,    30,    13,    -1,     6,    -1,     7,    -1,    15,    32,
+      -1,    16,    33,    41,    17,    13,    -1,    -1,    33,    34,
+      -1,    43,     5,    18,    35,    13,    -1,    43,     5,    13,
+      -1,    36,    10,    -1,    36,    19,    37,    20,    -1,    36,
+      21,    40,    22,    -1,    36,    12,    -1,    35,    11,    -1,
+      -1,    35,    23,    -1,    36,    11,    -1,    -1,    37,    39,
+      -1,    37,    12,    -1,    37,    11,    -1,    -1,     8,    -1,
+       6,    -1,    38,     7,    -1,    -1,    40,     9,    -1,    40,
+      11,    -1,    -1,    42,    41,    -1,    42,    34,    -1,    43,
+       5,    32,    -1,    -1,    11,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,    85,    85,    89,    97,   100,   107,   115,   118,   125,
+     129,   136,   140,   147,   154,   162,   165,   172,   176,   183,
+     187,   191,   195,   199,   207,   210,   214,   222,   225,   229,
+     234,   242,   245,   249,   253,   261,   264,   268,   276,   279,
+     283,   291,   299,   302
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
+  "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
+  "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "';'", "'-'", "'/'", "'{'",
+  "'}'", "'='", "'<'", "'>'", "'['", "']'", "','", "$accept", "sourcefile",
+  "memreserves", "memreserve", "v0_memreserves", "v0_memreserve", "addr",
+  "devicetree", "nodedef", "proplist", "propdef", "propdata",
+  "propdataprefix", "celllist", "cellbase", "cellval", "bytestring",
+  "subnodes", "subnode", "label", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,    59,    45,    47,   123,   125,    61,    60,
+      62,    91,    93,    44
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    24,    25,    25,    26,    26,    27,    28,    28,    29,
+      29,    30,    30,    31,    32,    33,    33,    34,    34,    35,
+      35,    35,    35,    35,    36,    36,    36,    37,    37,    37,
+      37,    38,    38,    39,    39,    40,    40,    40,    41,    41,
+      41,    42,    43,    43
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     4,     2,     0,     2,     5,     0,     2,     1,
+       6,     1,     1,     2,     5,     0,     2,     5,     3,     2,
+       4,     4,     2,     2,     0,     2,     2,     0,     2,     2,
+       2,     0,     1,     1,     2,     0,     2,     2,     0,     2,
+       2,     3,     0,     1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       7,     0,    43,     0,     9,     0,     7,     0,     4,     1,
+       0,     3,     8,     0,     0,     4,     0,    15,    13,    11,
+      12,     0,     2,     5,     0,    38,     0,     0,     0,    16,
+       0,    38,     0,     0,     6,     0,    40,    39,     0,    10,
+      14,    18,    24,    41,     0,     0,    23,    17,    25,    19,
+      26,    22,    27,    35,    31,     0,    33,    32,    30,    29,
+      20,     0,    28,    36,    37,    21,    34
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     3,    14,     4,     5,     6,    27,    11,    18,    25,
+      29,    44,    45,    54,    61,    62,    55,    30,    31,     7
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -13
+static const yytype_int8 yypact[] =
+{
+      23,    11,   -13,    37,   -13,    -4,    18,    39,    18,   -13,
+      28,   -13,   -13,    34,    -4,    18,    41,   -13,   -13,   -13,
+     -13,    25,   -13,   -13,    34,    -3,    34,    33,    34,   -13,
+      30,    -3,    43,    36,   -13,    38,   -13,   -13,    20,   -13,
+     -13,   -13,   -13,   -13,     2,     9,   -13,   -13,   -13,   -13,
+     -13,   -13,   -13,   -13,    -2,    -6,   -13,   -13,   -13,   -13,
+     -13,    45,   -13,   -13,   -13,   -13,   -13
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -13,   -13,    35,    27,    47,   -13,   -12,    40,    17,   -13,
+      26,   -13,   -13,   -13,   -13,   -13,   -13,    29,   -13,    -8
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -43
+static const yytype_int8 yytable[] =
+{
+      16,    21,   -42,    63,    56,    64,    57,    16,     2,    58,
+      59,    10,    28,    46,    33,    47,    65,    32,    60,    49,
+      50,    51,   -42,    32,     8,    48,     1,   -42,    52,     2,
+      53,    19,    20,    41,     2,    15,    17,     9,    42,    26,
+      19,    20,    15,    13,    17,    24,    34,    35,    38,    39,
+      23,    40,    66,    12,    22,    43,     0,    36,     0,     0,
+      37
+};
+
+static const yytype_int8 yycheck[] =
+{
+       8,    13,     5,     9,     6,    11,     8,    15,    11,    11,
+      12,    15,    24,    11,    26,    13,    22,    25,    20,    10,
+      11,    12,     4,    31,    13,    23,     3,     4,    19,    11,
+      21,     6,     7,    13,    11,     8,    16,     0,    18,    14,
+       6,     7,    15,     4,    16,     4,    13,    17,     5,    13,
+      15,    13,     7,     6,    14,    38,    -1,    31,    -1,    -1,
+      31
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     3,    11,    25,    27,    28,    29,    43,    13,     0,
+      15,    31,    28,     4,    26,    27,    43,    16,    32,     6,
+       7,    30,    31,    26,     4,    33,    14,    30,    30,    34,
+      41,    42,    43,    30,    13,    17,    34,    41,     5,    13,
+      13,    13,    18,    32,    35,    36,    11,    13,    23,    10,
+      11,    12,    19,    21,    37,    40,     6,     8,    11,    12,
+      20,    38,    39,     9,    11,    22,     7
+};
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                (-2)
+#define YYEOF          0
+
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT                goto yyabortlab
+#define YYERROR                goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL         goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yytoken = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK (1);                                          \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;                                                 \
+    }                                                          \
+while (YYID (0))
+
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+       }                                                               \
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)                 \
+     fprintf (File, "%d.%d-%d.%d",                     \
+             (Loc).first_line, (Loc).first_column,     \
+             (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                   \
+do {                                                                     \
+  if (yydebug)                                                           \
+    {                                                                    \
+      YYFPRINTF (stderr, "%s ", Title);                                          \
+      yy_symbol_print (stderr,                                           \
+                 Type, Value, Location); \
+      YYFPRINTF (stderr, "\n");                                                  \
+    }                                                                    \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (yylocationp);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+       break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  YY_LOCATION_PRINT (yyoutput, *yylocationp);
+  YYFPRINTF (yyoutput, ": ");
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+    yytype_int16 *bottom;
+    yytype_int16 *top;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; bottom <= top; ++bottom)
+    YYFPRINTF (stderr, " %d", *bottom);
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                           \
+do {                                                           \
+  if (yydebug)                                                 \
+    yy_stack_print ((Bottom), (Top));                          \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule)
+    YYSTYPE *yyvsp;
+    YYLTYPE *yylsp;
+    int yyrule;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+            yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      fprintf (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+                      &(yyvsp[(yyi + 1) - (yynrhs)])
+                      , &(yylsp[(yyi + 1) - (yynrhs)])                );
+      fprintf (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)         \
+do {                                   \
+  if (yydebug)                         \
+    yy_reduce_print (yyvsp, yylsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+       switch (*++yyp)
+         {
+         case '\'':
+         case ',':
+           goto do_not_strip_quotes;
+
+         case '\\':
+           if (*++yyp != '\\')
+             goto do_not_strip_quotes;
+           /* Fall through.  */
+         default:
+           if (yyres)
+             yyres[yyn] = *yyp;
+           yyn++;
+           break;
+
+         case '"':
+           if (yyres)
+             yyres[yyn] = '\0';
+           return yyn;
+         }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+        constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+                   + sizeof yyexpecting - 1
+                   + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+                      * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+        YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+       if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+         {
+           if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+             {
+               yycount = 1;
+               yysize = yysize0;
+               yyformat[sizeof yyunexpected - 1] = '\0';
+               break;
+             }
+           yyarg[yycount++] = yytname[yyx];
+           yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+           yysize_overflow |= (yysize1 < yysize);
+           yysize = yysize1;
+           yyfmt = yystpcpy (yyfmt, yyprefix);
+           yyprefix = yyor;
+         }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+       return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+       {
+         /* Avoid sprintf, as that infringes on the user's name space.
+            Don't have undefined behavior even if the translation
+            produced a string with the wrong number of "%s"s.  */
+         char *yyp = yyresult;
+         int yyi = 0;
+         while ((*yyp = *yyf) != '\0')
+           {
+             if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+               {
+                 yyp += yytnamerr (yyp, yyarg[yyi++]);
+                 yyf += 2;
+               }
+             else
+               {
+                 yyp++;
+                 yyf++;
+               }
+           }
+       }
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    YYLTYPE *yylocationp;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (yylocationp);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+       break;
+    }
+}
+\f
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol.  */
+int yychar;
+
+/* The semantic value of the look-ahead symbol.  */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far.  */
+int yynerrs;
+/* Location data for the look-ahead symbol.  */
+YYLTYPE yylloc;
+
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+  
+  int yystate;
+  int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Look-ahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to reallocate them elsewhere.  */
+
+  /* The state stack.  */
+  yytype_int16 yyssa[YYINITDEPTH];
+  yytype_int16 *yyss = yyssa;
+  yytype_int16 *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  YYSTYPE *yyvsp;
+
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+  /* The locations where the error started and ended.  */
+  YYLTYPE yyerror_range[2];
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+  YYLTYPE yyloc;
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+  yylsp = yyls;
+#if YYLTYPE_IS_TRIVIAL
+  /* Initialize the default location before parsing starts.  */
+  yylloc.first_line   = yylloc.last_line   = 1;
+  yylloc.first_column = yylloc.last_column = 0;
+#endif
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to reallocate the stack.  Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       yytype_int16 *yyss1 = yyss;
+       YYLTYPE *yyls1 = yyls;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  This used to be a
+          conditional around just the two extra args, but that might
+          be undefined if yyoverflow is a macro.  */
+       yyoverflow (YY_("memory exhausted"),
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+       yyls = yyls1;
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+       goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       yytype_int16 *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyexhaustedlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+       YYSTACK_RELOCATE (yyls);
+#  undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+      yylsp = yyls + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     look-ahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to look-ahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a look-ahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the look-ahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+  *++yylsp = yylloc;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+  /* Default location.  */
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 86 "dtc-parser.y"
+    {
+                       the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node));
+               ;}
+    break;
+
+  case 3:
+#line 90 "dtc-parser.y"
+    {
+                       the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node));
+               ;}
+    break;
+
+  case 4:
+#line 97 "dtc-parser.y"
+    {
+                       (yyval.re) = NULL;
+               ;}
+    break;
+
+  case 5:
+#line 101 "dtc-parser.y"
+    {
+                       (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+               ;}
+    break;
+
+  case 6:
+#line 108 "dtc-parser.y"
+    {
+                       (yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
+               ;}
+    break;
+
+  case 7:
+#line 115 "dtc-parser.y"
+    {
+                       (yyval.re) = NULL;
+               ;}
+    break;
+
+  case 8:
+#line 119 "dtc-parser.y"
+    {
+                       (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+               ;}
+    break;
+
+  case 9:
+#line 126 "dtc-parser.y"
+    {
+                       (yyval.re) = (yyvsp[(1) - (1)].re);
+               ;}
+    break;
+
+  case 10:
+#line 130 "dtc-parser.y"
+    {
+                       (yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
+               ;}
+    break;
+
+  case 11:
+#line 137 "dtc-parser.y"
+    {
+                       (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+               ;}
+    break;
+
+  case 12:
+#line 141 "dtc-parser.y"
+    {
+                       (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
+               ;}
+    break;
+
+  case 13:
+#line 148 "dtc-parser.y"
+    {
+                       (yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
+               ;}
+    break;
+
+  case 14:
+#line 155 "dtc-parser.y"
+    {
+                       (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
+               ;}
+    break;
+
+  case 15:
+#line 162 "dtc-parser.y"
+    {
+                       (yyval.proplist) = NULL;
+               ;}
+    break;
+
+  case 16:
+#line 166 "dtc-parser.y"
+    {
+                       (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
+               ;}
+    break;
+
+  case 17:
+#line 173 "dtc-parser.y"
+    {
+                       (yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
+               ;}
+    break;
+
+  case 18:
+#line 177 "dtc-parser.y"
+    {
+                       (yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
+               ;}
+    break;
+
+  case 19:
+#line 184 "dtc-parser.y"
+    {
+                       (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+               ;}
+    break;
+
+  case 20:
+#line 188 "dtc-parser.y"
+    {
+                       (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+               ;}
+    break;
+
+  case 21:
+#line 192 "dtc-parser.y"
+    {
+                       (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+               ;}
+    break;
+
+  case 22:
+#line 196 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 23:
+#line 200 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 24:
+#line 207 "dtc-parser.y"
+    {
+                       (yyval.data) = empty_data;
+               ;}
+    break;
+
+  case 25:
+#line 211 "dtc-parser.y"
+    {
+                       (yyval.data) = (yyvsp[(1) - (2)].data);
+               ;}
+    break;
+
+  case 26:
+#line 215 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 27:
+#line 222 "dtc-parser.y"
+    {
+                       (yyval.data) = empty_data;
+               ;}
+    break;
+
+  case 28:
+#line 226 "dtc-parser.y"
+    {
+                       (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+               ;}
+    break;
+
+  case 29:
+#line 230 "dtc-parser.y"
+    {
+                       (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
+                                                             (yyvsp[(2) - (2)].labelref)), -1);
+               ;}
+    break;
+
+  case 30:
+#line 235 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 31:
+#line 242 "dtc-parser.y"
+    {
+                       (yyval.cbase) = 16;
+               ;}
+    break;
+
+  case 33:
+#line 250 "dtc-parser.y"
+    {
+                       (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+               ;}
+    break;
+
+  case 34:
+#line 254 "dtc-parser.y"
+    {
+                       (yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
+               ;}
+    break;
+
+  case 35:
+#line 261 "dtc-parser.y"
+    {
+                       (yyval.data) = empty_data;
+               ;}
+    break;
+
+  case 36:
+#line 265 "dtc-parser.y"
+    {
+                       (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+               ;}
+    break;
+
+  case 37:
+#line 269 "dtc-parser.y"
+    {
+                       (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+               ;}
+    break;
+
+  case 38:
+#line 276 "dtc-parser.y"
+    {
+                       (yyval.nodelist) = NULL;
+               ;}
+    break;
+
+  case 39:
+#line 280 "dtc-parser.y"
+    {
+                       (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
+               ;}
+    break;
+
+  case 40:
+#line 284 "dtc-parser.y"
+    {
+                       yyerror("syntax error: properties must precede subnodes\n");
+                       YYERROR;
+               ;}
+    break;
+
+  case 41:
+#line 292 "dtc-parser.y"
+    {
+                       (yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
+               ;}
+    break;
+
+  case 42:
+#line 299 "dtc-parser.y"
+    {
+                       (yyval.labelref) = NULL;
+               ;}
+    break;
+
+  case 43:
+#line 303 "dtc-parser.y"
+    {
+                       (yyval.labelref) = (yyvsp[(1) - (1)].labelref);
+               ;}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 1734 "dtc-parser.tab.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+  *++yylsp = yyloc;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+      {
+       YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+       if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+         {
+           YYSIZE_T yyalloc = 2 * yysize;
+           if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+             yyalloc = YYSTACK_ALLOC_MAXIMUM;
+           if (yymsg != yymsgbuf)
+             YYSTACK_FREE (yymsg);
+           yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+           if (yymsg)
+             yymsg_alloc = yyalloc;
+           else
+             {
+               yymsg = yymsgbuf;
+               yymsg_alloc = sizeof yymsgbuf;
+             }
+         }
+
+       if (0 < yysize && yysize <= yymsg_alloc)
+         {
+           (void) yysyntax_error (yymsg, yystate, yychar);
+           yyerror (yymsg);
+         }
+       else
+         {
+           yyerror (YY_("syntax error"));
+           if (yysize != 0)
+             goto yyexhaustedlab;
+         }
+      }
+#endif
+    }
+
+  yyerror_range[0] = yylloc;
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse look-ahead token after an
+        error, discard it.  */
+
+      if (yychar <= YYEOF)
+       {
+         /* Return failure if at end of input.  */
+         if (yychar == YYEOF)
+           YYABORT;
+       }
+      else
+       {
+         yydestruct ("Error: discarding",
+                     yytoken, &yylval, &yylloc);
+         yychar = YYEMPTY;
+       }
+    }
+
+  /* Else will try to reuse look-ahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  yyerror_range[0] = yylsp[1-yylen];
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;     /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+       {
+         yyn += YYTERROR;
+         if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+           {
+             yyn = yytable[yyn];
+             if (0 < yyn)
+               break;
+           }
+       }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+       YYABORT;
+
+      yyerror_range[0] = *yylsp;
+      yydestruct ("Error: popping",
+                 yystos[yystate], yyvsp, yylsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  *++yyvsp = yylval;
+
+  yyerror_range[1] = yylloc;
+  /* Using YYLLOC is tempting, but would change the location of
+     the look-ahead.  YYLOC is available though.  */
+  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+  *++yylsp = yyloc;
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+                yytoken, &yylval, &yylloc);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                 yystos[*yyssp], yyvsp, yylsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 308 "dtc-parser.y"
+
+
+void yyerror (char const *s)
+{
+       const char *fname = srcpos_filename_for_num(yylloc.filenum);
+
+       if (strcmp(fname, "-") == 0)
+               fname = "stdin";
+
+       fprintf(stderr, "%s:%d %s\n",
+               fname, yylloc.first_line, s);
+}
+
+unsigned long long eval_literal(const char *s, int base, int bits)
+{
+       unsigned long long val;
+       char *e;
+
+       errno = 0;
+       val = strtoull(s, &e, base);
+       if (*e)
+               yyerror("bad characters in literal");
+       else if ((errno == ERANGE)
+                || ((bits < 64) && (val >= (1ULL << bits))))
+               yyerror("literal out of range");
+       else if (errno != 0)
+               yyerror("bad literal");
+       return val;
+}
+
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped b/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped
new file mode 100644 (file)
index 0000000..4707b02
--- /dev/null
@@ -0,0 +1,111 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     DT_V1 = 258,
+     DT_MEMRESERVE = 259,
+     DT_PROPNODENAME = 260,
+     DT_LITERAL = 261,
+     DT_LEGACYLITERAL = 262,
+     DT_BASE = 263,
+     DT_BYTE = 264,
+     DT_STRING = 265,
+     DT_LABEL = 266,
+     DT_REF = 267
+   };
+#endif
+/* Tokens.  */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 34 "dtc-parser.y"
+{
+       char *propnodename;
+       char *literal;
+       char *labelref;
+       unsigned int cbase;
+       u8 byte;
+       struct data data;
+
+       u64 addr;
+       cell_t cell;
+       struct property *prop;
+       struct property *proplist;
+       struct node *node;
+       struct node *nodelist;
+       struct reserve_info *re;
+}
+/* Line 1489 of yacc.c.  */
+#line 90 "dtc-parser.tab.h"
+       YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYLTYPE yylloc;
diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.y b/arch/powerpc/boot/dtc-src/dtc-parser.y
new file mode 100644 (file)
index 0000000..002ea7f
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+%locations
+
+%{
+#include "dtc.h"
+#include "srcpos.h"
+
+int yylex(void);
+unsigned long long eval_literal(const char *s, int base, int bits);
+
+extern struct boot_info *the_boot_info;
+
+%}
+
+%union {
+       char *propnodename;
+       char *literal;
+       char *labelref;
+       unsigned int cbase;
+       u8 byte;
+       struct data data;
+
+       u64 addr;
+       cell_t cell;
+       struct property *prop;
+       struct property *proplist;
+       struct node *node;
+       struct node *nodelist;
+       struct reserve_info *re;
+}
+
+%token DT_V1
+%token DT_MEMRESERVE
+%token <propnodename> DT_PROPNODENAME
+%token <literal> DT_LITERAL
+%token <literal> DT_LEGACYLITERAL
+%token <cbase> DT_BASE
+%token <byte> DT_BYTE
+%token <data> DT_STRING
+%token <labelref> DT_LABEL
+%token <labelref> DT_REF
+
+%type <data> propdata
+%type <data> propdataprefix
+%type <re> memreserve
+%type <re> memreserves
+%type <re> v0_memreserve
+%type <re> v0_memreserves
+%type <addr> addr
+%type <data> celllist
+%type <cbase> cellbase
+%type <cell> cellval
+%type <data> bytestring
+%type <prop> propdef
+%type <proplist> proplist
+
+%type <node> devicetree
+%type <node> nodedef
+%type <node> subnode
+%type <nodelist> subnodes
+%type <labelref> label
+
+%%
+
+sourcefile:
+         DT_V1 ';' memreserves devicetree
+               {
+                       the_boot_info = build_boot_info($3, $4);
+               }
+       | v0_memreserves devicetree
+               {
+                       the_boot_info = build_boot_info($1, $2);
+               }
+       ;
+
+memreserves:
+         /* empty */
+               {
+                       $$ = NULL;
+               }
+       | memreserve memreserves
+               {
+                       $$ = chain_reserve_entry($1, $2);
+               }
+       ;
+
+memreserve:
+         label DT_MEMRESERVE addr addr ';'
+               {
+                       $$ = build_reserve_entry($3, $4, $1);
+               }
+       ;
+
+v0_memreserves:
+         /* empty */
+               {
+                       $$ = NULL;
+               }
+       | v0_memreserve v0_memreserves
+               {
+                       $$ = chain_reserve_entry($1, $2);
+               };
+       ;
+
+v0_memreserve:
+         memreserve
+               {
+                       $$ = $1;
+               }
+       | label DT_MEMRESERVE addr '-' addr ';'
+               {
+                       $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
+               }
+       ;
+
+addr:
+         DT_LITERAL
+               {
+                       $$ = eval_literal($1, 0, 64);
+               }
+       | DT_LEGACYLITERAL
+               {
+                       $$ = eval_literal($1, 16, 64);
+               }
+         ;
+
+devicetree:
+         '/' nodedef
+               {
+                       $$ = name_node($2, "", NULL);
+               }
+       ;
+
+nodedef:
+         '{' proplist subnodes '}' ';'
+               {
+                       $$ = build_node($2, $3);
+               }
+       ;
+
+proplist:
+         /* empty */
+               {
+                       $$ = NULL;
+               }
+       | proplist propdef
+               {
+                       $$ = chain_property($2, $1);
+               }
+       ;
+
+propdef:
+         label DT_PROPNODENAME '=' propdata ';'
+               {
+                       $$ = build_property($2, $4, $1);
+               }
+       | label DT_PROPNODENAME ';'
+               {
+                       $$ = build_property($2, empty_data, $1);
+               }
+       ;
+
+propdata:
+         propdataprefix DT_STRING
+               {
+                       $$ = data_merge($1, $2);
+               }
+       | propdataprefix '<' celllist '>'
+               {
+                       $$ = data_merge($1, $3);
+               }
+       | propdataprefix '[' bytestring ']'
+               {
+                       $$ = data_merge($1, $3);
+               }
+       | propdataprefix DT_REF
+               {
+                       $$ = data_add_marker($1, REF_PATH, $2);
+               }
+       | propdata DT_LABEL
+               {
+                       $$ = data_add_marker($1, LABEL, $2);
+               }
+       ;
+
+propdataprefix:
+         /* empty */
+               {
+                       $$ = empty_data;
+               }
+       | propdata ','
+               {
+                       $$ = $1;
+               }
+       | propdataprefix DT_LABEL
+               {
+                       $$ = data_add_marker($1, LABEL, $2);
+               }
+       ;
+
+celllist:
+         /* empty */
+               {
+                       $$ = empty_data;
+               }
+       | celllist cellval
+               {
+                       $$ = data_append_cell($1, $2);
+               }
+       | celllist DT_REF
+               {
+                       $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
+                                                             $2), -1);
+               }
+       | celllist DT_LABEL
+               {
+                       $$ = data_add_marker($1, LABEL, $2);
+               }
+       ;
+
+cellbase:
+         /* empty */
+               {
+                       $$ = 16;
+               }
+       | DT_BASE
+       ;
+
+cellval:
+         DT_LITERAL
+               {
+                       $$ = eval_literal($1, 0, 32);
+               }
+       | cellbase DT_LEGACYLITERAL
+               {
+                       $$ = eval_literal($2, $1, 32);
+               }
+       ;
+
+bytestring:
+         /* empty */
+               {
+                       $$ = empty_data;
+               }
+       | bytestring DT_BYTE
+               {
+                       $$ = data_append_byte($1, $2);
+               }
+       | bytestring DT_LABEL
+               {
+                       $$ = data_add_marker($1, LABEL, $2);
+               }
+       ;
+
+subnodes:
+         /* empty */
+               {
+                       $$ = NULL;
+               }
+       |  subnode subnodes
+               {
+                       $$ = chain_node($1, $2);
+               }
+       | subnode propdef
+               {
+                       yyerror("syntax error: properties must precede subnodes\n");
+                       YYERROR;
+               }
+       ;
+
+subnode:
+         label DT_PROPNODENAME nodedef
+               {
+                       $$ = name_node($3, $2, $1);
+               }
+       ;
+
+label:
+         /* empty */
+               {
+                       $$ = NULL;
+               }
+       | DT_LABEL
+               {
+                       $$ = $1;
+               }
+       ;
+
+%%
+
+void yyerror (char const *s)
+{
+       const char *fname = srcpos_filename_for_num(yylloc.filenum);
+
+       if (strcmp(fname, "-") == 0)
+               fname = "stdin";
+
+       fprintf(stderr, "%s:%d %s\n",
+               fname, yylloc.first_line, s);
+}
+
+unsigned long long eval_literal(const char *s, int base, int bits)
+{
+       unsigned long long val;
+       char *e;
+
+       errno = 0;
+       val = strtoull(s, &e, base);
+       if (*e)
+               yyerror("bad characters in literal");
+       else if ((errno == ERANGE)
+                || ((bits < 64) && (val >= (1ULL << bits))))
+               yyerror("literal out of range");
+       else if (errno != 0)
+               yyerror("bad literal");
+       return val;
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc.c b/arch/powerpc/boot/dtc-src/dtc.c
new file mode 100644 (file)
index 0000000..01131d7
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+#include "srcpos.h"
+
+#include "version_gen.h"
+
+/*
+ * Command line options
+ */
+int quiet;             /* Level of quietness */
+int reservenum;                /* Number of memory reservation slots */
+int minsize;           /* Minimum blob size */
+int padsize;           /* Additional padding to blob */
+
+char *join_path(const char *path, const char *name)
+{
+       int lenp = strlen(path);
+       int lenn = strlen(name);
+       int len;
+       int needslash = 1;
+       char *str;
+
+       len = lenp + lenn + 2;
+       if ((lenp > 0) && (path[lenp-1] == '/')) {
+               needslash = 0;
+               len--;
+       }
+
+       str = xmalloc(len);
+       memcpy(str, path, lenp);
+       if (needslash) {
+               str[lenp] = '/';
+               lenp++;
+       }
+       memcpy(str+lenp, name, lenn+1);
+       return str;
+}
+
+void fill_fullpaths(struct node *tree, const char *prefix)
+{
+       struct node *child;
+       const char *unit;
+
+       tree->fullpath = join_path(prefix, tree->name);
+
+       unit = strchr(tree->name, '@');
+       if (unit)
+               tree->basenamelen = unit - tree->name;
+       else
+               tree->basenamelen = strlen(tree->name);
+
+       for_each_child(tree, child)
+               fill_fullpaths(child, tree->fullpath);
+}
+
+static void  __attribute__ ((noreturn)) usage(void)
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\tdtc [options] <input file>\n");
+       fprintf(stderr, "\nOptions:\n");
+       fprintf(stderr, "\t-h\n");
+       fprintf(stderr, "\t\tThis help text\n");
+       fprintf(stderr, "\t-q\n");
+       fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
+       fprintf(stderr, "\t-I <input format>\n");
+       fprintf(stderr, "\t\tInput formats are:\n");
+       fprintf(stderr, "\t\t\tdts - device tree source text\n");
+       fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+       fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
+       fprintf(stderr, "\t-o <output file>\n");
+       fprintf(stderr, "\t-O <output format>\n");
+       fprintf(stderr, "\t\tOutput formats are:\n");
+       fprintf(stderr, "\t\t\tdts - device tree source text\n");
+       fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+       fprintf(stderr, "\t\t\tasm - assembler source\n");
+       fprintf(stderr, "\t-V <output version>\n");
+       fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
+       fprintf(stderr, "\t-R <number>\n");
+       fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
+       fprintf(stderr, "\t-S <bytes>\n");
+       fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
+       fprintf(stderr, "\t-p <bytes>\n");
+       fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
+       fprintf(stderr, "\t-b <number>\n");
+       fprintf(stderr, "\t\tSet the physical boot cpu\n");
+       fprintf(stderr, "\t-f\n");
+       fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+       fprintf(stderr, "\t-v\n");
+       fprintf(stderr, "\t\tPrint DTC version and exit\n");
+       exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+       struct boot_info *bi;
+       const char *inform = "dts";
+       const char *outform = "dts";
+       const char *outname = "-";
+       int force = 0, check = 0;
+       const char *arg;
+       int opt;
+       FILE *inf = NULL;
+       FILE *outf = NULL;
+       int outversion = DEFAULT_FDT_VERSION;
+       int boot_cpuid_phys = 0xfeedbeef;
+
+       quiet      = 0;
+       reservenum = 0;
+       minsize    = 0;
+       padsize    = 0;
+
+       while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
+               switch (opt) {
+               case 'I':
+                       inform = optarg;
+                       break;
+               case 'O':
+                       outform = optarg;
+                       break;
+               case 'o':
+                       outname = optarg;
+                       break;
+               case 'V':
+                       outversion = strtol(optarg, NULL, 0);
+                       break;
+               case 'R':
+                       reservenum = strtol(optarg, NULL, 0);
+                       break;
+               case 'S':
+                       minsize = strtol(optarg, NULL, 0);
+                       break;
+               case 'p':
+                       padsize = strtol(optarg, NULL, 0);
+                       break;
+               case 'f':
+                       force = 1;
+                       break;
+               case 'c':
+                       check = 1;
+                       break;
+               case 'q':
+                       quiet++;
+                       break;
+               case 'b':
+                       boot_cpuid_phys = strtol(optarg, NULL, 0);
+                       break;
+               case 'v':
+                   printf("Version: %s\n", DTC_VERSION);
+                   exit(0);
+               case 'h':
+               default:
+                       usage();
+               }
+       }
+
+       if (argc > (optind+1))
+               usage();
+       else if (argc < (optind+1))
+               arg = "-";
+       else
+               arg = argv[optind];
+
+       /* minsize and padsize are mutually exclusive */
+       if ((minsize) && (padsize)) {
+               die("Can't set both -p and -S\n");
+       }
+
+       fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
+               inform, outform, arg);
+
+       if (streq(inform, "dts")) {
+               bi = dt_from_source(arg);
+       } else if (streq(inform, "fs")) {
+               bi = dt_from_fs(arg);
+       } else if(streq(inform, "dtb")) {
+               inf = dtc_open_file(arg);
+               bi = dt_from_blob(inf);
+       } else {
+               die("Unknown input format \"%s\"\n", inform);
+       }
+
+       if (inf && (inf != stdin))
+               fclose(inf);
+
+       if (! bi || ! bi->dt)
+               die("Couldn't read input tree\n");
+
+       process_checks(force, bi, check, outversion, boot_cpuid_phys);
+
+       if (streq(outname, "-")) {
+               outf = stdout;
+       } else {
+               outf = fopen(outname, "w");
+               if (! outf)
+                       die("Couldn't open output file %s: %s\n",
+                           outname, strerror(errno));
+       }
+
+       if (streq(outform, "dts")) {
+               dt_to_source(outf, bi);
+       } else if (streq(outform, "dtb")) {
+               dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
+       } else if (streq(outform, "asm")) {
+               dt_to_asm(outf, bi, outversion, boot_cpuid_phys);
+       } else if (streq(outform, "null")) {
+               /* do nothing */
+       } else {
+               die("Unknown output format \"%s\"\n", outform);
+       }
+
+       exit(0);
+}
diff --git a/arch/powerpc/boot/dtc-src/dtc.h b/arch/powerpc/boot/dtc-src/dtc.h
new file mode 100644 (file)
index 0000000..6528177
--- /dev/null
@@ -0,0 +1,269 @@
+#ifndef _DTC_H
+#define _DTC_H
+
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#include <fdt.h>
+
+#define DEFAULT_FDT_VERSION    17
+/*
+ * Command line options
+ */
+extern int quiet;              /* Level of quietness */
+extern int reservenum;         /* Number of memory reservation slots */
+extern int minsize;            /* Minimum blob size */
+extern int padsize;            /* Additional padding to blob */
+
+static inline void __attribute__((noreturn)) die(char * str, ...)
+{
+       va_list ap;
+
+       va_start(ap, str);
+       fprintf(stderr, "FATAL ERROR: ");
+       vfprintf(stderr, str, ap);
+       exit(1);
+}
+
+static inline void *xmalloc(size_t len)
+{
+       void *new = malloc(len);
+
+       if (! new)
+               die("malloc() failed\n");
+
+       return new;
+}
+
+static inline void *xrealloc(void *p, size_t len)
+{
+       void *new = realloc(p, len);
+
+       if (! new)
+               die("realloc() failed (len=%d)\n", len);
+
+       return new;
+}
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef u32 cell_t;
+
+#define cpu_to_be16(x) htons(x)
+#define be16_to_cpu(x) ntohs(x)
+
+#define cpu_to_be32(x) htonl(x)
+#define be32_to_cpu(x) ntohl(x)
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cpu_to_be64(x) (x)
+#define be64_to_cpu(x) (x)
+#else
+#define cpu_to_be64(x) bswap_64(x)
+#define be64_to_cpu(x) bswap_64(x)
+#endif
+
+#define streq(a, b)    (strcmp((a), (b)) == 0)
+#define strneq(a, b, n)        (strncmp((a), (b), (n)) == 0)
+
+#define ALIGN(x, a)    (((x) + (a) - 1) & ~((a) - 1))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Data blobs */
+enum markertype {
+       REF_PHANDLE,
+       REF_PATH,
+       LABEL,
+};
+
+struct  marker {
+       enum markertype type;
+       int offset;
+       char *ref;
+       struct marker *next;
+};
+
+struct data {
+       int len;
+       char *val;
+       int asize;
+       struct marker *markers;
+};
+
+
+#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
+
+#define for_each_marker(m) \
+       for (; (m); (m) = (m)->next)
+#define for_each_marker_of_type(m, t) \
+       for_each_marker(m) \
+               if ((m)->type == (t))
+
+void data_free(struct data d);
+
+struct data data_grow_for(struct data d, int xlen);
+
+struct data data_copy_mem(const char *mem, int len);
+struct data data_copy_escape_string(const char *s, int len);
+struct data data_copy_file(FILE *f, size_t len);
+
+struct data data_append_data(struct data d, const void *p, int len);
+struct data data_insert_at_marker(struct data d, struct marker *m,
+                                 const void *p, int len);
+struct data data_merge(struct data d1, struct data d2);
+struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
+struct data data_append_addr(struct data d, u64 addr);
+struct data data_append_byte(struct data d, uint8_t byte);
+struct data data_append_zeroes(struct data d, int len);
+struct data data_append_align(struct data d, int align);
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref);
+
+int data_is_one_string(struct data d);
+
+/* DT constraints */
+
+#define MAX_PROPNAME_LEN       31
+#define MAX_NODENAME_LEN       31
+
+/* Live trees */
+struct property {
+       char *name;
+       struct data val;
+
+       struct property *next;
+
+       char *label;
+};
+
+struct node {
+       char *name;
+       struct property *proplist;
+       struct node *children;
+
+       struct node *parent;
+       struct node *next_sibling;
+
+       char *fullpath;
+       int basenamelen;
+
+       cell_t phandle;
+       int addr_cells, size_cells;
+
+       char *label;
+};
+
+#define for_each_property(n, p) \
+       for ((p) = (n)->proplist; (p); (p) = (p)->next)
+
+#define for_each_child(n, c)   \
+       for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+
+struct property *build_property(char *name, struct data val, char *label);
+struct property *chain_property(struct property *first, struct property *list);
+struct property *reverse_properties(struct property *first);
+
+struct node *build_node(struct property *proplist, struct node *children);
+struct node *name_node(struct node *node, char *name, char *label);
+struct node *chain_node(struct node *first, struct node *list);
+
+void add_property(struct node *node, struct property *prop);
+void add_child(struct node *parent, struct node *child);
+
+const char *get_unitname(struct node *node);
+struct property *get_property(struct node *node, const char *propname);
+cell_t propval_cell(struct property *prop);
+struct node *get_subnode(struct node *node, const char *nodename);
+struct node *get_node_by_path(struct node *tree, const char *path);
+struct node *get_node_by_label(struct node *tree, const char *label);
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
+struct node *get_node_by_ref(struct node *tree, const char *ref);
+cell_t get_node_phandle(struct node *root, struct node *node);
+
+/* Boot info (tree plus memreserve information */
+
+struct reserve_info {
+       struct fdt_reserve_entry re;
+
+       struct reserve_info *next;
+
+       char *label;
+};
+
+struct reserve_info *build_reserve_entry(u64 start, u64 len, char *label);
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+                                        struct reserve_info *list);
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+                                      struct reserve_info *new);
+
+
+struct boot_info {
+       struct reserve_info *reservelist;
+       struct node *dt;                /* the device tree */
+};
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+                                 struct node *tree);
+
+/* Checks */
+
+void process_checks(int force, struct boot_info *bi,
+                   int checkflag, int outversion, int boot_cpuid_phys);
+
+/* Flattened trees */
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version,
+               int boot_cpuid_phys);
+void dt_to_asm(FILE *f, struct boot_info *bi, int version,
+              int boot_cpuid_phys);
+
+struct boot_info *dt_from_blob(FILE *f);
+
+/* Tree source */
+
+void dt_to_source(FILE *f, struct boot_info *bi);
+struct boot_info *dt_from_source(const char *f);
+
+/* FS trees */
+
+struct boot_info *dt_from_fs(const char *dirname);
+
+/* misc */
+
+char *join_path(const char *path, const char *name);
+void fill_fullpaths(struct node *tree, const char *prefix);
+
+#endif /* _DTC_H */
diff --git a/arch/powerpc/boot/dtc-src/flattree.c b/arch/powerpc/boot/dtc-src/flattree.c
new file mode 100644 (file)
index 0000000..a7cfb84
--- /dev/null
@@ -0,0 +1,968 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+#define FTF_FULLPATH   0x1
+#define FTF_VARALIGN   0x2
+#define FTF_NAMEPROPS  0x4
+#define FTF_BOOTCPUID  0x8
+#define FTF_STRTABSIZE 0x10
+#define FTF_STRUCTSIZE 0x20
+#define FTF_NOPS       0x40
+
+static struct version_info {
+       int version;
+       int last_comp_version;
+       int hdr_size;
+       int flags;
+} version_table[] = {
+       {1, 1, FDT_V1_SIZE,
+        FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
+       {2, 1, FDT_V2_SIZE,
+        FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
+       {3, 1, FDT_V3_SIZE,
+        FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
+       {16, 16, FDT_V3_SIZE,
+        FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
+       {17, 16, FDT_V17_SIZE,
+        FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
+};
+
+struct emitter {
+       void (*cell)(void *, cell_t);
+       void (*string)(void *, char *, int);
+       void (*align)(void *, int);
+       void (*data)(void *, struct data);
+       void (*beginnode)(void *, const char *);
+       void (*endnode)(void *, const char *);
+       void (*property)(void *, const char *);
+};
+
+static void bin_emit_cell(void *e, cell_t val)
+{
+       struct data *dtbuf = e;
+
+       *dtbuf = data_append_cell(*dtbuf, val);
+}
+
+static void bin_emit_string(void *e, char *str, int len)
+{
+       struct data *dtbuf = e;
+
+       if (len == 0)
+               len = strlen(str);
+
+       *dtbuf = data_append_data(*dtbuf, str, len);
+       *dtbuf = data_append_byte(*dtbuf, '\0');
+}
+
+static void bin_emit_align(void *e, int a)
+{
+       struct data *dtbuf = e;
+
+       *dtbuf = data_append_align(*dtbuf, a);
+}
+
+static void bin_emit_data(void *e, struct data d)
+{
+       struct data *dtbuf = e;
+
+       *dtbuf = data_append_data(*dtbuf, d.val, d.len);
+}
+
+static void bin_emit_beginnode(void *e, const char *label)
+{
+       bin_emit_cell(e, FDT_BEGIN_NODE);
+}
+
+static void bin_emit_endnode(void *e, const char *label)
+{
+       bin_emit_cell(e, FDT_END_NODE);
+}
+
+static void bin_emit_property(void *e, const char *label)
+{
+       bin_emit_cell(e, FDT_PROP);
+}
+
+static struct emitter bin_emitter = {
+       .cell = bin_emit_cell,
+       .string = bin_emit_string,
+       .align = bin_emit_align,
+       .data = bin_emit_data,
+       .beginnode = bin_emit_beginnode,
+       .endnode = bin_emit_endnode,
+       .property = bin_emit_property,
+};
+
+static void emit_label(FILE *f, const char *prefix, const char *label)
+{
+       fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
+       fprintf(f, "%s_%s:\n", prefix, label);
+       fprintf(f, "_%s_%s:\n", prefix, label);
+}
+
+static void emit_offset_label(FILE *f, const char *label, int offset)
+{
+       fprintf(f, "\t.globl\t%s\n", label);
+       fprintf(f, "%s\t= . + %d\n", label, offset);
+}
+
+static void asm_emit_cell(void *e, cell_t val)
+{
+       FILE *f = e;
+
+       fprintf(f, "\t.long\t0x%x\n", val);
+}
+
+static void asm_emit_string(void *e, char *str, int len)
+{
+       FILE *f = e;
+       char c = 0;
+
+       if (len != 0) {
+               /* XXX: ewww */
+               c = str[len];
+               str[len] = '\0';
+       }
+
+       fprintf(f, "\t.string\t\"%s\"\n", str);
+
+       if (len != 0) {
+               str[len] = c;
+       }
+}
+
+static void asm_emit_align(void *e, int a)
+{
+       FILE *f = e;
+
+       fprintf(f, "\t.balign\t%d\n", a);
+}
+
+static void asm_emit_data(void *e, struct data d)
+{
+       FILE *f = e;
+       int off = 0;
+       struct marker *m;
+
+       m = d.markers;
+       while (m) {
+               if (m->type == LABEL)
+                       emit_offset_label(f, m->ref, m->offset);
+               m = m->next;
+       }
+
+       while ((d.len - off) >= sizeof(u32)) {
+               fprintf(f, "\t.long\t0x%x\n",
+                       be32_to_cpu(*((u32 *)(d.val+off))));
+               off += sizeof(u32);
+       }
+
+       if ((d.len - off) >= sizeof(u16)) {
+               fprintf(f, "\t.short\t0x%hx\n",
+                       be16_to_cpu(*((u16 *)(d.val+off))));
+               off += sizeof(u16);
+       }
+
+       if ((d.len - off) >= 1) {
+               fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
+               off += 1;
+       }
+
+       assert(off == d.len);
+}
+
+static void asm_emit_beginnode(void *e, const char *label)
+{
+       FILE *f = e;
+
+       if (label) {
+               fprintf(f, "\t.globl\t%s\n", label);
+               fprintf(f, "%s:\n", label);
+       }
+       fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
+}
+
+static void asm_emit_endnode(void *e, const char *label)
+{
+       FILE *f = e;
+
+       fprintf(f, "\t.long\tFDT_END_NODE\n");
+       if (label) {
+               fprintf(f, "\t.globl\t%s_end\n", label);
+               fprintf(f, "%s_end:\n", label);
+       }
+}
+
+static void asm_emit_property(void *e, const char *label)
+{
+       FILE *f = e;
+
+       if (label) {
+               fprintf(f, "\t.globl\t%s\n", label);
+               fprintf(f, "%s:\n", label);
+       }
+       fprintf(f, "\t.long\tFDT_PROP\n");
+}
+
+static struct emitter asm_emitter = {
+       .cell = asm_emit_cell,
+       .string = asm_emit_string,
+       .align = asm_emit_align,
+       .data = asm_emit_data,
+       .beginnode = asm_emit_beginnode,
+       .endnode = asm_emit_endnode,
+       .property = asm_emit_property,
+};
+
+static int stringtable_insert(struct data *d, const char *str)
+{
+       int i;
+
+       /* FIXME: do this more efficiently? */
+
+       for (i = 0; i < d->len; i++) {
+               if (streq(str, d->val + i))
+                       return i;
+       }
+
+       *d = data_append_data(*d, str, strlen(str)+1);
+       return i;
+}
+
+static void flatten_tree(struct node *tree, struct emitter *emit,
+                        void *etarget, struct data *strbuf,
+                        struct version_info *vi)
+{
+       struct property *prop;
+       struct node *child;
+       int seen_name_prop = 0;
+
+       emit->beginnode(etarget, tree->label);
+
+       if (vi->flags & FTF_FULLPATH)
+               emit->string(etarget, tree->fullpath, 0);
+       else
+               emit->string(etarget, tree->name, 0);
+
+       emit->align(etarget, sizeof(cell_t));
+
+       for_each_property(tree, prop) {
+               int nameoff;
+
+               if (streq(prop->name, "name"))
+                       seen_name_prop = 1;
+
+               nameoff = stringtable_insert(strbuf, prop->name);
+
+               emit->property(etarget, prop->label);
+               emit->cell(etarget, prop->val.len);
+               emit->cell(etarget, nameoff);
+
+               if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
+                       emit->align(etarget, 8);
+
+               emit->data(etarget, prop->val);
+               emit->align(etarget, sizeof(cell_t));
+       }
+
+       if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
+               emit->property(etarget, NULL);
+               emit->cell(etarget, tree->basenamelen+1);
+               emit->cell(etarget, stringtable_insert(strbuf, "name"));
+
+               if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
+                       emit->align(etarget, 8);
+
+               emit->string(etarget, tree->name, tree->basenamelen);
+               emit->align(etarget, sizeof(cell_t));
+       }
+
+       for_each_child(tree, child) {
+               flatten_tree(child, emit, etarget, strbuf, vi);
+       }
+
+       emit->endnode(etarget, tree->label);
+}
+
+static struct data flatten_reserve_list(struct reserve_info *reservelist,
+                                struct version_info *vi)
+{
+       struct reserve_info *re;
+       struct data d = empty_data;
+       static struct fdt_reserve_entry null_re = {0,0};
+       int    j;
+
+       for (re = reservelist; re; re = re->next) {
+               d = data_append_re(d, &re->re);
+       }
+       /*
+        * Add additional reserved slots if the user asked for them.
+        */
+       for (j = 0; j < reservenum; j++) {
+               d = data_append_re(d, &null_re);
+       }
+
+       return d;
+}
+
+static void make_fdt_header(struct fdt_header *fdt,
+                           struct version_info *vi,
+                           int reservesize, int dtsize, int strsize,
+                           int boot_cpuid_phys)
+{
+       int reserve_off;
+
+       reservesize += sizeof(struct fdt_reserve_entry);
+
+       memset(fdt, 0xff, sizeof(*fdt));
+
+       fdt->magic = cpu_to_be32(FDT_MAGIC);
+       fdt->version = cpu_to_be32(vi->version);
+       fdt->last_comp_version = cpu_to_be32(vi->last_comp_version);
+
+       /* Reserve map should be doubleword aligned */
+       reserve_off = ALIGN(vi->hdr_size, 8);
+
+       fdt->off_mem_rsvmap = cpu_to_be32(reserve_off);
+       fdt->off_dt_struct = cpu_to_be32(reserve_off + reservesize);
+       fdt->off_dt_strings = cpu_to_be32(reserve_off + reservesize
+                                         + dtsize);
+       fdt->totalsize = cpu_to_be32(reserve_off + reservesize + dtsize + strsize);
+
+       if (vi->flags & FTF_BOOTCPUID)
+               fdt->boot_cpuid_phys = cpu_to_be32(boot_cpuid_phys);
+       if (vi->flags & FTF_STRTABSIZE)
+               fdt->size_dt_strings = cpu_to_be32(strsize);
+       if (vi->flags & FTF_STRUCTSIZE)
+               fdt->size_dt_struct = cpu_to_be32(dtsize);
+}
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version,
+               int boot_cpuid_phys)
+{
+       struct version_info *vi = NULL;
+       int i;
+       struct data blob       = empty_data;
+       struct data reservebuf = empty_data;
+       struct data dtbuf      = empty_data;
+       struct data strbuf     = empty_data;
+       struct fdt_header fdt;
+       int padlen = 0;
+
+       for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+               if (version_table[i].version == version)
+                       vi = &version_table[i];
+       }
+       if (!vi)
+               die("Unknown device tree blob version %d\n", version);
+
+       flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
+       bin_emit_cell(&dtbuf, FDT_END);
+
+       reservebuf = flatten_reserve_list(bi->reservelist, vi);
+
+       /* Make header */
+       make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+                       boot_cpuid_phys);
+
+       /*
+        * If the user asked for more space than is used, adjust the totalsize.
+        */
+       if (minsize > 0) {
+               padlen = minsize - be32_to_cpu(fdt.totalsize);
+               if ((padlen < 0) && (quiet < 1))
+                       fprintf(stderr,
+                               "Warning: blob size %d >= minimum size %d\n",
+                               be32_to_cpu(fdt.totalsize), minsize);
+       }
+
+       if (padsize > 0)
+               padlen = padsize;
+
+       if (padlen > 0) {
+               int tsize = be32_to_cpu(fdt.totalsize);
+               tsize += padlen;
+               fdt.totalsize = cpu_to_be32(tsize);
+       }
+
+       /*
+        * Assemble the blob: start with the header, add with alignment
+        * the reserve buffer, add the reserve map terminating zeroes,
+        * the device tree itself, and finally the strings.
+        */
+       blob = data_append_data(blob, &fdt, sizeof(fdt));
+       blob = data_append_align(blob, 8);
+       blob = data_merge(blob, reservebuf);
+       blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
+       blob = data_merge(blob, dtbuf);
+       blob = data_merge(blob, strbuf);
+
+       /*
+        * If the user asked for more space than is used, pad out the blob.
+        */
+       if (padlen > 0)
+               blob = data_append_zeroes(blob, padlen);
+
+       fwrite(blob.val, blob.len, 1, f);
+
+       if (ferror(f))
+               die("Error writing device tree blob: %s\n", strerror(errno));
+
+       /*
+        * data_merge() frees the right-hand element so only the blob
+        * remains to be freed.
+        */
+       data_free(blob);
+}
+
+static void dump_stringtable_asm(FILE *f, struct data strbuf)
+{
+       const char *p;
+       int len;
+
+       p = strbuf.val;
+
+       while (p < (strbuf.val + strbuf.len)) {
+               len = strlen(p);
+               fprintf(f, "\t.string \"%s\"\n", p);
+               p += len+1;
+       }
+}
+
+void dt_to_asm(FILE *f, struct boot_info *bi, int version, int boot_cpuid_phys)
+{
+       struct version_info *vi = NULL;
+       int i;
+       struct data strbuf = empty_data;
+       struct reserve_info *re;
+       const char *symprefix = "dt";
+
+       for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+               if (version_table[i].version == version)
+                       vi = &version_table[i];
+       }
+       if (!vi)
+               die("Unknown device tree blob version %d\n", version);
+
+       fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
+       fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
+       fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
+       fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
+       fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
+       fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
+       fprintf(f, "\n");
+
+       emit_label(f, symprefix, "blob_start");
+       emit_label(f, symprefix, "header");
+       fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
+       fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
+               symprefix, symprefix);
+       fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
+               symprefix, symprefix);
+       fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
+               symprefix, symprefix);
+       fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
+               symprefix, symprefix);
+       fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
+       fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
+               vi->last_comp_version);
+
+       if (vi->flags & FTF_BOOTCPUID)
+               fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
+                       boot_cpuid_phys);
+
+       if (vi->flags & FTF_STRTABSIZE)
+               fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
+                       symprefix, symprefix);
+
+       if (vi->flags & FTF_STRUCTSIZE)
+               fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
+                       symprefix, symprefix);
+
+       /*
+        * Reserve map entries.
+        * Align the reserve map to a doubleword boundary.
+        * Each entry is an (address, size) pair of u64 values.
+        * Always supply a zero-sized temination entry.
+        */
+       asm_emit_align(f, 8);
+       emit_label(f, symprefix, "reserve_map");
+
+       fprintf(f, "/* Memory reserve map from source file */\n");
+
+       /*
+        * Use .long on high and low halfs of u64s to avoid .quad
+        * as it appears .quad isn't available in some assemblers.
+        */
+       for (re = bi->reservelist; re; re = re->next) {
+               if (re->label) {
+                       fprintf(f, "\t.globl\t%s\n", re->label);
+                       fprintf(f, "%s:\n", re->label);
+               }
+               fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+                       (unsigned int)(re->re.address >> 32),
+                       (unsigned int)(re->re.address & 0xffffffff));
+               fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+                       (unsigned int)(re->re.size >> 32),
+                       (unsigned int)(re->re.size & 0xffffffff));
+       }
+       for (i = 0; i < reservenum; i++) {
+               fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+       }
+
+       fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+
+       emit_label(f, symprefix, "struct_start");
+       flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
+       fprintf(f, "\t.long\tFDT_END\n");
+       emit_label(f, symprefix, "struct_end");
+
+       emit_label(f, symprefix, "strings_start");
+       dump_stringtable_asm(f, strbuf);
+       emit_label(f, symprefix, "strings_end");
+
+       emit_label(f, symprefix, "blob_end");
+
+       /*
+        * If the user asked for more space than is used, pad it out.
+        */
+       if (minsize > 0) {
+               fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
+                       minsize, symprefix, symprefix);
+       }
+       if (padsize > 0) {
+               fprintf(f, "\t.space\t%d, 0\n", padsize);
+       }
+       emit_label(f, symprefix, "blob_abs_end");
+
+       data_free(strbuf);
+}
+
+struct inbuf {
+       char *base, *limit, *ptr;
+};
+
+static void inbuf_init(struct inbuf *inb, void *base, void *limit)
+{
+       inb->base = base;
+       inb->limit = limit;
+       inb->ptr = inb->base;
+}
+
+static void flat_read_chunk(struct inbuf *inb, void *p, int len)
+{
+       if ((inb->ptr + len) > inb->limit)
+               die("Premature end of data parsing flat device tree\n");
+
+       memcpy(p, inb->ptr, len);
+
+       inb->ptr += len;
+}
+
+static u32 flat_read_word(struct inbuf *inb)
+{
+       u32 val;
+
+       assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
+
+       flat_read_chunk(inb, &val, sizeof(val));
+
+       return be32_to_cpu(val);
+}
+
+static void flat_realign(struct inbuf *inb, int align)
+{
+       int off = inb->ptr - inb->base;
+
+       inb->ptr = inb->base + ALIGN(off, align);
+       if (inb->ptr > inb->limit)
+               die("Premature end of data parsing flat device tree\n");
+}
+
+static char *flat_read_string(struct inbuf *inb)
+{
+       int len = 0;
+       const char *p = inb->ptr;
+       char *str;
+
+       do {
+               if (p >= inb->limit)
+                       die("Premature end of data parsing flat device tree\n");
+               len++;
+       } while ((*p++) != '\0');
+
+       str = strdup(inb->ptr);
+
+       inb->ptr += len;
+
+       flat_realign(inb, sizeof(u32));
+
+       return str;
+}
+
+static struct data flat_read_data(struct inbuf *inb, int len)
+{
+       struct data d = empty_data;
+
+       if (len == 0)
+               return empty_data;
+
+       d = data_grow_for(d, len);
+       d.len = len;
+
+       flat_read_chunk(inb, d.val, len);
+
+       flat_realign(inb, sizeof(u32));
+
+       return d;
+}
+
+static char *flat_read_stringtable(struct inbuf *inb, int offset)
+{
+       const char *p;
+
+       p = inb->base + offset;
+       while (1) {
+               if (p >= inb->limit || p < inb->base)
+                       die("String offset %d overruns string table\n",
+                           offset);
+
+               if (*p == '\0')
+                       break;
+
+               p++;
+       }
+
+       return strdup(inb->base + offset);
+}
+
+static struct property *flat_read_property(struct inbuf *dtbuf,
+                                          struct inbuf *strbuf, int flags)
+{
+       u32 proplen, stroff;
+       char *name;
+       struct data val;
+
+       proplen = flat_read_word(dtbuf);
+       stroff = flat_read_word(dtbuf);
+
+       name = flat_read_stringtable(strbuf, stroff);
+
+       if ((flags & FTF_VARALIGN) && (proplen >= 8))
+               flat_realign(dtbuf, 8);
+
+       val = flat_read_data(dtbuf, proplen);
+
+       return build_property(name, val, NULL);
+}
+
+
+static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
+{
+       struct reserve_info *reservelist = NULL;
+       struct reserve_info *new;
+       const char *p;
+       struct fdt_reserve_entry re;
+
+       /*
+        * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
+        * List terminates at an entry with size equal to zero.
+        *
+        * First pass, count entries.
+        */
+       p = inb->ptr;
+       while (1) {
+               flat_read_chunk(inb, &re, sizeof(re));
+               re.address  = be64_to_cpu(re.address);
+               re.size = be64_to_cpu(re.size);
+               if (re.size == 0)
+                       break;
+
+               new = build_reserve_entry(re.address, re.size, NULL);
+               reservelist = add_reserve_entry(reservelist, new);
+       }
+
+       return reservelist;
+}
+
+
+static char *nodename_from_path(const char *ppath, const char *cpath)
+{
+       const char *lslash;
+       int plen;
+
+       lslash = strrchr(cpath, '/');
+       if (! lslash)
+               return NULL;
+
+       plen = lslash - cpath;
+
+       if (streq(cpath, "/") && streq(ppath, ""))
+               return "";
+
+       if ((plen == 0) && streq(ppath, "/"))
+               return strdup(lslash+1);
+
+       if (! strneq(ppath, cpath, plen))
+               return NULL;
+
+       return strdup(lslash+1);
+}
+
+static const char PROPCHAR[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,._+*#?-";
+static const char UNITCHAR[] = "0123456789abcdef,";
+
+static int check_node_name(const char *name)
+{
+       const char *atpos;
+       int basenamelen;
+
+       atpos = strrchr(name, '@');
+
+       if (atpos)
+               basenamelen = atpos - name;
+       else
+               basenamelen = strlen(name);
+
+       if (strspn(name, PROPCHAR) < basenamelen)
+               return -1;
+
+       if (atpos
+           && ((basenamelen + 1 + strspn(atpos+1, UNITCHAR)) < strlen(name)))
+               return -1;
+
+       return basenamelen;
+}
+
+static struct node *unflatten_tree(struct inbuf *dtbuf,
+                                  struct inbuf *strbuf,
+                                  const char *parent_path, int flags)
+{
+       struct node *node;
+       u32 val;
+
+       node = build_node(NULL, NULL);
+
+       if (flags & FTF_FULLPATH) {
+               node->fullpath = flat_read_string(dtbuf);
+               node->name = nodename_from_path(parent_path, node->fullpath);
+
+               if (! node->name)
+                       die("Path \"%s\" is not valid as a child of \"%s\"\n",
+                           node->fullpath, parent_path);
+       } else {
+               node->name = flat_read_string(dtbuf);
+               node->fullpath = join_path(parent_path, node->name);
+       }
+
+       node->basenamelen = check_node_name(node->name);
+       if (node->basenamelen < 0) {
+               fprintf(stderr, "Warning \"%s\" has incorrect format\n", node->name);
+       }
+
+       do {
+               struct property *prop;
+               struct node *child;
+
+               val = flat_read_word(dtbuf);
+               switch (val) {
+               case FDT_PROP:
+                       if (node->children)
+                               fprintf(stderr, "Warning: Flat tree input has "
+                                       "subnodes preceding a property.\n");
+                       prop = flat_read_property(dtbuf, strbuf, flags);
+                       add_property(node, prop);
+                       break;
+
+               case FDT_BEGIN_NODE:
+                       child = unflatten_tree(dtbuf,strbuf, node->fullpath,
+                                              flags);
+                       add_child(node, child);
+                       break;
+
+               case FDT_END_NODE:
+                       break;
+
+               case FDT_END:
+                       die("Premature FDT_END in device tree blob\n");
+                       break;
+
+               case FDT_NOP:
+                       if (!(flags & FTF_NOPS))
+                               fprintf(stderr, "Warning: NOP tag found in flat tree"
+                                       " version <16\n");
+
+                       /* Ignore */
+                       break;
+
+               default:
+                       die("Invalid opcode word %08x in device tree blob\n",
+                           val);
+               }
+       } while (val != FDT_END_NODE);
+
+       return node;
+}
+
+
+struct boot_info *dt_from_blob(FILE *f)
+{
+       u32 magic, totalsize, version, size_str, size_dt;
+       u32 off_dt, off_str, off_mem_rsvmap;
+       int rc;
+       char *blob;
+       struct fdt_header *fdt;
+       char *p;
+       struct inbuf dtbuf, strbuf;
+       struct inbuf memresvbuf;
+       int sizeleft;
+       struct reserve_info *reservelist;
+       struct node *tree;
+       u32 val;
+       int flags = 0;
+
+       rc = fread(&magic, sizeof(magic), 1, f);
+       if (ferror(f))
+               die("Error reading DT blob magic number: %s\n",
+                   strerror(errno));
+       if (rc < 1) {
+               if (feof(f))
+                       die("EOF reading DT blob magic number\n");
+               else
+                       die("Mysterious short read reading magic number\n");
+       }
+
+       magic = be32_to_cpu(magic);
+       if (magic != FDT_MAGIC)
+               die("Blob has incorrect magic number\n");
+
+       rc = fread(&totalsize, sizeof(totalsize), 1, f);
+       if (ferror(f))
+               die("Error reading DT blob size: %s\n", strerror(errno));
+       if (rc < 1) {
+               if (feof(f))
+                       die("EOF reading DT blob size\n");
+               else
+                       die("Mysterious short read reading blob size\n");
+       }
+
+       totalsize = be32_to_cpu(totalsize);
+       if (totalsize < FDT_V1_SIZE)
+               die("DT blob size (%d) is too small\n", totalsize);
+
+       blob = xmalloc(totalsize);
+
+       fdt = (struct fdt_header *)blob;
+       fdt->magic = cpu_to_be32(magic);
+       fdt->totalsize = cpu_to_be32(totalsize);
+
+       sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
+       p = blob + sizeof(magic)  + sizeof(totalsize);
+
+       while (sizeleft) {
+               if (feof(f))
+                       die("EOF before reading %d bytes of DT blob\n",
+                           totalsize);
+
+               rc = fread(p, 1, sizeleft, f);
+               if (ferror(f))
+                       die("Error reading DT blob: %s\n",
+                           strerror(errno));
+
+               sizeleft -= rc;
+               p += rc;
+       }
+
+       off_dt = be32_to_cpu(fdt->off_dt_struct);
+       off_str = be32_to_cpu(fdt->off_dt_strings);
+       off_mem_rsvmap = be32_to_cpu(fdt->off_mem_rsvmap);
+       version = be32_to_cpu(fdt->version);
+
+       fprintf(stderr, "\tmagic:\t\t\t0x%x\n", magic);
+       fprintf(stderr, "\ttotalsize:\t\t%d\n", totalsize);
+       fprintf(stderr, "\toff_dt_struct:\t\t0x%x\n", off_dt);
+       fprintf(stderr, "\toff_dt_strings:\t\t0x%x\n", off_str);
+       fprintf(stderr, "\toff_mem_rsvmap:\t\t0x%x\n", off_mem_rsvmap);
+       fprintf(stderr, "\tversion:\t\t0x%x\n", version );
+       fprintf(stderr, "\tlast_comp_version:\t0x%x\n",
+               be32_to_cpu(fdt->last_comp_version));
+
+       if (off_mem_rsvmap >= totalsize)
+               die("Mem Reserve structure offset exceeds total size\n");
+
+       if (off_dt >= totalsize)
+               die("DT structure offset exceeds total size\n");
+
+       if (off_str > totalsize)
+               die("String table offset exceeds total size\n");
+
+       if (version >= 2)
+               fprintf(stderr, "\tboot_cpuid_phys:\t0x%x\n",
+                       be32_to_cpu(fdt->boot_cpuid_phys));
+
+       size_str = -1;
+       if (version >= 3) {
+               size_str = be32_to_cpu(fdt->size_dt_strings);
+               fprintf(stderr, "\tsize_dt_strings:\t%d\n", size_str);
+               if (off_str+size_str > totalsize)
+                       die("String table extends past total size\n");
+       }
+
+       if (version >= 17) {
+               size_dt = be32_to_cpu(fdt->size_dt_struct);
+               fprintf(stderr, "\tsize_dt_struct:\t\t%d\n", size_dt);
+               if (off_dt+size_dt > totalsize)
+                       die("Structure block extends past total size\n");
+       }
+
+       if (version < 16) {
+               flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
+       } else {
+               flags |= FTF_NOPS;
+       }
+
+       inbuf_init(&memresvbuf,
+                  blob + off_mem_rsvmap, blob + totalsize);
+       inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
+       if (size_str >= 0)
+               inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
+       else
+               inbuf_init(&strbuf, blob + off_str, blob + totalsize);
+
+       reservelist = flat_read_mem_reserve(&memresvbuf);
+
+       val = flat_read_word(&dtbuf);
+
+       if (val != FDT_BEGIN_NODE)
+               die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
+
+       tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
+
+       val = flat_read_word(&dtbuf);
+       if (val != FDT_END)
+               die("Device tree blob doesn't end with FDT_END\n");
+
+       free(blob);
+
+       return build_boot_info(reservelist, tree);
+}
diff --git a/arch/powerpc/boot/dtc-src/fstree.c b/arch/powerpc/boot/dtc-src/fstree.c
new file mode 100644 (file)
index 0000000..2a160a4
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+static struct node *read_fstree(const char *dirname)
+{
+       DIR *d;
+       struct dirent *de;
+       struct stat st;
+       struct node *tree;
+
+       d = opendir(dirname);
+       if (! d)
+               die("opendir(): %s\n", strerror(errno));
+
+       tree = build_node(NULL, NULL);
+
+       while ((de = readdir(d)) != NULL) {
+               char *tmpnam;
+
+               if (streq(de->d_name, ".")
+                   || streq(de->d_name, ".."))
+                       continue;
+
+               tmpnam = join_path(dirname, de->d_name);
+
+               if (lstat(tmpnam, &st) < 0)
+                       die("stat(%s): %s\n", tmpnam, strerror(errno));
+
+               if (S_ISREG(st.st_mode)) {
+                       struct property *prop;
+                       FILE *pfile;
+
+                       pfile = fopen(tmpnam, "r");
+                       if (! pfile) {
+                               fprintf(stderr,
+                                       "WARNING: Cannot open %s: %s\n",
+                                       tmpnam, strerror(errno));
+                       } else {
+                               prop = build_property(strdup(de->d_name),
+                                                     data_copy_file(pfile,
+                                                                    st.st_size),
+                                                     NULL);
+                               add_property(tree, prop);
+                               fclose(pfile);
+                       }
+               } else if (S_ISDIR(st.st_mode)) {
+                       struct node *newchild;
+
+                       newchild = read_fstree(tmpnam);
+                       newchild = name_node(newchild, strdup(de->d_name),
+                                            NULL);
+                       add_child(tree, newchild);
+               }
+
+               free(tmpnam);
+       }
+
+       return tree;
+}
+
+struct boot_info *dt_from_fs(const char *dirname)
+{
+       struct node *tree;
+
+       tree = read_fstree(dirname);
+       tree = name_node(tree, "", NULL);
+
+       fill_fullpaths(tree, "");
+
+       return build_boot_info(NULL, tree);
+}
+
diff --git a/arch/powerpc/boot/dtc-src/livetree.c b/arch/powerpc/boot/dtc-src/livetree.c
new file mode 100644 (file)
index 0000000..6ba0846
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+/*
+ * Tree building functions
+ */
+
+struct property *build_property(char *name, struct data val, char *label)
+{
+       struct property *new = xmalloc(sizeof(*new));
+
+       new->name = name;
+       new->val = val;
+
+       new->next = NULL;
+
+       new->label = label;
+
+       return new;
+}
+
+struct property *chain_property(struct property *first, struct property *list)
+{
+       assert(first->next == NULL);
+
+       first->next = list;
+       return first;
+}
+
+struct property *reverse_properties(struct property *first)
+{
+       struct property *p = first;
+       struct property *head = NULL;
+       struct property *next;
+
+       while (p) {
+               next = p->next;
+               p->next = head;
+               head = p;
+               p = next;
+       }
+       return head;
+}
+
+struct node *build_node(struct property *proplist, struct node *children)
+{
+       struct node *new = xmalloc(sizeof(*new));
+       struct node *child;
+
+       memset(new, 0, sizeof(*new));
+
+       new->proplist = reverse_properties(proplist);
+       new->children = children;
+
+       for_each_child(new, child) {
+               child->parent = new;
+       }
+
+       return new;
+}
+
+struct node *name_node(struct node *node, char *name, char * label)
+{
+       assert(node->name == NULL);
+
+       node->name = name;
+
+       node->label = label;
+
+       return node;
+}
+
+struct node *chain_node(struct node *first, struct node *list)
+{
+       assert(first->next_sibling == NULL);
+
+       first->next_sibling = list;
+       return first;
+}
+
+void add_property(struct node *node, struct property *prop)
+{
+       struct property **p;
+
+       prop->next = NULL;
+
+       p = &node->proplist;
+       while (*p)
+               p = &((*p)->next);
+
+       *p = prop;
+}
+
+void add_child(struct node *parent, struct node *child)
+{
+       struct node **p;
+
+       child->next_sibling = NULL;
+
+       p = &parent->children;
+       while (*p)
+               p = &((*p)->next_sibling);
+
+       *p = child;
+}
+
+struct reserve_info *build_reserve_entry(u64 address, u64 size, char *label)
+{
+       struct reserve_info *new = xmalloc(sizeof(*new));
+
+       new->re.address = address;
+       new->re.size = size;
+
+       new->next = NULL;
+
+       new->label = label;
+
+       return new;
+}
+
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+                                       struct reserve_info *list)
+{
+       assert(first->next == NULL);
+
+       first->next = list;
+       return first;
+}
+
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+                                     struct reserve_info *new)
+{
+       struct reserve_info *last;
+
+       new->next = NULL;
+
+       if (! list)
+               return new;
+
+       for (last = list; last->next; last = last->next)
+               ;
+
+       last->next = new;
+
+       return list;
+}
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+                                 struct node *tree)
+{
+       struct boot_info *bi;
+
+       bi = xmalloc(sizeof(*bi));
+       bi->reservelist = reservelist;
+       bi->dt = tree;
+
+       return bi;
+}
+
+/*
+ * Tree accessor functions
+ */
+
+const char *get_unitname(struct node *node)
+{
+       if (node->name[node->basenamelen] == '\0')
+               return "";
+       else
+               return node->name + node->basenamelen + 1;
+}
+
+struct property *get_property(struct node *node, const char *propname)
+{
+       struct property *prop;
+
+       for_each_property(node, prop)
+               if (streq(prop->name, propname))
+                       return prop;
+
+       return NULL;
+}
+
+cell_t propval_cell(struct property *prop)
+{
+       assert(prop->val.len == sizeof(cell_t));
+       return be32_to_cpu(*((cell_t *)prop->val.val));
+}
+
+struct node *get_subnode(struct node *node, const char *nodename)
+{
+       struct node *child;
+
+       for_each_child(node, child)
+               if (streq(child->name, nodename))
+                       return child;
+
+       return NULL;
+}
+
+struct node *get_node_by_path(struct node *tree, const char *path)
+{
+       const char *p;
+       struct node *child;
+
+       if (!path || ! (*path))
+               return tree;
+
+       while (path[0] == '/')
+               path++;
+
+       p = strchr(path, '/');
+
+       for_each_child(tree, child) {
+               if (p && strneq(path, child->name, p-path))
+                       return get_node_by_path(child, p+1);
+               else if (!p && streq(path, child->name))
+                       return child;
+       }
+
+       return NULL;
+}
+
+struct node *get_node_by_label(struct node *tree, const char *label)
+{
+       struct node *child, *node;
+
+       assert(label && (strlen(label) > 0));
+
+       if (tree->label && streq(tree->label, label))
+               return tree;
+
+       for_each_child(tree, child) {
+               node = get_node_by_label(child, label);
+               if (node)
+                       return node;
+       }
+
+       return NULL;
+}
+
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
+{
+       struct node *child, *node;
+
+       assert((phandle != 0) && (phandle != -1));
+
+       if (tree->phandle == phandle)
+               return tree;
+
+       for_each_child(tree, child) {
+               node = get_node_by_phandle(child, phandle);
+               if (node)
+                       return node;
+       }
+
+       return NULL;
+}
+
+struct node *get_node_by_ref(struct node *tree, const char *ref)
+{
+       if (ref[0] == '/')
+               return get_node_by_path(tree, ref);
+       else
+               return get_node_by_label(tree, ref);
+}
+
+cell_t get_node_phandle(struct node *root, struct node *node)
+{
+       static cell_t phandle = 1; /* FIXME: ick, static local */
+
+       if ((node->phandle != 0) && (node->phandle != -1))
+               return node->phandle;
+
+       assert(! get_property(node, "linux,phandle"));
+
+       while (get_node_by_phandle(root, phandle))
+               phandle++;
+
+       node->phandle = phandle;
+       add_property(node,
+                    build_property("linux,phandle",
+                                   data_append_cell(empty_data, phandle),
+                                   NULL));
+
+       return node->phandle;
+}
diff --git a/arch/powerpc/boot/dtc-src/srcpos.c b/arch/powerpc/boot/dtc-src/srcpos.c
new file mode 100644 (file)
index 0000000..352b0fe
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+#include "srcpos.h"
+
+
+/*
+ * Record the complete unique set of opened file names.
+ * Primarily used to cache source position file names.
+ */
+#define MAX_N_FILE_NAMES       (100)
+
+const char *file_names[MAX_N_FILE_NAMES];
+static int n_file_names = 0;
+
+/*
+ * Like yylineno, this is the current open file pos.
+ */
+
+int srcpos_filenum = -1;
+
+
+
+FILE *dtc_open_file(const char *fname)
+{
+       FILE *f;
+
+       if (lookup_file_name(fname, 1) < 0)
+               die("Too many files opened\n");
+
+       if (streq(fname, "-"))
+               f = stdin;
+       else
+               f = fopen(fname, "r");
+
+       if (! f)
+               die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+
+       return f;
+}
+
+
+
+/*
+ * Locate and optionally add filename fname in the file_names[] array.
+ *
+ * If the filename is currently not in the array and the boolean
+ * add_it is non-zero, an attempt to add the filename will be made.
+ *
+ * Returns;
+ *    Index [0..MAX_N_FILE_NAMES) where the filename is kept
+ *    -1 if the name can not be recorded
+ */
+
+int lookup_file_name(const char *fname, int add_it)
+{
+       int i;
+
+       for (i = 0; i < n_file_names; i++) {
+               if (strcmp(file_names[i], fname) == 0)
+                       return i;
+       }
+
+       if (add_it) {
+               if (n_file_names < MAX_N_FILE_NAMES) {
+                       file_names[n_file_names] = strdup(fname);
+                       return n_file_names++;
+               }
+       }
+
+       return -1;
+}
+
+
+const char *srcpos_filename_for_num(int filenum)
+{
+       if (0 <= filenum && filenum < n_file_names) {
+               return file_names[filenum];
+       }
+
+       return 0;
+}
+
+
+const char *srcpos_get_filename(void)
+{
+       return srcpos_filename_for_num(srcpos_filenum);
+}
diff --git a/arch/powerpc/boot/dtc-src/srcpos.h b/arch/powerpc/boot/dtc-src/srcpos.h
new file mode 100644 (file)
index 0000000..ce7ab5b
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+/*
+ * Augment the standard YYLTYPE with a filenum index into an
+ * array of all opened filenames.
+ */
+
+#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
+typedef struct YYLTYPE {
+    int first_line;
+    int first_column;
+    int last_line;
+    int last_column;
+    int filenum;
+} YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED    1
+#define YYLTYPE_IS_TRIVIAL     1
+#endif
+
+/* Cater to old parser templates. */
+#ifndef YYID
+#define YYID(n)        (n)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)                                        \
+    do                                                                 \
+      if (YYID (N))                                                    \
+       {                                                               \
+         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+         (Current).filenum      = YYRHSLOC (Rhs, N).filenum;           \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         (Current).first_line   = (Current).last_line   =              \
+           YYRHSLOC (Rhs, 0).last_line;                                \
+         (Current).first_column = (Current).last_column =              \
+           YYRHSLOC (Rhs, 0).last_column;                              \
+         (Current).filenum      = YYRHSLOC (Rhs, 0).filenum;           \
+       }                                                               \
+    while (YYID (0))
+
+
+
+extern void yyerror(char const *);
+
+extern int srcpos_filenum;
+
+extern int push_input_file(const char *filename);
+extern int pop_input_file(void);
+
+extern FILE *dtc_open_file(const char *fname);
+extern int lookup_file_name(const char *fname, int add_it);
+extern const char *srcpos_filename_for_num(int filenum);
+const char *srcpos_get_filename(void);
diff --git a/arch/powerpc/boot/dtc-src/treesource.c b/arch/powerpc/boot/dtc-src/treesource.c
new file mode 100644 (file)
index 0000000..a6a7767
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+#include "srcpos.h"
+
+extern FILE *yyin;
+extern int yyparse(void);
+extern void yyerror(char const *);
+
+struct boot_info *the_boot_info;
+
+struct boot_info *dt_from_source(const char *fname)
+{
+       the_boot_info = NULL;
+
+       push_input_file(fname);
+
+       if (yyparse() != 0)
+               return NULL;
+
+       fill_fullpaths(the_boot_info->dt, "");
+
+       return the_boot_info;
+}
+
+static void write_prefix(FILE *f, int level)
+{
+       int i;
+
+       for (i = 0; i < level; i++)
+               fputc('\t', f);
+}
+
+int isstring(char c)
+{
+       return (isprint(c)
+               || (c == '\0')
+               || strchr("\a\b\t\n\v\f\r", c));
+}
+
+static void write_propval_string(FILE *f, struct data val)
+{
+       const char *str = val.val;
+       int i;
+       int newchunk = 1;
+       struct marker *m = val.markers;
+
+       assert(str[val.len-1] == '\0');
+
+       for (i = 0; i < (val.len-1); i++) {
+               char c = str[i];
+
+               if (newchunk) {
+                       while (m && (m->offset <= i)) {
+                               if (m->type == LABEL) {
+                                       assert(m->offset == i);
+                                       fprintf(f, "%s: ", m->ref);
+                               }
+                               m = m->next;
+                       }
+                       fprintf(f, "\"");
+                       newchunk = 0;
+               }
+
+               switch (c) {
+               case '\a':
+                       fprintf(f, "\\a");
+                       break;
+               case '\b':
+                       fprintf(f, "\\b");
+                       break;
+               case '\t':
+                       fprintf(f, "\\t");
+                       break;
+               case '\n':
+                       fprintf(f, "\\n");
+                       break;
+               case '\v':
+                       fprintf(f, "\\v");
+                       break;
+               case '\f':
+                       fprintf(f, "\\f");
+                       break;
+               case '\r':
+                       fprintf(f, "\\r");
+                       break;
+               case '\\':
+                       fprintf(f, "\\\\");
+                       break;
+               case '\"':
+                       fprintf(f, "\\\"");
+                       break;
+               case '\0':
+                       fprintf(f, "\", ");
+                       newchunk = 1;
+                       break;
+               default:
+                       if (isprint(c))
+                               fprintf(f, "%c", c);
+                       else
+                               fprintf(f, "\\x%02hhx", c);
+               }
+       }
+       fprintf(f, "\"");
+
+       /* Wrap up any labels at the end of the value */
+       for_each_marker_of_type(m, LABEL) {
+               assert (m->offset == val.len);
+               fprintf(f, " %s:", m->ref);
+       }
+}
+
+static void write_propval_cells(FILE *f, struct data val)
+{
+       void *propend = val.val + val.len;
+       cell_t *cp = (cell_t *)val.val;
+       struct marker *m = val.markers;
+
+       fprintf(f, "<");
+       for (;;) {
+               while (m && (m->offset <= ((char *)cp - val.val))) {
+                       if (m->type == LABEL) {
+                               assert(m->offset == ((char *)cp - val.val));
+                               fprintf(f, "%s: ", m->ref);
+                       }
+                       m = m->next;
+               }
+
+               fprintf(f, "0x%x", be32_to_cpu(*cp++));
+               if ((void *)cp >= propend)
+                       break;
+               fprintf(f, " ");
+       }
+
+       /* Wrap up any labels at the end of the value */
+       for_each_marker_of_type(m, LABEL) {
+               assert (m->offset == val.len);
+               fprintf(f, " %s:", m->ref);
+       }
+       fprintf(f, ">");
+}
+
+static void write_propval_bytes(FILE *f, struct data val)
+{
+       void *propend = val.val + val.len;
+       const char *bp = val.val;
+       struct marker *m = val.markers;
+
+       fprintf(f, "[");
+       for (;;) {
+               while (m && (m->offset == (bp-val.val))) {
+                       if (m->type == LABEL)
+                               fprintf(f, "%s: ", m->ref);
+                       m = m->next;
+               }
+
+               fprintf(f, "%02hhx", *bp++);
+               if ((void *)bp >= propend)
+                       break;
+               fprintf(f, " ");
+       }
+
+       /* Wrap up any labels at the end of the value */
+       for_each_marker_of_type(m, LABEL) {
+               assert (m->offset == val.len);
+               fprintf(f, " %s:", m->ref);
+       }
+       fprintf(f, "]");
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+       int len = prop->val.len;
+       const char *p = prop->val.val;
+       struct marker *m = prop->val.markers;
+       int nnotstring = 0, nnul = 0;
+       int nnotstringlbl = 0, nnotcelllbl = 0;
+       int i;
+
+       if (len == 0) {
+               fprintf(f, ";\n");
+               return;
+       }
+
+       for (i = 0; i < len; i++) {
+               if (! isstring(p[i]))
+                       nnotstring++;
+               if (p[i] == '\0')
+                       nnul++;
+       }
+
+       for_each_marker_of_type(m, LABEL) {
+               if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
+                       nnotstringlbl++;
+               if ((m->offset % sizeof(cell_t)) != 0)
+                       nnotcelllbl++;
+       }
+
+       fprintf(f, " = ");
+       if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+           && (nnotstringlbl == 0)) {
+               write_propval_string(f, prop->val);
+       } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
+               write_propval_cells(f, prop->val);
+       } else {
+               write_propval_bytes(f, prop->val);
+       }
+
+       fprintf(f, ";\n");
+}
+
+static void write_tree_source_node(FILE *f, struct node *tree, int level)
+{
+       struct property *prop;
+       struct node *child;
+
+       write_prefix(f, level);
+       if (tree->label)
+               fprintf(f, "%s: ", tree->label);
+       if (tree->name && (*tree->name))
+               fprintf(f, "%s {\n", tree->name);
+       else
+               fprintf(f, "/ {\n");
+
+       for_each_property(tree, prop) {
+               write_prefix(f, level+1);
+               if (prop->label)
+                       fprintf(f, "%s: ", prop->label);
+               fprintf(f, "%s", prop->name);
+               write_propval(f, prop);
+       }
+       for_each_child(tree, child) {
+               fprintf(f, "\n");
+               write_tree_source_node(f, child, level+1);
+       }
+       write_prefix(f, level);
+       fprintf(f, "};\n");
+}
+
+
+void dt_to_source(FILE *f, struct boot_info *bi)
+{
+       struct reserve_info *re;
+
+       fprintf(f, "/dts-v1/;\n\n");
+
+       for (re = bi->reservelist; re; re = re->next) {
+               if (re->label)
+                       fprintf(f, "%s: ", re->label);
+               fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
+                       (unsigned long long)re->re.address,
+                       (unsigned long long)re->re.size);
+       }
+
+       write_tree_source_node(f, bi->dt, 0);
+}
+
diff --git a/arch/powerpc/boot/dtc-src/version_gen.h b/arch/powerpc/boot/dtc-src/version_gen.h
new file mode 100644 (file)
index 0000000..6c34303
--- /dev/null
@@ -0,0 +1 @@
+#define DTC_VERSION "DTC 1.0.0-gd6f9b62f"
index ec71ab819fee8a21522a35fe24a96bfbb481626b..4469588545190ffce105c9e89c97be3c9f56a715 100644 (file)
@@ -23,6 +23,12 @@ XXXX add flash parts, rtc, ??
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -60,7 +66,7 @@ XXXX add flash parts, rtc, ??
                i2c@80003000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <80003000 1000>;
                        interrupts = <5 2>;
@@ -73,7 +79,8 @@ XXXX add flash parts, rtc, ??
                        };
                };
 
-               serial@80004500 {
+               serial0: serial@80004500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <80004500 8>;
@@ -83,7 +90,8 @@ XXXX add flash parts, rtc, ??
                        interrupt-parent = <&mpic>;
                };
 
-               serial@80004600 {
+               serial1: serial@80004600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <80004600 8>;
@@ -102,7 +110,7 @@ XXXX add flash parts, rtc, ??
                        reg = <80040000 40000>;
                };
 
-               pci@fec00000 {
+               pci0: pci@fec00000 {
                        #address-cells = <3>;
                        #size-cells = <2>;
                        #interrupt-cells = <1>;
index 32ecd23199285bed81435759dfc86e54b60386e1..8443c85b7b3096ba00a2ea439a0685e3ffb4e35f 100644 (file)
@@ -23,6 +23,12 @@ XXXX add flash parts, rtc, ??
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -60,7 +66,7 @@ XXXX add flash parts, rtc, ??
                i2c@80003000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <80003000 1000>;
                        interrupts = <5 2>;
@@ -73,7 +79,8 @@ XXXX add flash parts, rtc, ??
                        };
                };
 
-               serial@80004500 {
+               serial0: serial@80004500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <80004500 8>;
@@ -83,7 +90,8 @@ XXXX add flash parts, rtc, ??
                        interrupt-parent = <&mpic>;
                };
 
-               serial@80004600 {
+               serial1: serial@80004600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <80004600 8>;
@@ -102,7 +110,7 @@ XXXX add flash parts, rtc, ??
                        reg = <80040000 40000>;
                };
 
-               pci@fec00000 {
+               pci0: pci@fec00000 {
                        #address-cells = <3>;
                        #size-cells = <2>;
                        #interrupt-cells = <1>;
index 6731763f028248d2569987d7f4f0c3585d5ae2c9..23eeeb1fc61eccc350cf554eefea3a9ca67e8f2a 100644 (file)
                };
 
                i2c@3d00 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "mpc5200-i2c","fsl-i2c";
                        cell-index = <0>;
                        reg = <3d00 40>;
                };
 
                i2c@3d40 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "mpc5200-i2c","fsl-i2c";
                        cell-index = <1>;
                        reg = <3d40 40>;
index b540388c608c4ec9addf0a3d66c9664f6d2d5ac6..f94e073de9a79bed7ac615580f7bc6154fd61e67 100644 (file)
                };
 
                i2c@3d00 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "mpc5200b-i2c","mpc5200-i2c","fsl-i2c";
                        cell-index = <0>;
                        reg = <3d00 40>;
                };
 
                i2c@3d40 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "mpc5200b-i2c","mpc5200-i2c","fsl-i2c";
                        cell-index = <1>;
                        reg = <3d40 40>;
index 9e7eba973262405fa00ea6b3facdb7f72b71f0b2..c5b6665a8209d44dff118581280f21e5c74a393b 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -52,7 +60,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -61,7 +71,9 @@
                };
 
                i2c@3100 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
                };
 
                mdio@24520 {
-                       device_type = "mdio";
-                       compatible = "gianfar";
-                       reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <24520 20>;
                        phy1: ethernet-phy@1 {
                                interrupt-parent = < &ipic >;
                                interrupts = <13 8>;
                        };
                };
 
-               ethernet@24000 {
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-handle = < &phy1 >;
                };
 
-               ethernet@25000 {
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-handle = < &phy4 >;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index c64f3037a13b4a0fd33fc1faec3ab106bf13e8e2..26ac467b10ea910c265e940fa8acea7b24616bd7 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -59,7 +67,7 @@
                i2c@3000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -72,7 +80,8 @@
                        };
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
@@ -81,7 +90,8 @@
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                        mode = "slave";
                };
 
-               ucc@2200 {
+               enet0: ucc@2200 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <3>;
                        device-id = <3>;
                        reg = <2200 200>;
                        interrupts = <22>;
                        interrupt-parent = < &qeic >;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <19>;
-                       tx-clock = <1a>;
+                       rx-clock-name = "clk9";
+                       tx-clock-name = "clk10";
                        phy-handle = < &phy3 >;
                        pio-handle = < &pio3 >;
                };
 
-               ucc@3200 {
+               enet1: ucc@3200 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <4>;
                        device-id = <4>;
                        reg = <3200 200>;
                        interrupts = <23>;
                        interrupt-parent = < &qeic >;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <17>;
-                       tx-clock = <18>;
+                       rx-clock-name = "clk7";
+                       tx-clock-name = "clk8";
                        phy-handle = < &phy4 >;
                        pio-handle = < &pio4 >;
                };
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                                /* IDSEL 0x11 AD17 */
index 388c8a7012e138910626babe9675bbe26b05abb6..10ff7aadf9dcce63335cc1e8640ac4f3e52ee487 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -52,7 +60,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -60,7 +70,8 @@
                        dfsrr;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
@@ -69,7 +80,8 @@
                        interrupt-parent = <&pic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                        mode = "cpu";
                };
 
-               ucc@3000 {
+               enet0: ucc@3000 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <2>;
                        device-id = <2>;
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = <&qeic>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <20>;
-                       tx-clock = <13>;
+                       rx-clock-name = "clk16";
+                       tx-clock-name = "clk3";
                        phy-handle = <&phy00>;
                        pio-handle = <&ucc2pio>;
                };
 
-               ucc@2200 {
+               enet1: ucc@2200 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <3>;
                        device-id = <3>;
                        reg = <2200 200>;
                        interrupts = <22>;
                        interrupt-parent = <&qeic>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <19>;
-                       tx-clock = <1a>;
+                       rx-clock-name = "clk9";
+                       tx-clock-name = "clk10";
                        phy-handle = <&phy04>;
                        pio-handle = <&ucc3pio>;
                };
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                                /* IDSEL 0x10 AD16 (USB) */
index 5072f6d0a46d3a9631591b85f920cb2ed4668e8e..e354f26342466595900870cc80fffb4f363a3972 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -51,7 +60,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -60,7 +71,9 @@
                };
 
                i2c@3100 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
                };
 
                mdio@24520 {
-                       device_type = "mdio";
-                       compatible = "gianfar";
-                       reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <24520 20>;
 
                        /* Vitesse 8201 */
                        phy1c: ethernet-phy@1c {
                        };
                };
 
-               ethernet@24000 {
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
                        interrupt-parent = < &ipic >;
                        linux,network-index = <0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
                        interrupt-parent = < &ipic >;
                        linux,network-index = <1>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                                /* IDSEL 0x10 - SATA */
                device_type = "pci";
        };
 
-       pci@e0008600 {
+       pci1: pci@e0008600 {
+               cell-index = <2>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                                /* IDSEL 0x0E - MiniPCI Slot */
index 074f7a2ab7e4ccd97d5d425afe6d009ff4f3f443..ebdf0b75008687a0be4459a9be6a9144abed9921 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -51,7 +58,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -60,7 +69,9 @@
                };
 
                i2c@3100 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
                };
 
                mdio@24520 {
-                       device_type = "mdio";
-                       compatible = "gianfar";
-                       reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <24520 20>;
 
                        /* Vitesse 8201 */
                        phy1c: ethernet-phy@1c {
                        };
                };
 
-               ethernet@24000 {
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        linux,network-index = <0>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pci@e0008600 {
+       pci0: pci@e0008600 {
+               cell-index = <2>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                                /* IDSEL 0x0F - PCI Slot */
index 49363f89cb712494e64db301eafb7ebbbbfac187..0ba13ebcea688d8012be8b20408934d64a8378b3 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -59,7 +68,7 @@
                i2c@3000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -75,7 +84,7 @@
                i2c@3100 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
                };
 
                mdio@24520 {
-                       device_type = "mdio";
-                       compatible = "gianfar";
-                       reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = < &ipic >;
                                interrupts = <11 8>;
                        };
                };
 
-               ethernet@24000 {
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <20 8 21 8 22 8>;
                        interrupt-parent = < &ipic >;
                        linux,network-index = <0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 8 24 8 25 8>;
                        interrupt-parent = < &ipic >;
                        linux,network-index = <1>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
                device_type = "pci";
        };
 
-       pci@e0008600 {
+       pci1: pci@e0008600 {
+               cell-index = <2>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 0b2d2b588daa0c907523bb258e8aa11ec628fb25..fd841b2fddd016375b08e3f694a719b1756f23d7 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -64,7 +72,7 @@
                i2c@3000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <e 8>;
@@ -80,7 +88,7 @@
                i2c@3100 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <f 8>;
@@ -88,7 +96,8 @@
                        dfsrr;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = < &ipic >;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                        mode = "slave";
                };
 
-               ucc@2000 {
+               enet0: ucc@2000 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <1>;
                        device-id = <1>;
                        reg = <2000 200>;
                        interrupts = <20>;
                        interrupt-parent = < &qeic >;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <0>;
-                       tx-clock = <19>;
+                       rx-clock-name = "none";
+                       tx-clock-name = "clk9";
                        phy-handle = < &phy0 >;
                        phy-connection-type = "rgmii-id";
                        pio-handle = < &pio1 >;
                };
 
-               ucc@3000 {
+               enet1: ucc@3000 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <2>;
                        device-id = <2>;
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = < &qeic >;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <0>;
-                       tx-clock = <14>;
+                       rx-clock-name = "none";
+                       tx-clock-name = "clk4";
                        phy-handle = < &phy1 >;
                        phy-connection-type = "rgmii-id";
                        pio-handle = < &pio2 >;
                };
        };
 
-       pci@e0008500 {
+       pci0: pci@e0008500 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 6442a717ec3bf7532477372b9fd74b5f8a92d167..975248491b7b9dcb258a5377781a07d0ae6ed12f 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -63,7 +72,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
@@ -74,9 +85,9 @@
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <5 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy1>;
                };
 
-               ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet2: ethernet@26000 {
+                       cell-index = <2>;
                        device_type = "network";
                        model = "FEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <29 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                };
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index f3f4d79deb636f3442b58cd87f206e269e3b8e01..fa8d9aaad157974645ac5988a9ce4d1fcc632217 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -63,7 +72,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
@@ -74,9 +85,9 @@
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <5 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy1>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                };
        };
 
-       pci1: pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                interrupt-map-mask = <1f800 0 0 7>;
                interrupt-map = <
 
                        #interrupt-cells = <2>;
                        compatible = "chrp,iic";
                        interrupts = <1>;
-                       interrupt-parent = <&pci1>;
+                       interrupt-parent = <&pci0>;
                };
        };
 
-       pci@e0009000 {
+       pci1: pci@e0009000 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 6c608de1fc1b53e499bf972a9d6dd48dc2a613db..54b3bdf7fc97ed2b1ecb82bead79027f6775c98c 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               pci2 = &pci2;
+               pci3 = &pci3;
+       };
+
        cpus {
                #cpus = <1>;
                #address-cells = <1>;
@@ -64,7 +75,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
                        dfsrr;
                };
 
+               i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <3100 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <a 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@26000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                compatible = "fsl,mpc8540-pci";
                device_type = "pci";
                interrupt-map-mask = <f800 0 0 7>;
                reg = <e0008000 1000>;
        };
 
-       pcie@e0009000 {
+       pci1: pcie@e0009000 {
+               cell-index = <1>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
                };
        };
 
-       pcie@e000a000 {
+       pci2: pcie@e000a000 {
+               cell-index = <2>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
                };
        };
 
-       pcie@e000b000 {
+       pci3: pcie@e000b000 {
+               cell-index = <3>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
                                };
                        };
                };
-
        };
 };
index 69ca5025d9723cc143b2e0e711c4ba50d6f0304f..1f470c6a1c63cf89a08452196862e5d5e149d0ea 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+/*
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+*/
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               pci2 = &pci2;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -63,7 +77,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
                        dfsrr;
                };
 
+               i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <3100 100>;
+                       interrupts = <2b 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <5 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                };
 
 /* eTSEC 3/4 are currently broken
-               ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet2: ethernet@26000 {
+                       cell-index = <2>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy2>;
                };
 
-               ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet3: ethernet@27000 {
+                       cell-index = <3>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                };
  */
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                };
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                        /* IDSEL 0x4 (PCIX Slot 2) */
                };
        };
 
-       pci@e0009000 {
+       pci1: pci@e0009000 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
                device_type = "pci";
        };
 
-       pcie@e000a000 {
+       pci2: pcie@e000a000 {
+               cell-index = <2>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 57029cca32b2de2d4aa0e17a5039d3ab63ae9032..4538f3c388629cd68da8ed93914e8ee2f82e4d9f 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -63,7 +72,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
@@ -74,9 +85,9 @@
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <5 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        phy-handle = <&phy1>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;       // reg base, size
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;       // reg base, size
                };
        };
 
-       pci1: pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                interrupt-map-mask = <1f800 0 0 7>;
                interrupt-map = <
 
                        #interrupt-cells = <2>;
                        compatible = "chrp,iic";
                        interrupts = <1>;
-                       interrupt-parent = <&pci1>;
+                       interrupt-parent = <&pci0>;
                };
        };
 
-       pci@e0009000 {
+       pci1: pci@e0009000 {
+               cell-index = <1>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 6b362f8222c15173bca7b1f6af6a0cb637bba883..639ce8a709a63b03fb05761a927ee52566b0a9e9 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                };
 
                mdio@24520 {
-                       device_type = "mdio";
-                       compatible = "gianfar";
-                       reg = <24520 20>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <5 1>;
                        };
                };
 
-               ethernet@24000 {
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy0>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                                compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
                        };
 
-                       serial@91a00 {
+                       serial0: serial@91a00 {
                                device_type = "serial";
                                compatible = "fsl,mpc8560-scc-uart",
                                             "fsl,cpm2-scc-uart";
                                interrupt-parent = <&cpmpic>;
                        };
 
-                       serial@91a20 {
+                       serial1: serial@91a20 {
                                device_type = "serial";
                                compatible = "fsl,mpc8560-scc-uart",
                                             "fsl,cpm2-scc-uart";
                                interrupt-parent = <&cpmpic>;
                        };
 
-                       ethernet@91320 {
+                       enet2: ethernet@91320 {
                                device_type = "network";
                                compatible = "fsl,mpc8560-fcc-enet",
                                             "fsl,cpm2-fcc-enet";
                                reg = <91320 20 88500 100 913b0 1>;
-                               /*
-                                * mac-address is deprecated and will be removed
-                                * in 2.6.25.  Only recent versions of
-                                * U-Boot support local-mac-address, however.
-                                */
-                               mac-address = [ 00 00 00 00 00 00 ];
                                local-mac-address = [ 00 00 00 00 00 00 ];
                                fsl,cpm-command = <16200300>;
                                interrupts = <21 8>;
                                phy-handle = <&phy2>;
                        };
 
-                       ethernet@91340 {
+                       enet3: ethernet@91340 {
                                device_type = "network";
                                compatible = "fsl,mpc8560-fcc-enet",
                                             "fsl,cpm2-fcc-enet";
                                reg = <91340 20 88600 100 913d0 1>;
-                               /*
-                                * mac-address is deprecated and will be removed
-                                * in 2.6.25.  Only recent versions of
-                                * U-Boot support local-mac-address, however.
-                                */
-                               mac-address = [ 00 00 00 00 00 00 ];
                                local-mac-address = [ 00 00 00 00 00 00 ];
                                fsl,cpm-command = <1a400300>;
                                interrupts = <22 8>;
                };
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                #interrupt-cells = <1>;
                #size-cells = <2>;
                #address-cells = <3>;
index 54394372b12afb5db116318e63f688272166d137..5818a7c861e734c9a1e5dd5d379cb4556a01a48c 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -74,7 +85,7 @@
                i2c@3000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
                i2c@3100 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "i2c";
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <2b 2>;
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@7 {
                                interrupt-parent = <&mpic>;
                                interrupts = <1 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy2>;
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        fsl,has-rstcr;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                        mode = "cpu";
                };
 
-               ucc@2000 {
+               enet2: ucc@2000 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <1>;
                        device-id = <1>;
                        reg = <2000 200>;
                        interrupts = <20>;
                        interrupt-parent = <&qeic>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <0>;
-                       tx-clock = <20>;
+                       rx-clock-name = "none";
+                       tx-clock-name = "clk16";
                        pio-handle = <&pio1>;
                        phy-handle = <&phy0>;
                        phy-connection-type = "rgmii-id";
                };
 
-               ucc@3000 {
+               enet3: ucc@3000 {
                        device_type = "network";
                        compatible = "ucc_geth";
                        model = "UCC";
+                       cell-index = <2>;
                        device-id = <2>;
                        reg = <3000 200>;
                        interrupts = <21>;
                        interrupt-parent = <&qeic>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
-                       rx-clock = <0>;
-                       tx-clock = <20>;
+                       rx-clock-name = "none";
+                       tx-clock-name = "clk16";
                        pio-handle = <&pio2>;
                        phy-handle = <&phy1>;
                        phy-connection-type = "rgmii-id";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <2120 18>;
-                       device_type = "mdio";
                        compatible = "ucc_geth_phy";
 
                        /* These are the same PHYs as on
 
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
                        /* IDSEL 0x12 AD18 */
        };
 
        /* PCI Express */
-       pcie@e000a000 {
+       pci1: pcie@e000a000 {
+               cell-index = <2>;
                interrupt-map-mask = <f800 0 0 7>;
                interrupt-map = <
 
index 0eb44fb9647dbccf50177d452d0486af529b51ae..233e0d5a8b9de63880606fa087d39c6195a7b9e3 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+               pci2 = &pci2;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -69,7 +81,9 @@
                };
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
@@ -78,7 +92,9 @@
                };
 
                i2c@3100 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <2b 2>;
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <a 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet2: ethernet@26000 {
+                       cell-index = <2>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet3: ethernet@27000 {
+                       cell-index = <3>;
                        device_type = "network";
                        model = "eTSEC";
                        compatible = "gianfar";
                        phy-connection-type = "rgmii-id";
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pcie@ffe08000 {
+       pci0: pcie@ffe08000 {
+               cell-index = <0>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
 
        };
 
-       pcie@ffe09000 {
+       pci1: pcie@ffe09000 {
+               cell-index = <1>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
                };
        };
 
-       pcie@ffe0a000 {
+       pci2: pcie@ffe0a000 {
+               cell-index = <2>;
                compatible = "fsl,mpc8548-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
index 966edf1161a63f811bbe9951250767d34f481c7e..01040a752c823946107ee7e8f5d4f63bed988325 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                bus-frequency = <0>;
 
                i2c@3000 {
-                       device_type = "i2c";
-                       compatible = "fsl-i2c";
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       cell-index = <0>;
+                       compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                };
 
                i2c@3100 {
-                       device_type = "i2c";
-                       compatible = "fsl-i2c";
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <2b 2>;
                        interrupt-parent = <&mpic>;
                        dfsrr;
                };
 
-               serial@4500 {
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
@@ -77,7 +85,8 @@
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
@@ -86,7 +95,6 @@
                        interrupt-parent = <&mpic>;
                };
 
-
                mpic: interrupt-controller@40000 {
                        clock-frequency = <0>;
                        interrupt-controller;
                };
        };
 
-       pci@e0008000 {
+       pci0: pci@e0008000 {
+               cell-index = <0>;
                compatible = "fsl,mpc8610-pci";
                device_type = "pci";
                #interrupt-cells = <1>;
                        >;
        };
 
-       pcie@e000a000 {
+       pci1: pcie@e000a000 {
+               cell-index = <1>;
                compatible = "fsl,mpc8641-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
index abb26dc425588aeb38782d7a1a0b459224568000..86fc2280c16d1158486b7d4aebf9aa9e9f983a41 100644 (file)
        #address-cells = <1>;
        #size-cells = <1>;
 
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               serial1 = &serial1;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
@@ -58,7 +69,9 @@
                bus-frequency = <0>;
 
                i2c@3000 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
                        compatible = "fsl-i2c";
                        reg = <3000 100>;
                        interrupts = <2b 2>;
@@ -67,7 +80,9 @@
                };
 
                i2c@3100 {
-                       device_type = "i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
                        compatible = "fsl-i2c";
                        reg = <3100 100>;
                        interrupts = <2b 2>;
@@ -78,9 +93,9 @@
                mdio@24520 {
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       device_type = "mdio";
-                       compatible = "gianfar";
+                       compatible = "fsl,gianfar-mdio";
                        reg = <24520 20>;
+
                        phy0: ethernet-phy@0 {
                                interrupt-parent = <&mpic>;
                                interrupts = <a 1>;
                        };
                };
 
-               ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <24000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1d 2 1e 2 22 2>;
                        interrupt-parent = <&mpic>;
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <25000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <23 2 24 2 28 2>;
                        interrupt-parent = <&mpic>;
                        phy-connection-type = "rgmii-id";
                };
                
-               ethernet@26000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet2: ethernet@26000 {
+                       cell-index = <2>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <26000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <1F 2 20 2 21 2>;
                        interrupt-parent = <&mpic>;
                        phy-connection-type = "rgmii-id";
                };
 
-               ethernet@27000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+               enet3: ethernet@27000 {
+                       cell-index = <3>;
                        device_type = "network";
                        model = "TSEC";
                        compatible = "gianfar";
                        reg = <27000 1000>;
-                       /*
-                        * mac-address is deprecated and will be removed
-                        * in 2.6.25.  Only recent versions of
-                        * U-Boot support local-mac-address, however.
-                        */
-                       mac-address = [ 00 00 00 00 00 00 ];
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <25 2 26 2 27 2>;
                        interrupt-parent = <&mpic>;
                        phy-handle = <&phy3>;
                        phy-connection-type = "rgmii-id";
                };
-               serial@4500 {
+
+               serial0: serial@4500 {
+                       cell-index = <0>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4500 100>;
                        interrupt-parent = <&mpic>;
                };
 
-               serial@4600 {
+               serial1: serial@4600 {
+                       cell-index = <1>;
                        device_type = "serial";
                        compatible = "ns16550";
                        reg = <4600 100>;
                };
        };
 
-       pcie@f8008000 {
+       pci0: pcie@f8008000 {
+               cell-index = <0>;
                compatible = "fsl,mpc8641-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
 
        };
 
-       pcie@f8009000 {
+       pci1: pcie@f8009000 {
+               cell-index = <1>;
                compatible = "fsl,mpc8641-pcie";
                device_type = "pci";
                #interrupt-cells = <1>;
index 90f2293ed3cde4b221136a0eaba5dad51b7bf6f7..daf9433e906b5626987237e5a19a99c54b430519 100644 (file)
@@ -12,7 +12,7 @@
 
 / {
        model = "MPC866ADS";
-       compatible = "mpc8xx";
+       compatible = "fsl,mpc866ads";
        #address-cells = <1>;
        #size-cells = <1>;
 
                PowerPC,866@0 {
                        device_type = "cpu";
                        reg = <0>;
-                       d-cache-line-size = <20>;       // 32 bytes
-                       i-cache-line-size = <20>;       // 32 bytes
+                       d-cache-line-size = <10>;       // 16 bytes
+                       i-cache-line-size = <10>;       // 16 bytes
                        d-cache-size = <2000>;          // L1, 8K
                        i-cache-size = <4000>;          // L1, 16K
                        timebase-frequency = <0>;
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                        interrupts = <f 2>;     // decrementer interrupt
-                       interrupt-parent = <&Mpc8xx_pic>;
+                       interrupt-parent = <&PIC>;
                };
        };
 
                reg = <00000000 800000>;
        };
 
-       soc866@ff000000 {
+       localbus@ff000100 {
+               compatible = "fsl,mpc866-localbus", "fsl,pq1-localbus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               reg = <ff000100 40>;
+
+               ranges = <
+                       1 0 ff080000 00008000
+                       5 0 ff0a0000 00008000
+               >;
+
+               board-control@1,0 {
+                       reg = <1 0 20 5 300 4>;
+                       compatible = "fsl,mpc866ads-bcsr";
+               };
+       };
+
+       soc@ff000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                device_type = "soc";
                ranges = <0 ff000000 00100000>;
                reg = <ff000000 00000200>;
                bus-frequency = <0>;
-               mdio@e80 {
-                       device_type = "mdio";
-                       compatible = "fs_enet";
-                       reg = <e80 8>;
+
+               mdio@e00 {
+                       compatible = "fsl,mpc866-fec-mdio", "fsl,pq1-fec-mdio";
+                       reg = <e00 188>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       phy: ethernet-phy@f {
+                       PHY: ethernet-phy@f {
                                reg = <f>;
                                device_type = "ethernet-phy";
                        };
                };
 
-               fec@e00 {
+               ethernet@e00 {
                        device_type = "network";
-                       compatible = "fs_enet";
-                       model = "FEC";
-                       device-id = <1>;
+                       compatible = "fsl,mpc866-fec-enet",
+                                    "fsl,pq1-fec-enet";
                        reg = <e00 188>;
-                       mac-address = [ 00 00 0C 00 01 FD ];
+                       local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <3 1>;
-                       interrupt-parent = <&Mpc8xx_pic>;
-                       phy-handle = <&Phy>;
+                       interrupt-parent = <&PIC>;
+                       phy-handle = <&PHY>;
+                       linux,network-index = <0>;
                };
 
-               mpc8xx_pic: pic@ff000000 {
+               PIC: pic@0 {
                        interrupt-controller;
-                       #address-cells = <0>;
                        #interrupt-cells = <2>;
                        reg = <0 24>;
-                       device_type = "mpc8xx-pic";
-                       compatible = "CPM";
+                       compatible = "fsl,mpc866-pic", "fsl,pq1-pic";
                };
 
-               cpm@ff000000 {
+               cpm@9c0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       device_type = "cpm";
-                       model = "CPM";
-                       ranges = <0 0 4000>;
-                       reg = <860 f0>;
-                       command-proc = <9c0>;
+                       compatible = "fsl,mpc866-cpm", "fsl,cpm1";
+                       ranges;
+                       reg = <9c0 40>;
                        brg-frequency = <0>;
                        interrupts = <0 2>;     // cpm error interrupt
-                       interrupt-parent = <&Cpm_pic>;
+                       interrupt-parent = <&CPM_PIC>;
 
-                       cpm_pic: pic@930 {
+                       muram@2000 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 2000 2000>;
+
+                               data@0 {
+                                       compatible = "fsl,cpm-muram-data";
+                                       reg = <0 1c00>;
+                               };
+                       };
+
+                       brg@9f0 {
+                               compatible = "fsl,mpc866-brg",
+                                            "fsl,cpm1-brg",
+                                            "fsl,cpm-brg";
+                               reg = <9f0 10>;
+                               clock-frequency = <0>;
+                       };
+
+                       CPM_PIC: pic@930 {
                                interrupt-controller;
                                #address-cells = <0>;
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <1>;
                                interrupts = <5 2 0 2>;
-                               interrupt-parent = <&Mpc8xx_pic>;
+                               interrupt-parent = <&PIC>;
                                reg = <930 20>;
-                               device_type = "cpm-pic";
-                               compatible = "CPM";
+                               compatible = "fsl,mpc866-cpm-pic",
+                                            "fsl,cpm1-pic";
                        };
 
-                       smc@a80 {
+
+                       serial@a80 {
                                device_type = "serial";
-                               compatible = "cpm_uart";
-                               model = "SMC";
-                               device-id = <1>;
+                               compatible = "fsl,mpc866-smc-uart",
+                                            "fsl,cpm1-smc-uart";
                                reg = <a80 10 3e80 40>;
-                               clock-setup = <00ffffff 0>;
-                               rx-clock = <1>;
-                               tx-clock = <1>;
-                               current-speed = <0>;
-                               interrupts = <4 3>;
-                               interrupt-parent = <&Cpm_pic>;
+                               interrupts = <4>;
+                               interrupt-parent = <&CPM_PIC>;
+                               fsl,cpm-brg = <1>;
+                               fsl,cpm-command = <0090>;
                        };
 
-                       smc@a90 {
+                       serial@a90 {
                                device_type = "serial";
-                               compatible = "cpm_uart";
-                               model = "SMC";
-                               device-id = <2>;
-                               reg = <a90 20 3f80 40>;
-                               clock-setup = <ff00ffff 90000>;
-                               rx-clock = <2>;
-                               tx-clock = <2>;
-                               current-speed = <0>;
-                               interrupts = <3 3>;
-                               interrupt-parent = <&Cpm_pic>;
+                               compatible = "fsl,mpc866-smc-uart",
+                                            "fsl,cpm1-smc-uart";
+                               reg = <a90 10 3f80 40>;
+                               interrupts = <3>;
+                               interrupt-parent = <&CPM_PIC>;
+                               fsl,cpm-brg = <2>;
+                               fsl,cpm-command = <00d0>;
                        };
 
-                       scc@a00 {
+                       ethernet@a00 {
                                device_type = "network";
-                               compatible = "fs_enet";
-                               model = "SCC";
-                               device-id = <1>;
-                               reg = <a00 18 3c00 80>;
-                               mac-address = [ 00 00 0C 00 03 FD ];
-                               interrupts = <1e 3>;
-                               interrupt-parent = <&Cpm_pic>;
+                               compatible = "fsl,mpc866-scc-enet",
+                                            "fsl,cpm1-scc-enet";
+                               reg = <a00 18 3c00 100>;
+                               local-mac-address = [ 00 00 00 00 00 00 ];
+                               interrupts = <1e>;
+                               interrupt-parent = <&CPM_PIC>;
+                               fsl,cpm-command = <0000>;
+                               linux,network-index = <1>;
                        };
                };
        };
+
+       chosen {
+               linux,stdout-path = "/soc/cpm/serial@a80";
+       };
 };
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..97af36c
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <page.h>
+#include <libfdt.h>
+#include "ops.h"
+
+#define DEBUG  0
+#define BAD_ERROR(err) (((err) < 0) \
+                        && ((err) != -FDT_ERR_NOTFOUND) \
+                        && ((err) != -FDT_ERR_EXISTS))
+
+#define check_err(err) \
+       ({ \
+               if (BAD_ERROR(err) || ((err < 0) && DEBUG)) \
+                       printf("%s():%d  %s\n\r", __FUNCTION__, __LINE__, \
+                              fdt_strerror(err)); \
+               if (BAD_ERROR(err)) \
+                       exit(); \
+               (err < 0) ? -1 : 0; \
+       })
+
+#define offset_devp(off)       \
+       ({ \
+               int _offset = (off); \
+               check_err(_offset) ? NULL : (void *)(_offset+1); \
+       })
+
+#define devp_offset_find(devp) (((int)(devp))-1)
+#define devp_offset(devp)      (devp ? ((int)(devp))-1 : 0)
+
+static void *fdt;
+static void *buf; /* = NULL */
+
+#define EXPAND_GRANULARITY     1024
+
+static void expand_buf(int minexpand)
+{
+       int size = fdt_totalsize(fdt);
+       int rc;
+
+       size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
+       buf = platform_ops.realloc(buf, size);
+       if (!buf)
+               fatal("Couldn't find %d bytes to expand device tree\n\r", size);
+       rc = fdt_open_into(fdt, buf, size);
+       if (rc != 0)
+               fatal("Couldn't expand fdt into new buffer: %s\n\r",
+                     fdt_strerror(rc));
+
+       fdt = buf;
+}
+
+static void *fdt_wrapper_finddevice(const char *path)
+{
+       return offset_devp(fdt_path_offset(fdt, path));
+}
+
+static int fdt_wrapper_getprop(const void *devp, const char *name,
+                              void *buf, const int buflen)
+{
+       const void *p;
+       int len;
+
+       p = fdt_getprop(fdt, devp_offset(devp), name, &len);
+       if (!p)
+               return check_err(len);
+       memcpy(buf, p, min(len, buflen));
+       return len;
+}
+
+static int fdt_wrapper_setprop(const void *devp, const char *name,
+                              const void *buf, const int len)
+{
+       int rc;
+
+       rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+       if (rc == -FDT_ERR_NOSPACE) {
+               expand_buf(len + 16);
+               rc = fdt_setprop(fdt, devp_offset(devp), name, buf, len);
+       }
+
+       return check_err(rc);
+}
+
+static void *fdt_wrapper_get_parent(const void *devp)
+{
+       return offset_devp(fdt_parent_offset(fdt, devp_offset(devp)));
+}
+
+static void *fdt_wrapper_create_node(const void *devp, const char *name)
+{
+       int offset;
+
+       offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+       if (offset == -FDT_ERR_NOSPACE) {
+               expand_buf(strlen(name) + 16);
+               offset = fdt_add_subnode(fdt, devp_offset(devp), name);
+       }
+
+       return offset_devp(offset);
+}
+
+static void *fdt_wrapper_find_node_by_prop_value(const void *prev,
+                                                const char *name,
+                                                const char *val,
+                                                int len)
+{
+       int offset = fdt_node_offset_by_prop_value(fdt, devp_offset_find(prev),
+                                                  name, val, len);
+       return offset_devp(offset);
+}
+
+static char *fdt_wrapper_get_path(const void *devp, char *buf, int len)
+{
+       int rc;
+
+       rc = fdt_get_path(fdt, devp_offset(devp), buf, len);
+       if (check_err(rc))
+               return NULL;
+       return buf;
+}
+
+static unsigned long fdt_wrapper_finalize(void)
+{
+       int rc;
+
+       rc = fdt_pack(fdt);
+       if (rc != 0)
+               fatal("Couldn't pack flat tree: %s\n\r",
+                     fdt_strerror(rc));
+       return (unsigned long)fdt;
+}
+
+void fdt_init(void *blob)
+{
+       int err;
+
+       dt_ops.finddevice = fdt_wrapper_finddevice;
+       dt_ops.getprop = fdt_wrapper_getprop;
+       dt_ops.setprop = fdt_wrapper_setprop;
+       dt_ops.get_parent = fdt_wrapper_get_parent;
+       dt_ops.create_node = fdt_wrapper_create_node;
+       dt_ops.find_node_by_prop_value = fdt_wrapper_find_node_by_prop_value;
+       dt_ops.get_path = fdt_wrapper_get_path;
+       dt_ops.finalize = fdt_wrapper_finalize;
+
+       /* Make sure the dt blob is the right version and so forth */
+       fdt = blob;
+       err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
+       if (err == -FDT_ERR_NOSPACE) {
+               int bufsize = fdt_totalsize(fdt) + 4;
+               buf = malloc(bufsize);
+               err = fdt_open_into(fdt, buf, bufsize);
+       }
+
+       if (err != 0)
+               fatal("fdt_init(): %s\n\r", fdt_strerror(err));
+
+       if (buf)
+               fdt = buf;
+}
diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/arch/powerpc/boot/libfdt/Makefile.libfdt
new file mode 100644 (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..f961cdeb97a24434647342bfadc237bd01eb0012 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,10 +118,13 @@ 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
-    dtc -O dtb -o "$dtb" -b 0 -V 16 "$dts"
+    $object/dtc -O dtb -o "$dtb" -b 0 "$dts"
 fi
 
 if [ -z "$kernel" ]; then
@@ -246,11 +251,11 @@ 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
diff --git a/arch/powerpc/configs/mpc837x_mds_defconfig b/arch/powerpc/configs/mpc837x_mds_defconfig
new file mode 100644 (file)
index 0000000..4f49aee
--- /dev/null
@@ -0,0 +1,878 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23
+# Wed Oct 10 16:31:39 2007
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
+# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
+# CONFIG_MPC834x_ITX is not set
+# CONFIG_MPC836x_MDS is not set
+CONFIG_MPC837x_MDS=y
+CONFIG_PPC_MPC837x=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
+# CONFIG_FSL_ULI1575 is not set
+CONFIG_FSL_SERDES=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_HIBERNATION_UP_POSSIBLE=y
+CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_FSL=y
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_FIXED_PHY is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_NETDEV_1000=y
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_EDAC is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+CONFIG_CRYPTO_HW=y
index 5760b9f033ea794ad9ff5c129bccd94242d53d61..7695a4c66e8009989bd55259dba279f544b1d29d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.24-rc4
-# Thu Dec  6 16:49:07 2007
+# Fri Dec 21 14:47:29 2007
 #
 CONFIG_PPC64=y
 
@@ -211,7 +211,7 @@ CONFIG_MMIO_NVRAM=y
 CONFIG_MPIC_U3_HT_IRQS=y
 CONFIG_MPIC_BROKEN_REGREAD=y
 CONFIG_IBMVIO=y
-# CONFIG_IBMEBUS is not set
+CONFIG_IBMEBUS=y
 # CONFIG_PPC_MPC106 is not set
 CONFIG_PPC_970_NAP=y
 CONFIG_PPC_INDIRECT_IO=y
@@ -375,7 +375,7 @@ CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+CONFIG_INET_LRO=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -929,6 +929,7 @@ CONFIG_SPIDER_NET=m
 CONFIG_NETDEV_10000=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_CHELSIO_T3 is not set
+CONFIG_EHEA=m
 # CONFIG_IXGBE is not set
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
@@ -1558,6 +1559,7 @@ CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
 # CONFIG_INFINIBAND_IPATH is not set
+CONFIG_INFINIBAND_EHCA=m
 # CONFIG_INFINIBAND_AMSO1100 is not set
 # CONFIG_MLX4_INFINIBAND is not set
 CONFIG_INFINIBAND_IPOIB=m
index ca51f0cf27ab3a77661ca9ff02e1e1de03196d12..9374bc9a2dd1a597332ee8afc9c12cb39971852c 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 ifeq ($(CONFIG_PPC64),y)
-EXTRA_CFLAGS   += -mno-minimal-toc
+CFLAGS_prom_init.o     += -mno-minimal-toc
 endif
 ifeq ($(CONFIG_PPC32),y)
 CFLAGS_prom_init.o      += -fPIC
index 9ed351f3c96625dd6e4862cb7c40bc5d1393a8bd..7c21f52d982a35ca5719c967c101beebbf7b05d0 100644 (file)
@@ -888,7 +888,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_603,
                .platform               = "ppc603",
        },
-       {       /* e300c3 on 83xx  */
+       {       /* e300c3 (e300c1, plus one IU, half cache size) on 83xx */
                .pvr_mask               = 0x7fff0000,
                .pvr_value              = 0x00850000,
                .cpu_name               = "e300c3",
@@ -899,6 +899,17 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_setup              = __setup_cpu_603,
                .platform               = "ppc603",
        },
+       {       /* e300c4 (e300c1, plus one IU) */
+               .pvr_mask               = 0x7fff0000,
+               .pvr_value              = 0x00860000,
+               .cpu_name               = "e300c4",
+               .cpu_features           = CPU_FTRS_E300,
+               .cpu_user_features      = COMMON_USER,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .cpu_setup              = __setup_cpu_603,
+               .platform               = "ppc603",
+       },
        {       /* default match, we assume split I/D cache & TB (non-601)... */
                .pvr_mask               = 0x00000000,
                .pvr_value              = 0x00000000,
index 72fd87156b24b662ee8abb08878197c3a6b6a02b..caae49ff06683eb44f3ed6d1e89a98bf4f37d5ab 100644 (file)
@@ -52,7 +52,7 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */
 struct bus_type ibmebus_bus_type;
 
 /* These devices will automatically be added to the bus during init */
-static struct of_device_id builtin_matches[] = {
+static struct of_device_id __initdata builtin_matches[] = {
        { .compatible = "IBM,lhca" },
        { .compatible = "IBM,lhea" },
        {},
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 4ed58875ee17ffe490268e6fb5f36dd14c27ae6a..b9cae6b1f8caf057d4328378c84902e8bc739e7b 100644 (file)
@@ -474,7 +474,7 @@ static int __init serial_dev_init(void)
 
        /*
         * Before we register the platfrom serial devices, we need
-        * to fixup their interrutps and their IO ports.
+        * to fixup their interrupts and their IO ports.
         */
        DBG("Fixing serial ports interrupts and IO ports ...\n");
 
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 07a89a3986394ebfd5eafabaaeb468358445beff..eab313858315ef991b5efc0d6886433105e1ac89 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/cache.h>
 #include <linux/bug.h>
+#include <linux/sort.h>
 
 #include "setup.h"
 
@@ -54,22 +55,60 @@ void module_free(struct module *mod, void *module_region)
    addend) */
 static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
 {
-       unsigned int i, j, ret = 0;
-
-       /* Sure, this is order(n^2), but it's usually short, and not
-           time critical */
-       for (i = 0; i < num; i++) {
-               for (j = 0; j < i; j++) {
-                       /* If this addend appeared before, it's
-                           already been counted */
-                       if (ELF32_R_SYM(rela[i].r_info)
-                           == ELF32_R_SYM(rela[j].r_info)
-                           && rela[i].r_addend == rela[j].r_addend)
-                               break;
+       unsigned int i, r_info, r_addend, _count_relocs;
+
+       _count_relocs = 0;
+       r_info = 0;
+       r_addend = 0;
+       for (i = 0; i < num; i++)
+               /* Only count 24-bit relocs, others don't need stubs */
+               if (ELF32_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
+                   (r_info != ELF32_R_SYM(rela[i].r_info) ||
+                    r_addend != rela[i].r_addend)) {
+                       _count_relocs++;
+                       r_info = ELF32_R_SYM(rela[i].r_info);
+                       r_addend = rela[i].r_addend;
                }
-               if (j == i) ret++;
+
+       return _count_relocs;
+}
+
+static int relacmp(const void *_x, const void *_y)
+{
+       const Elf32_Rela *x, *y;
+
+       y = (Elf32_Rela *)_x;
+       x = (Elf32_Rela *)_y;
+
+       /* Compare the entire r_info (as opposed to ELF32_R_SYM(r_info) only) to
+        * make the comparison cheaper/faster. It won't affect the sorting or
+        * the counting algorithms' performance
+        */
+       if (x->r_info < y->r_info)
+               return -1;
+       else if (x->r_info > y->r_info)
+               return 1;
+       else if (x->r_addend < y->r_addend)
+               return -1;
+       else if (x->r_addend > y->r_addend)
+               return 1;
+       else
+               return 0;
+}
+
+static void relaswap(void *_x, void *_y, int size)
+{
+       uint32_t *x, *y, tmp;
+       int i;
+
+       y = (uint32_t *)_x;
+       x = (uint32_t *)_y;
+
+       for (i = 0; i < sizeof(Elf32_Rela) / sizeof(uint32_t); i++) {
+               tmp = x[i];
+               x[i] = y[i];
+               y[i] = tmp;
        }
-       return ret;
 }
 
 /* Get the potential trampolines size required of the init and
@@ -100,6 +139,16 @@ static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
                        DEBUGP("Ptr: %p.  Number: %u\n",
                               (void *)hdr + sechdrs[i].sh_offset,
                               sechdrs[i].sh_size / sizeof(Elf32_Rela));
+
+                       /* Sort the relocation information based on a symbol and
+                        * addend key. This is a stable O(n*log n) complexity
+                        * alogrithm but it will reduce the complexity of
+                        * count_relocs() to linear complexity O(n)
+                        */
+                       sort((void *)hdr + sechdrs[i].sh_offset,
+                            sechdrs[i].sh_size / sizeof(Elf32_Rela),
+                            sizeof(Elf32_Rela), relacmp, relaswap);
+
                        ret += count_relocs((void *)hdr
                                             + sechdrs[i].sh_offset,
                                             sechdrs[i].sh_size
index 75c7c4f1928059689353927c2c67d198c62e715f..3a82b02b784b0c8a4d8da7467b8c7d4410cf9ea4 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/module.h>
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
+#include <linux/sort.h>
 
 #include "setup.h"
 
@@ -81,25 +82,23 @@ static struct ppc64_stub_entry ppc64_stub =
    different addend) */
 static unsigned int count_relocs(const Elf64_Rela *rela, unsigned int num)
 {
-       unsigned int i, j, ret = 0;
+       unsigned int i, r_info, r_addend, _count_relocs;
 
        /* FIXME: Only count external ones --RR */
-       /* Sure, this is order(n^2), but it's usually short, and not
-           time critical */
-       for (i = 0; i < num; i++) {
+       _count_relocs = 0;
+       r_info = 0;
+       r_addend = 0;
+       for (i = 0; i < num; i++)
                /* Only count 24-bit relocs, others don't need stubs */
-               if (ELF64_R_TYPE(rela[i].r_info) != R_PPC_REL24)
-                       continue;
-               for (j = 0; j < i; j++) {
-                       /* If this addend appeared before, it's
-                           already been counted */
-                       if (rela[i].r_info == rela[j].r_info
-                           && rela[i].r_addend == rela[j].r_addend)
-                               break;
+               if (ELF64_R_TYPE(rela[i].r_info) == R_PPC_REL24 &&
+                   (r_info != ELF64_R_SYM(rela[i].r_info) ||
+                    r_addend != rela[i].r_addend)) {
+                       _count_relocs++;
+                       r_info = ELF64_R_SYM(rela[i].r_info);
+                       r_addend = rela[i].r_addend;
                }
-               if (j == i) ret++;
-       }
-       return ret;
+
+       return _count_relocs;
 }
 
 void *module_alloc(unsigned long size)
@@ -118,6 +117,44 @@ void module_free(struct module *mod, void *module_region)
            table entries. */
 }
 
+static int relacmp(const void *_x, const void *_y)
+{
+       const Elf64_Rela *x, *y;
+
+       y = (Elf64_Rela *)_x;
+       x = (Elf64_Rela *)_y;
+
+       /* Compare the entire r_info (as opposed to ELF64_R_SYM(r_info) only) to
+        * make the comparison cheaper/faster. It won't affect the sorting or
+        * the counting algorithms' performance
+        */
+       if (x->r_info < y->r_info)
+               return -1;
+       else if (x->r_info > y->r_info)
+               return 1;
+       else if (x->r_addend < y->r_addend)
+               return -1;
+       else if (x->r_addend > y->r_addend)
+               return 1;
+       else
+               return 0;
+}
+
+static void relaswap(void *_x, void *_y, int size)
+{
+       uint64_t *x, *y, tmp;
+       int i;
+
+       y = (uint64_t *)_x;
+       x = (uint64_t *)_y;
+
+       for (i = 0; i < sizeof(Elf64_Rela) / sizeof(uint64_t); i++) {
+               tmp = x[i];
+               x[i] = y[i];
+               y[i] = tmp;
+       }
+}
+
 /* Get size of potential trampolines required. */
 static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
                                    const Elf64_Shdr *sechdrs)
@@ -133,6 +170,16 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
                        DEBUGP("Ptr: %p.  Number: %lu\n",
                               (void *)sechdrs[i].sh_addr,
                               sechdrs[i].sh_size / sizeof(Elf64_Rela));
+
+                       /* Sort the relocation information based on a symbol and
+                        * addend key. This is a stable O(n*log n) complexity
+                        * alogrithm but it will reduce the complexity of
+                        * count_relocs() to linear complexity O(n)
+                        */
+                       sort((void *)sechdrs[i].sh_addr,
+                            sechdrs[i].sh_size / sizeof(Elf64_Rela),
+                            sizeof(Elf64_Rela), relacmp, relaswap);
+
                        relocs += count_relocs((void *)sechdrs[i].sh_addr,
                                               sechdrs[i].sh_size
                                               / sizeof(Elf64_Rela));
@@ -343,7 +390,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        /* Simply set it */
                        *(u32 *)location = value;
                        break;
-                       
+
                case R_PPC64_ADDR64:
                        /* Simply set it */
                        *(unsigned long *)location = value;
@@ -399,7 +446,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        }
 
                        /* Only replace bits 2 through 26 */
-                       *(uint32_t *)location 
+                       *(uint32_t *)location
                                = (*(uint32_t *)location & ~0x03fffffc)
                                | (value & 0x03fffffc);
                        break;
index aeaa20268ce2deef9b93d137b5d8148f334327f3..de36e235a60a3a2b4be2a9a8379f88b0cc29047b 100644 (file)
@@ -40,7 +40,7 @@
  * a bus type in the list
  */
 
-static struct of_device_id of_default_bus_ids[] = {
+static const struct of_device_id of_default_bus_ids[] = {
        { .type = "soc", },
        { .compatible = "soc", },
        { .type = "spider", },
@@ -64,26 +64,6 @@ 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)
@@ -120,8 +100,8 @@ EXPORT_SYMBOL(of_platform_device_create);
  * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
  * disallow recursive creation of child busses
  */
-static int of_platform_bus_create(struct device_node *bus,
-                                 struct of_device_id *matches,
+static int of_platform_bus_create(const struct device_node *bus,
+                                 const struct of_device_id *matches,
                                  struct device *parent)
 {
        struct device_node *child;
@@ -157,7 +137,7 @@ static int of_platform_bus_create(struct device_node *bus,
  */
 
 int of_platform_bus_probe(struct device_node *root,
-                         struct of_device_id *matches,
+                         const struct of_device_id *matches,
                          struct device *parent)
 {
        struct device_node *child;
index 2ae3b6f778a3c4e5cff5922c10c96a705d44c2de..571854f2906c7ddeec465ecd451e767231babb62 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;
+/* ISA Memory physical address */
+resource_size_t isa_mem_base;
 
-/*
- * pci_controller(phb) initialized common variables.
- */
-static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
-{
-       memset(hose, 0, sizeof(struct pci_controller));
-
-       spin_lock(&hose_spinlock);
-       hose->global_number = global_phb_number++;
-       list_add_tail(&hose->list_node, &hose_list);
-       spin_unlock(&hose_spinlock);
-}
+/* Default PCI flags is 0 */
+unsigned int ppc_pci_flags;
 
-struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
        struct pci_controller *phb;
 
-       phb = alloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
+       phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
        if (phb == NULL)
                return NULL;
-       pci_setup_pci_controller(phb);
-       phb->arch_data = dev;
+       spin_lock(&hose_spinlock);
+       phb->global_number = global_phb_number++;
+       list_add_tail(&phb->list_node, &hose_list);
+       spin_unlock(&hose_spinlock);
+       phb->dn = dev;
        phb->is_dynamic = mem_init_done;
 #ifdef CONFIG_PPC64
        if (dev) {
@@ -126,15 +120,10 @@ int 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 +142,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;
        }
@@ -201,6 +190,20 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
        struct of_irq oirq;
        unsigned int virq;
 
+       /* The current device-tree that iSeries generates from the HV
+        * PCI informations doesn't contain proper interrupt routing,
+        * and all the fallback would do is print out crap, so we
+        * don't attempt to resolve the interrupts here at all, some
+        * iSeries specific fixup does it.
+        *
+        * In the long run, we will hopefully fix the generated device-tree
+        * instead.
+        */
+#ifdef CONFIG_PPC_ISERIES
+       if (firmware_has_feature(FW_FEATURE_ISERIES))
+               return -1;
+#endif
+
        DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
 #ifdef DEBUG
@@ -222,10 +225,11 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
                if (pin == 0)
                        return -1;
                if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-                   line == 0xff) {
+                   line == 0xff || line == 0) {
                        return -1;
                }
-               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
+               DBG(" -> no map ! Using line %d (pin %d) from PCI config\n",
+                   line, pin);
 
                virq = irq_create_mapping(NULL, line);
                if (virq != NO_IRQ)
@@ -475,3 +479,722 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
        *start = rsrc->start - offset;
        *end = rsrc->end - offset;
 }
+
+/**
+ * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
+ * @hose: newly allocated pci_controller to be setup
+ * @dev: device node of the host bridge
+ * @primary: set if primary bus (32 bits only, soon to be deprecated)
+ *
+ * This function will parse the "ranges" property of a PCI host bridge device
+ * node and setup the resource mapping of a pci controller based on its
+ * content.
+ *
+ * Life would be boring if it wasn't for a few issues that we have to deal
+ * with here:
+ *
+ *   - We can only cope with one IO space range and up to 3 Memory space
+ *     ranges. However, some machines (thanks Apple !) tend to split their
+ *     space into lots of small contiguous ranges. So we have to coalesce.
+ *
+ *   - We can only cope with all memory ranges having the same offset
+ *     between CPU addresses and PCI addresses. Unfortunately, some bridges
+ *     are setup for a large 1:1 mapping along with a small "window" which
+ *     maps PCI address 0 to some arbitrary high address of the CPU space in
+ *     order to give access to the ISA memory hole.
+ *     The way out of here that I've chosen for now is to always set the
+ *     offset based on the first resource found, then override it if we
+ *     have a different offset and the previous was set by an ISA hole.
+ *
+ *   - Some busses have IO space not starting at 0, which causes trouble with
+ *     the way we do our IO resource renumbering. The code somewhat deals with
+ *     it for 64 bits but I would expect problems on 32 bits.
+ *
+ *   - Some 32 bits platforms such as 4xx can have physical space larger than
+ *     32 bits so we need to use 64 bits values for the parsing
+ */
+void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
+                                           struct device_node *dev,
+                                           int primary)
+{
+       const u32 *ranges;
+       int rlen;
+       int pna = of_n_addr_cells(dev);
+       int np = pna + 5;
+       int memno = 0, isa_hole = -1;
+       u32 pci_space;
+       unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
+       unsigned long long isa_mb = 0;
+       struct resource *res;
+
+       printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
+              dev->full_name, primary ? "(primary)" : "");
+
+       /* Get ranges property */
+       ranges = of_get_property(dev, "ranges", &rlen);
+       if (ranges == NULL)
+               return;
+
+       /* Parse it */
+       while ((rlen -= np * 4) >= 0) {
+               /* Read next ranges element */
+               pci_space = ranges[0];
+               pci_addr = of_read_number(ranges + 1, 2);
+               cpu_addr = of_translate_address(dev, ranges + 3);
+               size = of_read_number(ranges + pna + 3, 2);
+               ranges += np;
+               if (cpu_addr == OF_BAD_ADDR || size == 0)
+                       continue;
+
+               /* Now consume following elements while they are contiguous */
+               for (; rlen >= np * sizeof(u32);
+                    ranges += np, rlen -= np * 4) {
+                       if (ranges[0] != pci_space)
+                               break;
+                       pci_next = of_read_number(ranges + 1, 2);
+                       cpu_next = of_translate_address(dev, ranges + 3);
+                       if (pci_next != pci_addr + size ||
+                           cpu_next != cpu_addr + size)
+                               break;
+                       size += of_read_number(ranges + pna + 3, 2);
+               }
+
+               /* Act based on address space type */
+               res = NULL;
+               switch ((pci_space >> 24) & 0x3) {
+               case 1:         /* PCI IO space */
+                       printk(KERN_INFO
+                              "  IO 0x%016llx..0x%016llx -> 0x%016llx\n",
+                              cpu_addr, cpu_addr + size - 1, pci_addr);
+
+                       /* We support only one IO range */
+                       if (hose->pci_io_size) {
+                               printk(KERN_INFO
+                                      " \\--> Skipped (too many) !\n");
+                               continue;
+                       }
+#ifdef CONFIG_PPC32
+                       /* On 32 bits, limit I/O space to 16MB */
+                       if (size > 0x01000000)
+                               size = 0x01000000;
+
+                       /* 32 bits needs to map IOs here */
+                       hose->io_base_virt = ioremap(cpu_addr, size);
+
+                       /* Expect trouble if pci_addr is not 0 */
+                       if (primary)
+                               isa_io_base =
+                                       (unsigned long)hose->io_base_virt;
+#endif /* CONFIG_PPC32 */
+                       /* pci_io_size and io_base_phys always represent IO
+                        * space starting at 0 so we factor in pci_addr
+                        */
+                       hose->pci_io_size = pci_addr + size;
+                       hose->io_base_phys = cpu_addr - pci_addr;
+
+                       /* Build resource */
+                       res = &hose->io_resource;
+                       res->flags = IORESOURCE_IO;
+                       res->start = pci_addr;
+                       break;
+               case 2:         /* PCI Memory space */
+                       printk(KERN_INFO
+                              " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
+                              cpu_addr, cpu_addr + size - 1, pci_addr,
+                              (pci_space & 0x40000000) ? "Prefetch" : "");
+
+                       /* We support only 3 memory ranges */
+                       if (memno >= 3) {
+                               printk(KERN_INFO
+                                      " \\--> Skipped (too many) !\n");
+                               continue;
+                       }
+                       /* Handles ISA memory hole space here */
+                       if (pci_addr == 0) {
+                               isa_mb = cpu_addr;
+                               isa_hole = memno;
+                               if (primary || isa_mem_base == 0)
+                                       isa_mem_base = cpu_addr;
+                       }
+
+                       /* We get the PCI/Mem offset from the first range or
+                        * the, current one if the offset came from an ISA
+                        * hole. If they don't match, bugger.
+                        */
+                       if (memno == 0 ||
+                           (isa_hole >= 0 && pci_addr != 0 &&
+                            hose->pci_mem_offset == isa_mb))
+                               hose->pci_mem_offset = cpu_addr - pci_addr;
+                       else if (pci_addr != 0 &&
+                                hose->pci_mem_offset != cpu_addr - pci_addr) {
+                               printk(KERN_INFO
+                                      " \\--> Skipped (offset mismatch) !\n");
+                               continue;
+                       }
+
+                       /* Build resource */
+                       res = &hose->mem_resources[memno++];
+                       res->flags = IORESOURCE_MEM;
+                       if (pci_space & 0x40000000)
+                               res->flags |= IORESOURCE_PREFETCH;
+                       res->start = cpu_addr;
+                       break;
+               }
+               if (res != NULL) {
+                       res->name = dev->full_name;
+                       res->end = res->start + size - 1;
+                       res->parent = NULL;
+                       res->sibling = NULL;
+                       res->child = NULL;
+               }
+       }
+
+       /* Out of paranoia, let's put the ISA hole last if any */
+       if (isa_hole >= 0 && memno > 0 && isa_hole != (memno-1)) {
+               struct resource tmp = hose->mem_resources[isa_hole];
+               hose->mem_resources[isa_hole] = hose->mem_resources[memno-1];
+               hose->mem_resources[memno-1] = tmp;
+       }
+}
+
+/* Decide whether to display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+#ifdef CONFIG_PPC64
+       return hose->buid != 0;
+#else
+       if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
+               return 0;
+       if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
+               return hose->global_number != 0;
+       return 1;
+#endif
+}
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+                            struct resource *res)
+{
+       resource_size_t offset = 0, mask = (resource_size_t)-1;
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+       if (!hose)
+               return;
+       if (res->flags & IORESOURCE_IO) {
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+               mask = 0xffffffffu;
+       } else if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+
+       region->start = (res->start - offset) & mask;
+       region->end = (res->end - offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+                            struct pci_bus_region *region)
+{
+       resource_size_t offset = 0, mask = (resource_size_t)-1;
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+       if (!hose)
+               return;
+       if (res->flags & IORESOURCE_IO) {
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+               mask = 0xffffffffu;
+       } else if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+       res->start = (region->start + offset) & mask;
+       res->end = (region->end + offset) & mask;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/* Fixup a bus resource into a linux resource */
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       resource_size_t offset = 0, mask = (resource_size_t)-1;
+
+       if (res->flags & IORESOURCE_IO) {
+               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+               mask = 0xffffffffu;
+       } else if (res->flags & IORESOURCE_MEM)
+               offset = hose->pci_mem_offset;
+
+       res->start = (res->start + offset) & mask;
+       res->end = (res->end + offset) & mask;
+
+       pr_debug("PCI:%s            %016llx-%016llx\n",
+                pci_name(dev),
+                (unsigned long long)res->start,
+                (unsigned long long)res->end);
+}
+
+
+/* This header fixup will do the resource fixup for all devices as they are
+ * probed, but not for bridge ranges
+ */
+static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       int i;
+
+       if (!hose) {
+               printk(KERN_ERR "No host bridge for PCI dev %s !\n",
+                      pci_name(dev));
+               return;
+       }
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               struct resource *res = dev->resource + i;
+               if (!res->flags)
+                       continue;
+               if (res->end == 0xffffffff) {
+                       pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
+                                pci_name(dev), i,
+                                (unsigned long long)res->start,
+                                (unsigned long long)res->end,
+                                (unsigned int)res->flags);
+                       res->end -= res->start;
+                       res->start = 0;
+                       res->flags |= IORESOURCE_UNSET;
+                       continue;
+               }
+
+               pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
+                        pci_name(dev), i,
+                        (unsigned long long)res->start,\
+                        (unsigned long long)res->end,
+                        (unsigned int)res->flags);
+
+               fixup_resource(res, dev);
+       }
+
+       /* Call machine specific resource fixup */
+       if (ppc_md.pcibios_fixup_resources)
+               ppc_md.pcibios_fixup_resources(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
+
+static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+{
+       struct pci_controller *hose = pci_bus_to_host(bus);
+       struct pci_dev *dev = bus->self;
+
+       pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
+
+       /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
+        * now differently between 32 and 64 bits.
+        */
+       if (dev != NULL) {
+               struct resource *res;
+               int i;
+
+               for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+                       if ((res = bus->resource[i]) == NULL)
+                               continue;
+                       if (!res->flags || bus->self->transparent)
+                               continue;
+
+                       /* On PowerMac, Apple leaves bridge windows open over
+                        * an inaccessible region of memory space (0...fffff)
+                        * which is somewhat bogus, but that's what they think
+                        * means disabled...
+                        *
+                        * We clear those to force them to be reallocated later
+                        *
+                        * We detect such regions by the fact that the base is
+                        * equal to the pci_mem_offset of the host bridge and
+                        * their size is smaller than 1M.
+                        */
+                       if (res->start == hose->pci_mem_offset &&
+                           res->end < 0x100000) {
+                               printk(KERN_INFO
+                                      "PCI: Closing bogus Apple Firmware"
+                                      " region %d on bus 0x%02x\n",
+                                      i, bus->number);
+                               res->flags = 0;
+                               continue;
+                       }
+
+                       pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
+                                pci_name(dev), i,
+                                (unsigned long long)res->start,\
+                                (unsigned long long)res->end,
+                                (unsigned int)res->flags);
+
+                       fixup_resource(res, dev);
+               }
+       }
+
+       /* Additional setup that is different between 32 and 64 bits for now */
+       pcibios_do_bus_setup(bus);
+
+       /* Platform specific bus fixups */
+       if (ppc_md.pcibios_fixup_bus)
+               ppc_md.pcibios_fixup_bus(bus);
+
+       /* Read default IRQs and fixup if necessary */
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               pci_read_irq_line(dev);
+               if (ppc_md.pci_irq_fixup)
+                       ppc_md.pci_irq_fixup(dev);
+       }
+}
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+       /* When called from the generic PCI probe, read PCI<->PCI bridge
+        * bases before proceeding
+        */
+       if (bus->self != NULL)
+               pci_read_bridge_bases(bus);
+       __pcibios_fixup_bus(bus);
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/* When building a bus from the OF tree rather than probing, we need a
+ * slightly different version of the fixup which doesn't read the
+ * bridge bases using config space accesses
+ */
+void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
+{
+       __pcibios_fixup_bus(bus);
+}
+
+static int skip_isa_ioresource_align(struct pci_dev *dev)
+{
+       if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) &&
+           !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
+               return 1;
+       return 0;
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res,
+                               resource_size_t size, resource_size_t align)
+{
+       struct pci_dev *dev = data;
+
+       if (res->flags & IORESOURCE_IO) {
+               resource_size_t start = res->start;
+
+               if (skip_isa_ioresource_align(dev))
+                       return;
+               if (start & 0x300) {
+                       start = (start + 0x3ff) & ~0x3ff;
+                       res->start = start;
+               }
+       }
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init reparent_resources(struct resource *parent,
+                                    struct resource *res)
+{
+       struct resource *p, **pp;
+       struct resource **firstpp = NULL;
+
+       for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+               if (p->end < res->start)
+                       continue;
+               if (res->end < p->start)
+                       break;
+               if (p->start < res->start || p->end > res->end)
+                       return -1;      /* not completely contained */
+               if (firstpp == NULL)
+                       firstpp = pp;
+       }
+       if (firstpp == NULL)
+               return -1;      /* didn't find any conflicting entries? */
+       res->parent = parent;
+       res->child = *firstpp;
+       res->sibling = *pp;
+       *firstpp = res;
+       *pp = NULL;
+       for (p = res->child; p != NULL; p = p->sibling) {
+               p->parent = res;
+               DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
+                   p->name,
+                   (unsigned long long)p->start,
+                   (unsigned long long)p->end, res->name);
+       }
+       return 0;
+}
+
+/*
+ *  Handle resources of PCI devices.  If the world were perfect, we could
+ *  just allocate all the resource regions and do nothing more.  It isn't.
+ *  On the other hand, we cannot just re-allocate all devices, as it would
+ *  require us to know lots of host bridge internals.  So we attempt to
+ *  keep as much of the original configuration as possible, but tweak it
+ *  when it's found to be wrong.
+ *
+ *  Known BIOS problems we have to work around:
+ *     - I/O or memory regions not configured
+ *     - regions configured, but not enabled in the command register
+ *     - bogus I/O addresses above 64K used
+ *     - expansion ROMs left enabled (this may sound harmless, but given
+ *       the fact the PCI specs explicitly allow address decoders to be
+ *       shared between expansion ROMs and other resource regions, it's
+ *       at least dangerous)
+ *
+ *  Our solution:
+ *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ *         This gives us fixed barriers on where we can allocate.
+ *     (2) Allocate resources for all enabled devices.  If there is
+ *         a collision, just mark the resource as unallocated. Also
+ *         disable expansion ROMs during this step.
+ *     (3) Try to allocate resources for disabled devices.  If the
+ *         resources were assigned correctly, everything goes well,
+ *         if they weren't, they won't disturb allocation of other
+ *         resources.
+ *     (4) Assign new addresses to resources which were either
+ *         not configured at all or misconfigured.  If explicitly
+ *         requested by the user, configure expansion ROM address
+ *         as well.
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+       struct pci_bus *bus;
+       int i;
+       struct resource *res, *pr;
+
+       /* Depth-First Search on bus tree */
+       list_for_each_entry(bus, bus_list, node) {
+               for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+                       if ((res = bus->resource[i]) == NULL || !res->flags
+                           || res->start > res->end)
+                               continue;
+                       if (bus->parent == NULL)
+                               pr = (res->flags & IORESOURCE_IO) ?
+                                       &ioport_resource : &iomem_resource;
+                       else {
+                               /* Don't bother with non-root busses when
+                                * re-assigning all resources. We clear the
+                                * resource flags as if they were colliding
+                                * and as such ensure proper re-allocation
+                                * later.
+                                */
+                               if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)
+                                       goto clear_resource;
+                               pr = pci_find_parent_resource(bus->self, res);
+                               if (pr == res) {
+                                       /* this happens when the generic PCI
+                                        * code (wrongly) decides that this
+                                        * bridge is transparent  -- paulus
+                                        */
+                                       continue;
+                               }
+                       }
+
+                       DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
+                           "[0x%x], parent %p (%s)\n",
+                           bus->self ? pci_name(bus->self) : "PHB",
+                           bus->number, i,
+                           (unsigned long long)res->start,
+                           (unsigned long long)res->end,
+                           (unsigned int)res->flags,
+                           pr, (pr && pr->name) ? pr->name : "nil");
+
+                       if (pr && !(pr->flags & IORESOURCE_UNSET)) {
+                               if (request_resource(pr, res) == 0)
+                                       continue;
+                               /*
+                                * Must be a conflict with an existing entry.
+                                * Move that entry (or entries) under the
+                                * bridge resource and try again.
+                                */
+                               if (reparent_resources(pr, res) == 0)
+                                       continue;
+                       }
+                       printk(KERN_WARNING
+                              "PCI: Cannot allocate resource region "
+                              "%d of PCI bridge %d, will remap\n",
+                              i, bus->number);
+clear_resource:
+                       res->flags = 0;
+               }
+               pcibios_allocate_bus_resources(&bus->children);
+       }
+}
+
+static inline int __devinit alloc_resource(struct pci_dev *dev, int idx)
+{
+       struct resource *pr, *r = &dev->resource[idx];
+
+       DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
+           pci_name(dev), idx,
+           (unsigned long long)r->start,
+           (unsigned long long)r->end,
+           (unsigned int)r->flags);
+
+       pr = pci_find_parent_resource(dev, r);
+       if (!pr || (pr->flags & IORESOURCE_UNSET) ||
+           request_resource(pr, r) < 0) {
+               printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
+                      " of device %s, will remap\n", idx, pci_name(dev));
+               if (pr)
+                       DBG("PCI:  parent is %p: %016llx-%016llx [%x]\n", pr,
+                           (unsigned long long)pr->start,
+                           (unsigned long long)pr->end,
+                           (unsigned int)pr->flags);
+               /* We'll assign a new address later */
+               r->flags |= IORESOURCE_UNSET;
+               r->end -= r->start;
+               r->start = 0;
+
+               return -EBUSY;
+       }
+       return 0;
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+       struct pci_dev *dev = NULL;
+       int idx, disabled;
+       u16 command;
+       struct resource *r;
+
+       for_each_pci_dev(dev) {
+               pci_read_config_word(dev, PCI_COMMAND, &command);
+               for (idx = 0; idx < 6; idx++) {
+                       r = &dev->resource[idx];
+                       if (r->parent)          /* Already allocated */
+                               continue;
+                       if (!r->flags || (r->flags & IORESOURCE_UNSET))
+                               continue;       /* Not assigned at all */
+                       if (r->flags & IORESOURCE_IO)
+                               disabled = !(command & PCI_COMMAND_IO);
+                       else
+                               disabled = !(command & PCI_COMMAND_MEMORY);
+                       if (pass == disabled && alloc_resource(dev, idx)) {
+                               command &= ~(r->flags & (IORESOURCE_IO |
+                                                        IORESOURCE_MEM));
+                               pci_write_config_word(dev,
+                                                     PCI_COMMAND, command);
+                       }
+               }
+               if (pass)
+                       continue;
+               r = &dev->resource[PCI_ROM_RESOURCE];
+               if (r->flags & IORESOURCE_ROM_ENABLE) {
+                       /* Turn the ROM off, leave the resource region,
+                        * but keep it unregistered.
+                        */
+                       u32 reg;
+                       DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+                       r->flags &= ~IORESOURCE_ROM_ENABLE;
+                       pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+                       pci_write_config_dword(dev, dev->rom_base_reg,
+                                              reg & ~PCI_ROM_ADDRESS_ENABLE);
+               }
+       }
+}
+
+void __init pcibios_resource_survey(void)
+{
+       /* Allocate and assign resources. If we re-assign everything, then
+        * we skip the allocate phase
+        */
+       pcibios_allocate_bus_resources(&pci_root_buses);
+
+       if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) {
+               pcibios_allocate_resources(0);
+               pcibios_allocate_resources(1);
+       }
+
+       if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+               DBG("PCI: Assigning unassigned resouces...\n");
+               pci_assign_unassigned_resources();
+       }
+
+       /* Call machine dependent fixup */
+       if (ppc_md.pcibios_fixup)
+               ppc_md.pcibios_fixup();
+}
+
+#ifdef CONFIG_HOTPLUG
+/* This is used by the pSeries hotplug driver to allocate resource
+ * of newly plugged busses. We can try to consolidate with the
+ * rest of the code later, for now, keep it as-is
+ */
+void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       struct pci_bus *child_bus;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               int i;
+
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       struct resource *r = &dev->resource[i];
+
+                       if (r->parent || !r->start || !r->flags)
+                               continue;
+                       pci_claim_resource(dev, i);
+               }
+       }
+
+       list_for_each_entry(child_bus, &bus->children, node)
+               pcibios_claim_one_bus(child_bus);
+}
+EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+#endif /* CONFIG_HOTPLUG */
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       u16 cmd, old_cmd;
+       int idx;
+       struct resource *r;
+
+       if (ppc_md.pcibios_enable_device_hook)
+               if (ppc_md.pcibios_enable_device_hook(dev))
+                       return -EINVAL;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+               /* Only set up the requested stuff */
+               if (!(mask & (1 << idx)))
+                       continue;
+               r = &dev->resource[idx];
+               if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+                       continue;
+               if ((idx == PCI_ROM_RESOURCE) &&
+                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
+                       continue;
+               if (r->parent == NULL) {
+                       printk(KERN_ERR "PCI: Device %s not available because"
+                              " of resource collisions\n", pci_name(dev));
+                       return -EINVAL;
+               }
+               if (r->flags & IORESOURCE_IO)
+                       cmd |= PCI_COMMAND_IO;
+               if (r->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       if (cmd != old_cmd) {
+               printk("PCI: Enabling device %s (%04x -> %04x)\n",
+                      pci_name(dev), old_cmd, cmd);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       return 0;
+}
+
index 0e2bee46304c51fc109d0e2b899a6ce6a559f841..a9c6cb24aab0c16f4165f7cfcf3389e4c1a826f0 100644 (file)
 #endif
 
 unsigned long isa_io_base     = 0;
-unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
-static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
-static int probe_resource(struct pci_bus *parent, struct resource *pr,
-                         struct resource *res, struct resource **conflict);
-static void update_bridge_base(struct pci_bus *bus, int i);
-static void pcibios_fixup_resources(struct pci_dev* dev);
 static void fixup_broken_pcnet32(struct pci_dev* dev);
-static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
@@ -53,7 +46,7 @@ static u8* pci_to_OF_bus_map;
 /* By default, we don't re-assign bus numbers. We do this only on
  * some pmacs
  */
-int pci_assign_all_buses;
+static int pci_assign_all_buses;
 
 LIST_HEAD(hose_list);
 
@@ -100,338 +93,6 @@ fixup_cpc710_pci64(struct pci_dev* dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,    PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
 
-static void
-pcibios_fixup_resources(struct pci_dev *dev)
-{
-       struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
-       int i;
-       unsigned long offset;
-
-       if (!hose) {
-               printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
-               return;
-       }
-       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-               struct resource *res = dev->resource + i;
-               if (!res->flags)
-                       continue;
-               if (res->end == 0xffffffff) {
-                       DBG("PCI:%s Resource %d [%016llx-%016llx] is unassigned\n",
-                           pci_name(dev), i, (u64)res->start, (u64)res->end);
-                       res->end -= res->start;
-                       res->start = 0;
-                       res->flags |= IORESOURCE_UNSET;
-                       continue;
-               }
-               offset = 0;
-               if (res->flags & IORESOURCE_MEM) {
-                       offset = hose->pci_mem_offset;
-               } else if (res->flags & IORESOURCE_IO) {
-                       offset = (unsigned long) hose->io_base_virt
-                               - isa_io_base;
-               }
-               if (offset != 0) {
-                       res->start += offset;
-                       res->end += offset;
-                       DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
-                           i, res->flags, pci_name(dev),
-                           (u64)res->start - offset, (u64)res->start);
-               }
-       }
-
-       /* Call machine specific resource fixup */
-       if (ppc_md.pcibios_fixup_resources)
-               ppc_md.pcibios_fixup_resources(dev);
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,           PCI_ANY_ID,                     pcibios_fixup_resources);
-
-void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-                       struct resource *res)
-{
-       unsigned long offset = 0;
-       struct pci_controller *hose = dev->sysdata;
-
-       if (hose && res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - isa_io_base;
-       else if (hose && res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-       region->start = res->start - offset;
-       region->end = res->end - offset;
-}
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-                            struct pci_bus_region *region)
-{
-       unsigned long offset = 0;
-       struct pci_controller *hose = dev->sysdata;
-
-       if (hose && res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - isa_io_base;
-       else if (hose && res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-       res->start = region->start + offset;
-       res->end = region->end + offset;
-}
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-                               resource_size_t size, resource_size_t align)
-{
-       struct pci_dev *dev = data;
-
-       if (res->flags & IORESOURCE_IO) {
-               resource_size_t start = res->start;
-
-               if (size > 0x100) {
-                       printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-                              " (%lld bytes)\n", pci_name(dev),
-                              dev->resource - res, (unsigned long long)size);
-               }
-
-               if (start & 0x300) {
-                       start = (start + 0x3ff) & ~0x3ff;
-                       res->start = start;
-               }
-       }
-}
-EXPORT_SYMBOL(pcibios_align_resource);
-
-/*
- *  Handle resources of PCI devices.  If the world were perfect, we could
- *  just allocate all the resource regions and do nothing more.  It isn't.
- *  On the other hand, we cannot just re-allocate all devices, as it would
- *  require us to know lots of host bridge internals.  So we attempt to
- *  keep as much of the original configuration as possible, but tweak it
- *  when it's found to be wrong.
- *
- *  Known BIOS problems we have to work around:
- *     - I/O or memory regions not configured
- *     - regions configured, but not enabled in the command register
- *     - bogus I/O addresses above 64K used
- *     - expansion ROMs left enabled (this may sound harmless, but given
- *       the fact the PCI specs explicitly allow address decoders to be
- *       shared between expansion ROMs and other resource regions, it's
- *       at least dangerous)
- *
- *  Our solution:
- *     (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- *         This gives us fixed barriers on where we can allocate.
- *     (2) Allocate resources for all enabled devices.  If there is
- *         a collision, just mark the resource as unallocated. Also
- *         disable expansion ROMs during this step.
- *     (3) Try to allocate resources for disabled devices.  If the
- *         resources were assigned correctly, everything goes well,
- *         if they weren't, they won't disturb allocation of other
- *         resources.
- *     (4) Assign new addresses to resources which were either
- *         not configured at all or misconfigured.  If explicitly
- *         requested by the user, configure expansion ROM address
- *         as well.
- */
-
-static void __init
-pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
-       struct pci_bus *bus;
-       int i;
-       struct resource *res, *pr;
-
-       /* Depth-First Search on bus tree */
-       list_for_each_entry(bus, bus_list, node) {
-               for (i = 0; i < 4; ++i) {
-                       if ((res = bus->resource[i]) == NULL || !res->flags
-                           || res->start > res->end)
-                               continue;
-                       if (bus->parent == NULL)
-                               pr = (res->flags & IORESOURCE_IO)?
-                                       &ioport_resource: &iomem_resource;
-                       else {
-                               pr = pci_find_parent_resource(bus->self, res);
-                               if (pr == res) {
-                                       /* this happens when the generic PCI
-                                        * code (wrongly) decides that this
-                                        * bridge is transparent  -- paulus
-                                        */
-                                       continue;
-                               }
-                       }
-
-                       DBG("PCI: bridge rsrc %llx..%llx (%lx), parent %p\n",
-                           (u64)res->start, (u64)res->end, res->flags, pr);
-                       if (pr) {
-                               if (request_resource(pr, res) == 0)
-                                       continue;
-                               /*
-                                * Must be a conflict with an existing entry.
-                                * Move that entry (or entries) under the
-                                * bridge resource and try again.
-                                */
-                               if (reparent_resources(pr, res) == 0)
-                                       continue;
-                       }
-                       printk(KERN_ERR "PCI: Cannot allocate resource region "
-                              "%d of PCI bridge %d\n", i, bus->number);
-                       if (pci_relocate_bridge_resource(bus, i))
-                               bus->resource[i] = NULL;
-               }
-               pcibios_allocate_bus_resources(&bus->children);
-       }
-}
-
-/*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init
-reparent_resources(struct resource *parent, struct resource *res)
-{
-       struct resource *p, **pp;
-       struct resource **firstpp = NULL;
-
-       for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
-               if (p->end < res->start)
-                       continue;
-               if (res->end < p->start)
-                       break;
-               if (p->start < res->start || p->end > res->end)
-                       return -1;      /* not completely contained */
-               if (firstpp == NULL)
-                       firstpp = pp;
-       }
-       if (firstpp == NULL)
-               return -1;      /* didn't find any conflicting entries? */
-       res->parent = parent;
-       res->child = *firstpp;
-       res->sibling = *pp;
-       *firstpp = res;
-       *pp = NULL;
-       for (p = res->child; p != NULL; p = p->sibling) {
-               p->parent = res;
-               DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
-                   p->name, (u64)p->start, (u64)p->end, res->name);
-       }
-       return 0;
-}
-
-/*
- * A bridge has been allocated a range which is outside the range
- * of its parent bridge, so it needs to be moved.
- */
-static int __init
-pci_relocate_bridge_resource(struct pci_bus *bus, int i)
-{
-       struct resource *res, *pr, *conflict;
-       unsigned long try, size;
-       int j;
-       struct pci_bus *parent = bus->parent;
-
-       if (parent == NULL) {
-               /* shouldn't ever happen */
-               printk(KERN_ERR "PCI: can't move host bridge resource\n");
-               return -1;
-       }
-       res = bus->resource[i];
-       if (res == NULL)
-               return -1;
-       pr = NULL;
-       for (j = 0; j < 4; j++) {
-               struct resource *r = parent->resource[j];
-               if (!r)
-                       continue;
-               if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
-                       continue;
-               if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
-                       pr = r;
-                       break;
-               }
-               if (res->flags & IORESOURCE_PREFETCH)
-                       pr = r;
-       }
-       if (pr == NULL)
-               return -1;
-       size = res->end - res->start;
-       if (pr->start > pr->end || size > pr->end - pr->start)
-               return -1;
-       try = pr->end;
-       for (;;) {
-               res->start = try - size;
-               res->end = try;
-               if (probe_resource(bus->parent, pr, res, &conflict) == 0)
-                       break;
-               if (conflict->start <= pr->start + size)
-                       return -1;
-               try = conflict->start - 1;
-       }
-       if (request_resource(pr, res)) {
-               DBG(KERN_ERR "PCI: huh? couldn't move to %llx..%llx\n",
-                   (u64)res->start, (u64)res->end);
-               return -1;              /* "can't happen" */
-       }
-       update_bridge_base(bus, i);
-       printk(KERN_INFO "PCI: bridge %d resource %d moved to %llx..%llx\n",
-              bus->number, i, (unsigned long long)res->start,
-              (unsigned long long)res->end);
-       return 0;
-}
-
-static int __init
-probe_resource(struct pci_bus *parent, struct resource *pr,
-              struct resource *res, struct resource **conflict)
-{
-       struct pci_bus *bus;
-       struct pci_dev *dev;
-       struct resource *r;
-       int i;
-
-       for (r = pr->child; r != NULL; r = r->sibling) {
-               if (r->end >= res->start && res->end >= r->start) {
-                       *conflict = r;
-                       return 1;
-               }
-       }
-       list_for_each_entry(bus, &parent->children, node) {
-               for (i = 0; i < 4; ++i) {
-                       if ((r = bus->resource[i]) == NULL)
-                               continue;
-                       if (!r->flags || r->start > r->end || r == res)
-                               continue;
-                       if (pci_find_parent_resource(bus->self, r) != pr)
-                               continue;
-                       if (r->end >= res->start && res->end >= r->start) {
-                               *conflict = r;
-                               return 1;
-                       }
-               }
-       }
-       list_for_each_entry(dev, &parent->devices, bus_list) {
-               for (i = 0; i < 6; ++i) {
-                       r = &dev->resource[i];
-                       if (!r->flags || (r->flags & IORESOURCE_UNSET))
-                               continue;
-                       if (pci_find_parent_resource(dev, r) != pr)
-                               continue;
-                       if (r->end >= res->start && res->end >= r->start) {
-                               *conflict = r;
-                               return 1;
-                       }
-               }
-       }
-       return 0;
-}
 
 void __init
 update_bridge_resource(struct pci_dev *dev, struct resource *res)
@@ -439,7 +100,7 @@ update_bridge_resource(struct pci_dev *dev, struct resource *res)
        u8 io_base_lo, io_limit_lo;
        u16 mem_base, mem_limit;
        u16 cmd;
-       unsigned long start, end, off;
+       resource_size_t start, end, off;
        struct pci_controller *hose = dev->sysdata;
 
        if (!hose) {
@@ -489,115 +150,6 @@ update_bridge_resource(struct pci_dev *dev, struct resource *res)
        pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
-static void __init
-update_bridge_base(struct pci_bus *bus, int i)
-{
-       struct resource *res = bus->resource[i];
-       struct pci_dev *dev = bus->self;
-       update_bridge_resource(dev, res);
-}
-
-static inline void alloc_resource(struct pci_dev *dev, int idx)
-{
-       struct resource *pr, *r = &dev->resource[idx];
-
-       DBG("PCI:%s: Resource %d: %016llx-%016llx (f=%lx)\n",
-           pci_name(dev), idx, (u64)r->start, (u64)r->end, r->flags);
-       pr = pci_find_parent_resource(dev, r);
-       if (!pr || request_resource(pr, r) < 0) {
-               printk(KERN_ERR "PCI: Cannot allocate resource region %d"
-                      " of device %s\n", idx, pci_name(dev));
-               if (pr)
-                       DBG("PCI:  parent is %p: %016llx-%016llx (f=%lx)\n",
-                           pr, (u64)pr->start, (u64)pr->end, pr->flags);
-               /* We'll assign a new address later */
-               r->flags |= IORESOURCE_UNSET;
-               r->end -= r->start;
-               r->start = 0;
-       }
-}
-
-static void __init
-pcibios_allocate_resources(int pass)
-{
-       struct pci_dev *dev = NULL;
-       int idx, disabled;
-       u16 command;
-       struct resource *r;
-
-       for_each_pci_dev(dev) {
-               pci_read_config_word(dev, PCI_COMMAND, &command);
-               for (idx = 0; idx < 6; idx++) {
-                       r = &dev->resource[idx];
-                       if (r->parent)          /* Already allocated */
-                               continue;
-                       if (!r->flags || (r->flags & IORESOURCE_UNSET))
-                               continue;       /* Not assigned at all */
-                       if (r->flags & IORESOURCE_IO)
-                               disabled = !(command & PCI_COMMAND_IO);
-                       else
-                               disabled = !(command & PCI_COMMAND_MEMORY);
-                       if (pass == disabled)
-                               alloc_resource(dev, idx);
-               }
-               if (pass)
-                       continue;
-               r = &dev->resource[PCI_ROM_RESOURCE];
-               if (r->flags & IORESOURCE_ROM_ENABLE) {
-                       /* Turn the ROM off, leave the resource region, but keep it unregistered. */
-                       u32 reg;
-                       DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
-                       r->flags &= ~IORESOURCE_ROM_ENABLE;
-                       pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-                       pci_write_config_dword(dev, dev->rom_base_reg,
-                                              reg & ~PCI_ROM_ADDRESS_ENABLE);
-               }
-       }
-}
-
-static void __init
-pcibios_assign_resources(void)
-{
-       struct pci_dev *dev = NULL;
-       int idx;
-       struct resource *r;
-
-       for_each_pci_dev(dev) {
-               int class = dev->class >> 8;
-
-               /* Don't touch classless devices and host bridges */
-               if (!class || class == PCI_CLASS_BRIDGE_HOST)
-                       continue;
-
-               for (idx = 0; idx < 6; idx++) {
-                       r = &dev->resource[idx];
-
-                       /*
-                        * We shall assign a new address to this resource,
-                        * either because the BIOS (sic) forgot to do so
-                        * or because we have decided the old address was
-                        * unusable for some reason.
-                        */
-                       if ((r->flags & IORESOURCE_UNSET) && r->end &&
-                           (!ppc_md.pcibios_enable_device_hook ||
-                            !ppc_md.pcibios_enable_device_hook(dev, 1))) {
-                               int rc;
-
-                               r->flags &= ~IORESOURCE_UNSET;
-                               rc = pci_assign_resource(dev, idx);
-                               BUG_ON(rc);
-                       }
-               }
-
-#if 0 /* don't assign ROMs */
-               r = &dev->resource[PCI_ROM_RESOURCE];
-               r->end -= r->start;
-               r->start = 0;
-               if (r->end)
-                       pci_assign_resource(dev, PCI_ROM_RESOURCE);
-#endif
-       }
-}
 
 #ifdef CONFIG_PPC_OF
 /*
@@ -662,8 +214,8 @@ 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 +294,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 +364,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);
@@ -843,120 +395,6 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
 }
 EXPORT_SYMBOL(pci_device_from_OF_node);
 
-void __init
-pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                          struct device_node *dev, int primary)
-{
-       static unsigned int static_lc_ranges[256] __initdata;
-       const unsigned int *dt_ranges;
-       unsigned int *lc_ranges, *ranges, *prev, size;
-       int rlen = 0, orig_rlen;
-       int memno = 0;
-       struct resource *res;
-       int np, na = of_n_addr_cells(dev);
-       np = na + 5;
-
-       /* First we try to merge ranges to fix a problem with some pmacs
-        * that can have more than 3 ranges, fortunately using contiguous
-        * addresses -- BenH
-        */
-       dt_ranges = of_get_property(dev, "ranges", &rlen);
-       if (!dt_ranges)
-               return;
-       /* Sanity check, though hopefully that never happens */
-       if (rlen > sizeof(static_lc_ranges)) {
-               printk(KERN_WARNING "OF ranges property too large !\n");
-               rlen = sizeof(static_lc_ranges);
-       }
-       lc_ranges = static_lc_ranges;
-       memcpy(lc_ranges, dt_ranges, rlen);
-       orig_rlen = rlen;
-
-       /* Let's work on a copy of the "ranges" property instead of damaging
-        * the device-tree image in memory
-        */
-       ranges = lc_ranges;
-       prev = NULL;
-       while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-               if (prev) {
-                       if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
-                               (prev[2] + prev[na+4]) == ranges[2] &&
-                               (prev[na+2] + prev[na+4]) == ranges[na+2]) {
-                               prev[na+4] += ranges[na+4];
-                               ranges[0] = 0;
-                               ranges += np;
-                               continue;
-                       }
-               }
-               prev = ranges;
-               ranges += np;
-       }
-
-       /*
-        * The ranges property is laid out as an array of elements,
-        * each of which comprises:
-        *   cells 0 - 2:       a PCI address
-        *   cells 3 or 3+4:    a CPU physical address
-        *                      (size depending on dev->n_addr_cells)
-        *   cells 4+5 or 5+6:  the size of the range
-        */
-       ranges = lc_ranges;
-       rlen = orig_rlen;
-       while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
-               res = NULL;
-               size = ranges[na+4];
-               switch ((ranges[0] >> 24) & 0x3) {
-               case 1:         /* I/O space */
-                       if (ranges[2] != 0)
-                               break;
-                       hose->io_base_phys = ranges[na+2];
-                       /* limit I/O space to 16MB */
-                       if (size > 0x01000000)
-                               size = 0x01000000;
-                       hose->io_base_virt = ioremap(ranges[na+2], size);
-                       if (primary)
-                               isa_io_base = (unsigned long) hose->io_base_virt;
-                       res = &hose->io_resource;
-                       res->flags = IORESOURCE_IO;
-                       res->start = ranges[2];
-                       DBG("PCI: IO 0x%llx -> 0x%llx\n",
-                           (u64)res->start, (u64)res->start + size - 1);
-                       break;
-               case 2:         /* memory space */
-                       memno = 0;
-                       if (ranges[1] == 0 && ranges[2] == 0
-                           && ranges[na+4] <= (16 << 20)) {
-                               /* 1st 16MB, i.e. ISA memory area */
-                               if (primary)
-                                       isa_mem_base = ranges[na+2];
-                               memno = 1;
-                       }
-                       while (memno < 3 && hose->mem_resources[memno].flags)
-                               ++memno;
-                       if (memno == 0)
-                               hose->pci_mem_offset = ranges[na+2] - ranges[2];
-                       if (memno < 3) {
-                               res = &hose->mem_resources[memno];
-                               res->flags = IORESOURCE_MEM;
-                               if(ranges[0] & 0x40000000)
-                                       res->flags |= IORESOURCE_PREFETCH;
-                               res->start = ranges[na+2];
-                               DBG("PCI: MEM[%d] 0x%llx -> 0x%llx\n", memno,
-                                   (u64)res->start, (u64)res->start + size - 1);
-                       }
-                       break;
-               }
-               if (res != NULL) {
-                       res->name = dev->full_name;
-                       res->end = res->start + size - 1;
-                       res->parent = NULL;
-                       res->sibling = NULL;
-                       res->child = NULL;
-               }
-               ranges += np;
-       }
-}
-
 /* We create the "pci-OF-bus-map" property now so it appears in the
  * /proc device tree
  */
@@ -986,219 +424,7 @@ void pcibios_make_OF_bus_map(void)
 }
 #endif /* CONFIG_PPC_OF */
 
-#ifdef CONFIG_PPC_PMAC
-/*
- * This set of routines checks for PCI<->PCI bridges that have closed
- * IO resources and have child devices. It tries to re-open an IO
- * window on them.
- *
- * This is a _temporary_ fix to workaround a problem with Apple's OF
- * closing IO windows on P2P bridges when the OF drivers of cards
- * below this bridge don't claim any IO range (typically ATI or
- * Adaptec).
- *
- * A more complete fix would be to use drivers/pci/setup-bus.c, which
- * involves a working pcibios_fixup_pbus_ranges(), some more care about
- * ordering when creating the host bus resources, and maybe a few more
- * minor tweaks
- */
-
-/* Initialize bridges with base/limit values we have collected */
-static void __init
-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
-{
-       struct pci_dev *bridge = bus->self;
-       struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
-       u32 l;
-       u16 w;
-       struct resource res;
-
-       if (bus->resource[0] == NULL)
-               return;
-       res = *(bus->resource[0]);
-
-       DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
-       res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
-       res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
-       DBG("  IO window: %016llx-%016llx\n", res.start, res.end);
-
-       /* Set up the top and bottom of the PCI I/O segment for this bus. */
-       pci_read_config_dword(bridge, PCI_IO_BASE, &l);
-       l &= 0xffff000f;
-       l |= (res.start >> 8) & 0x00f0;
-       l |= res.end & 0xf000;
-       pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
-       if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
-               l = (res.start >> 16) | (res.end & 0xffff0000);
-               pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
-       }
-
-       pci_read_config_word(bridge, PCI_COMMAND, &w);
-       w |= PCI_COMMAND_IO;
-       pci_write_config_word(bridge, PCI_COMMAND, w);
-
-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
-       if (enable_vga) {
-               pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
-               w |= PCI_BRIDGE_CTL_VGA;
-               pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
-       }
-#endif
-}
-
-/* This function is pretty basic and actually quite broken for the
- * general case, it's enough for us right now though. It's supposed
- * to tell us if we need to open an IO range at all or not and what
- * size.
- */
-static int __init
-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
-{
-       struct pci_dev *dev;
-       int     i;
-       int     rc = 0;
-
-#define push_end(res, mask) do {               \
-       BUG_ON((mask+1) & mask);                \
-       res->end = (res->end + mask) | mask;    \
-} while (0)
-
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               u16 class = dev->class >> 8;
-
-               if (class == PCI_CLASS_DISPLAY_VGA ||
-                   class == PCI_CLASS_NOT_DEFINED_VGA)
-                       *found_vga = 1;
-               if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
-                       rc |= check_for_io_childs(dev->subordinate, res, found_vga);
-               if (class == PCI_CLASS_BRIDGE_CARDBUS)
-                       push_end(res, 0xfff);
-
-               for (i=0; i<PCI_NUM_RESOURCES; i++) {
-                       struct resource *r;
-                       unsigned long r_size;
-
-                       if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
-                           && i >= PCI_BRIDGE_RESOURCES)
-                               continue;
-                       r = &dev->resource[i];
-                       r_size = r->end - r->start;
-                       if (r_size < 0xfff)
-                               r_size = 0xfff;
-                       if (r->flags & IORESOURCE_IO && (r_size) != 0) {
-                               rc = 1;
-                               push_end(res, r_size);
-                       }
-               }
-       }
-
-       return rc;
-}
-
-/* Here we scan all P2P bridges of a given level that have a closed
- * IO window. Note that the test for the presence of a VGA card should
- * be improved to take into account already configured P2P bridges,
- * currently, we don't see them and might end up configuring 2 bridges
- * with VGA pass through enabled
- */
-static void __init
-do_fixup_p2p_level(struct pci_bus *bus)
-{
-       struct pci_bus *b;
-       int i, parent_io;
-       int has_vga = 0;
-
-       for (parent_io=0; parent_io<4; parent_io++)
-               if (bus->resource[parent_io]
-                   && bus->resource[parent_io]->flags & IORESOURCE_IO)
-                       break;
-       if (parent_io >= 4)
-               return;
-
-       list_for_each_entry(b, &bus->children, node) {
-               struct pci_dev *d = b->self;
-               struct pci_controller* hose = (struct pci_controller *)d->sysdata;
-               struct resource *res = b->resource[0];
-               struct resource tmp_res;
-               unsigned long max;
-               int found_vga = 0;
-
-               memset(&tmp_res, 0, sizeof(tmp_res));
-               tmp_res.start = bus->resource[parent_io]->start;
-
-               /* We don't let low addresses go through that closed P2P bridge, well,
-                * that may not be necessary but I feel safer that way
-                */
-               if (tmp_res.start == 0)
-                       tmp_res.start = 0x1000;
-       
-               if (!list_empty(&b->devices) && res && res->flags == 0 &&
-                   res != bus->resource[parent_io] &&
-                   (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
-                   check_for_io_childs(b, &tmp_res, &found_vga)) {
-                       u8 io_base_lo;
-
-                       printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
-
-                       if (found_vga) {
-                               if (has_vga) {
-                                       printk(KERN_WARNING "Skipping VGA, already active"
-                                           " on bus segment\n");
-                                       found_vga = 0;
-                               } else
-                                       has_vga = 1;
-                       }
-                       pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
-
-                       if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
-                               max = ((unsigned long) hose->io_base_virt
-                                       - isa_io_base) + 0xffffffff;
-                       else
-                               max = ((unsigned long) hose->io_base_virt
-                                       - isa_io_base) + 0xffff;
-
-                       *res = tmp_res;
-                       res->flags = IORESOURCE_IO;
-                       res->name = b->name;
-               
-                       /* Find a resource in the parent where we can allocate */
-                       for (i = 0 ; i < 4; i++) {
-                               struct resource *r = bus->resource[i];
-                               if (!r)
-                                       continue;
-                               if ((r->flags & IORESOURCE_IO) == 0)
-                                       continue;
-                               DBG("Trying to allocate from %016llx, size %016llx from parent"
-                                   " res %d: %016llx -> %016llx\n",
-                                       res->start, res->end, i, r->start, r->end);
-                       
-                               if (allocate_resource(r, res, res->end + 1, res->start, max,
-                                   res->end + 1, NULL, NULL) < 0) {
-                                       DBG("Failed !\n");
-                                       continue;
-                               }
-                               do_update_p2p_io_resource(b, found_vga);
-                               break;
-                       }
-               }
-               do_fixup_p2p_level(b);
-       }
-}
-
-static void
-pcibios_fixup_p2p_bridges(void)
-{
-       struct pci_bus *b;
-
-       list_for_each_entry(b, &pci_root_buses, node)
-               do_fixup_p2p_level(b);
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
-static int __init
-pcibios_init(void)
+static int __init pcibios_init(void)
 {
        struct pci_controller *hose, *tmp;
        struct pci_bus *bus;
@@ -1206,6 +432,9 @@ pcibios_init(void)
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
+       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+               pci_assign_all_buses = 1;
+
        /* Scan all of the recorded PCI controllers.  */
        list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                if (pci_assign_all_buses)
@@ -1213,9 +442,10 @@ pcibios_init(void)
                hose->last_busno = 0xff;
                bus = pci_scan_bus_parented(hose->parent, hose->first_busno,
                                            hose->ops, hose);
-               if (bus)
+               if (bus) {
                        pci_bus_add_devices(bus);
-               hose->last_busno = bus->subordinate;
+                       hose->last_busno = bus->subordinate;
+               }
                if (pci_assign_all_buses || next_busno <= hose->last_busno)
                        next_busno = hose->last_busno + pcibios_assign_bus_offset;
        }
@@ -1228,18 +458,8 @@ pcibios_init(void)
        if (pci_assign_all_buses && have_of)
                pcibios_make_OF_bus_map();
 
-       /* Call machine dependent fixup */
-       if (ppc_md.pcibios_fixup)
-               ppc_md.pcibios_fixup();
-
-       /* Allocate and assign resources */
-       pcibios_allocate_bus_resources(&pci_root_buses);
-       pcibios_allocate_resources(0);
-       pcibios_allocate_resources(1);
-#ifdef CONFIG_PPC_PMAC
-       pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_PPC_PMAC */
-       pcibios_assign_resources();
+       /* Call common code to handle resource allocation */
+       pcibios_resource_survey();
 
        /* Call machine dependent post-init code */
        if (ppc_md.pcibios_after_init)
@@ -1250,14 +470,14 @@ pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-void pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
        struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
        unsigned long io_offset;
        struct resource *res;
-       struct pci_dev *dev;
        int i;
 
+       /* Hookup PHB resources */
        io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
        if (bus->parent == NULL) {
                /* This is a host bridge - fill in its resources */
@@ -1272,8 +492,8 @@ void pcibios_fixup_bus(struct pci_bus *bus)
                        res->end = IO_SPACE_LIMIT;
                        res->flags = IORESOURCE_IO;
                }
-               res->start += io_offset;
-               res->end += io_offset;
+               res->start = (res->start + io_offset) & 0xffffffffu;
+               res->end = (res->end + io_offset) & 0xffffffffu;
 
                for (i = 0; i < 3; ++i) {
                        res = &hose->mem_resources[i];
@@ -1288,35 +508,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
                        }
                        bus->resource[i+1] = res;
                }
-       } else {
-               /* This is a subordinate bridge */
-               pci_read_bridge_bases(bus);
-
-               for (i = 0; i < 4; ++i) {
-                       if ((res = bus->resource[i]) == NULL)
-                               continue;
-                       if (!res->flags || bus->self->transparent)
-                               continue;
-                       if (io_offset && (res->flags & IORESOURCE_IO)) {
-                               res->start += io_offset;
-                               res->end += io_offset;
-                       } else if (hose->pci_mem_offset
-                                  && (res->flags & IORESOURCE_MEM)) {
-                               res->start += hose->pci_mem_offset;
-                               res->end += hose->pci_mem_offset;
-                       }
-               }
-       }
-
-       /* Platform specific bus fixups */
-       if (ppc_md.pcibios_fixup_bus)
-               ppc_md.pcibios_fixup_bus(bus);
-
-       /* Read default IRQs and fixup if necessary */
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               pci_read_irq_line(dev);
-               if (ppc_md.pci_irq_fixup)
-                       ppc_md.pci_irq_fixup(dev);
        }
 }
 
@@ -1328,37 +519,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
        /* XXX FIXME - update OF device tree node interrupt property */
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       if (ppc_md.pcibios_enable_device_hook)
-               if (ppc_md.pcibios_enable_device_hook(dev, 0))
-                       return -EINVAL;
-               
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx=0; idx<6; idx++) {
-               r = &dev->resource[idx];
-               if (r->flags & IORESOURCE_UNSET) {
-                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n",
-                      pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-}
-
 static struct pci_controller*
 pci_bus_to_hose(int bus)
 {
@@ -1381,17 +541,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
        struct pci_controller* hose;
        long result = -EOPNOTSUPP;
 
-       /* Argh ! Please forgive me for that hack, but that's the
-        * simplest way to get existing XFree to not lockup on some
-        * G5 machines... So when something asks for bus 0 io base
-        * (bus 0 is HT root), we return the AGP one instead.
-        */
-#ifdef CONFIG_PPC_PMAC
-       if (machine_is(powermac) && machine_is_compatible("MacRISC4"))
-               if (bus == 0)
-                       bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
        hose = pci_bus_to_hose(bus);
        if (!hose)
                return -ENODEV;
index 9f63bdcb0bdf88f0cdabe6de30b8276070ecebaf..5949bbabd7fb7620316d57b08ec012bef9f89a28 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>
 #endif
 
 unsigned long pci_probe_only = 1;
-int pci_assign_all_buses = 0;
-
-static void fixup_resource(struct resource *res, struct pci_dev *dev);
-static void do_bus_setup(struct pci_bus *bus);
 
 /* pci_io_base -- the base address from which io bars are offsets.
  * This is the lowest I/O base address (so bar values are always positive),
@@ -70,139 +65,31 @@ struct dma_mapping_ops *get_pci_dma_ops(void)
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
-static void fixup_broken_pcnet32(struct pci_dev* dev)
-{
-       if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
-               dev->vendor = PCI_VENDOR_ID_AMD;
-               pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
-void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-                             struct resource *res)
+int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
 {
-       unsigned long offset = 0;
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-       if (!hose)
-               return;
-
-       if (res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-
-       if (res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
-
-       region->start = res->start - offset;
-       region->end = res->end - offset;
+       return dma_set_mask(&dev->dev, mask);
 }
 
-void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-                             struct pci_bus_region *region)
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 {
-       unsigned long offset = 0;
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-       if (!hose)
-               return;
-
-       if (res->flags & IORESOURCE_IO)
-               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+       int rc;
 
-       if (res->flags & IORESOURCE_MEM)
-               offset = hose->pci_mem_offset;
+       rc = dma_set_mask(&dev->dev, mask);
+       dev->dev.coherent_dma_mask = dev->dma_mask;
 
-       res->start = region->start + offset;
-       res->end = region->end + offset;
+       return rc;
 }
 
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pcibios_resource_to_bus);
-EXPORT_SYMBOL(pcibios_bus_to_resource);
-#endif
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void pcibios_align_resource(void *data, struct resource *res,
-                           resource_size_t size, resource_size_t align)
-{
-       struct pci_dev *dev = data;
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       resource_size_t start = res->start;
-       unsigned long alignto;
-
-       if (res->flags & IORESOURCE_IO) {
-               unsigned long offset = (unsigned long)hose->io_base_virt -
-                                       _IO_BASE;
-               /* Make sure we start at our min on all hoses */
-               if (start - offset < PCIBIOS_MIN_IO)
-                       start = PCIBIOS_MIN_IO + offset;
-
-               /*
-                * Put everything into 0x00-0xff region modulo 0x400
-                */
-               if (start & 0x300)
-                       start = (start + 0x3ff) & ~0x3ff;
-
-       } else if (res->flags & IORESOURCE_MEM) {
-               /* Make sure we start at our min on all hoses */
-               if (start - hose->pci_mem_offset < PCIBIOS_MIN_MEM)
-                       start = PCIBIOS_MIN_MEM + hose->pci_mem_offset;
-
-               /* Align to multiple of size of minimum base.  */
-               alignto = max(0x1000UL, align);
-               start = ALIGN(start, alignto);
-       }
-
-       res->start = start;
-}
-
-void __devinit pcibios_claim_one_bus(struct pci_bus *b)
+static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
-       struct pci_dev *dev;
-       struct pci_bus *child_bus;
-
-       list_for_each_entry(dev, &b->devices, bus_list) {
-               int i;
-
-               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-                       struct resource *r = &dev->resource[i];
-
-                       if (r->parent || !r->start || !r->flags)
-                               continue;
-                       pci_claim_resource(dev, i);
-               }
+       if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
+               dev->vendor = PCI_VENDOR_ID_AMD;
+               pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
        }
-
-       list_for_each_entry(child_bus, &b->children, node)
-               pcibios_claim_one_bus(child_bus);
 }
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
-#endif
-
-static void __init pcibios_claim_of_setup(void)
-{
-       struct pci_bus *b;
-
-       if (firmware_has_feature(FW_FEATURE_ISERIES))
-               return;
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
-       list_for_each_entry(b, &pci_root_buses, node)
-               pcibios_claim_one_bus(b);
-}
 
 static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
 {
@@ -270,7 +157,6 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
                res->end = base + size - 1;
                res->flags = flags;
                res->name = pci_name(dev);
-               fixup_resource(res, dev);
        }
 }
 
@@ -339,7 +225,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 EXPORT_SYMBOL(of_create_pci_dev);
 
 void __devinit of_scan_bus(struct device_node *node,
-                                 struct pci_bus *bus)
+                          struct pci_bus *bus)
 {
        struct device_node *child = NULL;
        const u32 *reg;
@@ -348,6 +234,7 @@ void __devinit of_scan_bus(struct device_node *node,
 
        DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
 
+       /* Scan direct children */
        while ((child = of_get_next_child(node, child)) != NULL) {
                DBG("  * %s\n", child->full_name);
                reg = of_get_property(child, "reg", &reglen);
@@ -359,19 +246,26 @@ void __devinit of_scan_bus(struct device_node *node,
                dev = of_create_pci_dev(child, bus, devfn);
                if (!dev)
                        continue;
-               DBG("dev header type: %x\n", dev->hdr_type);
+               DBG("    dev header type: %x\n", dev->hdr_type);
+       }
+
+       /* Ally all fixups */
+       pcibios_fixup_of_probed_bus(bus);
 
+       /* Now scan child busses */
+       list_for_each_entry(dev, &bus->devices, bus_list) {
                if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
-                   dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-                       of_scan_pci_bridge(child, dev);
+                   dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+                       struct device_node *child = pci_device_to_OF_node(dev);
+                       if (dev)
+                               of_scan_pci_bridge(child, dev);
+               }
        }
-
-       do_bus_setup(bus);
 }
 EXPORT_SYMBOL(of_scan_bus);
 
 void __devinit of_scan_pci_bridge(struct device_node *node,
-                               struct pci_dev *dev)
+                                 struct pci_dev *dev)
 {
        struct pci_bus *bus;
        const u32 *busrange, *ranges;
@@ -441,7 +335,6 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
                res->start = of_read_number(&ranges[1], 2);
                res->end = res->start + size - 1;
                res->flags = flags;
-               fixup_resource(res, dev);
        }
        sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
                bus->number);
@@ -462,12 +355,13 @@ 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;
 
-       DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+       DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
 
+       /* Create an empty bus for the toplevel */
        bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
        if (bus == NULL) {
                printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
@@ -477,27 +371,29 @@ 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);
+       /* Get some IO space for the new PHB */
+       pcibios_map_io_space(bus);
 
-       bus->resource[0] = res = &hose->io_resource;
-       if (res->flags && request_resource(&ioport_resource, res)) {
-               printk(KERN_ERR "Failed to request PCI IO region "
-                      "on PCI domain %04x\n", hose->global_number);
-               DBG("res->start = 0x%016lx, res->end = 0x%016lx\n",
-                   res->start, res->end);
+       /* Wire up PHB bus resources */
+       if (hose->io_resource.flags) {
+               DBG("PCI: PHB IO resource    = %016lx-%016lx [%lx]\n",
+                   hose->io_resource.start, hose->io_resource.end,
+                   hose->io_resource.flags);
+               bus->resource[0] = res = &hose->io_resource;
        }
-
        for (i = 0; i < 3; ++i) {
-               res = &hose->mem_resources[i];
-               bus->resource[i+1] = res;
-               if (res->flags && request_resource(&iomem_resource, res))
-                       printk(KERN_ERR "Failed to request PCI memory region "
-                              "on PCI domain %04x\n", hose->global_number);
+               DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i,
+                   hose->mem_resources[i].start,
+                   hose->mem_resources[i].end,
+                   hose->mem_resources[i].flags);
+               bus->resource[i+1] = &hose->mem_resources[i];
        }
+       DBG("PCI: PHB MEM offset     = %016lx\n", hose->pci_mem_offset);
+       DBG("PCI: PHB IO  offset     = %08lx\n",
+           (unsigned long)hose->io_base_virt - _IO_BASE);
 
+       /* Get probe mode and perform scan */
        mode = PCI_PROBE_NORMAL;
-
        if (node && ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
        DBG("    probe mode: %d\n", mode);
@@ -514,15 +410,15 @@ static int __init pcibios_init(void)
 {
        struct pci_controller *hose, *tmp;
 
+       printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
        /* For now, override phys_mem_access_prot. If we need it,
         * later, we may move that initialization to each ppc_md
         */
        ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
 
-       if (firmware_has_feature(FW_FEATURE_ISERIES))
-               iSeries_pcibios_init();
-
-       printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
+       if (pci_probe_only)
+               ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
 
        /* Scan all of the recorded PCI controllers.  */
        list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -530,19 +426,8 @@ 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();
-       }
-
-       /* Call machine dependent final fixup */
-       if (ppc_md.pcibios_fixup)
-               ppc_md.pcibios_fixup();
+       /* Call common code to handle resource allocation */
+       pcibios_resource_survey();
 
        printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
@@ -551,141 +436,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-       u16 cmd, oldcmd;
-       int i;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       oldcmd = cmd;
-
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               struct resource *res = &dev->resource[i];
-
-               /* Only set up the requested stuff */
-               if (!(mask & (1<<i)))
-                       continue;
-
-               if (res->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (res->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-
-       if (cmd != oldcmd) {
-               printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
-                      pci_name(dev), cmd);
-                /* Enable the appropriate bits in the PCI command register.  */
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-}
-
-/* Decide whether to display the domain number in /proc */
-int pci_proc_domain(struct pci_bus *bus)
-{
-       if (firmware_has_feature(FW_FEATURE_ISERIES))
-               return 0;
-       else {
-               struct pci_controller *hose = pci_bus_to_host(bus);
-               return hose->buid != 0;
-       }
-}
-
-void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev, int prim)
-{
-       const unsigned int *ranges;
-       unsigned int pci_space;
-       unsigned long size;
-       int rlen = 0;
-       int memno = 0;
-       struct resource *res;
-       int np, na = of_n_addr_cells(dev);
-       unsigned long pci_addr, cpu_phys_addr;
-
-       np = na + 5;
-
-       /* From "PCI Binding to 1275"
-        * The ranges property is laid out as an array of elements,
-        * each of which comprises:
-        *   cells 0 - 2:       a PCI address
-        *   cells 3 or 3+4:    a CPU physical address
-        *                      (size depending on dev->n_addr_cells)
-        *   cells 4+5 or 5+6:  the size of the range
-        */
-       ranges = of_get_property(dev, "ranges", &rlen);
-       if (ranges == NULL)
-               return;
-       hose->io_base_phys = 0;
-       while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-               res = NULL;
-               pci_space = ranges[0];
-               pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
-               cpu_phys_addr = of_translate_address(dev, &ranges[3]);
-               size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
-               ranges += np;
-               if (size == 0)
-                       continue;
-
-               /* Now consume following elements while they are contiguous */
-               while (rlen >= np * sizeof(unsigned int)) {
-                       unsigned long addr, phys;
-
-                       if (ranges[0] != pci_space)
-                               break;
-                       addr = ((unsigned long)ranges[1] << 32) | ranges[2];
-                       phys = ranges[3];
-                       if (na >= 2)
-                               phys = (phys << 32) | ranges[4];
-                       if (addr != pci_addr + size ||
-                           phys != cpu_phys_addr + size)
-                               break;
-
-                       size += ((unsigned long)ranges[na+3] << 32)
-                               | ranges[na+4];
-                       ranges += np;
-                       rlen -= np * sizeof(unsigned int);
-               }
-
-               switch ((pci_space >> 24) & 0x3) {
-               case 1:         /* I/O space */
-                       hose->io_base_phys = cpu_phys_addr - pci_addr;
-                       /* handle from 0 to top of I/O window */
-                       hose->pci_io_size = pci_addr + size;
-
-                       res = &hose->io_resource;
-                       res->flags = IORESOURCE_IO;
-                       res->start = pci_addr;
-                       DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
-                                   res->start, res->start + size - 1);
-                       break;
-               case 2:         /* memory space */
-                       memno = 0;
-                       while (memno < 3 && hose->mem_resources[memno].flags)
-                               ++memno;
-
-                       if (memno == 0)
-                               hose->pci_mem_offset = cpu_phys_addr - pci_addr;
-                       if (memno < 3) {
-                               res = &hose->mem_resources[memno];
-                               res->flags = IORESOURCE_MEM;
-                               res->start = cpu_phys_addr;
-                               DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
-                                           res->start, res->start + size - 1);
-                       }
-                       break;
-               }
-               if (res != NULL) {
-                       res->name = dev->full_name;
-                       res->end = res->start + size - 1;
-                       res->parent = NULL;
-                       res->sibling = NULL;
-                       res->child = NULL;
-               }
-       }
-}
-
 #ifdef CONFIG_HOTPLUG
 
 int pcibios_unmap_io_space(struct pci_bus *bus)
@@ -719,8 +469,7 @@ 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 +528,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",
@@ -803,51 +551,13 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
-{
-       struct pci_controller *hose = pci_bus_to_host(dev->bus);
-       unsigned long offset;
-
-       if (res->flags & IORESOURCE_IO) {
-               offset = (unsigned long)hose->io_base_virt - _IO_BASE;
-               res->start += offset;
-               res->end += offset;
-       } else if (res->flags & IORESOURCE_MEM) {
-               res->start += hose->pci_mem_offset;
-               res->end += hose->pci_mem_offset;
-       }
-}
-
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-                                             struct pci_bus *bus)
-{
-       /* Update device resources.  */
-       int i;
-
-       DBG("%s: Fixup resources:\n", pci_name(dev));
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               struct resource *res = &dev->resource[i];
-               if (!res->flags)
-                       continue;
-
-               DBG("  0x%02x < %08lx:0x%016lx...0x%016lx\n",
-                   i, res->flags, res->start, res->end);
-
-               fixup_resource(res, dev);
-
-               DBG("       > %08lx:0x%016lx...0x%016lx\n",
-                   res->flags, res->start, res->end);
-       }
-}
-EXPORT_SYMBOL(pcibios_fixup_device_resources);
-
 void __devinit pcibios_setup_new_device(struct pci_dev *dev)
 {
        struct dev_archdata *sd = &dev->dev.archdata;
 
        sd->of_node = pci_device_to_OF_node(dev);
 
-       DBG("PCI device %s OF node: %s\n", pci_name(dev),
+       DBG("PCI: device %s OF node: %s\n", pci_name(dev),
            sd->of_node ? sd->of_node->full_name : "<none>");
 
        sd->dma_ops = pci_dma_ops;
@@ -861,7 +571,7 @@ void __devinit pcibios_setup_new_device(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pcibios_setup_new_device);
 
-static void __devinit do_bus_setup(struct pci_bus *bus)
+void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -870,42 +580,7 @@ static void __devinit do_bus_setup(struct pci_bus *bus)
 
        list_for_each_entry(dev, &bus->devices, bus_list)
                pcibios_setup_new_device(dev);
-
-       /* Read default IRQs and fixup if necessary */
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               pci_read_irq_line(dev);
-               if (ppc_md.pci_irq_fixup)
-                       ppc_md.pci_irq_fixup(dev);
-       }
-}
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-       struct pci_dev *dev = bus->self;
-       struct device_node *np;
-
-       np = pci_bus_to_OF_node(bus);
-
-       DBG("pcibios_fixup_bus(%s)\n", np ? np->full_name : "<???>");
-
-       if (dev && pci_probe_only &&
-           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               /* This is a subordinate bridge */
-
-               pci_read_bridge_bases(bus);
-               pcibios_fixup_device_resources(dev, bus);
-       }
-
-       do_bus_setup(bus);
-
-       if (!pci_probe_only)
-               return;
-
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-                       pcibios_fixup_device_resources(dev, bus);
 }
-EXPORT_SYMBOL(pcibios_fixup_bus);
 
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
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..90eb3a3e383ef008d81c848097e1b9f0fd8cd506 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)
@@ -419,7 +419,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
                            struct of_bus *pbus, u32 *addr,
-                           int na, int ns, int pna)
+                           int na, int ns, int pna, const char *rprop)
 {
        const u32 *ranges;
        unsigned int rlen;
@@ -438,7 +438,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * to translate addresses that aren't supposed to be translated in
         * the first place. --BenH.
         */
-       ranges = of_get_property(parent, "ranges", &rlen);
+       ranges = of_get_property(parent, rprop, &rlen);
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
@@ -481,7 +481,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+u64 __of_translate_address(struct device_node *dev, const u32 *in_addr,
+                          const char *rprop)
 {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
@@ -540,7 +541,7 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
                    pbus->name, pna, pns, parent->full_name);
 
                /* Apply bus translation */
-               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
                        break;
 
                /* Complete the move up one level */
@@ -556,8 +557,19 @@ u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
 
        return result;
 }
+
+u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "ranges");
+}
 EXPORT_SYMBOL(of_translate_address);
 
+u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr)
+{
+       return __of_translate_address(dev, in_addr, "dma-ranges");
+}
+EXPORT_SYMBOL(of_translate_dma_address);
+
 const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
                    unsigned int *flags)
 {
index 21f14e57d1f3d848d9d7d375abf96c2a83ae1b27..99aaae3409c0bf2b5148165c4d41f69fa00ae2df 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);
@@ -311,10 +311,12 @@ void __init find_and_init_phbs(void)
                if (prop)
                        pci_probe_only = *prop;
 
+#ifdef CONFIG_PPC32 /* Will be made generic soon */
                prop = of_get_property(of_chosen,
                                "linux,pci-assign-all-buses", NULL);
-               if (prop)
-                       pci_assign_all_buses = *prop;
+               if (prop && *prop)
+                       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+#endif /* CONFIG_PPC32 */
        }
 }
 
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 6126bca8b70a0c0ffd0d569fbd9f94782578bcd6..d840bc772fd346cffc8bd261726c850c4975cced 100644 (file)
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/elf.h>
+#include <linux/ptrace.h>
 #ifdef CONFIG_PPC64
 #include <linux/syscalls.h>
 #include <linux/compat.h>
-#include <linux/ptrace.h>
 #else
 #include <linux/wait.h>
-#include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
index a925a8eae121e1946c8d39959775b4b07de1c561..5cd3db5cae415198653a8d1a4e4bce846a7a40ef 100644 (file)
@@ -116,9 +116,12 @@ static struct clock_event_device decrementer_clockevent = {
        .features       = CLOCK_EVT_FEAT_ONESHOT,
 };
 
-static DEFINE_PER_CPU(struct clock_event_device, decrementers);
-void init_decrementer_clockevent(void);
-static DEFINE_PER_CPU(u64, decrementer_next_tb);
+struct decrementer_clock {
+       struct clock_event_device event;
+       u64 next_tb;
+};
+
+static DEFINE_PER_CPU(struct decrementer_clock, decrementers);
 
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long __initdata iSeries_recal_titan;
@@ -216,7 +219,11 @@ static u64 read_purr(void)
  */
 static u64 read_spurr(u64 purr)
 {
-       if (cpu_has_feature(CPU_FTR_SPURR))
+       /*
+        * cpus without PURR won't have a SPURR
+        * We already know the former when we use this, so tell gcc
+        */
+       if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR))
                return mfspr(SPRN_SPURR);
        return purr;
 }
@@ -227,29 +234,30 @@ static u64 read_spurr(u64 purr)
  */
 void account_system_vtime(struct task_struct *tsk)
 {
-       u64 now, nowscaled, delta, deltascaled;
+       u64 now, nowscaled, delta, deltascaled, sys_time;
        unsigned long flags;
 
        local_irq_save(flags);
        now = read_purr();
-       delta = now - get_paca()->startpurr;
-       get_paca()->startpurr = now;
        nowscaled = read_spurr(now);
+       delta = now - get_paca()->startpurr;
        deltascaled = nowscaled - get_paca()->startspurr;
+       get_paca()->startpurr = now;
        get_paca()->startspurr = nowscaled;
        if (!in_interrupt()) {
                /* deltascaled includes both user and system time.
                 * Hence scale it based on the purr ratio to estimate
                 * the system time */
+               sys_time = get_paca()->system_time;
                if (get_paca()->user_time)
-                       deltascaled = deltascaled * get_paca()->system_time /
-                            (get_paca()->system_time + get_paca()->user_time);
-               delta += get_paca()->system_time;
+                       deltascaled = deltascaled * sys_time /
+                            (sys_time + get_paca()->user_time);
+               delta += sys_time;
                get_paca()->system_time = 0;
        }
        account_system_time(tsk, 0, delta);
-       get_paca()->purrdelta = delta;
        account_system_time_scaled(tsk, deltascaled);
+       get_paca()->purrdelta = delta;
        get_paca()->spurrdelta = deltascaled;
        local_irq_restore(flags);
 }
@@ -326,11 +334,9 @@ void calculate_steal_time(void)
        s64 stolen;
        struct cpu_purr_data *pme;
 
-       if (!cpu_has_feature(CPU_FTR_PURR))
-               return;
-       pme = &per_cpu(cpu_purr_data, smp_processor_id());
+       pme = &__get_cpu_var(cpu_purr_data);
        if (!pme->initialized)
-               return;         /* this can happen in early boot */
+               return;         /* !CPU_FTR_PURR or early in early boot */
        tb = mftb();
        purr = mfspr(SPRN_PURR);
        stolen = (tb - pme->tb) - (purr - pme->purr);
@@ -353,7 +359,7 @@ static void snapshot_purr(void)
        if (!cpu_has_feature(CPU_FTR_PURR))
                return;
        local_irq_save(flags);
-       pme = &per_cpu(cpu_purr_data, smp_processor_id());
+       pme = &__get_cpu_var(cpu_purr_data);
        pme->tb = mftb();
        pme->purr = mfspr(SPRN_PURR);
        pme->initialized = 1;
@@ -556,8 +562,8 @@ void __init iSeries_time_init_early(void)
 void timer_interrupt(struct pt_regs * regs)
 {
        struct pt_regs *old_regs;
-       int cpu = smp_processor_id();
-       struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+       struct decrementer_clock *decrementer =  &__get_cpu_var(decrementers);
+       struct clock_event_device *evt = &decrementer->event;
        u64 now;
 
        /* Ensure a positive value is written to the decrementer, or else
@@ -570,9 +576,9 @@ void timer_interrupt(struct pt_regs * regs)
 #endif
 
        now = get_tb_or_rtc();
-       if (now < per_cpu(decrementer_next_tb, cpu)) {
+       if (now < decrementer->next_tb) {
                /* not time for this event yet */
-               now = per_cpu(decrementer_next_tb, cpu) - now;
+               now = decrementer->next_tb - now;
                if (now <= DECREMENTER_MAX)
                        set_dec((int)now);
                return;
@@ -623,6 +629,45 @@ void wakeup_decrementer(void)
        set_dec(ticks);
 }
 
+#ifdef CONFIG_SUSPEND
+void generic_suspend_disable_irqs(void)
+{
+       preempt_disable();
+
+       /* Disable the decrementer, so that it doesn't interfere
+        * with suspending.
+        */
+
+       set_dec(0x7fffffff);
+       local_irq_disable();
+       set_dec(0x7fffffff);
+}
+
+void generic_suspend_enable_irqs(void)
+{
+       wakeup_decrementer();
+
+       local_irq_enable();
+       preempt_enable();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_disable_irqs(void)
+{
+       if (ppc_md.suspend_disable_irqs)
+               ppc_md.suspend_disable_irqs();
+       generic_suspend_disable_irqs();
+}
+
+/* Overrides the weak version in kernel/power/main.c */
+void arch_suspend_enable_irqs(void)
+{
+       generic_suspend_enable_irqs();
+       if (ppc_md.suspend_enable_irqs)
+               ppc_md.suspend_enable_irqs();
+}
+#endif
+
 #ifdef CONFIG_SMP
 void __init smp_space_timers(unsigned int max_cpus)
 {
@@ -811,7 +856,7 @@ void __init clocksource_init(void)
 static int decrementer_set_next_event(unsigned long evt,
                                      struct clock_event_device *dev)
 {
-       __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
+       __get_cpu_var(decrementers).next_tb = get_tb_or_rtc() + evt;
        set_dec(evt);
        return 0;
 }
@@ -825,7 +870,7 @@ static void decrementer_set_mode(enum clock_event_mode mode,
 
 static void register_decrementer_clockevent(int cpu)
 {
-       struct clock_event_device *dec = &per_cpu(decrementers, cpu);
+       struct clock_event_device *dec = &per_cpu(decrementers, cpu).event;
 
        *dec = decrementer_clockevent;
        dec->cpumask = cpumask_of_cpu(cpu);
@@ -836,7 +881,7 @@ static void register_decrementer_clockevent(int cpu)
        clockevents_register_device(dec);
 }
 
-void init_decrementer_clockevent(void)
+static void __init init_decrementer_clockevent(void)
 {
        int cpu = smp_processor_id();
 
index 59c464e26f38886ff0c6d9ed7f20488dc66b4740..cad64840fce49409c80d0dd0a9f970dd056ca15a 100644 (file)
@@ -622,6 +622,9 @@ static void parse_fpe(struct pt_regs *regs)
 #define INST_POPCNTB           0x7c0000f4
 #define INST_POPCNTB_MASK      0xfc0007fe
 
+#define INST_ISEL              0x7c00001e
+#define INST_ISEL_MASK         0xfc00003e
+
 static int emulate_string_inst(struct pt_regs *regs, u32 instword)
 {
        u8 rT = (instword >> 21) & 0x1f;
@@ -707,6 +710,23 @@ static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
        return 0;
 }
 
+static int emulate_isel(struct pt_regs *regs, u32 instword)
+{
+       u8 rT = (instword >> 21) & 0x1f;
+       u8 rA = (instword >> 16) & 0x1f;
+       u8 rB = (instword >> 11) & 0x1f;
+       u8 BC = (instword >> 6) & 0x1f;
+       u8 bit;
+       unsigned long tmp;
+
+       tmp = (rA == 0) ? 0 : regs->gpr[rA];
+       bit = (regs->ccr >> (31 - BC)) & 0x1;
+
+       regs->gpr[rT] = bit ? tmp : regs->gpr[rB];
+
+       return 0;
+}
+
 static int emulate_instruction(struct pt_regs *regs)
 {
        u32 instword;
@@ -749,6 +769,11 @@ static int emulate_instruction(struct pt_regs *regs)
                return emulate_popcntb_inst(regs, instword);
        }
 
+       /* Emulate isel (Integer Select) instruction */
+       if ((instword & INST_ISEL_MASK) == INST_ISEL) {
+               return emulate_isel(regs, instword);
+       }
+
        return -EINVAL;
 }
 
index d723070c9a33aaec3774dc2444b787c6f2f75b46..eba148f2a31c09b7b65a68def74628b4987c3815 100644 (file)
@@ -57,6 +57,10 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
        udbg_init_cpm();
 #endif
+
+#ifdef CONFIG_PPC_EARLY_DEBUG
+       console_loglevel = 10;
+#endif
 }
 
 /* udbg library, used by xmon et al */
index 833a3d0bcfa7ad197b71729a1bbb8058d3d0e1b9..df740eae77b856edc047ad4324df2dd1f579a991 100644 (file)
@@ -46,7 +46,7 @@ struct NS16550 {
 
 #define LCR_DLAB 0x80
 
-static volatile struct NS16550 __iomem *udbg_comport;
+static struct NS16550 __iomem *udbg_comport;
 
 static void udbg_550_putc(char c)
 {
@@ -117,7 +117,7 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
 {
        unsigned int dll, dlm, divisor, prescaler, speed;
        u8 old_lcr;
-       volatile struct NS16550 __iomem *port = comport;
+       struct NS16550 __iomem *port = comport;
 
        old_lcr = in_8(&port->lcr);
 
@@ -162,7 +162,7 @@ void udbg_maple_real_putc(char c)
 
 void __init udbg_init_maple_realmode(void)
 {
-       udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
+       udbg_comport = (struct NS16550 __iomem *)0xf40003f8;
 
        udbg_putc = udbg_maple_real_putc;
        udbg_getc = NULL;
@@ -184,7 +184,7 @@ void udbg_pas_real_putc(char c)
 
 void udbg_init_pas_realmode(void)
 {
-       udbg_comport = (volatile struct NS16550 __iomem *)0xfcff03f8UL;
+       udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL;
 
        udbg_putc = udbg_pas_real_putc;
        udbg_getc = NULL;
@@ -219,7 +219,7 @@ static int udbg_44x_as1_getc(void)
 void __init udbg_init_44x_as1(void)
 {
        udbg_comport =
-               (volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
+               (struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
 
        udbg_putc = udbg_44x_as1_putc;
        udbg_getc = udbg_44x_as1_getc;
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 c12adc3ddffd892b3238025873afc7764eb20831..1666e7d54cca9faa5cd687aaa64ae5290cebd752 100644 (file)
@@ -24,6 +24,8 @@
 
 static int numa_enabled = 1;
 
+static char *cmdline __initdata;
+
 static int numa_debug;
 #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
 
@@ -39,6 +41,43 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
 
+static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn,
+                                               unsigned int *nid)
+{
+       unsigned long long mem;
+       char *p = cmdline;
+       static unsigned int fake_nid = 0;
+       static unsigned long long curr_boundary = 0;
+
+       *nid = fake_nid;
+       if (!p)
+               return 0;
+
+       mem = memparse(p, &p);
+       if (!mem)
+               return 0;
+
+       if (mem < curr_boundary)
+               return 0;
+
+       curr_boundary = mem;
+
+       if ((end_pfn << PAGE_SHIFT) > mem) {
+               /*
+                * Skip commas and spaces
+                */
+               while (*p == ',' || *p == ' ' || *p == '\t')
+                       p++;
+
+               cmdline = p;
+               fake_nid++;
+               *nid = fake_nid;
+               dbg("created new fake_node with id %d\n", fake_nid);
+               return 1;
+       }
+       return 0;
+}
+
 static void __cpuinit map_cpu_to_node(int cpu, int node)
 {
        numa_cpu_lookup_table[cpu] = node;
@@ -344,12 +383,14 @@ static void __init parse_drconf_memory(struct device_node *memory)
                        if (nid == 0xffff || nid >= MAX_NUMNODES)
                                nid = default_nid;
                }
-               node_set_online(nid);
 
                size = numa_enforce_memory_limit(start, lmb_size);
                if (!size)
                        continue;
 
+               fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
+               node_set_online(nid);
+
                add_active_range(nid, start >> PAGE_SHIFT,
                                 (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
        }
@@ -429,7 +470,6 @@ new_range:
                nid = of_node_to_nid_single(memory);
                if (nid < 0)
                        nid = default_nid;
-               node_set_online(nid);
 
                if (!(size = numa_enforce_memory_limit(start, size))) {
                        if (--ranges)
@@ -438,6 +478,9 @@ new_range:
                                continue;
                }
 
+               fake_numa_create_new_node(((start + size) >> PAGE_SHIFT), &nid);
+               node_set_online(nid);
+
                add_active_range(nid, start >> PAGE_SHIFT,
                                (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
 
@@ -461,7 +504,7 @@ static void __init setup_nonnuma(void)
        unsigned long top_of_ram = lmb_end_of_DRAM();
        unsigned long total_ram = lmb_phys_mem_size();
        unsigned long start_pfn, end_pfn;
-       unsigned int i;
+       unsigned int i, nid = 0;
 
        printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
               top_of_ram, total_ram);
@@ -471,9 +514,11 @@ static void __init setup_nonnuma(void)
        for (i = 0; i < lmb.memory.cnt; ++i) {
                start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
                end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
-               add_active_range(0, start_pfn, end_pfn);
+
+               fake_numa_create_new_node(end_pfn, &nid);
+               add_active_range(nid, start_pfn, end_pfn);
+               node_set_online(nid);
        }
-       node_set_online(0);
 }
 
 void __init dump_numa_cpu_topology(void)
@@ -702,6 +747,10 @@ static int __init early_numa(char *p)
        if (strstr(p, "debug"))
                numa_debug = 1;
 
+       p = strstr(p, "fake=");
+       if (p)
+               cmdline = p + strlen("fake=");
+
        return 0;
 }
 early_param("numa", early_numa);
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 bb6bff51ce484e6dbc4b315cc1815e3fe04b0d1c..13929771bee7c10e3fe70effebcfd3f670868ec8 100644 (file)
@@ -61,7 +61,7 @@ static unsigned int spu_cycle_reset;
 #define NUM_THREADS 2         /* number of physical threads in
                               * physical processor
                               */
-#define NUM_TRACE_BUS_WORDS 4
+#define NUM_DEBUG_BUS_WORDS 4
 #define NUM_INPUT_BUS_WORDS 2
 
 #define MAX_SPU_COUNT 0xFFFFFF /* maximum 24 bit LFSR value */
@@ -169,7 +169,6 @@ static DEFINE_SPINLOCK(virt_cntr_lock);
 
 static u32 ctr_enabled;
 
-static unsigned char trace_bus[NUM_TRACE_BUS_WORDS];
 static unsigned char input_bus[NUM_INPUT_BUS_WORDS];
 
 /*
@@ -298,7 +297,7 @@ static void set_pm_event(u32 ctr, int event, u32 unit_mask)
 
        p->signal_group = event / 100;
        p->bus_word = bus_word;
-       p->sub_unit = (unit_mask & 0x0000f000) >> 12;
+       p->sub_unit = GET_SUB_UNIT(unit_mask);
 
        pm_regs.pm07_cntrl[ctr] = 0;
        pm_regs.pm07_cntrl[ctr] |= PM07_CTR_COUNT_CYCLES(count_cycles);
@@ -334,16 +333,16 @@ static void set_pm_event(u32 ctr, int event, u32 unit_mask)
                p->bit = signal_bit;
        }
 
-       for (i = 0; i < NUM_TRACE_BUS_WORDS; i++) {
+       for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) {
                if (bus_word & (1 << i)) {
                        pm_regs.debug_bus_control |=
-                           (bus_type << (31 - (2 * i) + 1));
+                           (bus_type << (30 - (2 * i)));
 
                        for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) {
                                if (input_bus[j] == 0xff) {
                                        input_bus[j] = i;
                                        pm_regs.group_control |=
-                                           (i << (31 - i));
+                                           (i << (30 - (2 * j)));
 
                                        break;
                                }
@@ -450,6 +449,12 @@ static void cell_virtual_cntr(unsigned long data)
        hdw_thread = 1 ^ hdw_thread;
        next_hdw_thread = hdw_thread;
 
+       pm_regs.group_control = 0;
+       pm_regs.debug_bus_control = 0;
+
+       for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
+               input_bus[i] = 0xff;
+
        /*
         * There are some per thread events.  Must do the
         * set event, for the thread that is being started
@@ -619,9 +624,6 @@ static int cell_reg_setup(struct op_counter_config *ctr,
                pmc_cntrl[1][i].vcntr = i;
        }
 
-       for (i = 0; i < NUM_TRACE_BUS_WORDS; i++)
-               trace_bus[i] = 0xff;
-
        for (i = 0; i < NUM_INPUT_BUS_WORDS; i++)
                input_bus[i] = 0xff;
 
index 4c6c82a684b1eb23bb43642b86200d564c491f29..262eda8659d07ef31be4cc715153f5cc5943032d 100644 (file)
@@ -363,7 +363,7 @@ mpc52xx_add_bridge(struct device_node *node)
 
        pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
        if (of_address_to_resource(node, 0, &rsrc) != 0) {
                printk(KERN_ERR "Can't get %s resources\n", node->full_name);
index a497cbaa1ac5ad7ba76db0d2a0890fe47b2171d9..1b75902fad64a9a848e0bd4050c3a01345021c80 100644 (file)
@@ -53,13 +53,13 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
        if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
                goto err;
 
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
 
        hose = pcibios_alloc_controller(np);
        if (!hose)
                return;
 
-       hose->arch_data = np;
+       hose->dn = np;
 
        setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0);
        pci_process_bridge_OF_ranges(hose, np, 1);
index 4f457a9c79aebee64db8e8e717147cf6ac852c20..1be50050180644811985bfe60f119c6e23b14541 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
 
 #include <asm/io.h>
 #include <asm/cpm2.h>
 #include <asm/udbg.h>
 #include <asm/machdep.h>
-#include <asm/of_platform.h>
 #include <asm/time.h>
 
 #include <sysdev/fsl_soc.h>
index ec305f18abd8f4da243a1fbea875c43be75b1933..2430ac840493cb4c6a9a84213af490e42a4b188d 100644 (file)
@@ -50,6 +50,11 @@ config MPC836x_MDS
        help
          This option enables support for the MPC836x MDS Processor Board.
 
+config MPC837x_MDS
+       bool "Freescale MPC837x MDS"
+       select DEFAULT_UIMAGE
+       help
+         This option enables support for the MPC837x MDS Processor Board.
 endchoice
 
 config PPC_MPC831x
@@ -75,3 +80,9 @@ config PPC_MPC836x
        select PPC_UDBG_16550
        select PPC_INDIRECT_PCI
        default y if MPC836x_MDS
+
+config PPC_MPC837x
+       bool
+       select PPC_UDBG_16550
+       select PPC_INDIRECT_PCI
+       default y if MPC837x_MDS
index 5a98f885779f80765a4560a4328efb36e05e7fec..df4662999a950fc77aee61e6bc7a9f25b8941d07 100644 (file)
@@ -9,3 +9,4 @@ obj-$(CONFIG_MPC834x_MDS)       += mpc834x_mds.o
 obj-$(CONFIG_MPC834x_ITX)      += mpc834x_itx.o
 obj-$(CONFIG_MPC836x_MDS)      += mpc836x_mds.o
 obj-$(CONFIG_MPC832x_MDS)      += mpc832x_mds.o
+obj-$(CONFIG_MPC837x_MDS)      += mpc837x_mds.o
index 33766b8f259445ff36682cb9b2061e6a15ce87a2..6fb82993967c0e5c7fb5e795c161ad0d6a38c834 100644 (file)
@@ -70,9 +70,9 @@ void __init mpc8313_rdb_init_IRQ(void)
  */
 static int __init mpc8313_rdb_probe(void)
 {
-        unsigned long root = of_get_flat_dt_root();
+       unsigned long root = of_get_flat_dt_root();
 
-        return of_flat_dt_is_compatible(root, "MPC8313ERDB");
+       return of_flat_dt_is_compatible(root, "MPC8313ERDB");
 }
 
 define_machine(mpc8313_rdb) {
index 39ee7a13b25a61622dab10bf9f95c75f9299b03b..1e570bb947fc49642d7765218a5e27cdeaa10f26 100644 (file)
@@ -23,9 +23,9 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
index d4bd04001b99567035247758b1d22919955b56ae..ffb2e9361ce3fc0b7e694f1a3e36d72a1f2f4ae1 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
 #include <linux/mmc/host.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
 #include <asm/time.h>
 #include <asm/ipic.h>
 #include <asm/udbg.h>
index a81bb3ce6b94460faf95cffe7f8a88e45696e289..459fb7227e764ce71a539209287819b0c238181f 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -106,14 +107,30 @@ static void __init mpc834x_mds_init_IRQ(void)
        ipic_set_default_priority();
 }
 
+static struct of_device_id mpc834x_ids[] = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       {},
+};
+
+static int __init mpc834x_declare_of_platform_devices(void)
+{
+       if (!machine_is(mpc834x_mds))
+               return 0;
+
+       of_platform_bus_probe(NULL, mpc834x_ids, NULL);
+       return 0;
+}
+device_initcall(mpc834x_declare_of_platform_devices);
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc834x_mds_probe(void)
 {
-        unsigned long root = of_get_flat_dt_root();
+       unsigned long root = of_get_flat_dt_root();
 
-        return of_flat_dt_is_compatible(root, "MPC834xMDS");
+       return of_flat_dt_is_compatible(root, "MPC834xMDS");
 }
 
 define_machine(mpc834x_mds) {
index e40012f8f4886b323a83442baabf5dc720185d8a..2ac9890b763c42573a4d6f24dc37d66608fb00e7 100644 (file)
@@ -29,9 +29,9 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
new file mode 100644 (file)
index 0000000..166c111
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc837x_mds.c
+ *
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * MPC837x MDS board specific routines
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include <asm/time.h>
+#include <asm/ipic.h>
+#include <asm/udbg.h>
+#include <asm/prom.h>
+
+#include "mpc83xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc837x_mds_setup_arch(void)
+{
+#ifdef CONFIG_PCI
+       struct device_node *np;
+#endif
+
+       if (ppc_md.progress)
+               ppc_md.progress("mpc837x_mds_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+       for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+               mpc83xx_add_bridge(np);
+#endif
+}
+
+static struct of_device_id mpc837x_ids[] = {
+       { .type = "soc", },
+       { .compatible = "soc", },
+       {},
+};
+
+static int __init mpc837x_declare_of_platform_devices(void)
+{
+       if (!machine_is(mpc837x_mds))
+               return 0;
+
+       /* Publish of_device */
+       of_platform_bus_probe(NULL, mpc837x_ids, NULL);
+
+       return 0;
+}
+device_initcall(mpc837x_declare_of_platform_devices);
+
+static void __init mpc837x_mds_init_IRQ(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,ipic");
+       if (!np)
+               return;
+
+       ipic_init(np, 0);
+
+       /* Initialize the default interrupt mapping priorities,
+        * in case the boot rom changed something on us.
+        */
+       ipic_set_default_priority();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc837x_mds_probe(void)
+{
+        unsigned long root = of_get_flat_dt_root();
+
+        return of_flat_dt_is_compatible(root, "fsl,mpc837xmds");
+}
+
+define_machine(mpc837x_mds) {
+       .name                   = "MPC837x MDS",
+       .probe                  = mpc837x_mds_probe,
+       .setup_arch             = mpc837x_mds_setup_arch,
+       .init_IRQ               = mpc837x_mds_init_IRQ,
+       .get_irq                = ipic_get_irq,
+       .restart                = mpc83xx_restart,
+       .time_init              = mpc83xx_time_init,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index 80425d7b14f8b0b24376a1de86458c61a163684e..14f1080c6c9d40c616eebbfbd37f0e26ead5b781 100644 (file)
@@ -54,7 +54,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
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 61b3eedf41b9920e38e1ccee0cc3c9ff94dcfda4..e6c63a5b1efb56bbf9407cae92108d7b37448e44 100644 (file)
@@ -30,9 +30,9 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
 
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
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 bd28655043a0851a74ce3c0e679fc23d39a2bc05..91fbe4241918d5dae118a8979c0d0ff73af6d4ac 100644 (file)
@@ -18,6 +18,7 @@ config MPC8XXFADS
 config MPC86XADS
        bool "MPC86XADS"
        select CPM1
+       select PPC_CPM_NEW_BINDING
        help
          MPC86x Application Development System by Freescale Semiconductor.
          The MPC86xADS is meant to serve as a platform for s/w and h/w
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 cffa194ccf1ffe014812bb026db3d2306f6f0123..17b1fe75e0b234441d5fe5c940ace0a78a536680 100644 (file)
 #ifndef __ASM_MPC86XADS_H__
 #define __ASM_MPC86XADS_H__
 
-#include <sysdev/fsl_soc.h>
-
-/* U-Boot maps BCSR to 0xff080000 */
-#define BCSR_ADDR              ((uint)0xff080000)
-#define BCSR_SIZE              ((uint)32)
-#define BCSR0                  ((uint)(BCSR_ADDR + 0x00))
-#define BCSR1                  ((uint)(BCSR_ADDR + 0x04))
-#define BCSR2                  ((uint)(BCSR_ADDR + 0x08))
-#define BCSR3                  ((uint)(BCSR_ADDR + 0x0c))
-#define BCSR4                  ((uint)(BCSR_ADDR + 0x10))
-
-#define CFG_PHYDEV_ADDR                ((uint)0xff0a0000)
-#define BCSR5                  ((uint)(CFG_PHYDEV_ADDR + 0x300))
-
-#define MPC8xx_CPM_OFFSET      (0x9c0)
-#define CPM_MAP_ADDR           (get_immrbase() + MPC8xx_CPM_OFFSET)
-#define CPM_IRQ_OFFSET         16     // for compability with cpm_uart driver
-
-#define PCMCIA_MEM_ADDR                ((uint)0xff020000)
-#define PCMCIA_MEM_SIZE                ((uint)(64 * 1024))
-
 /* Bits of interest in the BCSRs.
  */
 #define BCSR1_ETHEN            ((uint)0x20000000)
 #define BCSR5_MII1_EN          0x02
 #define BCSR5_MII1_RST         0x01
 
-/* Interrupt level assignments */
-#define PHY_INTERRUPT  SIU_IRQ7        /* PHY link change interrupt */
-#define SIU_INT_FEC1   SIU_LEVEL1      /* FEC1 interrupt */
-#define FEC_INTERRUPT  SIU_INT_FEC1    /* FEC interrupt */
-
-/* We don't use the 8259 */
-#define NR_8259_INTS   0
-
-/* CPM Ethernet through SCC1 */
-#define PA_ENET_RXD     ((ushort)0x0001)
-#define PA_ENET_TXD     ((ushort)0x0002)
-#define PA_ENET_TCLK    ((ushort)0x0100)
-#define PA_ENET_RCLK    ((ushort)0x0200)
-#define PB_ENET_TENA    ((uint)0x00001000)
-#define PC_ENET_CLSN    ((ushort)0x0010)
-#define PC_ENET_RENA    ((ushort)0x0020)
-
-/* Control bits in the SICR to route TCLK (CLK1) and RCLK (CLK2) to
- * SCC1.  Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
- */
-#define SICR_ENET_MASK  ((uint)0x000000ff)
-#define SICR_ENET_CLKRT ((uint)0x0000002c)
-
 #endif /* __ASM_MPC86XADS_H__ */
 #endif /* __KERNEL__ */
index 49012835f453575619686b14b6706b1e2419b029..d2927a434aefe34b7589d82fc5741ae24906495e 100644 (file)
  *
  * Copyright 2005 MontaVista Software Inc.
  *
+ * Heavily modified by Scott Wood <scottwood@freescale.com>
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ *
  * This file is licensed under the terms of the GNU General Public License
  * version 2. This program is licensed "as is" without any warranty of any
  * kind, whether express or implied.
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/root_dev.h>
-
-#include <linux/fs_enet_pd.h>
-#include <linux/fs_uart_pd.h>
-#include <linux/mii.h>
+#include <linux/of_platform.h>
 
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/page.h>
-#include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/time.h>
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/commproc.h>
 #include <asm/fs_pd.h>
-#include <asm/prom.h>
+#include <asm/udbg.h>
 
 #include <sysdev/commproc.h>
 
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
-static void init_scc1_ioports(struct fs_platform_info* ptr);
-
-void __init mpc86xads_board_setup(void)
-{
-       cpm8xx_t *cp;
-       unsigned int *bcsr_io;
-       u8 tmpval8;
-
-       bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-       cp = (cpm8xx_t *)immr_map(im_cpm);
-
-       if (bcsr_io == NULL) {
-               printk(KERN_CRIT "Could not remap BCSR\n");
-               return;
-       }
-#ifdef CONFIG_SERIAL_CPM_SMC1
-       clrbits32(bcsr_io, BCSR1_RS232EN_1);
-       clrbits32(&cp->cp_simode, 0xe0000000 >> 17);    /* brg1 */
-       tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX);
-       out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
-       clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);
-#else
-       setbits32(bcsr_io,BCSR1_RS232EN_1);
-       out_be16(&cp->cp_smc[0].smc_smcmr, 0);
-       out_8(&cp->cp_smc[0].smc_smce, 0);
-#endif
-
-#ifdef CONFIG_SERIAL_CPM_SMC2
-       clrbits32(bcsr_io,BCSR1_RS232EN_2);
-       clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
-       setbits32(&cp->cp_simode, 0x20000000 >> 1);     /* brg2 */
-       tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
-       out_8(&(cp->cp_smc[1].smc_smcm), tmpval8);
-       clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN);
+#include "mpc86xads.h"
 
-       init_smc2_uart_ioports(0);
-#else
-       setbits32(bcsr_io,BCSR1_RS232EN_2);
-       out_be16(&cp->cp_smc[1].smc_smcmr, 0);
-       out_8(&cp->cp_smc[1].smc_smce, 0);
-#endif
-       immr_unmap(cp);
-       iounmap(bcsr_io);
-}
+struct cpm_pin {
+       int port, pin, flags;
+};
 
+static struct cpm_pin mpc866ads_pins[] = {
+       /* SMC1 */
+       {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
+       {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
+
+       /* SMC2 */
+       {CPM_PORTB, 21, CPM_PIN_INPUT}, /* RX */
+       {CPM_PORTB, 20, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
+
+       /* SCC1 */
+       {CPM_PORTA, 6, CPM_PIN_INPUT}, /* CLK1 */
+       {CPM_PORTA, 7, CPM_PIN_INPUT}, /* CLK2 */
+       {CPM_PORTA, 14, CPM_PIN_INPUT}, /* TX */
+       {CPM_PORTA, 15, CPM_PIN_INPUT}, /* RX */
+       {CPM_PORTB, 19, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TENA */
+       {CPM_PORTC, 10, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* RENA */
+       {CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, /* CLSN */
+
+       /* MII */
+       {CPM_PORTD, 3, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 4, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 5, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 6, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 7, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 8, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 9, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 10, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 11, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 12, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 13, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 14, CPM_PIN_OUTPUT},
+       {CPM_PORTD, 15, CPM_PIN_OUTPUT},
+};
 
-static void init_fec1_ioports(struct fs_platform_info* ptr)
+static void __init init_ioports(void)
 {
-       iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+       int i;
 
-       /* configure FEC1 pins  */
+       for (i = 0; i < ARRAY_SIZE(mpc866ads_pins); i++) {
+               struct cpm_pin *pin = &mpc866ads_pins[i];
+               cpm1_set_pin(pin->port, pin->pin, pin->flags);
+       }
 
-       setbits16(&io_port->iop_pdpar, 0x1fff);
-       setbits16(&io_port->iop_pddir, 0x1fff);
+       cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
+       cpm1_clk_setup(CPM_CLK_SMC2, CPM_BRG2, CPM_CLK_RTX);
+       cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK1, CPM_CLK_TX);
+       cpm1_clk_setup(CPM_CLK_SCC1, CPM_CLK2, CPM_CLK_RX);
 
-       immr_unmap(io_port);
+       /* Set FEC1 and FEC2 to MII mode */
+       clrbits32(&mpc8xx_immr->im_cpm.cp_cptr, 0x00000180);
 }
 
-void init_fec_ioports(struct fs_platform_info *fpi)
+static void __init mpc86xads_setup_arch(void)
 {
-       int fec_no = fs_get_fec_index(fpi->fs_no);
+       struct device_node *np;
+       u32 __iomem *bcsr_io;
+
+       cpm_reset();
+       init_ioports();
 
-       switch (fec_no) {
-       case 0:
-               init_fec1_ioports(fpi);
-               break;
-       default:
-               printk(KERN_ERR "init_fec_ioports: invalid FEC number\n");
+       np = of_find_compatible_node(NULL, NULL, "fsl,mpc866ads-bcsr");
+       if (!np) {
+               printk(KERN_CRIT "Could not find fsl,mpc866ads-bcsr node\n");
                return;
        }
-}
 
-static void init_scc1_ioports(struct fs_platform_info* fpi)
-{
-       unsigned *bcsr_io;
-       iop8xx_t *io_port;
-       cpm8xx_t *cp;
-
-       bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
-       io_port = (iop8xx_t *)immr_map(im_ioport);
-       cp = (cpm8xx_t *)immr_map(im_cpm);
+       bcsr_io = of_iomap(np, 0);
+       of_node_put(np);
 
        if (bcsr_io == NULL) {
                printk(KERN_CRIT "Could not remap BCSR\n");
                return;
        }
 
-       /* Configure port A pins for Txd and Rxd.
-        */
-       setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
-       clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD);
-       clrbits16(&io_port->iop_paodr, PA_ENET_TXD);
-
-       /* Configure port C pins to enable CLSN and RENA.
-        */
-       clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
-       clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
-       setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
-
-       /* Configure port A for TCLK and RCLK.
-        */
-       setbits16(&io_port->iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
-        clrbits16(&io_port->iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
-        clrbits32(&cp->cp_pbpar, PB_ENET_TENA);
-        clrbits32(&cp->cp_pbdir, PB_ENET_TENA);
-
-       /* Configure Serial Interface clock routing.
-        * First, clear all SCC bits to zero, then set the ones we want.
-        */
-       clrbits32(&cp->cp_sicr, SICR_ENET_MASK);
-       setbits32(&cp->cp_sicr, SICR_ENET_CLKRT);
-
-       /* In the original SCC enet driver the following code is placed at
-          the end of the initialization */
-        setbits32(&cp->cp_pbpar, PB_ENET_TENA);
-        setbits32(&cp->cp_pbdir, PB_ENET_TENA);
-
-       clrbits32(bcsr_io+1, BCSR1_ETHEN);
+       clrbits32(bcsr_io, BCSR1_RS232EN_1 | BCSR1_RS232EN_2 | BCSR1_ETHEN);
        iounmap(bcsr_io);
-       immr_unmap(cp);
-       immr_unmap(io_port);
-}
-
-void init_scc_ioports(struct fs_platform_info *fpi)
-{
-       int scc_no = fs_get_scc_index(fpi->fs_no);
-
-       switch (scc_no) {
-       case 0:
-               init_scc1_ioports(fpi);
-               break;
-       default:
-               printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
-               return;
-       }
 }
 
-
-
-static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
+static int __init mpc86xads_probe(void)
 {
-        unsigned *bcsr_io;
-       cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-
-       setbits32(&cp->cp_pbpar, 0x000000c0);
-       clrbits32(&cp->cp_pbdir, 0x000000c0);
-       clrbits16(&cp->cp_pbodr, 0x00c0);
-       immr_unmap(cp);
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_1);
-        iounmap(bcsr_io);
+       unsigned long root = of_get_flat_dt_root();
+       return of_flat_dt_is_compatible(root, "fsl,mpc866ads");
 }
 
-static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
-{
-        unsigned *bcsr_io;
-       cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
-
-       setbits32(&cp->cp_pbpar, 0x00000c00);
-       clrbits32(&cp->cp_pbdir, 0x00000c00);
-       clrbits16(&cp->cp_pbodr, 0x0c00);
-       immr_unmap(cp);
-
-        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
-
-        if (bcsr_io == NULL) {
-                printk(KERN_CRIT "Could not remap BCSR1\n");
-                return;
-        }
-        clrbits32(bcsr_io,BCSR1_RS232EN_2);
-        iounmap(bcsr_io);
-}
+static struct of_device_id __initdata of_bus_ids[] = {
+       { .name = "soc", },
+       { .name = "cpm", },
+       { .name = "localbus", },
+       {},
+};
 
-void init_smc_ioports(struct fs_uart_platform_info *data)
+static int __init declare_of_platform_devices(void)
 {
-       int smc_no = fs_uart_id_fsid2smc(data->fs_no);
+       if (machine_is(mpc86x_ads))
+               of_platform_bus_probe(NULL, of_bus_ids, NULL);
 
-       switch (smc_no) {
-       case 0:
-               init_smc1_uart_ioports(data);
-               data->brg = data->clk_rx;
-               break;
-       case 1:
-               init_smc2_uart_ioports(data);
-               data->brg = data->clk_rx;
-               break;
-       default:
-               printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
-               return;
-       }
-}
-
-int platform_device_skip(const char *model, int id)
-{
        return 0;
 }
-
-static void __init mpc86xads_setup_arch(void)
-{
-       cpm_reset();
-
-       mpc86xads_board_setup();
-
-       ROOT_DEV = Root_NFS;
-}
-
-static int __init mpc86xads_probe(void)
-{
-       char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
-                                         "model", NULL);
-       if (model == NULL)
-               return 0;
-       if (strcmp(model, "MPC866ADS"))
-               return 0;
-
-       return 1;
-}
+device_initcall(declare_of_platform_devices);
 
 define_machine(mpc86x_ads) {
        .name                   = "MPC86x ADS",
@@ -275,4 +145,5 @@ define_machine(mpc86x_ads) {
        .calibrate_decr         = mpc8xx_calibrate_decr,
        .set_rtc_time           = mpc8xx_set_rtc_time,
        .get_rtc_time           = mpc8xx_get_rtc_time,
+       .progress               = udbg_progress,
 };
index 61d12f1830364e984a63a44ecebb40863af7042c..3cd565a04d0a919b901de9faae5996ec4b6b0366 100644 (file)
@@ -19,7 +19,7 @@ spu-manage-$(CONFIG_PPC_CELLEB)               += spu_manage.o
 spu-manage-$(CONFIG_PPC_CELL_NATIVE)   += spu_manage.o
 
 obj-$(CONFIG_SPU_BASE)                 += spu_callbacks.o spu_base.o \
-                                          spu_syscalls.o \
+                                          spu_syscalls.o spu_fault.o \
                                           $(spu-priv1-y) \
                                           $(spu-manage-y) \
                                           spufs/
index 13d5a87f13b17396acdf52800fd0c8c1b30a8984..ec7c8f45a21556c9a7a7bb0ec96331b64f4bb52d 100644 (file)
@@ -21,8 +21,9 @@
  */
 
 #include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+
 #include <asm/machdep.h>
-#include <asm/of_platform.h>
 #include <asm/prom.h>
 #include <asm/cell-regs.h>
 #include "cbe_cpufreq.h"
index 6a2c1b0a9a9448432fe1cc7375ca4e8665127d47..69288f653144f0a77f949d402c4e5fee014c66ff 100644 (file)
@@ -23,7 +23,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <asm/of_platform.h>
+#include <linux/of_platform.h>
+
 #include <asm/processor.h>
 #include <asm/prom.h>
 #include <asm/pmi.h>
index 16a9b07e7b0c24b75b2a5c17b779a5f3e12f4a27..dbc338f187a25a0288d6fda276ded42bc3f0705e 100644 (file)
@@ -9,13 +9,13 @@
 #include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 /*
@@ -256,6 +256,7 @@ void __init cbe_regs_init(void)
                        printk(KERN_ERR "cbe_regs: More BE chips than supported"
                               "!\n");
                        cbe_regs_map_count--;
+                       of_node_put(cpu);
                        return;
                }
                map->cpu_node = cpu;
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..1221c6d8650f09014b8ffcdbb947576a3140523c 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
+#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/udbg.h>
-#include <asm/of_platform.h>
 #include <asm/lmb.h>
+#include <asm/firmware.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
@@ -699,7 +700,8 @@ static int __init cell_iommu_init(void)
 {
        struct device_node *np;
 
-       if (!machine_is(cell))
+       if (!machine_is(cell) &&
+           !machine_is(celleb_native))
                return -ENODEV;
 
        /* If IOMMU is disabled or we have little enough RAM to not need
index 1ed3036788879d018c7dcdab5bf68925d87f9fce..99d688e88cbe1e51888f7fc6ec3b9f900a518ffe 100644 (file)
@@ -213,7 +213,7 @@ u32 cbe_read_pm(u32 cpu, enum pm_reg_name reg)
                break;
 
        case pm_interval:
-               READ_SHADOW_REG(val, pm_interval);
+               READ_MMIO_UPPER32(val, pm_interval);
                break;
 
        case pm_start_stop:
index 98e7ef8e6fc66a5becd6c3cd18a676bd6ef96fdb..4f6347c9fe68266d4d88638fa33b18d61f6fb7d1 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/console.h>
 #include <linux/mutex.h>
 #include <linux/memory_hotplug.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -51,7 +52,6 @@
 #include <asm/spu_priv1.h>
 #include <asm/udbg.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 #include <asm/cell-regs.h>
 
 #include "interrupt.h"
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 c83c3e3f51784c55a3ed85f4e67e2e2513cec2f3..fb266ae320954ed2e344e2786e526dd24d5b0347 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/linux_logo.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
+#include <asm/spu_csa.h>
 #include <asm/xmon.h>
 #include <asm/prom.h>
 
@@ -46,6 +47,13 @@ EXPORT_SYMBOL_GPL(spu_priv1_ops);
 struct cbe_spu_info cbe_spu_info[MAX_NUMNODES];
 EXPORT_SYMBOL_GPL(cbe_spu_info);
 
+/*
+ * The spufs fault-handling code needs to call force_sig_info to raise signals
+ * on DMA errors. Export it here to avoid general kernel-wide access to this
+ * function
+ */
+EXPORT_SYMBOL_GPL(force_sig_info);
+
 /*
  * Protects cbe_spu_info and spu->number.
  */
@@ -66,6 +74,10 @@ static LIST_HEAD(spu_full_list);
 static DEFINE_SPINLOCK(spu_full_list_lock);
 static DEFINE_MUTEX(spu_full_list_mutex);
 
+struct spu_slb {
+       u64 esid, vsid;
+};
+
 void spu_invalidate_slbs(struct spu *spu)
 {
        struct spu_priv2 __iomem *priv2 = spu->priv2;
@@ -114,40 +126,36 @@ void spu_associate_mm(struct spu *spu, struct mm_struct *mm)
 }
 EXPORT_SYMBOL_GPL(spu_associate_mm);
 
-static int __spu_trap_invalid_dma(struct spu *spu)
+int spu_64k_pages_available(void)
 {
-       pr_debug("%s\n", __FUNCTION__);
-       spu->dma_callback(spu, SPE_EVENT_INVALID_DMA);
-       return 0;
+       return mmu_psize_defs[MMU_PAGE_64K].shift != 0;
 }
+EXPORT_SYMBOL_GPL(spu_64k_pages_available);
 
-static int __spu_trap_dma_align(struct spu *spu)
+static void spu_restart_dma(struct spu *spu)
 {
-       pr_debug("%s\n", __FUNCTION__);
-       spu->dma_callback(spu, SPE_EVENT_DMA_ALIGNMENT);
-       return 0;
-}
+       struct spu_priv2 __iomem *priv2 = spu->priv2;
 
-static int __spu_trap_error(struct spu *spu)
-{
-       pr_debug("%s\n", __FUNCTION__);
-       spu->dma_callback(spu, SPE_EVENT_SPE_ERROR);
-       return 0;
+       if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags))
+               out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
 }
 
-static void spu_restart_dma(struct spu *spu)
+static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
 {
        struct spu_priv2 __iomem *priv2 = spu->priv2;
 
-       if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags))
-               out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
+       pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
+                       __func__, slbe, slb->vsid, slb->esid);
+
+       out_be64(&priv2->slb_index_W, slbe);
+       out_be64(&priv2->slb_vsid_RW, slb->vsid);
+       out_be64(&priv2->slb_esid_RW, slb->esid);
 }
 
 static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 {
-       struct spu_priv2 __iomem *priv2 = spu->priv2;
        struct mm_struct *mm = spu->mm;
-       u64 esid, vsid, llp;
+       struct spu_slb slb;
        int psize;
 
        pr_debug("%s\n", __FUNCTION__);
@@ -159,7 +167,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
                printk("%s: invalid access during switch!\n", __func__);
                return 1;
        }
-       esid = (ea & ESID_MASK) | SLB_ESID_V;
+       slb.esid = (ea & ESID_MASK) | SLB_ESID_V;
 
        switch(REGION_ID(ea)) {
        case USER_REGION_ID:
@@ -168,21 +176,21 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 #else
                psize = mm->context.user_psize;
 #endif
-               vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-                               SLB_VSID_USER;
+               slb.vsid = (get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M)
+                               << SLB_VSID_SHIFT) | SLB_VSID_USER;
                break;
        case VMALLOC_REGION_ID:
                if (ea < VMALLOC_END)
                        psize = mmu_vmalloc_psize;
                else
                        psize = mmu_io_psize;
-               vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-                       SLB_VSID_KERNEL;
+               slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+                               << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
                break;
        case KERNEL_REGION_ID:
                psize = mmu_linear_psize;
-               vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-                       SLB_VSID_KERNEL;
+               slb.vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M)
+                               << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
                break;
        default:
                /* Future: support kernel segments so that drivers
@@ -191,11 +199,9 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
                pr_debug("invalid region access at %016lx\n", ea);
                return 1;
        }
-       llp = mmu_psize_defs[psize].sllp;
+       slb.vsid |= mmu_psize_defs[psize].sllp;
 
-       out_be64(&priv2->slb_index_W, spu->slb_replace);
-       out_be64(&priv2->slb_vsid_RW, vsid | llp);
-       out_be64(&priv2->slb_esid_RW, esid);
+       spu_load_slb(spu, spu->slb_replace, &slb);
 
        spu->slb_replace++;
        if (spu->slb_replace >= 8)
@@ -225,13 +231,83 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
                return 1;
        }
 
+       spu->class_0_pending = 0;
        spu->dar = ea;
        spu->dsisr = dsisr;
-       mb();
+
        spu->stop_callback(spu);
+
+       return 0;
+}
+
+static void __spu_kernel_slb(void *addr, struct spu_slb *slb)
+{
+       unsigned long ea = (unsigned long)addr;
+       u64 llp;
+
+       if (REGION_ID(ea) == KERNEL_REGION_ID)
+               llp = mmu_psize_defs[mmu_linear_psize].sllp;
+       else
+               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+
+       slb->vsid = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
+               SLB_VSID_KERNEL | llp;
+       slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
+}
+
+/**
+ * Given an array of @nr_slbs SLB entries, @slbs, return non-zero if the
+ * address @new_addr is present.
+ */
+static inline int __slb_present(struct spu_slb *slbs, int nr_slbs,
+               void *new_addr)
+{
+       unsigned long ea = (unsigned long)new_addr;
+       int i;
+
+       for (i = 0; i < nr_slbs; i++)
+               if (!((slbs[i].esid ^ ea) & ESID_MASK))
+                       return 1;
+
        return 0;
 }
 
+/**
+ * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
+ * need to map both the context save area, and the save/restore code.
+ *
+ * Because the lscsa and code may cross segment boundaires, we check to see
+ * if mappings are required for the start and end of each range. We currently
+ * assume that the mappings are smaller that one segment - if not, something
+ * is seriously wrong.
+ */
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+               void *code, int code_size)
+{
+       struct spu_slb slbs[4];
+       int i, nr_slbs = 0;
+       /* start and end addresses of both mappings */
+       void *addrs[] = {
+               lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
+               code, code + code_size - 1
+       };
+
+       /* check the set of addresses, and create a new entry in the slbs array
+        * if there isn't already a SLB for that address */
+       for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+               if (__slb_present(slbs, nr_slbs, addrs[i]))
+                       continue;
+
+               __spu_kernel_slb(addrs[i], &slbs[nr_slbs]);
+               nr_slbs++;
+       }
+
+       /* Add the set of SLBs */
+       for (i = 0; i < nr_slbs; i++)
+               spu_load_slb(spu, i, &slbs[i]);
+}
+EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
+
 static irqreturn_t
 spu_irq_class_0(int irq, void *data)
 {
@@ -240,12 +316,13 @@ spu_irq_class_0(int irq, void *data)
 
        spu = data;
 
+       spin_lock(&spu->register_lock);
        mask = spu_int_mask_get(spu, 0);
-       stat = spu_int_stat_get(spu, 0);
-       stat &= mask;
+       stat = spu_int_stat_get(spu, 0) & mask;
 
-       spin_lock(&spu->register_lock);
        spu->class_0_pending |= stat;
+       spu->dsisr = spu_mfc_dsisr_get(spu);
+       spu->dar = spu_mfc_dar_get(spu);
        spin_unlock(&spu->register_lock);
 
        spu->stop_callback(spu);
@@ -255,31 +332,6 @@ spu_irq_class_0(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-int
-spu_irq_class_0_bottom(struct spu *spu)
-{
-       unsigned long flags;
-       unsigned long stat;
-
-       spin_lock_irqsave(&spu->register_lock, flags);
-       stat = spu->class_0_pending;
-       spu->class_0_pending = 0;
-
-       if (stat & 1) /* invalid DMA alignment */
-               __spu_trap_dma_align(spu);
-
-       if (stat & 2) /* invalid MFC DMA */
-               __spu_trap_invalid_dma(spu);
-
-       if (stat & 4) /* error on SPU */
-               __spu_trap_error(spu);
-
-       spin_unlock_irqrestore(&spu->register_lock, flags);
-
-       return (stat & 0x7) ? -EIO : 0;
-}
-EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
-
 static irqreturn_t
 spu_irq_class_1(int irq, void *data)
 {
@@ -294,24 +346,23 @@ spu_irq_class_1(int irq, void *data)
        stat  = spu_int_stat_get(spu, 1) & mask;
        dar   = spu_mfc_dar_get(spu);
        dsisr = spu_mfc_dsisr_get(spu);
-       if (stat & 2) /* mapping fault */
+       if (stat & CLASS1_STORAGE_FAULT_INTR)
                spu_mfc_dsisr_set(spu, 0ul);
        spu_int_stat_clear(spu, 1, stat);
        spin_unlock(&spu->register_lock);
        pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat,
                        dar, dsisr);
 
-       if (stat & 1) /* segment fault */
+       if (stat & CLASS1_SEGMENT_FAULT_INTR)
                __spu_trap_data_seg(spu, dar);
 
-       if (stat & 2) { /* mapping fault */
+       if (stat & CLASS1_STORAGE_FAULT_INTR)
                __spu_trap_data_map(spu, dar, dsisr);
-       }
 
-       if (stat & 4) /* ls compare & suspend on get */
+       if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR)
                ;
 
-       if (stat & 8) /* ls compare & suspend on put */
+       if (stat & CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR)
                ;
 
        return stat ? IRQ_HANDLED : IRQ_NONE;
@@ -323,6 +374,8 @@ spu_irq_class_2(int irq, void *data)
        struct spu *spu;
        unsigned long stat;
        unsigned long mask;
+       const int mailbox_intrs =
+               CLASS2_MAILBOX_THRESHOLD_INTR | CLASS2_MAILBOX_INTR;
 
        spu = data;
        spin_lock(&spu->register_lock);
@@ -330,31 +383,30 @@ spu_irq_class_2(int irq, void *data)
        mask = spu_int_mask_get(spu, 2);
        /* ignore interrupts we're not waiting for */
        stat &= mask;
-       /*
-        * mailbox interrupts (0x1 and 0x10) are level triggered.
-        * mask them now before acknowledging.
-        */
-       if (stat & 0x11)
-               spu_int_mask_and(spu, 2, ~(stat & 0x11));
+
+       /* mailbox interrupts are level triggered. mask them now before
+        * acknowledging */
+       if (stat & mailbox_intrs)
+               spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs));
        /* acknowledge all interrupts before the callbacks */
        spu_int_stat_clear(spu, 2, stat);
        spin_unlock(&spu->register_lock);
 
        pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
 
-       if (stat & 1)  /* PPC core mailbox */
+       if (stat & CLASS2_MAILBOX_INTR)
                spu->ibox_callback(spu);
 
-       if (stat & 2) /* SPU stop-and-signal */
+       if (stat & CLASS2_SPU_STOP_INTR)
                spu->stop_callback(spu);
 
-       if (stat & 4) /* SPU halted */
+       if (stat & CLASS2_SPU_HALT_INTR)
                spu->stop_callback(spu);
 
-       if (stat & 8) /* DMA tag group complete */
+       if (stat & CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR)
                spu->mfc_callback(spu);
 
-       if (stat & 0x10) /* SPU mailbox threshold */
+       if (stat & CLASS2_MAILBOX_THRESHOLD_INTR)
                spu->wbox_callback(spu);
 
        spu->stats.class2_intr++;
@@ -479,13 +531,27 @@ EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
 int spu_add_sysdev_attr_group(struct attribute_group *attrs)
 {
        struct spu *spu;
+       int rc = 0;
 
        mutex_lock(&spu_full_list_mutex);
-       list_for_each_entry(spu, &spu_full_list, full_list)
-               sysfs_create_group(&spu->sysdev.kobj, attrs);
+       list_for_each_entry(spu, &spu_full_list, full_list) {
+               rc = sysfs_create_group(&spu->sysdev.kobj, attrs);
+
+               /* we're in trouble here, but try unwinding anyway */
+               if (rc) {
+                       printk(KERN_ERR "%s: can't create sysfs group '%s'\n",
+                                       __func__, attrs->name);
+
+                       list_for_each_entry_continue_reverse(spu,
+                                       &spu_full_list, full_list)
+                               sysfs_remove_group(&spu->sysdev.kobj, attrs);
+                       break;
+               }
+       }
+
        mutex_unlock(&spu_full_list_mutex);
 
-       return 0;
+       return rc;
 }
 EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
 
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c
new file mode 100644 (file)
index 0000000..c8b1cd4
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * SPU mm fault handler
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.com>
+ * Author: Jeremy Kerr <jk@ozlabs.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+
+/*
+ * This ought to be kept in sync with the powerpc specific do_page_fault
+ * function. Currently, there are a few corner cases that we haven't had
+ * to handle fortunately.
+ */
+int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+               unsigned long dsisr, unsigned *flt)
+{
+       struct vm_area_struct *vma;
+       unsigned long is_write;
+       int ret;
+
+#if 0
+       if (!IS_VALID_EA(ea)) {
+               return -EFAULT;
+       }
+#endif /* XXX */
+       if (mm == NULL) {
+               return -EFAULT;
+       }
+       if (mm->pgd == NULL) {
+               return -EFAULT;
+       }
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, ea);
+       if (!vma)
+               goto bad_area;
+       if (vma->vm_start <= ea)
+               goto good_area;
+       if (!(vma->vm_flags & VM_GROWSDOWN))
+               goto bad_area;
+       if (expand_stack(vma, ea))
+               goto bad_area;
+good_area:
+       is_write = dsisr & MFC_DSISR_ACCESS_PUT;
+       if (is_write) {
+               if (!(vma->vm_flags & VM_WRITE))
+                       goto bad_area;
+       } else {
+               if (dsisr & MFC_DSISR_ACCESS_DENIED)
+                       goto bad_area;
+               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                       goto bad_area;
+       }
+       ret = 0;
+       *flt = handle_mm_fault(mm, vma, ea, is_write);
+       if (unlikely(*flt & VM_FAULT_ERROR)) {
+               if (*flt & VM_FAULT_OOM) {
+                       ret = -ENOMEM;
+                       goto bad_area;
+               } else if (*flt & VM_FAULT_SIGBUS) {
+                       ret = -EFAULT;
+                       goto bad_area;
+               }
+               BUG();
+       }
+       if (*flt & VM_FAULT_MAJOR)
+               current->maj_flt++;
+       else
+               current->min_flt++;
+       up_read(&mm->mmap_sem);
+       return ret;
+
+bad_area:
+       up_read(&mm->mmap_sem);
+       return -EFAULT;
+}
+EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
index 1b010707488d5d913cd0da6eaf5d3f26a60c6eca..d351bdebf5f1e350c8144855b41c37e4545c6d83 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/firmware.h>
 #include <asm/prom.h>
 
+#include "spufs/spufs.h"
 #include "interrupt.h"
 
 struct device_node *spu_devnode(struct spu *spu)
@@ -345,7 +346,7 @@ static int __init of_create_spu(struct spu *spu, void *data)
                }
                ret = spu_map_interrupts_old(spu, spe);
                if (ret) {
-                       printk(KERN_ERR "%s: could not map interrupts",
+                       printk(KERN_ERR "%s: could not map interrupts\n",
                                spu->name);
                        goto out_unmap;
                }
@@ -369,6 +370,16 @@ static int of_destroy_spu(struct spu *spu)
        return 0;
 }
 
+static void enable_spu_by_master_run(struct spu_context *ctx)
+{
+       ctx->ops->master_start(ctx);
+}
+
+static void disable_spu_by_master_run(struct spu_context *ctx)
+{
+       ctx->ops->master_stop(ctx);
+}
+
 /* Hardcoded affinity idxs for qs20 */
 #define QS20_SPES_PER_BE 8
 static int qs20_reg_idxs[QS20_SPES_PER_BE] =   { 0, 2, 4, 6, 7, 5, 3, 1 };
@@ -411,10 +422,15 @@ static void init_affinity_qs20_harcoded(void)
 
 static int of_has_vicinity(void)
 {
-       struct spu* spu;
+       struct device_node *dn;
 
-       spu = list_first_entry(&cbe_spu_info[0].spus, struct spu, cbe_list);
-       return of_find_property(spu_devnode(spu), "vicinity", NULL) != NULL;
+       for_each_node_by_type(dn, "spe") {
+               if (of_find_property(dn, "vicinity", NULL))  {
+                       of_node_put(dn);
+                       return 1;
+               }
+       }
+       return 0;
 }
 
 static struct spu *devnode_spu(int cbe, struct device_node *dn)
@@ -525,7 +541,7 @@ static int __init init_affinity(void)
                if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
                        init_affinity_qs20_harcoded();
                else
-                       printk("No affinity configuration found");
+                       printk("No affinity configuration found\n");
        }
 
        return 0;
@@ -535,5 +551,7 @@ const struct spu_management_ops spu_management_of_ops = {
        .enumerate_spus = of_enumerate_spus,
        .create_spu = of_create_spu,
        .destroy_spu = of_destroy_spu,
+       .enable_spu = enable_spu_by_master_run,
+       .disable_spu = disable_spu_by_master_run,
        .init_affinity = init_affinity,
 };
index 328afcf895032e50a7f36b0a7f00a38d3ca7aade..d3a349fb42e58c9b2164a45a6bbb46d804aae72a 100644 (file)
@@ -1,8 +1,8 @@
-obj-y += switch.o fault.o lscsa_alloc.o
 
 obj-$(CONFIG_SPU_FS) += spufs.o
 spufs-y += inode.o file.o context.o syscalls.o coredump.o
 spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o
+spufs-y += switch.o fault.o lscsa_alloc.o
 
 # Rules to build switch.o with the help of SPU tool chain
 SPU_CROSS      := spu-
index ec01214e51ee9034062b97ffed7f16f34db9aee4..50d98a154aaf257ae58a75373c13281874dc40a2 100644 (file)
@@ -106,16 +106,20 @@ static unsigned int spu_backing_mbox_stat_poll(struct spu_context *ctx,
                if (stat & 0xff0000)
                        ret |= POLLIN | POLLRDNORM;
                else {
-                       ctx->csa.priv1.int_stat_class0_RW &= ~0x1;
-                       ctx->csa.priv1.int_mask_class2_RW |= 0x1;
+                       ctx->csa.priv1.int_stat_class2_RW &=
+                               ~CLASS2_MAILBOX_INTR;
+                       ctx->csa.priv1.int_mask_class2_RW |=
+                               CLASS2_ENABLE_MAILBOX_INTR;
                }
        }
        if (events & (POLLOUT | POLLWRNORM)) {
                if (stat & 0x00ff00)
                        ret = POLLOUT | POLLWRNORM;
                else {
-                       ctx->csa.priv1.int_stat_class0_RW &= ~0x10;
-                       ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+                       ctx->csa.priv1.int_stat_class2_RW &=
+                               ~CLASS2_MAILBOX_THRESHOLD_INTR;
+                       ctx->csa.priv1.int_mask_class2_RW |=
+                               CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
                }
        }
        spin_unlock_irq(&ctx->csa.register_lock);
@@ -139,7 +143,7 @@ static int spu_backing_ibox_read(struct spu_context *ctx, u32 * data)
                ret = 4;
        } else {
                /* make sure we get woken up by the interrupt */
-               ctx->csa.priv1.int_mask_class2_RW |= 0x1UL;
+               ctx->csa.priv1.int_mask_class2_RW |= CLASS2_ENABLE_MAILBOX_INTR;
                ret = 0;
        }
        spin_unlock(&ctx->csa.register_lock);
@@ -169,7 +173,8 @@ static int spu_backing_wbox_write(struct spu_context *ctx, u32 data)
        } else {
                /* make sure we get woken up by the interrupt when space
                   becomes available */
-               ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+               ctx->csa.priv1.int_mask_class2_RW |=
+                       CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR;
                ret = 0;
        }
        spin_unlock(&ctx->csa.register_lock);
@@ -268,6 +273,11 @@ static char *spu_backing_get_ls(struct spu_context *ctx)
        return ctx->csa.lscsa->ls;
 }
 
+static void spu_backing_privcntl_write(struct spu_context *ctx, u64 val)
+{
+       ctx->csa.priv2.spu_privcntl_RW = val;
+}
+
 static u32 spu_backing_runcntl_read(struct spu_context *ctx)
 {
        return ctx->csa.prob.spu_runcntl_RW;
@@ -285,6 +295,11 @@ static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
        spin_unlock(&ctx->csa.register_lock);
 }
 
+static void spu_backing_runcntl_stop(struct spu_context *ctx)
+{
+       spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
+}
+
 static void spu_backing_master_start(struct spu_context *ctx)
 {
        struct spu_state *csa = &ctx->csa;
@@ -358,7 +373,7 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx,
 
 static void spu_backing_restart_dma(struct spu_context *ctx)
 {
-       /* nothing to do here */
+       ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND;
 }
 
 struct spu_context_ops spu_backing_ops = {
@@ -379,8 +394,10 @@ struct spu_context_ops spu_backing_ops = {
        .npc_write = spu_backing_npc_write,
        .status_read = spu_backing_status_read,
        .get_ls = spu_backing_get_ls,
+       .privcntl_write = spu_backing_privcntl_write,
        .runcntl_read = spu_backing_runcntl_read,
        .runcntl_write = spu_backing_runcntl_write,
+       .runcntl_stop = spu_backing_runcntl_stop,
        .master_start = spu_backing_master_start,
        .master_stop = spu_backing_master_stop,
        .set_mfc_query = spu_backing_set_mfc_query,
index 9cb081c26e7120f5ca84c8ecb2e7ff7ae7814df4..237e152d31dc9d3e7e5793dc267414412a0e78da 100644 (file)
@@ -52,6 +52,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
        init_waitqueue_head(&ctx->wbox_wq);
        init_waitqueue_head(&ctx->stop_wq);
        init_waitqueue_head(&ctx->mfc_wq);
+       init_waitqueue_head(&ctx->run_wq);
        ctx->state = SPU_STATE_SAVED;
        ctx->ops = &spu_backing_ops;
        ctx->owner = get_task_mm(current);
@@ -105,7 +106,17 @@ int put_spu_context(struct spu_context *ctx)
 void spu_forget(struct spu_context *ctx)
 {
        struct mm_struct *mm;
-       spu_acquire_saved(ctx);
+
+       /*
+        * This is basically an open-coded spu_acquire_saved, except that
+        * we don't acquire the state mutex interruptible.
+        */
+       mutex_lock(&ctx->state_mutex);
+       if (ctx->state != SPU_STATE_SAVED) {
+               set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
+               spu_deactivate(ctx);
+       }
+
        mm = ctx->owner;
        ctx->owner = NULL;
        mmput(mm);
@@ -133,47 +144,23 @@ void spu_unmap_mappings(struct spu_context *ctx)
 }
 
 /**
- * spu_acquire_runnable - lock spu contex and make sure it is in runnable state
+ * spu_acquire_saved - lock spu contex and make sure it is in saved state
  * @ctx:       spu contex to lock
- *
- * Note:
- *     Returns 0 and with the context locked on success
- *     Returns negative error and with the context _unlocked_ on failure.
  */
-int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags)
+int spu_acquire_saved(struct spu_context *ctx)
 {
-       int ret = -EINVAL;
-
-       spu_acquire(ctx);
-       if (ctx->state == SPU_STATE_SAVED) {
-               /*
-                * Context is about to be freed, so we can't acquire it anymore.
-                */
-               if (!ctx->owner)
-                       goto out_unlock;
-               ret = spu_activate(ctx, flags);
-               if (ret)
-                       goto out_unlock;
-       }
+       int ret;
 
-       return 0;
-
- out_unlock:
-       spu_release(ctx);
-       return ret;
-}
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 
-/**
- * spu_acquire_saved - lock spu contex and make sure it is in saved state
- * @ctx:       spu contex to lock
- */
-void spu_acquire_saved(struct spu_context *ctx)
-{
-       spu_acquire(ctx);
        if (ctx->state != SPU_STATE_SAVED) {
                set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
                spu_deactivate(ctx);
        }
+
+       return 0;
 }
 
 /**
index 80f62363e1ce1708c19662fa003bebc9b5459a72..0c6a96b82b2db9d22bfcd49c0e5df08a182e15f4 100644 (file)
@@ -148,7 +148,9 @@ int spufs_coredump_extra_notes_size(void)
 
        fd = 0;
        while ((ctx = coredump_next_context(&fd)) != NULL) {
-               spu_acquire_saved(ctx);
+               rc = spu_acquire_saved(ctx);
+               if (rc)
+                       break;
                rc = spufs_ctx_note_size(ctx, fd);
                spu_release_saved(ctx);
                if (rc < 0)
@@ -224,7 +226,9 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
 
        fd = 0;
        while ((ctx = coredump_next_context(&fd)) != NULL) {
-               spu_acquire_saved(ctx);
+               rc = spu_acquire_saved(ctx);
+               if (rc)
+                       return rc;
 
                for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
                        rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
index 917eab4be486d40ce8f4aa105d84c3325cb2e55f..eff4d291ba855de23099b9ed36ee2183f892f7d6 100644 (file)
 
 #include "spufs.h"
 
-/*
- * This ought to be kept in sync with the powerpc specific do_page_fault
- * function. Currently, there are a few corner cases that we haven't had
- * to handle fortunately.
+/**
+ * Handle an SPE event, depending on context SPU_CREATE_EVENTS_ENABLED flag.
+ *
+ * If the context was created with events, we just set the return event.
+ * Otherwise, send an appropriate signal to the process.
  */
-static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
-               unsigned long dsisr, unsigned *flt)
+static void spufs_handle_event(struct spu_context *ctx,
+                               unsigned long ea, int type)
 {
-       struct vm_area_struct *vma;
-       unsigned long is_write;
-       int ret;
+       siginfo_t info;
 
-#if 0
-       if (!IS_VALID_EA(ea)) {
-               return -EFAULT;
-       }
-#endif /* XXX */
-       if (mm == NULL) {
-               return -EFAULT;
-       }
-       if (mm->pgd == NULL) {
-               return -EFAULT;
+       if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
+               ctx->event_return |= type;
+               wake_up_all(&ctx->stop_wq);
+               return;
        }
 
-       down_read(&mm->mmap_sem);
-       vma = find_vma(mm, ea);
-       if (!vma)
-               goto bad_area;
-       if (vma->vm_start <= ea)
-               goto good_area;
-       if (!(vma->vm_flags & VM_GROWSDOWN))
-               goto bad_area;
-       if (expand_stack(vma, ea))
-               goto bad_area;
-good_area:
-       is_write = dsisr & MFC_DSISR_ACCESS_PUT;
-       if (is_write) {
-               if (!(vma->vm_flags & VM_WRITE))
-                       goto bad_area;
-       } else {
-               if (dsisr & MFC_DSISR_ACCESS_DENIED)
-                       goto bad_area;
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-                       goto bad_area;
+       memset(&info, 0, sizeof(info));
+
+       switch (type) {
+       case SPE_EVENT_INVALID_DMA:
+               info.si_signo = SIGBUS;
+               info.si_code = BUS_OBJERR;
+               break;
+       case SPE_EVENT_SPE_DATA_STORAGE:
+               info.si_signo = SIGSEGV;
+               info.si_addr = (void __user *)ea;
+               info.si_code = SEGV_ACCERR;
+               ctx->ops->restart_dma(ctx);
+               break;
+       case SPE_EVENT_DMA_ALIGNMENT:
+               info.si_signo = SIGBUS;
+               /* DAR isn't set for an alignment fault :( */
+               info.si_code = BUS_ADRALN;
+               break;
+       case SPE_EVENT_SPE_ERROR:
+               info.si_signo = SIGILL;
+               info.si_addr = (void __user *)(unsigned long)
+                       ctx->ops->npc_read(ctx) - 4;
+               info.si_code = ILL_ILLOPC;
+               break;
        }
-       ret = 0;
-       *flt = handle_mm_fault(mm, vma, ea, is_write);
-       if (unlikely(*flt & VM_FAULT_ERROR)) {
-               if (*flt & VM_FAULT_OOM) {
-                       ret = -ENOMEM;
-                       goto bad_area;
-               } else if (*flt & VM_FAULT_SIGBUS) {
-                       ret = -EFAULT;
-                       goto bad_area;
-               }
-               BUG();
-       }
-       if (*flt & VM_FAULT_MAJOR)
-               current->maj_flt++;
-       else
-               current->min_flt++;
-       up_read(&mm->mmap_sem);
-       return ret;
 
-bad_area:
-       up_read(&mm->mmap_sem);
-       return -EFAULT;
+       if (info.si_signo)
+               force_sig_info(info.si_signo, &info, current);
 }
 
-static void spufs_handle_dma_error(struct spu_context *ctx,
-                               unsigned long ea, int type)
+int spufs_handle_class0(struct spu_context *ctx)
 {
-       if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) {
-               ctx->event_return |= type;
-               wake_up_all(&ctx->stop_wq);
-       } else {
-               siginfo_t info;
-               memset(&info, 0, sizeof(info));
-
-               switch (type) {
-               case SPE_EVENT_INVALID_DMA:
-                       info.si_signo = SIGBUS;
-                       info.si_code = BUS_OBJERR;
-                       break;
-               case SPE_EVENT_SPE_DATA_STORAGE:
-                       info.si_signo = SIGBUS;
-                       info.si_addr = (void __user *)ea;
-                       info.si_code = BUS_ADRERR;
-                       break;
-               case SPE_EVENT_DMA_ALIGNMENT:
-                       info.si_signo = SIGBUS;
-                       /* DAR isn't set for an alignment fault :( */
-                       info.si_code = BUS_ADRALN;
-                       break;
-               case SPE_EVENT_SPE_ERROR:
-                       info.si_signo = SIGILL;
-                       info.si_addr = (void __user *)(unsigned long)
-                               ctx->ops->npc_read(ctx) - 4;
-                       info.si_code = ILL_ILLOPC;
-                       break;
-               }
-               if (info.si_signo)
-                       force_sig_info(info.si_signo, &info, current);
-       }
-}
+       unsigned long stat = ctx->csa.class_0_pending & CLASS0_INTR_MASK;
 
-void spufs_dma_callback(struct spu *spu, int type)
-{
-       spufs_handle_dma_error(spu->ctx, spu->dar, type);
+       if (likely(!stat))
+               return 0;
+
+       if (stat & CLASS0_DMA_ALIGNMENT_INTR)
+               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_DMA_ALIGNMENT);
+
+       if (stat & CLASS0_INVALID_DMA_COMMAND_INTR)
+               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_INVALID_DMA);
+
+       if (stat & CLASS0_SPU_ERROR_INTR)
+               spufs_handle_event(ctx, ctx->csa.dar, SPE_EVENT_SPE_ERROR);
+
+       return -EIO;
 }
-EXPORT_SYMBOL_GPL(spufs_dma_callback);
 
 /*
  * bottom half handler for page faults, we can't do this from
@@ -154,7 +108,7 @@ int spufs_handle_class1(struct spu_context *ctx)
        u64 ea, dsisr, access;
        unsigned long flags;
        unsigned flt = 0;
-       int ret;
+       int ret, ret2;
 
        /*
         * dar and dsisr get passed from the registers
@@ -165,16 +119,8 @@ int spufs_handle_class1(struct spu_context *ctx)
         * in time, we can still expect to get the same fault
         * the immediately after the context restore.
         */
-       if (ctx->state == SPU_STATE_RUNNABLE) {
-               ea = ctx->spu->dar;
-               dsisr = ctx->spu->dsisr;
-               ctx->spu->dar= ctx->spu->dsisr = 0;
-       } else {
-               ea = ctx->csa.priv1.mfc_dar_RW;
-               dsisr = ctx->csa.priv1.mfc_dsisr_RW;
-               ctx->csa.priv1.mfc_dar_RW = 0;
-               ctx->csa.priv1.mfc_dsisr_RW = 0;
-       }
+       ea = ctx->csa.dar;
+       dsisr = ctx->csa.dsisr;
 
        if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
                return 0;
@@ -201,7 +147,22 @@ int spufs_handle_class1(struct spu_context *ctx)
        if (ret)
                ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
-       spu_acquire(ctx);
+       /*
+        * If spu_acquire fails due to a pending signal we just want to return
+        * EINTR to userspace even if that means missing the dma restart or
+        * updating the page fault statistics.
+        */
+       ret2 = spu_acquire(ctx);
+       if (ret2)
+               goto out;
+
+       /*
+        * Clear dsisr under ctxt lock after handling the fault, so that
+        * time slicing will not preempt the context while the page fault
+        * handler is running. Context switch code removes mappings.
+        */
+       ctx->csa.dar = ctx->csa.dsisr = 0;
+
        /*
         * If we handled the fault successfully and are in runnable
         * state, restart the DMA.
@@ -222,9 +183,9 @@ int spufs_handle_class1(struct spu_context *ctx)
                if (ctx->spu)
                        ctx->ops->restart_dma(ctx);
        } else
-               spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
+               spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+ out:
        spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
        return ret;
 }
-EXPORT_SYMBOL_GPL(spufs_handle_class1);
index d9e56a503795246ee9f4848a23224a27635a2577..3fcd06418b01d165ba1d01f7d9930608d6d15c6d 100644 (file)
 
 #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000)
 
+/* Simple attribute files */
+struct spufs_attr {
+       int (*get)(void *, u64 *);
+       int (*set)(void *, u64);
+       char get_buf[24];       /* enough to store a u64 and "\n\0" */
+       char set_buf[24];
+       void *data;
+       const char *fmt;        /* format for read operation */
+       struct mutex mutex;     /* protects access to these buffers */
+};
+
+static int spufs_attr_open(struct inode *inode, struct file *file,
+               int (*get)(void *, u64 *), int (*set)(void *, u64),
+               const char *fmt)
+{
+       struct spufs_attr *attr;
+
+       attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+       if (!attr)
+               return -ENOMEM;
+
+       attr->get = get;
+       attr->set = set;
+       attr->data = inode->i_private;
+       attr->fmt = fmt;
+       mutex_init(&attr->mutex);
+       file->private_data = attr;
+
+       return nonseekable_open(inode, file);
+}
+
+static int spufs_attr_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static ssize_t spufs_attr_read(struct file *file, char __user *buf,
+               size_t len, loff_t *ppos)
+{
+       struct spufs_attr *attr;
+       size_t size;
+       ssize_t ret;
+
+       attr = file->private_data;
+       if (!attr->get)
+               return -EACCES;
+
+       ret = mutex_lock_interruptible(&attr->mutex);
+       if (ret)
+               return ret;
+
+       if (*ppos) {            /* continued read */
+               size = strlen(attr->get_buf);
+       } else {                /* first read */
+               u64 val;
+               ret = attr->get(attr->data, &val);
+               if (ret)
+                       goto out;
+
+               size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+                                attr->fmt, (unsigned long long)val);
+       }
+
+       ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+out:
+       mutex_unlock(&attr->mutex);
+       return ret;
+}
+
+static ssize_t spufs_attr_write(struct file *file, const char __user *buf,
+               size_t len, loff_t *ppos)
+{
+       struct spufs_attr *attr;
+       u64 val;
+       size_t size;
+       ssize_t ret;
+
+       attr = file->private_data;
+       if (!attr->set)
+               return -EACCES;
+
+       ret = mutex_lock_interruptible(&attr->mutex);
+       if (ret)
+               return ret;
+
+       ret = -EFAULT;
+       size = min(sizeof(attr->set_buf) - 1, len);
+       if (copy_from_user(attr->set_buf, buf, size))
+               goto out;
+
+       ret = len; /* claim we got the whole input */
+       attr->set_buf[size] = '\0';
+       val = simple_strtol(attr->set_buf, NULL, 0);
+       attr->set(attr->data, val);
+out:
+       mutex_unlock(&attr->mutex);
+       return ret;
+}
+
+#define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)     \
+static int __fops ## _open(struct inode *inode, struct file *file)     \
+{                                                                      \
+       __simple_attr_check_format(__fmt, 0ull);                        \
+       return spufs_attr_open(inode, file, __get, __set, __fmt);       \
+}                                                                      \
+static struct file_operations __fops = {                               \
+       .owner   = THIS_MODULE,                                         \
+       .open    = __fops ## _open,                                     \
+       .release = spufs_attr_release,                                  \
+       .read    = spufs_attr_read,                                     \
+       .write   = spufs_attr_write,                                    \
+};
+
 
 static int
 spufs_mem_open(struct inode *inode, struct file *file)
@@ -84,9 +198,12 @@ spufs_mem_read(struct file *file, char __user *buffer,
        struct spu_context *ctx = file->private_data;
        ssize_t ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_mem_read(ctx, buffer, size, pos);
        spu_release(ctx);
+
        return ret;
 }
 
@@ -106,7 +223,10 @@ spufs_mem_write(struct file *file, const char __user *buffer,
        if (size > LS_SIZE - pos)
                size = LS_SIZE - pos;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+
        local_store = ctx->ops->get_ls(ctx);
        ret = copy_from_user(local_store + pos, buffer, size);
        spu_release(ctx);
@@ -146,7 +266,8 @@ static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
        pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n",
                 addr0, address, offset);
 
-       spu_acquire(ctx);
+       if (spu_acquire(ctx))
+               return NOPFN_REFAULT;
 
        if (ctx->state == SPU_STATE_SAVED) {
                vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
@@ -236,23 +357,32 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
 {
        struct spu_context *ctx = vma->vm_file->private_data;
        unsigned long area, offset = address - vma->vm_start;
-       int ret;
 
        offset += vma->vm_pgoff << PAGE_SHIFT;
        if (offset >= ps_size)
                return NOPFN_SIGBUS;
 
-       /* error here usually means a signal.. we might want to test
-        * the error code more precisely though
+       /*
+        * We have to wait for context to be loaded before we have
+        * pages to hand out to the user, but we don't want to wait
+        * with the mmap_sem held.
+        * It is possible to drop the mmap_sem here, but then we need
+        * to return NOPFN_REFAULT because the mappings may have
+        * hanged.
         */
-       ret = spu_acquire_runnable(ctx, 0);
-       if (ret)
+       if (spu_acquire(ctx))
                return NOPFN_REFAULT;
 
-       area = ctx->spu->problem_phys + ps_offs;
-       vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
-       spu_release(ctx);
+       if (ctx->state == SPU_STATE_SAVED) {
+               up_read(&current->mm->mmap_sem);
+               spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
+               down_read(&current->mm->mmap_sem);
+       } else {
+               area = ctx->spu->problem_phys + ps_offs;
+               vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
+       }
 
+       spu_release(ctx);
        return NOPFN_REFAULT;
 }
 
@@ -286,25 +416,32 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
 #define spufs_cntl_mmap NULL
 #endif /* !SPUFS_MMAP_4K */
 
-static u64 spufs_cntl_get(void *data)
+static int spufs_cntl_get(void *data, u64 *val)
 {
        struct spu_context *ctx = data;
-       u64 val;
+       int ret;
 
-       spu_acquire(ctx);
-       val = ctx->ops->status_read(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+       *val = ctx->ops->status_read(ctx);
        spu_release(ctx);
 
-       return val;
+       return 0;
 }
 
-static void spufs_cntl_set(void *data, u64 val)
+static int spufs_cntl_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->runcntl_write(ctx, val);
        spu_release(ctx);
+
+       return 0;
 }
 
 static int spufs_cntl_open(struct inode *inode, struct file *file)
@@ -317,7 +454,7 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
        if (!i->i_openers++)
                ctx->cntl = inode->i_mapping;
        mutex_unlock(&ctx->mapping_lock);
-       return simple_attr_open(inode, file, spufs_cntl_get,
+       return spufs_attr_open(inode, file, spufs_cntl_get,
                                        spufs_cntl_set, "0x%08lx");
 }
 
@@ -327,7 +464,7 @@ spufs_cntl_release(struct inode *inode, struct file *file)
        struct spufs_inode_info *i = SPUFS_I(inode);
        struct spu_context *ctx = i->i_ctx;
 
-       simple_attr_close(inode, file);
+       spufs_attr_release(inode, file);
 
        mutex_lock(&ctx->mapping_lock);
        if (!--i->i_openers)
@@ -339,8 +476,8 @@ spufs_cntl_release(struct inode *inode, struct file *file)
 static const struct file_operations spufs_cntl_fops = {
        .open = spufs_cntl_open,
        .release = spufs_cntl_release,
-       .read = simple_attr_read,
-       .write = simple_attr_write,
+       .read = spufs_attr_read,
+       .write = spufs_attr_write,
        .mmap = spufs_cntl_mmap,
 };
 
@@ -368,7 +505,9 @@ spufs_regs_read(struct file *file, char __user *buffer,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_regs_read(ctx, buffer, size, pos);
        spu_release_saved(ctx);
        return ret;
@@ -387,7 +526,9 @@ spufs_regs_write(struct file *file, const char __user *buffer,
                return -EFBIG;
        *pos += size;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
 
        ret = copy_from_user(lscsa->gprs + *pos - size,
                             buffer, size) ? -EFAULT : size;
@@ -419,7 +560,9 @@ spufs_fpcr_read(struct file *file, char __user * buffer,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_fpcr_read(ctx, buffer, size, pos);
        spu_release_saved(ctx);
        return ret;
@@ -436,10 +579,12 @@ spufs_fpcr_write(struct file *file, const char __user * buffer,
        size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
        if (size <= 0)
                return -EFBIG;
-       *pos += size;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
 
+       *pos += size;
        ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
                             buffer, size) ? -EFAULT : size;
 
@@ -486,7 +631,10 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
 
        udata = (void __user *)buf;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
+
        for (count = 0; (count + 4) <= len; count += 4, udata++) {
                int ret;
                ret = ctx->ops->mbox_read(ctx, &mbox_data);
@@ -522,12 +670,15 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 mbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 
        mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
 
@@ -562,6 +713,9 @@ void spufs_ibox_callback(struct spu *spu)
 {
        struct spu_context *ctx = spu->ctx;
 
+       if (!ctx)
+               return;
+
        wake_up_all(&ctx->ibox_wq);
        kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
 }
@@ -593,7 +747,9 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
 
        udata = (void __user *)buf;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
 
        /* wait only for the first element */
        count = 0;
@@ -639,7 +795,11 @@ static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &ctx->ibox_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
        spu_release(ctx);
 
@@ -657,12 +817,15 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 ibox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
        spu_release(ctx);
 
@@ -698,6 +861,9 @@ void spufs_wbox_callback(struct spu *spu)
 {
        struct spu_context *ctx = spu->ctx;
 
+       if (!ctx)
+               return;
+
        wake_up_all(&ctx->wbox_wq);
        kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
 }
@@ -731,7 +897,9 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
        if (__get_user(wbox_data, udata))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
 
        /*
         * make sure we can at least write one element, by waiting
@@ -772,7 +940,11 @@ static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &ctx->wbox_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
        spu_release(ctx);
 
@@ -790,12 +962,15 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 wbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
        spu_release(ctx);
 
@@ -866,7 +1041,9 @@ static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_signal1_read(ctx, buf, len, pos);
        spu_release_saved(ctx);
 
@@ -877,6 +1054,7 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
+       ssize_t ret;
        u32 data;
 
        ctx = file->private_data;
@@ -887,7 +1065,9 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal1_write(ctx, data);
        spu_release(ctx);
 
@@ -997,7 +1177,9 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_signal2_read(ctx, buf, len, pos);
        spu_release_saved(ctx);
 
@@ -1008,6 +1190,7 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
+       ssize_t ret;
        u32 data;
 
        ctx = file->private_data;
@@ -1018,7 +1201,9 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal2_write(ctx, data);
        spu_release(ctx);
 
@@ -1086,33 +1271,42 @@ static const struct file_operations spufs_signal2_nosched_fops = {
 #define SPU_ATTR_ACQUIRE_SAVED 2
 
 #define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \
-static u64 __##__get(void *data)                                       \
+static int __##__get(void *data, u64 *val)                             \
 {                                                                      \
        struct spu_context *ctx = data;                                 \
-       u64 ret;                                                        \
+       int ret = 0;                                                    \
                                                                        \
        if (__acquire == SPU_ATTR_ACQUIRE) {                            \
-               spu_acquire(ctx);                                       \
-               ret = __get(ctx);                                       \
+               ret = spu_acquire(ctx);                                 \
+               if (ret)                                                \
+                       return ret;                                     \
+               *val = __get(ctx);                                      \
                spu_release(ctx);                                       \
        } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) {               \
-               spu_acquire_saved(ctx);                                 \
-               ret = __get(ctx);                                       \
+               ret = spu_acquire_saved(ctx);                           \
+               if (ret)                                                \
+                       return ret;                                     \
+               *val = __get(ctx);                                      \
                spu_release_saved(ctx);                                 \
        } else                                                          \
-               ret = __get(ctx);                                       \
+               *val = __get(ctx);                                      \
                                                                        \
-       return ret;                                                     \
+       return 0;                                                       \
 }                                                                      \
-DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
+DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
 
-static void spufs_signal1_type_set(void *data, u64 val)
+static int spufs_signal1_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal1_type_set(ctx, val);
        spu_release(ctx);
+
+       return 0;
 }
 
 static u64 spufs_signal1_type_get(struct spu_context *ctx)
@@ -1123,13 +1317,18 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
                       spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
 
 
-static void spufs_signal2_type_set(void *data, u64 val)
+static int spufs_signal2_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal2_type_set(ctx, val);
        spu_release(ctx);
+
+       return 0;
 }
 
 static u64 spufs_signal2_type_get(struct spu_context *ctx)
@@ -1329,6 +1528,9 @@ void spufs_mfc_callback(struct spu *spu)
 {
        struct spu_context *ctx = spu->ctx;
 
+       if (!ctx)
+               return;
+
        wake_up_all(&ctx->mfc_wq);
 
        pr_debug("%s %s\n", __FUNCTION__, spu->name);
@@ -1375,12 +1577,17 @@ static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
        if (size != 4)
                goto out;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+
+       ret = -EINVAL;
        if (file->f_flags & O_NONBLOCK) {
                status = ctx->ops->read_mfc_tagstatus(ctx);
                if (!(status & ctx->tagwait))
                        ret = -EAGAIN;
                else
+                       /* XXX(hch): shouldn't we clear ret here? */
                        ctx->tagwait &= ~status;
        } else {
                ret = spufs_wait(ctx->mfc_wq,
@@ -1505,7 +1712,11 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
        if (ret)
                goto out;
 
-       ret = spu_acquire_runnable(ctx, 0);
+       ret = spu_acquire(ctx);
+       if (ret)
+               goto out;
+
+       ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
        if (ret)
                goto out;
 
@@ -1539,7 +1750,11 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
 
        poll_wait(file, &ctx->mfc_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
        free_elements = ctx->ops->get_mfc_free_elements(ctx);
        tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
@@ -1562,7 +1777,9 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 #if 0
 /* this currently hangs */
        ret = spufs_wait(ctx->mfc_wq,
@@ -1605,12 +1822,18 @@ static const struct file_operations spufs_mfc_fops = {
        .mmap    = spufs_mfc_mmap,
 };
 
-static void spufs_npc_set(void *data, u64 val)
+static int spufs_npc_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       spu_acquire(ctx);
+       int ret;
+
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->npc_write(ctx, val);
        spu_release(ctx);
+
+       return 0;
 }
 
 static u64 spufs_npc_get(struct spu_context *ctx)
@@ -1620,13 +1843,19 @@ static u64 spufs_npc_get(struct spu_context *ctx)
 DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
                       "0x%llx\n", SPU_ATTR_ACQUIRE);
 
-static void spufs_decr_set(void *data, u64 val)
+static int spufs_decr_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->decr.slot[0] = (u32) val;
        spu_release_saved(ctx);
+
+       return 0;
 }
 
 static u64 spufs_decr_get(struct spu_context *ctx)
@@ -1637,15 +1866,21 @@ static u64 spufs_decr_get(struct spu_context *ctx)
 DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
                       "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
 
-static void spufs_decr_status_set(void *data, u64 val)
+static int spufs_decr_status_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        if (val)
                ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING;
        else
                ctx->csa.priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
        spu_release_saved(ctx);
+
+       return 0;
 }
 
 static u64 spufs_decr_status_get(struct spu_context *ctx)
@@ -1659,13 +1894,19 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
                       spufs_decr_status_set, "0x%llx\n",
                       SPU_ATTR_ACQUIRE_SAVED);
 
-static void spufs_event_mask_set(void *data, u64 val)
+static int spufs_event_mask_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->event_mask.slot[0] = (u32) val;
        spu_release_saved(ctx);
+
+       return 0;
 }
 
 static u64 spufs_event_mask_get(struct spu_context *ctx)
@@ -1690,13 +1931,19 @@ static u64 spufs_event_status_get(struct spu_context *ctx)
 DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
                       NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
 
-static void spufs_srr0_set(void *data, u64 val)
+static int spufs_srr0_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->srr0.slot[0] = (u32) val;
        spu_release_saved(ctx);
+
+       return 0;
 }
 
 static u64 spufs_srr0_get(struct spu_context *ctx)
@@ -1727,10 +1974,12 @@ static u64 spufs_object_id_get(struct spu_context *ctx)
        return ctx->object_id;
 }
 
-static void spufs_object_id_set(void *data, u64 id)
+static int spufs_object_id_set(void *data, u64 id)
 {
        struct spu_context *ctx = data;
        ctx->object_id = id;
+
+       return 0;
 }
 
 DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
@@ -1777,13 +2026,13 @@ static const struct file_operations spufs_caps_fops = {
 static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
                        char __user *buf, size_t len, loff_t *pos)
 {
-       u32 mbox_stat;
        u32 data;
 
-       mbox_stat = ctx->csa.prob.mb_stat_R;
-       if (mbox_stat & 0x0000ff) {
-               data = ctx->csa.prob.pu_mb_R;
-       }
+       /* EOF if there's no entry in the mbox */
+       if (!(ctx->csa.prob.mb_stat_R & 0x0000ff))
+               return 0;
+
+       data = ctx->csa.prob.pu_mb_R;
 
        return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
 }
@@ -1797,7 +2046,9 @@ static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_mbox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -1815,13 +2066,13 @@ static const struct file_operations spufs_mbox_info_fops = {
 static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
                                char __user *buf, size_t len, loff_t *pos)
 {
-       u32 ibox_stat;
        u32 data;
 
-       ibox_stat = ctx->csa.prob.mb_stat_R;
-       if (ibox_stat & 0xff0000) {
-               data = ctx->csa.priv2.puint_mb_R;
-       }
+       /* EOF if there's no entry in the ibox */
+       if (!(ctx->csa.prob.mb_stat_R & 0xff0000))
+               return 0;
+
+       data = ctx->csa.priv2.puint_mb_R;
 
        return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
 }
@@ -1835,7 +2086,9 @@ static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_ibox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -1876,7 +2129,9 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_wbox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -1926,7 +2181,9 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_dma_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -1977,7 +2234,9 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -2066,8 +2325,12 @@ static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
 static int spufs_show_stat(struct seq_file *s, void *private)
 {
        struct spu_context *ctx = s->private;
+       int ret;
+
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 
-       spu_acquire(ctx);
        seq_printf(s, "%s %llu %llu %llu %llu "
                      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
                ctx_state_names[ctx->stats.util_state],
index fc4ed1ffbd4ffb379da5e25aad08c78b0bdf7057..64f8540b832c32bc703b37498965985465bf6903 100644 (file)
@@ -76,16 +76,18 @@ static unsigned int spu_hw_mbox_stat_poll(struct spu_context *ctx,
                if (stat & 0xff0000)
                        ret |= POLLIN | POLLRDNORM;
                else {
-                       spu_int_stat_clear(spu, 2, 0x1);
-                       spu_int_mask_or(spu, 2, 0x1);
+                       spu_int_stat_clear(spu, 2, CLASS2_MAILBOX_INTR);
+                       spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
                }
        }
        if (events & (POLLOUT | POLLWRNORM)) {
                if (stat & 0x00ff00)
                        ret = POLLOUT | POLLWRNORM;
                else {
-                       spu_int_stat_clear(spu, 2, 0x10);
-                       spu_int_mask_or(spu, 2, 0x10);
+                       spu_int_stat_clear(spu, 2,
+                                       CLASS2_MAILBOX_THRESHOLD_INTR);
+                       spu_int_mask_or(spu, 2,
+                                       CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
                }
        }
        spin_unlock_irq(&spu->register_lock);
@@ -106,7 +108,7 @@ static int spu_hw_ibox_read(struct spu_context *ctx, u32 * data)
                ret = 4;
        } else {
                /* make sure we get woken up by the interrupt */
-               spu_int_mask_or(spu, 2, 0x1);
+               spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
                ret = 0;
        }
        spin_unlock_irq(&spu->register_lock);
@@ -127,7 +129,7 @@ static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
        } else {
                /* make sure we get woken up by the interrupt when space
                   becomes available */
-               spu_int_mask_or(spu, 2, 0x10);
+               spu_int_mask_or(spu, 2, CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR);
                ret = 0;
        }
        spin_unlock_irq(&spu->register_lock);
@@ -206,6 +208,11 @@ static char *spu_hw_get_ls(struct spu_context *ctx)
        return ctx->spu->local_store;
 }
 
+static void spu_hw_privcntl_write(struct spu_context *ctx, u64 val)
+{
+       out_be64(&ctx->spu->priv2->spu_privcntl_RW, val);
+}
+
 static u32 spu_hw_runcntl_read(struct spu_context *ctx)
 {
        return in_be32(&ctx->spu->problem->spu_runcntl_RW);
@@ -215,11 +222,21 @@ static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
 {
        spin_lock_irq(&ctx->spu->register_lock);
        if (val & SPU_RUNCNTL_ISOLATE)
-               out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
+               spu_hw_privcntl_write(ctx,
+                       SPU_PRIVCNT_LOAD_REQUEST_ENABLE_MASK);
        out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
        spin_unlock_irq(&ctx->spu->register_lock);
 }
 
+static void spu_hw_runcntl_stop(struct spu_context *ctx)
+{
+       spin_lock_irq(&ctx->spu->register_lock);
+       out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+       while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
+               cpu_relax();
+       spin_unlock_irq(&ctx->spu->register_lock);
+}
+
 static void spu_hw_master_start(struct spu_context *ctx)
 {
        struct spu *spu = ctx->spu;
@@ -319,8 +336,10 @@ struct spu_context_ops spu_hw_ops = {
        .npc_write = spu_hw_npc_write,
        .status_read = spu_hw_status_read,
        .get_ls = spu_hw_get_ls,
+       .privcntl_write = spu_hw_privcntl_write,
        .runcntl_read = spu_hw_runcntl_read,
        .runcntl_write = spu_hw_runcntl_write,
+       .runcntl_stop = spu_hw_runcntl_stop,
        .master_start = spu_hw_master_start,
        .master_stop = spu_hw_master_stop,
        .set_mfc_query = spu_hw_set_mfc_query,
index f4b3c052dabf599888fcb5661198f4139245f15f..0e9f325c9ff7572318d0e843d707af86593fb78a 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/spu_csa.h>
 #include <asm/mmu.h>
 
+#include "spufs.h"
+
 static int spu_alloc_lscsa_std(struct spu_state *csa)
 {
        struct spu_lscsa *lscsa;
@@ -73,7 +75,7 @@ int spu_alloc_lscsa(struct spu_state *csa)
        int             i, j, n_4k;
 
        /* Check availability of 64K pages */
-       if (mmu_psize_defs[MMU_PAGE_64K].shift == 0)
+       if (!spu_64k_pages_available())
                goto fail;
 
        csa->use_big_pages = 1;
index 1ce5e22ea5f44cfbb093b1167c4a01b60bba5e0d..c01a09da1e562b277ce8000396b7ae382c2758fc 100644 (file)
@@ -15,24 +15,55 @@ void spufs_stop_callback(struct spu *spu)
 {
        struct spu_context *ctx = spu->ctx;
 
-       wake_up_all(&ctx->stop_wq);
+       /*
+        * It should be impossible to preempt a context while an exception
+        * is being processed, since the context switch code is specially
+        * coded to deal with interrupts ... But, just in case, sanity check
+        * the context pointer.  It is OK to return doing nothing since
+        * the exception will be regenerated when the context is resumed.
+        */
+       if (ctx) {
+               /* Copy exception arguments into module specific structure */
+               ctx->csa.class_0_pending = spu->class_0_pending;
+               ctx->csa.dsisr = spu->dsisr;
+               ctx->csa.dar = spu->dar;
+
+               /* ensure that the exception status has hit memory before a
+                * thread waiting on the context's stop queue is woken */
+               smp_wmb();
+
+               wake_up_all(&ctx->stop_wq);
+       }
+
+       /* Clear callback arguments from spu structure */
+       spu->class_0_pending = 0;
+       spu->dsisr = 0;
+       spu->dar = 0;
 }
 
-static inline int spu_stopped(struct spu_context *ctx, u32 *stat)
+int spu_stopped(struct spu_context *ctx, u32 *stat)
 {
-       struct spu *spu;
-       u64 pte_fault;
+       u64 dsisr;
+       u32 stopped;
 
        *stat = ctx->ops->status_read(ctx);
 
-       spu = ctx->spu;
-       if (ctx->state != SPU_STATE_RUNNABLE ||
-           test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
+       if (test_bit(SPU_SCHED_NOTIFY_ACTIVE, &ctx->sched_flags))
                return 1;
-       pte_fault = spu->dsisr &
-           (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
-       return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ?
-               1 : 0;
+
+       stopped = SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
+               SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
+       if (*stat & stopped)
+               return 1;
+
+       dsisr = ctx->csa.dsisr;
+       if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))
+               return 1;
+
+       if (ctx->csa.class_0_pending)
+               return 1;
+
+       return 0;
 }
 
 static int spu_setup_isolated(struct spu_context *ctx)
@@ -128,34 +159,66 @@ out:
 
 static int spu_run_init(struct spu_context *ctx, u32 *npc)
 {
+       unsigned long runcntl = SPU_RUNCNTL_RUNNABLE;
+       int ret;
+
        spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
 
-       if (ctx->flags & SPU_CREATE_ISOLATE) {
-               unsigned long runcntl;
+       /*
+        * NOSCHED is synchronous scheduling with respect to the caller.
+        * The caller waits for the context to be loaded.
+        */
+       if (ctx->flags & SPU_CREATE_NOSCHED) {
+               if (ctx->state == SPU_STATE_SAVED) {
+                       ret = spu_activate(ctx, 0);
+                       if (ret)
+                               return ret;
+               }
+       }
 
+       /*
+        * Apply special setup as required.
+        */
+       if (ctx->flags & SPU_CREATE_ISOLATE) {
                if (!(ctx->ops->status_read(ctx) & SPU_STATUS_ISOLATED_STATE)) {
-                       int ret = spu_setup_isolated(ctx);
+                       ret = spu_setup_isolated(ctx);
                        if (ret)
                                return ret;
                }
 
-               /* if userspace has set the runcntrl register (eg, to issue an
-                * isolated exit), we need to re-set it here */
+               /*
+                * If userspace has set the runcntrl register (eg, to
+                * issue an isolated exit), we need to re-set it here
+                */
                runcntl = ctx->ops->runcntl_read(ctx) &
                        (SPU_RUNCNTL_RUNNABLE | SPU_RUNCNTL_ISOLATE);
                if (runcntl == 0)
                        runcntl = SPU_RUNCNTL_RUNNABLE;
+       }
+
+       if (ctx->flags & SPU_CREATE_NOSCHED) {
+               spuctx_switch_state(ctx, SPU_UTIL_USER);
                ctx->ops->runcntl_write(ctx, runcntl);
        } else {
-               unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL;
-               ctx->ops->npc_write(ctx, *npc);
+               unsigned long privcntl;
+
                if (test_thread_flag(TIF_SINGLESTEP))
-                       mode = SPU_PRIVCNTL_MODE_SINGLE_STEP;
-               out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode);
-               ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
-       }
+                       privcntl = SPU_PRIVCNTL_MODE_SINGLE_STEP;
+               else
+                       privcntl = SPU_PRIVCNTL_MODE_NORMAL;
 
-       spuctx_switch_state(ctx, SPU_UTIL_USER);
+               ctx->ops->npc_write(ctx, *npc);
+               ctx->ops->privcntl_write(ctx, privcntl);
+               ctx->ops->runcntl_write(ctx, runcntl);
+
+               if (ctx->state == SPU_STATE_SAVED) {
+                       ret = spu_activate(ctx, 0);
+                       if (ret)
+                               return ret;
+               } else {
+                       spuctx_switch_state(ctx, SPU_UTIL_USER);
+               }
+       }
 
        return 0;
 }
@@ -165,6 +228,8 @@ static int spu_run_fini(struct spu_context *ctx, u32 *npc,
 {
        int ret = 0;
 
+       spu_del_from_rq(ctx);
+
        *status = ctx->ops->status_read(ctx);
        *npc = ctx->ops->npc_read(ctx);
 
@@ -177,26 +242,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 *npc,
        return ret;
 }
 
-static int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
-                                        u32 *status)
-{
-       int ret;
-
-       ret = spu_run_fini(ctx, npc, status);
-       if (ret)
-               return ret;
-
-       if (*status & (SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_STOPPED_BY_HALT))
-               return *status;
-
-       ret = spu_acquire_runnable(ctx, 0);
-       if (ret)
-               return ret;
-
-       spuctx_switch_state(ctx, SPU_UTIL_USER);
-       return 0;
-}
-
 /*
  * SPU syscall restarting is tricky because we violate the basic
  * assumption that the signal handler is running on the interrupted
@@ -247,7 +292,7 @@ static int spu_process_callback(struct spu_context *ctx)
        u32 ls_pointer, npc;
        void __iomem *ls;
        long spu_ret;
-       int ret;
+       int ret, ret2;
 
        /* get syscall block from local store */
        npc = ctx->ops->npc_read(ctx) & ~3;
@@ -269,9 +314,11 @@ static int spu_process_callback(struct spu_context *ctx)
                if (spu_ret <= -ERESTARTSYS) {
                        ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
                }
-               spu_acquire(ctx);
+               ret2 = spu_acquire(ctx);
                if (ret == -ERESTARTSYS)
                        return ret;
+               if (ret2)
+                       return -EINTR;
        }
 
        /* write result, jump over indirect pointer */
@@ -281,18 +328,6 @@ static int spu_process_callback(struct spu_context *ctx)
        return ret;
 }
 
-static inline int spu_process_events(struct spu_context *ctx)
-{
-       struct spu *spu = ctx->spu;
-       int ret = 0;
-
-       if (spu->class_0_pending)
-               ret = spu_irq_class_0_bottom(spu);
-       if (!ret && signal_pending(current))
-               ret = -ERESTARTSYS;
-       return ret;
-}
-
 long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
 {
        int ret;
@@ -302,29 +337,14 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
        if (mutex_lock_interruptible(&ctx->run_mutex))
                return -ERESTARTSYS;
 
-       ctx->ops->master_start(ctx);
+       spu_enable_spu(ctx);
        ctx->event_return = 0;
 
-       spu_acquire(ctx);
-       if (ctx->state == SPU_STATE_SAVED) {
-               __spu_update_sched_info(ctx);
-               spu_set_timeslice(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               goto out_unlock;
 
-               ret = spu_activate(ctx, 0);
-               if (ret) {
-                       spu_release(ctx);
-                       goto out;
-               }
-       } else {
-               /*
-                * We have to update the scheduling priority under active_mutex
-                * to protect against find_victim().
-                *
-                * No need to update the timeslice ASAP, it will get updated
-                * once the current one has expired.
-                */
-               spu_update_sched_info(ctx);
-       }
+       spu_update_sched_info(ctx);
 
        ret = spu_run_init(ctx, npc);
        if (ret) {
@@ -358,14 +378,12 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
                if (ret)
                        break;
 
-               if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
-                       ret = spu_reacquire_runnable(ctx, npc, &status);
-                       if (ret)
-                               goto out2;
-                       continue;
-               }
-               ret = spu_process_events(ctx);
+               ret = spufs_handle_class0(ctx);
+               if (ret)
+                       break;
 
+               if (signal_pending(current))
+                       ret = -ERESTARTSYS;
        } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP |
                                      SPU_STATUS_STOPPED_BY_HALT |
                                       SPU_STATUS_SINGLE_STEP)));
@@ -376,11 +394,10 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
                ctx->stats.libassist++;
 
 
-       ctx->ops->master_stop(ctx);
+       spu_disable_spu(ctx);
        ret = spu_run_fini(ctx, npc, &status);
        spu_yield(ctx);
 
-out2:
        if ((ret == 0) ||
            ((ret == -ERESTARTSYS) &&
             ((status & SPU_STATUS_STOPPED_BY_HALT) ||
@@ -401,6 +418,7 @@ out2:
 
 out:
        *event = ctx->event_return;
+out_unlock:
        mutex_unlock(&ctx->run_mutex);
        return ret;
 }
index 4d257b3f93364bc34b667d836153451e0e2161e4..8c8af11b35b4f0e99fb18504de8ea3389cc0c04e 100644 (file)
@@ -58,6 +58,7 @@ static unsigned long spu_avenrun[3];
 static struct spu_prio_array *spu_prio;
 static struct task_struct *spusched_task;
 static struct timer_list spusched_timer;
+static struct timer_list spuloadavg_timer;
 
 /*
  * Priority of a normal, non-rt, non-niced'd process (aka nice level 0).
@@ -105,15 +106,21 @@ void spu_set_timeslice(struct spu_context *ctx)
 void __spu_update_sched_info(struct spu_context *ctx)
 {
        /*
-        * 32-Bit assignment are atomic on powerpc, and we don't care about
-        * memory ordering here because retriving the controlling thread is
-        * per defintion racy.
+        * assert that the context is not on the runqueue, so it is safe
+        * to change its scheduling parameters.
+        */
+       BUG_ON(!list_empty(&ctx->rq));
+
+       /*
+        * 32-Bit assignments are atomic on powerpc, and we don't care about
+        * memory ordering here because retrieving the controlling thread is
+        * per definition racy.
         */
        ctx->tid = current->pid;
 
        /*
         * We do our own priority calculations, so we normally want
-        * ->static_prio to start with. Unfortunately thies field
+        * ->static_prio to start with. Unfortunately this field
         * contains junk for threads with a realtime scheduling
         * policy so we have to look at ->prio in this case.
         */
@@ -124,23 +131,32 @@ void __spu_update_sched_info(struct spu_context *ctx)
        ctx->policy = current->policy;
 
        /*
-        * A lot of places that don't hold list_mutex poke into
-        * cpus_allowed, including grab_runnable_context which
-        * already holds the runq_lock.  So abuse runq_lock
-        * to protect this field aswell.
+        * TO DO: the context may be loaded, so we may need to activate
+        * it again on a different node. But it shouldn't hurt anything
+        * to update its parameters, because we know that the scheduler
+        * is not actively looking at this field, since it is not on the
+        * runqueue. The context will be rescheduled on the proper node
+        * if it is timesliced or preempted.
         */
-       spin_lock(&spu_prio->runq_lock);
        ctx->cpus_allowed = current->cpus_allowed;
-       spin_unlock(&spu_prio->runq_lock);
 }
 
 void spu_update_sched_info(struct spu_context *ctx)
 {
-       int node = ctx->spu->node;
+       int node;
 
-       mutex_lock(&cbe_spu_info[node].list_mutex);
-       __spu_update_sched_info(ctx);
-       mutex_unlock(&cbe_spu_info[node].list_mutex);
+       if (ctx->state == SPU_STATE_RUNNABLE) {
+               node = ctx->spu->node;
+
+               /*
+                * Take list_mutex to sync with find_victim().
+                */
+               mutex_lock(&cbe_spu_info[node].list_mutex);
+               __spu_update_sched_info(ctx);
+               mutex_unlock(&cbe_spu_info[node].list_mutex);
+       } else {
+               __spu_update_sched_info(ctx);
+       }
 }
 
 static int __node_allowed(struct spu_context *ctx, int node)
@@ -182,7 +198,7 @@ static void notify_spus_active(void)
         * Wake up the active spu_contexts.
         *
         * When the awakened processes see their "notify_active" flag is set,
-        * they will call spu_switch_notify();
+        * they will call spu_switch_notify().
         */
        for_each_online_node(node) {
                struct spu *spu;
@@ -245,7 +261,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
        spu->wbox_callback = spufs_wbox_callback;
        spu->stop_callback = spufs_stop_callback;
        spu->mfc_callback = spufs_mfc_callback;
-       spu->dma_callback = spufs_dma_callback;
        mb();
        spu_unmap_mappings(ctx);
        spu_restore(&ctx->csa, spu);
@@ -433,7 +448,6 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
        spu->wbox_callback = NULL;
        spu->stop_callback = NULL;
        spu->mfc_callback = NULL;
-       spu->dma_callback = NULL;
        spu_associate_mm(spu, NULL);
        spu->pid = 0;
        spu->tgid = 0;
@@ -478,6 +492,13 @@ static void __spu_add_to_rq(struct spu_context *ctx)
        }
 }
 
+static void spu_add_to_rq(struct spu_context *ctx)
+{
+       spin_lock(&spu_prio->runq_lock);
+       __spu_add_to_rq(ctx);
+       spin_unlock(&spu_prio->runq_lock);
+}
+
 static void __spu_del_from_rq(struct spu_context *ctx)
 {
        int prio = ctx->prio;
@@ -492,10 +513,24 @@ static void __spu_del_from_rq(struct spu_context *ctx)
        }
 }
 
+void spu_del_from_rq(struct spu_context *ctx)
+{
+       spin_lock(&spu_prio->runq_lock);
+       __spu_del_from_rq(ctx);
+       spin_unlock(&spu_prio->runq_lock);
+}
+
 static void spu_prio_wait(struct spu_context *ctx)
 {
        DEFINE_WAIT(wait);
 
+       /*
+        * The caller must explicitly wait for a context to be loaded
+        * if the nosched flag is set.  If NOSCHED is not set, the caller
+        * queues the context and waits for an spu event or error.
+        */
+       BUG_ON(!(ctx->flags & SPU_CREATE_NOSCHED));
+
        spin_lock(&spu_prio->runq_lock);
        prepare_to_wait_exclusive(&ctx->stop_wq, &wait, TASK_INTERRUPTIBLE);
        if (!signal_pending(current)) {
@@ -579,7 +614,7 @@ static struct spu *find_victim(struct spu_context *ctx)
        /*
         * Look for a possible preemption candidate on the local node first.
         * If there is no candidate look at the other nodes.  This isn't
-        * exactly fair, but so far the whole spu schedule tries to keep
+        * exactly fair, but so far the whole spu scheduler tries to keep
         * a strong node affinity.  We might want to fine-tune this in
         * the future.
         */
@@ -595,6 +630,7 @@ static struct spu *find_victim(struct spu_context *ctx)
                        struct spu_context *tmp = spu->ctx;
 
                        if (tmp && tmp->prio > ctx->prio &&
+                           !(tmp->flags & SPU_CREATE_NOSCHED) &&
                            (!victim || tmp->prio > victim->prio))
                                victim = spu->ctx;
                }
@@ -606,6 +642,10 @@ static struct spu *find_victim(struct spu_context *ctx)
                         * higher priority contexts before lower priority
                         * ones, so this is safe until we introduce
                         * priority inheritance schemes.
+                        *
+                        * XXX if the highest priority context is locked,
+                        * this can loop a long time.  Might be better to
+                        * look at another context or give up after X retries.
                         */
                        if (!mutex_trylock(&victim->state_mutex)) {
                                victim = NULL;
@@ -613,10 +653,10 @@ static struct spu *find_victim(struct spu_context *ctx)
                        }
 
                        spu = victim->spu;
-                       if (!spu) {
+                       if (!spu || victim->prio <= ctx->prio) {
                                /*
                                 * This race can happen because we've dropped
-                                * the active list mutex.  No a problem, just
+                                * the active list mutex.  Not a problem, just
                                 * restart the search.
                                 */
                                mutex_unlock(&victim->state_mutex);
@@ -631,13 +671,10 @@ static struct spu *find_victim(struct spu_context *ctx)
 
                        victim->stats.invol_ctx_switch++;
                        spu->stats.invol_ctx_switch++;
+                       spu_add_to_rq(victim);
+
                        mutex_unlock(&victim->state_mutex);
-                       /*
-                        * We need to break out of the wait loop in spu_run
-                        * manually to ensure this context gets put on the
-                        * runqueue again ASAP.
-                        */
-                       wake_up(&victim->stop_wq);
+
                        return spu;
                }
        }
@@ -645,6 +682,50 @@ static struct spu *find_victim(struct spu_context *ctx)
        return NULL;
 }
 
+static void __spu_schedule(struct spu *spu, struct spu_context *ctx)
+{
+       int node = spu->node;
+       int success = 0;
+
+       spu_set_timeslice(ctx);
+
+       mutex_lock(&cbe_spu_info[node].list_mutex);
+       if (spu->ctx == NULL) {
+               spu_bind_context(spu, ctx);
+               cbe_spu_info[node].nr_active++;
+               spu->alloc_state = SPU_USED;
+               success = 1;
+       }
+       mutex_unlock(&cbe_spu_info[node].list_mutex);
+
+       if (success)
+               wake_up_all(&ctx->run_wq);
+       else
+               spu_add_to_rq(ctx);
+}
+
+static void spu_schedule(struct spu *spu, struct spu_context *ctx)
+{
+       /* not a candidate for interruptible because it's called either
+          from the scheduler thread or from spu_deactivate */
+       mutex_lock(&ctx->state_mutex);
+       __spu_schedule(spu, ctx);
+       spu_release(ctx);
+}
+
+static void spu_unschedule(struct spu *spu, struct spu_context *ctx)
+{
+       int node = spu->node;
+
+       mutex_lock(&cbe_spu_info[node].list_mutex);
+       cbe_spu_info[node].nr_active--;
+       spu->alloc_state = SPU_FREE;
+       spu_unbind_context(spu, ctx);
+       ctx->stats.invol_ctx_switch++;
+       spu->stats.invol_ctx_switch++;
+       mutex_unlock(&cbe_spu_info[node].list_mutex);
+}
+
 /**
  * spu_activate - find a free spu for a context and execute it
  * @ctx:       spu context to schedule
@@ -656,39 +737,47 @@ static struct spu *find_victim(struct spu_context *ctx)
  */
 int spu_activate(struct spu_context *ctx, unsigned long flags)
 {
-       do {
-               struct spu *spu;
+       struct spu *spu;
 
-               /*
-                * If there are multiple threads waiting for a single context
-                * only one actually binds the context while the others will
-                * only be able to acquire the state_mutex once the context
-                * already is in runnable state.
-                */
-               if (ctx->spu)
-                       return 0;
+       /*
+        * If there are multiple threads waiting for a single context
+        * only one actually binds the context while the others will
+        * only be able to acquire the state_mutex once the context
+        * already is in runnable state.
+        */
+       if (ctx->spu)
+               return 0;
 
-               spu = spu_get_idle(ctx);
-               /*
-                * If this is a realtime thread we try to get it running by
-                * preempting a lower priority thread.
-                */
-               if (!spu && rt_prio(ctx->prio))
-                       spu = find_victim(ctx);
-               if (spu) {
-                       int node = spu->node;
+spu_activate_top:
+       if (signal_pending(current))
+               return -ERESTARTSYS;
 
-                       mutex_lock(&cbe_spu_info[node].list_mutex);
-                       spu_bind_context(spu, ctx);
-                       cbe_spu_info[node].nr_active++;
-                       mutex_unlock(&cbe_spu_info[node].list_mutex);
-                       return 0;
-               }
+       spu = spu_get_idle(ctx);
+       /*
+        * If this is a realtime thread we try to get it running by
+        * preempting a lower priority thread.
+        */
+       if (!spu && rt_prio(ctx->prio))
+               spu = find_victim(ctx);
+       if (spu) {
+               unsigned long runcntl;
+
+               runcntl = ctx->ops->runcntl_read(ctx);
+               __spu_schedule(spu, ctx);
+               if (runcntl & SPU_RUNCNTL_RUNNABLE)
+                       spuctx_switch_state(ctx, SPU_UTIL_USER);
 
+               return 0;
+       }
+
+       if (ctx->flags & SPU_CREATE_NOSCHED) {
                spu_prio_wait(ctx);
-       } while (!signal_pending(current));
+               goto spu_activate_top;
+       }
 
-       return -ERESTARTSYS;
+       spu_add_to_rq(ctx);
+
+       return 0;
 }
 
 /**
@@ -730,21 +819,19 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
        if (spu) {
                new = grab_runnable_context(max_prio, spu->node);
                if (new || force) {
-                       int node = spu->node;
-
-                       mutex_lock(&cbe_spu_info[node].list_mutex);
-                       spu_unbind_context(spu, ctx);
-                       spu->alloc_state = SPU_FREE;
-                       cbe_spu_info[node].nr_active--;
-                       mutex_unlock(&cbe_spu_info[node].list_mutex);
-
-                       ctx->stats.vol_ctx_switch++;
-                       spu->stats.vol_ctx_switch++;
-
-                       if (new)
-                               wake_up(&new->stop_wq);
+                       spu_unschedule(spu, ctx);
+                       if (new) {
+                               if (new->flags & SPU_CREATE_NOSCHED)
+                                       wake_up(&new->stop_wq);
+                               else {
+                                       spu_release(ctx);
+                                       spu_schedule(spu, new);
+                                       /* this one can't easily be made
+                                          interruptible */
+                                       mutex_lock(&ctx->state_mutex);
+                               }
+                       }
                }
-
        }
 
        return new != NULL;
@@ -781,43 +868,38 @@ void spu_yield(struct spu_context *ctx)
 
 static noinline void spusched_tick(struct spu_context *ctx)
 {
+       struct spu_context *new = NULL;
+       struct spu *spu = NULL;
+       u32 status;
+
+       if (spu_acquire(ctx))
+               BUG();  /* a kernel thread never has signals pending */
+
+       if (ctx->state != SPU_STATE_RUNNABLE)
+               goto out;
+       if (spu_stopped(ctx, &status))
+               goto out;
        if (ctx->flags & SPU_CREATE_NOSCHED)
-               return;
+               goto out;
        if (ctx->policy == SCHED_FIFO)
-               return;
+               goto out;
 
        if (--ctx->time_slice)
-               return;
+               goto out;
 
-       /*
-        * Unfortunately list_mutex ranks outside of state_mutex, so
-        * we have to trylock here.  If we fail give the context another
-        * tick and try again.
-        */
-       if (mutex_trylock(&ctx->state_mutex)) {
-               struct spu *spu = ctx->spu;
-               struct spu_context *new;
-
-               new = grab_runnable_context(ctx->prio + 1, spu->node);
-               if (new) {
-                       spu_unbind_context(spu, ctx);
-                       ctx->stats.invol_ctx_switch++;
-                       spu->stats.invol_ctx_switch++;
-                       spu->alloc_state = SPU_FREE;
-                       cbe_spu_info[spu->node].nr_active--;
-                       wake_up(&new->stop_wq);
-                       /*
-                        * We need to break out of the wait loop in
-                        * spu_run manually to ensure this context
-                        * gets put on the runqueue again ASAP.
-                        */
-                       wake_up(&ctx->stop_wq);
-               }
-               spu_set_timeslice(ctx);
-               mutex_unlock(&ctx->state_mutex);
+       spu = ctx->spu;
+       new = grab_runnable_context(ctx->prio + 1, spu->node);
+       if (new) {
+               spu_unschedule(spu, ctx);
+               spu_add_to_rq(ctx);
        } else {
                ctx->time_slice++;
        }
+out:
+       spu_release(ctx);
+
+       if (new)
+               spu_schedule(spu, new);
 }
 
 /**
@@ -841,35 +923,31 @@ static unsigned long count_active_contexts(void)
 }
 
 /**
- * spu_calc_load - given tick count, update the avenrun load estimates.
- * @tick:      tick count
+ * spu_calc_load - update the avenrun load estimates.
  *
  * No locking against reading these values from userspace, as for
  * the CPU loadavg code.
  */
-static void spu_calc_load(unsigned long ticks)
+static void spu_calc_load(void)
 {
        unsigned long active_tasks; /* fixed-point */
-       static int count = LOAD_FREQ;
-
-       count -= ticks;
-
-       if (unlikely(count < 0)) {
-               active_tasks = count_active_contexts() * FIXED_1;
-               do {
-                       CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
-                       CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
-                       CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
-                       count += LOAD_FREQ;
-               } while (count < 0);
-       }
+
+       active_tasks = count_active_contexts() * FIXED_1;
+       CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks);
+       CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks);
+       CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks);
 }
 
 static void spusched_wake(unsigned long data)
 {
        mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK);
        wake_up_process(spusched_task);
-       spu_calc_load(SPUSCHED_TICK);
+}
+
+static void spuloadavg_wake(unsigned long data)
+{
+       mod_timer(&spuloadavg_timer, jiffies + LOAD_FREQ);
+       spu_calc_load();
 }
 
 static int spusched_thread(void *unused)
@@ -881,17 +959,58 @@ static int spusched_thread(void *unused)
                set_current_state(TASK_INTERRUPTIBLE);
                schedule();
                for (node = 0; node < MAX_NUMNODES; node++) {
-                       mutex_lock(&cbe_spu_info[node].list_mutex);
-                       list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list)
-                               if (spu->ctx)
-                                       spusched_tick(spu->ctx);
-                       mutex_unlock(&cbe_spu_info[node].list_mutex);
+                       struct mutex *mtx = &cbe_spu_info[node].list_mutex;
+
+                       mutex_lock(mtx);
+                       list_for_each_entry(spu, &cbe_spu_info[node].spus,
+                                       cbe_list) {
+                               struct spu_context *ctx = spu->ctx;
+
+                               if (ctx) {
+                                       mutex_unlock(mtx);
+                                       spusched_tick(ctx);
+                                       mutex_lock(mtx);
+                               }
+                       }
+                       mutex_unlock(mtx);
                }
        }
 
        return 0;
 }
 
+void spuctx_switch_state(struct spu_context *ctx,
+               enum spu_utilization_state new_state)
+{
+       unsigned long long curtime;
+       signed long long delta;
+       struct timespec ts;
+       struct spu *spu;
+       enum spu_utilization_state old_state;
+
+       ktime_get_ts(&ts);
+       curtime = timespec_to_ns(&ts);
+       delta = curtime - ctx->stats.tstamp;
+
+       WARN_ON(!mutex_is_locked(&ctx->state_mutex));
+       WARN_ON(delta < 0);
+
+       spu = ctx->spu;
+       old_state = ctx->stats.util_state;
+       ctx->stats.util_state = new_state;
+       ctx->stats.tstamp = curtime;
+
+       /*
+        * Update the physical SPU utilization statistics.
+        */
+       if (spu) {
+               ctx->stats.times[old_state] += delta;
+               spu->stats.times[old_state] += delta;
+               spu->stats.util_state = new_state;
+               spu->stats.tstamp = curtime;
+       }
+}
+
 #define LOAD_INT(x) ((x) >> FSHIFT)
 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
 
@@ -905,7 +1024,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
 
        /*
         * Note that last_pid doesn't really make much sense for the
-        * SPU loadavg (it even seems very odd on the CPU side..),
+        * SPU loadavg (it even seems very odd on the CPU side...),
         * but we include it here to have a 100% compatible interface.
         */
        seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
@@ -946,6 +1065,7 @@ int __init spu_sched_init(void)
        spin_lock_init(&spu_prio->runq_lock);
 
        setup_timer(&spusched_timer, spusched_wake, 0);
+       setup_timer(&spuloadavg_timer, spuloadavg_wake, 0);
 
        spusched_task = kthread_run(spusched_thread, NULL, "spusched");
        if (IS_ERR(spusched_task)) {
@@ -953,6 +1073,8 @@ int __init spu_sched_init(void)
                goto out_free_spu_prio;
        }
 
+       mod_timer(&spuloadavg_timer, 0);
+
        entry = create_proc_entry("spu_loadavg", 0, NULL);
        if (!entry)
                goto out_stop_kthread;
@@ -978,6 +1100,7 @@ void spu_sched_exit(void)
        remove_proc_entry("spu_loadavg", NULL);
 
        del_timer_sync(&spusched_timer);
+       del_timer_sync(&spuloadavg_timer);
        kthread_stop(spusched_task);
 
        for (node = 0; node < MAX_NUMNODES; node++) {
index ca47b991bda5e3dd639d8b40b5dccf47d4a1557e..0e114038ea6fc136b5ec74e675987d848553629f 100644 (file)
@@ -71,6 +71,7 @@ struct spu_context {
        wait_queue_head_t wbox_wq;
        wait_queue_head_t stop_wq;
        wait_queue_head_t mfc_wq;
+       wait_queue_head_t run_wq;
        struct fasync_struct *ibox_fasync;
        struct fasync_struct *wbox_fasync;
        struct fasync_struct *mfc_fasync;
@@ -168,8 +169,10 @@ struct spu_context_ops {
        void (*npc_write) (struct spu_context * ctx, u32 data);
         u32(*status_read) (struct spu_context * ctx);
        char*(*get_ls) (struct spu_context * ctx);
+       void (*privcntl_write) (struct spu_context *ctx, u64 data);
         u32 (*runcntl_read) (struct spu_context * ctx);
        void (*runcntl_write) (struct spu_context * ctx, u32 data);
+       void (*runcntl_stop) (struct spu_context * ctx);
        void (*master_start) (struct spu_context * ctx);
        void (*master_stop) (struct spu_context * ctx);
        int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
@@ -219,15 +222,16 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx);
 
 /* fault handling */
 int spufs_handle_class1(struct spu_context *ctx);
+int spufs_handle_class0(struct spu_context *ctx);
 
 /* affinity */
 struct spu *affinity_check(struct spu_context *ctx);
 
 /* context management */
 extern atomic_t nr_spu_contexts;
-static inline void spu_acquire(struct spu_context *ctx)
+static inline int __must_check spu_acquire(struct spu_context *ctx)
 {
-       mutex_lock(&ctx->state_mutex);
+       return mutex_lock_interruptible(&ctx->state_mutex);
 }
 
 static inline void spu_release(struct spu_context *ctx)
@@ -242,10 +246,11 @@ int put_spu_context(struct spu_context *ctx);
 void spu_unmap_mappings(struct spu_context *ctx);
 
 void spu_forget(struct spu_context *ctx);
-int spu_acquire_runnable(struct spu_context *ctx, unsigned long flags);
-void spu_acquire_saved(struct spu_context *ctx);
+int __must_check spu_acquire_saved(struct spu_context *ctx);
 void spu_release_saved(struct spu_context *ctx);
 
+int spu_stopped(struct spu_context *ctx, u32 * stat);
+void spu_del_from_rq(struct spu_context *ctx);
 int spu_activate(struct spu_context *ctx, unsigned long flags);
 void spu_deactivate(struct spu_context *ctx);
 void spu_yield(struct spu_context *ctx);
@@ -279,7 +284,9 @@ extern char *isolated_loader;
                }                                                       \
                spu_release(ctx);                                       \
                schedule();                                             \
-               spu_acquire(ctx);                                       \
+               __ret = spu_acquire(ctx);                               \
+               if (__ret)                                              \
+                       break;                                          \
        }                                                               \
        finish_wait(&(wq), &__wait);                                    \
        __ret;                                                          \
@@ -306,41 +313,16 @@ struct spufs_coredump_reader {
 extern struct spufs_coredump_reader spufs_coredump_read[];
 extern int spufs_coredump_num_notes;
 
-/*
- * This function is a little bit too large for an inline, but
- * as fault.c is built into the kernel we can't move it out of
- * line.
- */
-static inline void spuctx_switch_state(struct spu_context *ctx,
-               enum spu_utilization_state new_state)
-{
-       unsigned long long curtime;
-       signed long long delta;
-       struct timespec ts;
-       struct spu *spu;
-       enum spu_utilization_state old_state;
-
-       ktime_get_ts(&ts);
-       curtime = timespec_to_ns(&ts);
-       delta = curtime - ctx->stats.tstamp;
-
-       WARN_ON(!mutex_is_locked(&ctx->state_mutex));
-       WARN_ON(delta < 0);
-
-       spu = ctx->spu;
-       old_state = ctx->stats.util_state;
-       ctx->stats.util_state = new_state;
-       ctx->stats.tstamp = curtime;
-
-       /*
-        * Update the physical SPU utilization statistics.
-        */
-       if (spu) {
-               ctx->stats.times[old_state] += delta;
-               spu->stats.times[old_state] += delta;
-               spu->stats.util_state = new_state;
-               spu->stats.tstamp = curtime;
-       }
-}
+extern int spu_init_csa(struct spu_state *csa);
+extern void spu_fini_csa(struct spu_state *csa);
+extern int spu_save(struct spu_state *prev, struct spu *spu);
+extern int spu_restore(struct spu_state *new, struct spu *spu);
+extern int spu_switch(struct spu_state *prev, struct spu_state *new,
+                     struct spu *spu);
+extern int spu_alloc_lscsa(struct spu_state *csa);
+extern void spu_free_lscsa(struct spu_state *csa);
+
+extern void spuctx_switch_state(struct spu_context *ctx,
+               enum spu_utilization_state new_state);
 
 #endif
index 3d64c81cc6e2bc05bb0a0b0b41a71d7c6805830b..6063c88c26d208115e19b4bb56937fc2eb4edbe7 100644 (file)
@@ -48,6 +48,8 @@
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 
+#include "spufs.h"
+
 #include "spu_save_dump.h"
 #include "spu_restore_dump.h"
 
@@ -691,35 +693,9 @@ static inline void resume_mfc_queue(struct spu_state *csa, struct spu *spu)
        out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void get_kernel_slb(u64 ea, u64 slb[2])
+static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu,
+               unsigned int *code, int code_size)
 {
-       u64 llp;
-
-       if (REGION_ID(ea) == KERNEL_REGION_ID)
-               llp = mmu_psize_defs[mmu_linear_psize].sllp;
-       else
-               llp = mmu_psize_defs[mmu_virtual_psize].sllp;
-       slb[0] = (get_kernel_vsid(ea, MMU_SEGSIZE_256M) << SLB_VSID_SHIFT) |
-               SLB_VSID_KERNEL | llp;
-       slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
-}
-
-static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
-{
-       struct spu_priv2 __iomem *priv2 = spu->priv2;
-
-       out_be64(&priv2->slb_index_W, slbe);
-       eieio();
-       out_be64(&priv2->slb_vsid_RW, slb[0]);
-       out_be64(&priv2->slb_esid_RW, slb[1]);
-       eieio();
-}
-
-static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
-{
-       u64 code_slb[2];
-       u64 lscsa_slb[2];
-
        /* Save, Step 47:
         * Restore, Step 30.
         *     If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
@@ -735,11 +711,7 @@ static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
         *     translation is desired by OS environment).
         */
        spu_invalidate_slbs(spu);
-       get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
-       get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
-       load_mfc_slb(spu, code_slb, 0);
-       if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
-               load_mfc_slb(spu, lscsa_slb, 1);
+       spu_setup_kernel_slbs(spu, csa->lscsa, code, code_size);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
@@ -768,9 +740,9 @@ static inline void enable_interrupts(struct spu_state *csa, struct spu *spu)
         *     (translation) interrupts.
         */
        spin_lock_irq(&spu->register_lock);
-       spu_int_stat_clear(spu, 0, ~0ul);
-       spu_int_stat_clear(spu, 1, ~0ul);
-       spu_int_stat_clear(spu, 2, ~0ul);
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        spu_int_mask_set(spu, 0, 0ul);
        spu_int_mask_set(spu, 1, class1_mask);
        spu_int_mask_set(spu, 2, 0ul);
@@ -927,8 +899,8 @@ static inline void wait_tag_complete(struct spu_state *csa, struct spu *spu)
        POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask);
 
        local_irq_save(flags);
-       spu_int_stat_clear(spu, 0, ~(0ul));
-       spu_int_stat_clear(spu, 2, ~(0ul));
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        local_irq_restore(flags);
 }
 
@@ -946,8 +918,8 @@ static inline void wait_spu_stopped(struct spu_state *csa, struct spu *spu)
        POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
 
        local_irq_save(flags);
-       spu_int_stat_clear(spu, 0, ~(0ul));
-       spu_int_stat_clear(spu, 2, ~(0ul));
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        local_irq_restore(flags);
 }
 
@@ -1423,9 +1395,9 @@ static inline void clear_interrupts(struct spu_state *csa, struct spu *spu)
        spu_int_mask_set(spu, 0, 0ul);
        spu_int_mask_set(spu, 1, 0ul);
        spu_int_mask_set(spu, 2, 0ul);
-       spu_int_stat_clear(spu, 0, ~0ul);
-       spu_int_stat_clear(spu, 1, ~0ul);
-       spu_int_stat_clear(spu, 2, ~0ul);
+       spu_int_stat_clear(spu, 0, CLASS0_INTR_MASK);
+       spu_int_stat_clear(spu, 1, CLASS1_INTR_MASK);
+       spu_int_stat_clear(spu, 2, CLASS2_INTR_MASK);
        spin_unlock_irq(&spu->register_lock);
 }
 
@@ -1866,7 +1838,8 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu)
         */
 
        resume_mfc_queue(prev, spu);    /* Step 46. */
-       setup_mfc_slbs(prev, spu);      /* Step 47. */
+       /* Step 47. */
+       setup_mfc_slbs(prev, spu, spu_save_code, sizeof(spu_save_code));
        set_switch_active(prev, spu);   /* Step 48. */
        enable_interrupts(prev, spu);   /* Step 49. */
        save_ls_16kb(prev, spu);        /* Step 50. */
@@ -1971,7 +1944,8 @@ static void restore_lscsa(struct spu_state *next, struct spu *spu)
        setup_spu_status_part1(next, spu);      /* Step 27. */
        setup_spu_status_part2(next, spu);      /* Step 28. */
        restore_mfc_rag(next, spu);             /* Step 29. */
-       setup_mfc_slbs(next, spu);              /* Step 30. */
+       /* Step 30. */
+       setup_mfc_slbs(next, spu, spu_restore_code, sizeof(spu_restore_code));
        set_spu_npc(next, spu);                 /* Step 31. */
        set_signot1(next, spu);                 /* Step 32. */
        set_signot2(next, spu);                 /* Step 33. */
@@ -2103,10 +2077,6 @@ int spu_save(struct spu_state *prev, struct spu *spu)
        int rc;
 
        acquire_spu_lock(spu);          /* Step 1.     */
-       prev->dar = spu->dar;
-       prev->dsisr = spu->dsisr;
-       spu->dar = 0;
-       spu->dsisr = 0;
        rc = __do_spu_save(prev, spu);  /* Steps 2-53. */
        release_spu_lock(spu);
        if (rc != 0 && rc != 2 && rc != 6) {
@@ -2133,9 +2103,6 @@ int spu_restore(struct spu_state *new, struct spu *spu)
        acquire_spu_lock(spu);
        harvest(NULL, spu);
        spu->slb_replace = 0;
-       new->dar = 0;
-       new->dsisr = 0;
-       spu->class_0_pending = 0;
        rc = __do_spu_restore(new, spu);
        release_spu_lock(spu);
        if (rc) {
@@ -2215,10 +2182,8 @@ int spu_init_csa(struct spu_state *csa)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
        spu_free_lscsa(csa);
 }
-EXPORT_SYMBOL_GPL(spu_fini_csa);
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..fbe718d517a65e6c91ea83633a2eb5240f0de205 100644 (file)
@@ -22,8 +22,9 @@
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
+#include <asm/machdep.h>
 
 #include "beat_wrapper.h"
 
@@ -91,7 +92,7 @@ static struct notifier_block celleb_of_bus_notifier = {
 
 static int __init celleb_init_iommu(void)
 {
-       if (!machine_is(celleb))
+       if (!machine_is(celleb_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 b59c38a06e3e46299d6d622a039660ab7e61291b..cb4307994087638916db9c126fc5addcfaaf3b75 100644 (file)
@@ -47,7 +47,8 @@ static void enable_scc_uhc(struct pci_dev *dev)
        u32 val = 0;
        int i;
 
-       if (!machine_is(celleb))
+       if (!machine_is(celleb_beat) &&
+           !machine_is(celleb_native))
                return;
 
        uhc_base = ioremap(pci_resource_start(dev, 0),
index ddfb35ae741ff2abbdea105a79a2609623f67d07..0f0c4680bf013071dd11ba50c13e50e73acbe0c3 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/console.h>
+#include <linux/of_platform.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
 #include <asm/time.h>
 #include <asm/spu_priv1.h>
 #include <asm/firmware.h>
-#include <asm/of_platform.h>
+#include <asm/rtas.h>
+#include <asm/cell-regs.h>
 
 #include "interrupt.h"
 #include "beat_wrapper.h"
 #include "beat.h"
 #include "pci.h"
+#include "../cell/interrupt.h"
+#include "../cell/pervasive.h"
+#include "../cell/ras.h"
 
 static char celleb_machine_type[128] = "Celleb";
 
@@ -88,17 +93,8 @@ 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_setup_arch_common(void)
 {
-#ifdef CONFIG_SPU_BASE
-       spu_priv1_ops = &spu_priv1_beat_ops;
-       spu_management_ops = &spu_management_of_ops;
-#endif
-
-#ifdef CONFIG_SMP
-       smp_init_celleb();
-#endif
-
        /* init to some ~sane value until calibrate_delay() runs */
        loops_per_jiffy = 50000000;
 
@@ -107,18 +103,6 @@ static void __init celleb_setup_arch(void)
 #endif
 }
 
-static int __init celleb_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-
-       if (!of_flat_dt_is_compatible(root, "Beat"))
-               return 0;
-
-       powerpc_firmware_features |= FW_FEATURE_CELLEB_POSSIBLE;
-       hpte_init_beat_v3();
-       return 1;
-}
-
 static struct of_device_id celleb_bus_ids[] __initdata = {
        { .type = "scc", },
        { .type = "ioif", },    /* old style */
@@ -127,8 +111,9 @@ static struct of_device_id celleb_bus_ids[] __initdata = {
 
 static int __init celleb_publish_devices(void)
 {
-       if (!machine_is(celleb))
-               return 0;
+       if (!machine_is(celleb_beat) &&
+           !machine_is(celleb_native))
+               return -ENODEV;
 
        /* Publish OF platform devices for southbridge IOs */
        of_platform_bus_probe(NULL, celleb_bus_ids, NULL);
@@ -139,10 +124,94 @@ static int __init celleb_publish_devices(void)
 }
 device_initcall(celleb_publish_devices);
 
-define_machine(celleb) {
-       .name                   = "Cell Reference Set",
-       .probe                  = celleb_probe,
-       .setup_arch             = celleb_setup_arch,
+
+/*
+ * functions for Celleb-Beat
+ */
+static void __init celleb_setup_arch_beat(void)
+{
+#ifdef CONFIG_SPU_BASE
+       spu_priv1_ops           = &spu_priv1_beat_ops;
+       spu_management_ops      = &spu_management_of_ops;
+#endif
+
+#ifdef CONFIG_SMP
+       smp_init_celleb();
+#endif
+
+       celleb_setup_arch_common();
+}
+
+static int __init celleb_probe_beat(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (!of_flat_dt_is_compatible(root, "Beat"))
+               return 0;
+
+       powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
+               | FW_FEATURE_BEAT | FW_FEATURE_LPAR;
+       hpte_init_beat_v3();
+
+       return 1;
+}
+
+
+/*
+ * functions for Celleb-native
+ */
+static void __init celleb_init_IRQ_native(void)
+{
+       iic_init_IRQ();
+       spider_init_IRQ();
+}
+
+static void __init celleb_setup_arch_native(void)
+{
+#ifdef CONFIG_SPU_BASE
+       spu_priv1_ops           = &spu_priv1_mmio_ops;
+       spu_management_ops      = &spu_management_of_ops;
+#endif
+
+       cbe_regs_init();
+
+#ifdef CONFIG_CBE_RAS
+       cbe_ras_init();
+#endif
+
+#ifdef CONFIG_SMP
+       smp_init_cell();
+#endif
+
+       cbe_pervasive_init();
+
+       /* XXX: nvram initialization should be added */
+
+       celleb_setup_arch_common();
+}
+
+static int __init celleb_probe_native(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       if (of_flat_dt_is_compatible(root, "Beat") ||
+           !of_flat_dt_is_compatible(root, "TOSHIBA,Celleb"))
+               return 0;
+
+       powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
+       hpte_init_native();
+
+       return 1;
+}
+
+
+/*
+ * machine definitions
+ */
+define_machine(celleb_beat) {
+       .name                   = "Cell Reference Set (Beat)",
+       .probe                  = celleb_probe_beat,
+       .setup_arch             = celleb_setup_arch_beat,
        .show_cpuinfo           = celleb_show_cpuinfo,
        .restart                = beat_restart,
        .power_off              = beat_power_off,
@@ -167,3 +236,26 @@ define_machine(celleb) {
        .machine_crash_shutdown = default_machine_crash_shutdown,
 #endif
 };
+
+define_machine(celleb_native) {
+       .name                   = "Cell Reference Set (native)",
+       .probe                  = celleb_probe_native,
+       .setup_arch             = celleb_setup_arch_native,
+       .show_cpuinfo           = celleb_show_cpuinfo,
+       .restart                = rtas_restart,
+       .power_off              = rtas_power_off,
+       .halt                   = rtas_halt,
+       .get_boot_time          = rtas_get_boot_time,
+       .get_rtc_time           = rtas_get_rtc_time,
+       .set_rtc_time           = rtas_set_rtc_time,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = celleb_progress,
+       .pci_probe_mode         = celleb_pci_probe_mode,
+       .pci_setup_phb          = celleb_setup_phb,
+       .init_IRQ               = celleb_init_IRQ_native,
+#ifdef CONFIG_KEXEC
+       .machine_kexec          = default_machine_kexec,
+       .machine_kexec_prepare  = default_machine_kexec_prepare,
+       .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
+};
index 0340a342f7726c8a721eacf36491f2c604d50cce..d51f83aeef7ff2d9c6f6ae5914d52298d02372e3 100644 (file)
@@ -198,7 +198,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
                printk ("RTAS supporting Pegasos OF not found, please upgrade"
                        " your firmware\n");
        }
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        /* keep the reference to the root node */
 }
 
index 59306261f5b2991a329be96680c771ef134a9852..42a21bab76c860e51f97fdee3b6b32317f37e803 100644 (file)
@@ -115,7 +115,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
        seq_printf(m, "machine\t\t: CHRP %s\n", model);
 
        /* longtrail (goldengate) stuff */
-       if (!strncmp(model, "IBM,LongTrail", 13)) {
+       if (model && !strncmp(model, "IBM,LongTrail", 13)) {
                /* VLSI VAS96011/12 `Golden Gate 2' */
                /* Memory banks */
                sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL)
@@ -203,15 +203,20 @@ static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
 static void __init sio_init(void)
 {
        struct device_node *root;
+       const char *model;
 
-       if ((root = of_find_node_by_path("/")) &&
-           !strncmp(of_get_property(root, "model", NULL),
-                       "IBM,LongTrail", 13)) {
+       root = of_find_node_by_path("/");
+       if (!root)
+               return;
+
+       model = of_get_property(root, "model", NULL);
+       if (model && !strncmp(model, "IBM,LongTrail", 13)) {
                /* logical device 0 (KBC/Keyboard) */
                sio_fixup_irq("keyboard", 0, 1, 2);
                /* select logical device 1 (KBC/Mouse) */
                sio_fixup_irq("mouse", 1, 12, 2);
        }
+
        of_node_put(root);
 }
 
index b6de2b5223dd4682b61d9c9708b68c978c782059..b21fde589ca7800c14ffb4ec7d30117a1da52687 100644 (file)
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/serial_core.h>
+#include <linux/of_platform.h>
 
 #include <asm/system.h>
 #include <asm/time.h>
@@ -39,7 +39,6 @@
 #include <asm/tsi108_irq.h>
 #include <asm/tsi108_pci.h>
 #include <asm/mpic.h>
-#include <asm/of_platform.h>
 
 #undef DEBUG
 
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 49e9c664ea89b0745829dfd52058f620b35fdb27..6a0c6f6675cdf0d3dce57eda11ae7009ebb77e58 100644 (file)
@@ -163,8 +163,10 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
                    (it->it_type == TCE_PCI) &&
                    (it->it_offset == tbl->it_offset) &&
                    (it->it_index == tbl->it_index) &&
-                   (it->it_size == tbl->it_size))
+                   (it->it_size == tbl->it_size)) {
+                       of_node_put(node);
                        return it;
+               }
        }
        return NULL;
 }
index 275f49449839e189ff2776a0047fd03813595544..e5b40e3e0082cfd07c1597edd26c6f5ebbac54f5 100644 (file)
@@ -239,7 +239,7 @@ int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType)
                         * other CPUs, and that the deleted handler isn't
                         * still running on another CPU when we return.
                         */
-                       synchronize_rcu();
+                       synchronize_sched();
                        return 0;
                }
        }
index da87162000f0b25aa38c9189622a7105412b1272..30e3d992dc0d9a1988d44c27bcedc54f0d651008 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.
  *
@@ -19,6 +20,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+
+#undef DEBUG
+
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -26,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 
+#include <asm/types.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
@@ -35,6 +40,7 @@
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
+#include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
 #include <asm/iseries/iommu.h>
 #include "pci.h"
 #include "call_pci.h"
 
-/*
- * Forward declares of prototypes.
- */
-static struct device_node *find_Device_Node(int bus, int devfn);
-
-static int Pci_Retry_Max = 3;  /* Only retry 3 times  */
-static int Pci_Error_Flag = 1; /* Set Retry Error on. */
-
-static struct pci_ops iSeries_pci_ops;
+#define PCI_RETRY_MAX  3
+static int limit_pci_retries = 1;      /* Set Retry Error on. */
 
 /*
  * Table defines
@@ -62,6 +61,7 @@ static struct pci_ops iSeries_pci_ops;
 #define IOMM_TABLE_MAX_ENTRIES 1024
 #define IOMM_TABLE_ENTRY_SIZE  0x0000000000400000UL
 #define BASE_IO_MEMORY         0xE000000000000000UL
+#define END_IO_MEMORY          0xEFFFFFFFFFFFFFFFUL
 
 static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
@@ -72,9 +72,233 @@ static long current_iomm_table_entry;
 static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
 static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
+/*
+ * Generate a Direct Select Address for the Hypervisor
+ */
+static inline u64 iseries_ds_addr(struct device_node *node)
+{
+       struct pci_dn *pdn = PCI_DN(node);
+
+       return ((u64)pdn->busno << 48) + ((u64)pdn->bussubno << 40)
+                       + ((u64)0x10 << 32);
+}
+
+/*
+ * Size of Bus VPD data
+ */
+#define BUS_VPDSIZE      1024
+
+/*
+ * Bus Vpd Tags
+ */
+#define VPD_END_OF_AREA                0x79
+#define VPD_ID_STRING          0x82
+#define VPD_VENDOR_AREA                0x84
+
+/*
+ * Mfg Area Tags
+ */
+#define VPD_FRU_FRAME_ID       0x4649  /* "FI" */
+#define VPD_SLOT_MAP_FORMAT    0x4D46  /* "MF" */
+#define VPD_SLOT_MAP           0x534D  /* "SM" */
+
+/*
+ * Structures of the areas
+ */
+struct mfg_vpd_area {
+       u16     tag;
+       u8      length;
+       u8      data1;
+       u8      data2;
+};
+#define MFG_ENTRY_SIZE   3
+
+struct slot_map {
+       u8      agent;
+       u8      secondary_agent;
+       u8      phb;
+       char    card_location[3];
+       char    parms[8];
+       char    reserved[2];
+};
+#define SLOT_ENTRY_SIZE   16
+
+/*
+ * Parse the Slot Area
+ */
+static void __init iseries_parse_slot_area(struct slot_map *map, int len,
+               HvAgentId agent, u8 *phb, char card[4])
+{
+       /*
+        * Parse Slot label until we find the one requested
+        */
+       while (len > 0) {
+               if (map->agent == agent) {
+                       /*
+                        * If Phb wasn't found, grab the entry first one found.
+                        */
+                       if (*phb == 0xff)
+                               *phb = map->phb;
+                       /* Found it, extract the data. */
+                       if (map->phb == *phb) {
+                               memcpy(card, &map->card_location, 3);
+                               card[3]  = 0;
+                               break;
+                       }
+               }
+               /* Point to the next Slot */
+               map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
+               len -= SLOT_ENTRY_SIZE;
+       }
+}
+
+/*
+ * Parse the Mfg Area
+ */
+static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
+               HvAgentId agent, u8 *phb, u8 *frame, char card[4])
+{
+       u16 slot_map_fmt = 0;
+
+       /* Parse Mfg Data */
+       while (len > 0) {
+               int mfg_tag_len = area->length;
+               /* Frame ID         (FI 4649020310 ) */
+               if (area->tag == VPD_FRU_FRAME_ID)
+                       *frame = area->data1;
+               /* Slot Map Format  (MF 4D46020004 ) */
+               else if (area->tag == VPD_SLOT_MAP_FORMAT)
+                       slot_map_fmt = (area->data1 * 256)
+                               + area->data2;
+               /* Slot Map         (SM 534D90 */
+               else if (area->tag == VPD_SLOT_MAP) {
+                       struct slot_map *slot_map;
+
+                       if (slot_map_fmt == 0x1004)
+                               slot_map = (struct slot_map *)((char *)area
+                                               + MFG_ENTRY_SIZE + 1);
+                       else
+                               slot_map = (struct slot_map *)((char *)area
+                                               + MFG_ENTRY_SIZE);
+                       iseries_parse_slot_area(slot_map, mfg_tag_len,
+                                       agent, phb, card);
+               }
+               /*
+                * Point to the next Mfg Area
+                * Use defined size, sizeof give wrong answer
+                */
+               area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
+                               + MFG_ENTRY_SIZE);
+               len -= (mfg_tag_len + MFG_ENTRY_SIZE);
+       }
+}
+
+/*
+ * Look for "BUS".. Data is not Null terminated.
+ * PHBID of 0xFF indicates PHB was not found in VPD Data.
+ */
+static u8 __init iseries_parse_phbid(u8 *area, int len)
+{
+       while (len > 0) {
+               if ((*area == 'B') && (*(area + 1) == 'U')
+                               && (*(area + 2) == 'S')) {
+                       area += 3;
+                       while (*area == ' ')
+                               area++;
+                       return *area & 0x0F;
+               }
+               area++;
+               len--;
+       }
+       return 0xff;
+}
+
+/*
+ * Parse out the VPD Areas
+ */
+static void __init iseries_parse_vpd(u8 *data, int data_len,
+               HvAgentId agent, u8 *frame, char card[4])
+{
+       u8 phb = 0xff;
+
+       while (data_len > 0) {
+               int len;
+               u8 tag = *data;
+
+               if (tag == VPD_END_OF_AREA)
+                       break;
+               len = *(data + 1) + (*(data + 2) * 256);
+               data += 3;
+               data_len -= 3;
+               if (tag == VPD_ID_STRING)
+                       phb = iseries_parse_phbid(data, len);
+               else if (tag == VPD_VENDOR_AREA)
+                       iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
+                                       agent, &phb, frame, card);
+               /* Point to next Area. */
+               data += len;
+               data_len -= len;
+       }
+}
+
+static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
+               u8 *frame, char card[4])
+{
+       int status = 0;
+       int bus_vpd_len = 0;
+       u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+
+       if (bus_vpd == NULL) {
+               printk("PCI: Bus VPD Buffer allocation failure.\n");
+               return 0;
+       }
+       bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
+                                       BUS_VPDSIZE);
+       if (bus_vpd_len == 0) {
+               printk("PCI: Bus VPD Buffer zero length.\n");
+               goto out_free;
+       }
+       /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
+       /* Make sure this is what I think it is */
+       if (*bus_vpd != VPD_ID_STRING) {
+               printk("PCI: Bus VPD Buffer missing starting tag.\n");
+               goto out_free;
+       }
+       iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
+       status = 1;
+out_free:
+       kfree(bus_vpd);
+       return status;
+}
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
+ * controller
+ */
+static void __init iseries_device_information(struct pci_dev *pdev,
+                                             u16 bus, HvSubBusNumber subbus)
+{
+       u8 frame = 0;
+       char card[4];
+       HvAgentId agent;
+
+       agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+                       ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+
+       if (iseries_get_location_code(bus, agent, &frame, card)) {
+               printk(KERN_INFO "PCI: %s, Vendor %04X Frame%3d, "
+                      "Card %4s  0x%04X\n", pci_name(pdev), pdev->vendor,
+                      frame, card, (int)(pdev->class >> 8));
+       }
+}
+
 /*
  * iomm_table_allocate_entry
  *
@@ -87,7 +311,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);
@@ -101,7 +325,6 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
         * Set Resource values.
         */
        spin_lock(&iomm_table_lock);
-       bar_res->name = pci_io_text;
        bar_res->start = BASE_IO_MEMORY +
                IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
        bar_res->end = bar_res->start + bar_size - 1;
@@ -130,7 +353,7 @@ 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 +368,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 +393,67 @@ 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_pcibios_fixup_resources
+ *
+ * Fixes up all resources for devices
  */
-static struct device_node *get_Device_Node(struct pci_dev *pdev)
+void __init iSeries_pcibios_fixup_resources(struct pci_dev *pdev)
 {
+       const u32 *agent;
+       const u32 *sub_bus;
+       unsigned char bus = pdev->bus->number;
        struct device_node *node;
+       int i;
+
+       node = find_device_node(bus, pdev->devfn);
+       pr_debug("PCI: iSeries %s, pdev %p, node %p\n",
+                pci_name(pdev), pdev, node);
+       if (!node) {
+               printk("PCI: %s disabled, device tree entry not found !\n",
+                      pci_name(pdev));
+               for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+                       pdev->resource[i].flags = 0;
+               return;
+       }
+       sub_bus = of_get_property(node, "linux,subbus", NULL);
+       agent = of_get_property(node, "linux,agent-id", NULL);
+       if (agent && sub_bus) {
+               u8 irq = iSeries_allocate_IRQ(bus, 0, *sub_bus);
+               int err;
+
+               err = HvCallXm_connectBusUnit(bus, *sub_bus, *agent, irq);
+               if (err)
+                       pci_log_error("Connect Bus Unit",
+                                     bus, *sub_bus, *agent, err);
+               else {
+                       err = HvCallPci_configStore8(bus, *sub_bus,
+                                       *agent, PCI_INTERRUPT_LINE, irq);
+                       if (err)
+                               pci_log_error("PciCfgStore Irq Failed!",
+                                               bus, *sub_bus, *agent, err);
+                       else
+                               pdev->irq = irq;
+               }
+       }
 
-       node = pdev->sysdata;
-       if (node == NULL || PCI_DN(node)->pcidev != pdev)
-               node = find_Device_Node(pdev->bus->number, pdev->devfn);
-       return node;
+       pdev->sysdata = node;
+       PCI_DN(node)->pcidev = pdev;
+       allocate_device_bars(pdev);
+       iseries_device_information(pdev, bus, *sub_bus);
+       iommu_devnode_init_iSeries(pdev, node);
+}
+
+/*
+ * iSeries_pci_final_fixup(void)
+ */
+void __init iSeries_pci_final_fixup(void)
+{
+       /* Fix up at the device node and pci_dev relationship */
+       mf_display_src(0xC9000100);
+       iSeries_activate_IRQs();
+       mf_display_src(0xC9000200);
 }
-#endif
 
 /*
  * Config space read and write functions.
@@ -269,7 +477,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 +507,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 +539,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 +571,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;
 
-       OrigIoAddr = (unsigned long __force)IoAddress;
-       if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
+       orig_addr = (unsigned long __force)addr;
+       if ((orig_addr < BASE_IO_MEMORY) || (orig_addr >= max_io_memory)) {
+               static unsigned long last_jiffies;
+               static int num_printed;
+
+               if ((jiffies - last_jiffies) > 60 * HZ) {
+                       last_jiffies = jiffies;
+                       num_printed = 0;
+               }
+               if (num_printed++ < 10)
+                       printk(KERN_ERR
+                               "iSeries_%s: invalid access at IO address %p\n",
+                               func, addr);
                return NULL;
-       BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY;
-       TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE;
-       DevNode = iomm_table[TableIndex];
-
-       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 +612,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);
-
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_byte");
 
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
-                              IoAddress);
+       if (dn == NULL)
                return 0xff;
-       }
        do {
-               HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
-       } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
+               HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, bar_offset, 0);
+       } while (check_return_code("RDB", dn, &retry, ret.rc) != 0);
 
        return ret.value;
 }
 
-static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
+static u16 iseries_readw_be(const volatile void __iomem *addr)
 {
-       u64 BarOffset;
+       u64 bar_offset;
        u64 dsa;
        int retry = 0;
        struct HvCallPci_LoadReturn ret;
-       struct device_node *DevNode =
-               xlate_iomm_address(IoAddress, &dsa, &BarOffset);
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "read_word");
 
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
-                              IoAddress);
+       if (dn == NULL)
                return 0xffff;
-       }
        do {
                HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
-                               BarOffset, 0);
-       } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
+                               bar_offset, 0);
+       } while (check_return_code("RDW", dn, &retry, ret.rc) != 0);
 
        return ret.value;
 }
 
-static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
+static u32 iseries_readl_be(const volatile void __iomem *addr)
 {
-       u64 BarOffset;
+       u64 bar_offset;
        u64 dsa;
        int retry = 0;
        struct HvCallPci_LoadReturn ret;
-       struct device_node *DevNode =
-               xlate_iomm_address(IoAddress, &dsa, &BarOffset);
-
-       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 +672,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);
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_word");
 
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
-
-               if ((jiffies - last_jiffies) > 60 * HZ) {
-                       last_jiffies = jiffies;
-                       num_printed = 0;
-               }
-               if (num_printed++ < 10)
-                       printk(KERN_ERR "iSeries_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);
-
-       if (DevNode == NULL) {
-               static unsigned long last_jiffies;
-               static int num_printed;
+       struct device_node *dn =
+               xlate_iomm_address(addr, &dsa, &bar_offset, "write_long");
 
-               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 +745,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 +753,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 +761,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 +769,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 +777,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 +785,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 +794,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 +804,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 +814,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 +867,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,11 +894,21 @@ 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;
                phb->last_busno = bus;
                phb->ops = &iSeries_pci_ops;
+               phb->io_base_virt = (void __iomem *)_IO_BASE;
+               phb->io_resource.flags = IORESOURCE_IO;
+               phb->io_resource.start = BASE_IO_MEMORY;
+               phb->io_resource.end = END_IO_MEMORY;
+               phb->io_resource.name = "iSeries PCI IO";
+               phb->mem_resources[0].flags = IORESOURCE_MEM;
+               phb->mem_resources[0].start = BASE_IO_MEMORY;
+               phb->mem_resources[0].end = END_IO_MEMORY;
+               phb->mem_resources[0].name = "Series PCI MEM";
        }
 
        of_node_put(root);
index 33a8489fde54c636260781a944aa82b2549348e7..d9cf974c2718d12410073d4d23ddf8e470080934 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,16 @@ 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);
+struct pci_dev;
+
+#ifdef CONFIG_PCI
+extern void    iSeries_pcibios_init(void);
+extern void    iSeries_pci_final_fixup(void);
+extern void    iSeries_pcibios_fixup_resources(struct pci_dev *dev);
+#else
+static inline void     iSeries_pcibios_init(void) { }
+static inline void     iSeries_pci_final_fixup(void) { }
+static inline void     iSeries_pcibios_fixup_resources(struct pci_dev *dev) {}
+#endif
 
 #endif /* _PLATFORMS_ISERIES_PCI_H */
index 0877a88341100e7cdf25a49c3167f0c3a94fdffc..b72120751bbed16460b9f3c87c3e849b59228c2c 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)
@@ -641,24 +639,25 @@ static int __init iseries_probe(void)
 }
 
 define_machine(iseries) {
-       .name           = "iSeries",
-       .setup_arch     = iSeries_setup_arch,
-       .show_cpuinfo   = iSeries_show_cpuinfo,
-       .init_IRQ       = iSeries_init_IRQ,
-       .get_irq        = iSeries_get_irq,
-       .init_early     = iSeries_init_early,
-       .pcibios_fixup  = iSeries_pci_final_fixup,
-       .restart        = mf_reboot,
-       .power_off      = mf_power_off,
-       .halt           = mf_power_off,
-       .get_boot_time  = iSeries_get_boot_time,
-       .set_rtc_time   = iSeries_set_rtc_time,
-       .get_rtc_time   = iSeries_get_rtc_time,
-       .calibrate_decr = generic_calibrate_decr,
-       .progress       = iSeries_progress,
-       .probe          = iseries_probe,
-       .ioremap        = iseries_ioremap,
-       .iounmap        = iseries_iounmap,
+       .name                   = "iSeries",
+       .setup_arch             = iSeries_setup_arch,
+       .show_cpuinfo           = iSeries_show_cpuinfo,
+       .init_IRQ               = iSeries_init_IRQ,
+       .get_irq                = iSeries_get_irq,
+       .init_early             = iSeries_init_early,
+       .pcibios_fixup          = iSeries_pci_final_fixup,
+       .pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
+       .restart                = mf_reboot,
+       .power_off              = mf_power_off,
+       .halt                   = mf_power_off,
+       .get_boot_time          = iSeries_get_boot_time,
+       .set_rtc_time           = iSeries_set_rtc_time,
+       .get_rtc_time           = iSeries_get_rtc_time,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = iSeries_progress,
+       .probe                  = iseries_probe,
+       .ioremap                = iseries_ioremap,
+       .iounmap                = iseries_iounmap,
        /* XXX Implement enable_pmcs for iSeries */
 };
 
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 f7c95eb5d8baee6ac87afe31c57f5fa98a8c610c..a6467a5591fa921a3ac4faa0ea5b6450c08f5ea2 100644 (file)
@@ -1,6 +1,7 @@
 config PPC_MAPLE
        depends on PPC_MULTIPLATFORM && PPC64
        bool "Maple 970FX Evaluation Board"
+       select PCI
        select MPIC
        select U3_DART
        select MPIC_U3_HT_IRQS
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..b3458a181a150cb93277b5cf09e85cfd13722e76 100644 (file)
@@ -3,6 +3,7 @@ config PPC_PASEMI
        bool "PA Semi SoC-based platforms"
        default n
        select MPIC
+       select PCI
        select PPC_UDBG_16550
        select PPC_NATIVE
        select MPIC_BROKEN_REGREAD
@@ -17,7 +18,7 @@ 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..b5dfd42521102f8bfa72d6ea7e6ef0400b9b2e98 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);
@@ -215,7 +223,7 @@ static __init void pas_init_IRQ(void)
 
        mpic = mpic_alloc(mpic_node, openpic_addr,
                          MPIC_PRIMARY|MPIC_LARGE_VECTORS,
-                         0, 0, " PAS-OPIC  ");
+                         0, 0, "PASEMI-OPIC");
        BUG_ON(!mpic);
 
        mpic_assign_isu(mpic, 0, openpic_addr + 0x10000);
@@ -295,7 +303,7 @@ 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..1c58db9d42cb4d94251472cf88178599318baf24 100644 (file)
@@ -40,8 +40,6 @@
 static int has_uninorth;
 #ifdef CONFIG_PPC64
 static struct pci_controller *u3_agp;
-static struct pci_controller *u4_pcie;
-static struct pci_controller *u3_ht;
 #else
 static int has_second_ohare;
 #endif /* CONFIG_PPC64 */
@@ -314,12 +312,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
 
        /* We only allow config cycles to devices that are in OF device-tree
         * as we are apparently having some weird things going on with some
-        * revs of K2 on recent G5s
+        * revs of K2 on recent G5s, except for the host bridge itself, which
+        * is missing from the tree but we know we can probe.
         */
        if (bus->self)
                busdn = pci_device_to_OF_node(bus->self);
+       else if (devfn == 0)
+               return 0;
        else
-               busdn = hose->arch_data;
+               busdn = hose->dn;
        for (dn = busdn->child; dn; dn = dn->sibling)
                if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn)
                        break;
@@ -344,14 +345,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
                + (((unsigned int)bus) << 16) \
                + 0x01000000UL)
 
-static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose,
-                                            u8 bus, u8 devfn, u8 offset)
+static void __iomem *u3_ht_cfg_access(struct pci_controller *hose, u8 bus,
+                                     u8 devfn, u8 offset, int *swap)
 {
+       *swap = 1;
        if (bus == hose->first_busno) {
-               /* For now, we don't self probe U3 HT bridge */
-               if (PCI_SLOT(devfn) == 0)
-                       return NULL;
-               return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+               if (devfn != 0)
+                       return hose->cfg_data + U3_HT_CFA0(devfn, offset);
+               *swap = 0;
+               return ((void __iomem *)hose->cfg_addr) + (offset << 2);
        } else
                return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
 }
@@ -360,14 +362,15 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
                                    int offset, int len, u32 *val)
 {
        struct pci_controller *hose;
-       volatile void __iomem *addr;
+       void __iomem *addr;
+       int swap;
 
        hose = pci_bus_to_host(bus);
        if (hose == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (offset >= 0x100)
                return  PCIBIOS_BAD_REGISTER_NUMBER;
-       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -397,10 +400,10 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
                *val = in_8(addr);
                break;
        case 2:
-               *val = in_le16(addr);
+               *val = swap ? in_le16(addr) : in_be16(addr);
                break;
        default:
-               *val = in_le32(addr);
+               *val = swap ? in_le32(addr) : in_be32(addr);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
@@ -410,14 +413,15 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
                                     int offset, int len, u32 val)
 {
        struct pci_controller *hose;
-       volatile void __iomem *addr;
+       void __iomem *addr;
+       int swap;
 
        hose = pci_bus_to_host(bus);
        if (hose == NULL)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (offset >= 0x100)
                return  PCIBIOS_BAD_REGISTER_NUMBER;
-       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+       addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
        if (!addr)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -439,10 +443,10 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
                out_8(addr, val);
                break;
        case 2:
-               out_le16(addr, val);
+               swap ? out_le16(addr, val) : out_be16(addr, val);
                break;
        default:
-               out_le32((u32 __iomem *)addr, val);
+               swap ? out_le32(addr, val) : out_be32(addr, val);
                break;
        }
        return PCIBIOS_SUCCESSFUL;
@@ -725,7 +729,7 @@ static void __init setup_bandit(struct pci_controller *hose,
 static int __init setup_uninorth(struct pci_controller *hose,
                                 struct resource *addr)
 {
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
        hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -773,31 +777,72 @@ static void __init setup_u4_pcie(struct pci_controller* hose)
         */
        hose->first_busno = 0x00;
        hose->last_busno = 0xff;
-       u4_pcie = hose;
 }
 
-static void __init setup_u3_ht(struct pci_controller* hose)
+static void __init parse_region_decode(struct pci_controller *hose,
+                                      u32 decode)
 {
-       struct device_node *np = (struct device_node *)hose->arch_data;
-       struct pci_controller *other = NULL;
-       int i, cur;
+       unsigned long base, end, next = -1;
+       int i, cur = -1;
 
+       /* Iterate through all bits. We ignore the last bit as this region is
+        * reserved for the ROM among other niceties
+        */
+       for (i = 0; i < 31; i++) {
+               if ((decode & (0x80000000 >> i)) == 0)
+                       continue;
+               if (i < 16) {
+                       base = 0xf0000000 | (((u32)i) << 24);
+                       end = base + 0x00ffffff;
+               } else {
+                       base = ((u32)i-16) << 28;
+                       end = base + 0x0fffffff;
+               }
+               if (base != next) {
+                       if (++cur >= 3) {
+                               printk(KERN_WARNING "PCI: Too many ranges !\n");
+                               break;
+                       }
+                       hose->mem_resources[cur].flags = IORESOURCE_MEM;
+                       hose->mem_resources[cur].name = hose->dn->full_name;
+                       hose->mem_resources[cur].start = base;
+                       hose->mem_resources[cur].end = end;
+                       DBG("  %d: 0x%08lx-0x%08lx\n", cur, base, end);
+               } else {
+                       DBG("   :           -0x%08lx\n", end);
+                       hose->mem_resources[cur].end = end;
+               }
+               next = end + 1;
+       }
+}
+
+static void __init setup_u3_ht(struct pci_controller* hose)
+{
+       struct device_node *np = hose->dn;
+       struct resource cfg_res, self_res;
+       u32 decode;
 
        hose->ops = &u3_ht_pci_ops;
 
-       /* We hard code the address because of the different size of
-        * the reg address cell, we shall fix that by killing struct
-        * reg_property and using some accessor functions instead
+       /* Get base addresses from OF tree
         */
-       hose->cfg_data = ioremap(0xf2000000, 0x02000000);
+       if (of_address_to_resource(np, 0, &cfg_res) ||
+           of_address_to_resource(np, 1, &self_res)) {
+               printk(KERN_ERR "PCI: Failed to get U3/U4 HT resources !\n");
+               return;
+       }
+
+       /* Map external cfg space access into cfg_data and self registers
+        * into cfg_addr
+        */
+       hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
+       hose->cfg_addr = ioremap(self_res.start,
+                                self_res.end - self_res.start + 1);
 
        /*
-        * /ht node doesn't expose a "ranges" property, so we "remove"
-        * regions that have been allocated to AGP. So far, this version of
-        * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions
-        * to /ht. We need to fix that sooner or later by either parsing all
-        * child "ranges" properties or figuring out the U3 address space
-        * decoding logic and then read its configuration register (if any).
+        * /ht node doesn't expose a "ranges" property, we read the register
+        * that controls the decoding logic and use that for memory regions.
+        * The IO region is hard coded since it is fixed in HW as well.
         */
        hose->io_base_phys = 0xf4000000;
        hose->pci_io_size = 0x00400000;
@@ -808,76 +853,33 @@ static void __init setup_u3_ht(struct pci_controller* hose)
        hose->pci_mem_offset = 0;
        hose->first_busno = 0;
        hose->last_busno = 0xef;
-       hose->mem_resources[0].name = np->full_name;
-       hose->mem_resources[0].start = 0x80000000;
-       hose->mem_resources[0].end = 0xefffffff;
-       hose->mem_resources[0].flags = IORESOURCE_MEM;
-
-       u3_ht = hose;
 
-       if (u3_agp != NULL)
-               other = u3_agp;
-       else if (u4_pcie != NULL)
-               other = u4_pcie;
-
-       if (other == NULL) {
-               DBG("U3/4 has no AGP/PCIE, using full resource range\n");
-               return;
-       }
+       /* Note: fix offset when cfg_addr becomes a void * */
+       decode = in_be32(hose->cfg_addr + 0x80);
 
-       /* Fixup bus range vs. PCIE */
-       if (u4_pcie)
-               hose->last_busno = u4_pcie->first_busno - 1;
+       DBG("PCI: Apple HT bridge decode register: 0x%08x\n", decode);
 
-       /* We "remove" the AGP resources from the resources allocated to HT,
-        * that is we create "holes". However, that code does assumptions
-        * that so far happen to be true (cross fingers...), typically that
-        * resources in the AGP node are properly ordered
+       /* NOTE: The decode register setup is a bit weird... region
+        * 0xf8000000 for example is marked as enabled in there while it's
+        & actually the memory controller registers.
+        * That means that we are incorrectly attributing it to HT.
+        *
+        * In a similar vein, region 0xf4000000 is actually the HT IO space but
+        * also marked as enabled in here and 0xf9000000 is used by some other
+        * internal bits of the northbridge.
+        *
+        * Unfortunately, we can't just mask out those bit as we would end
+        * up with more regions than we can cope (linux can only cope with
+        * 3 memory regions for a PHB at this stage).
+        *
+        * So for now, we just do a little hack. We happen to -know- that
+        * Apple firmware doesn't assign things below 0xfa000000 for that
+        * bridge anyway so we mask out all bits we don't want.
         */
-       cur = 0;
-       for (i=0; i<3; i++) {
-               struct resource *res = &other->mem_resources[i];
-               if (res->flags != IORESOURCE_MEM)
-                       continue;
-               /* We don't care about "fine" resources */
-               if (res->start >= 0xf0000000)
-                       continue;
-               /* Check if it's just a matter of "shrinking" us in one
-                * direction
-                */
-               if (hose->mem_resources[cur].start == res->start) {
-                       DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
-                           cur, hose->mem_resources[cur].start,
-                           res->end + 1);
-                       hose->mem_resources[cur].start = res->end + 1;
-                       continue;
-               }
-               if (hose->mem_resources[cur].end == res->end) {
-                       DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
-                           cur, hose->mem_resources[cur].end,
-                           res->start - 1);
-                       hose->mem_resources[cur].end = res->start - 1;
-                       continue;
-               }
-               /* No, it's not the case, we need a hole */
-               if (cur == 2) {
-                       /* not enough resources for a hole, we drop part
-                        * of the range
-                        */
-                       printk(KERN_WARNING "Running out of resources"
-                              " for /ht host !\n");
-                       hose->mem_resources[cur].end = res->start - 1;
-                       continue;
-               }
-               cur++;
-               DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
-                   cur-1, res->start - 1, cur, res->end + 1);
-               hose->mem_resources[cur].name = np->full_name;
-               hose->mem_resources[cur].flags = IORESOURCE_MEM;
-               hose->mem_resources[cur].start = res->end + 1;
-               hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
-               hose->mem_resources[cur-1].end = res->start - 1;
-       }
+       decode &= 0x003fffff;
+
+       /* Now parse the resulting bits and build resources */
+       parse_region_decode(hose, decode);
 }
 #endif /* CONFIG_PPC64 */
 
@@ -994,6 +996,8 @@ void __init pmac_pci_init(void)
        struct device_node *np, *root;
        struct device_node *ht = NULL;
 
+       ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+
        root = of_find_node_by_path("/");
        if (root == NULL) {
                printk(KERN_CRIT "pmac_pci_init: can't find root "
@@ -1032,15 +1036,15 @@ 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;
        }
        /* pmac_check_ht_link(); */
 
-       /* Tell pci.c to not use the common resource allocation mechanism */
-       pci_probe_only = 1;
+       /* We can allocate missing resources if any */
+       pci_probe_only = 0;
 
 #else /* CONFIG_PPC64 */
        init_p2pbridge();
@@ -1051,13 +1055,13 @@ void __init pmac_pci_init(void)
         * some offset between bus number and domains for now when we
         * assign all busses should help for now
         */
-       if (pci_assign_all_buses)
+       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
                pcibios_assign_bus_offset = 0x10;
 #endif
 }
 
-int
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+#ifdef CONFIG_PPC32
+int pmac_pci_enable_device_hook(struct pci_dev *dev)
 {
        struct device_node* node;
        int updatecfg = 0;
@@ -1099,24 +1103,21 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
                updatecfg = 1;
        }
 
+       /*
+        * Fixup various header fields on 32 bits. We don't do that on
+        * 64 bits as some of these have strange values behind the HT
+        * bridge and we must not, for example, enable MWI or set the
+        * cache line size on them.
+        */
        if (updatecfg) {
                u16 cmd;
 
-               /*
-                * Make sure PCI is correctly configured
-                *
-                * We use old pci_bios versions of the function since, by
-                * default, gmac is not powered up, and so will be absent
-                * from the kernel initial PCI lookup.
-                *
-                * Should be replaced by 2.4 new PCI mechanisms and really
-                * register the device.
-                */
                pci_read_config_word(dev, PCI_COMMAND, &cmd);
                cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
                        | PCI_COMMAND_INVALIDATE;
                pci_write_config_word(dev, PCI_COMMAND, cmd);
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+
                pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
                                      L1_CACHE_BYTES >> 2);
        }
@@ -1124,6 +1125,18 @@ pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
        return 0;
 }
 
+void __devinit pmac_pci_fixup_ohci(struct pci_dev *dev)
+{
+       struct device_node *node = pci_device_to_OF_node(dev);
+
+       /* We don't want to assign resources to USB controllers
+        * absent from the OF tree (iBook second controller)
+        */
+       if (dev->class == PCI_CLASS_SERIAL_USB_OHCI && !node)
+               dev->resource[0].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_ANY_ID, pmac_pci_fixup_ohci);
+
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
@@ -1171,7 +1184,6 @@ void __init pmac_pcibios_after_init(void)
        of_node_put(nd);
 }
 
-#ifdef CONFIG_PPC32
 void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 {
        if (!machine_is(powermac))
@@ -1259,7 +1271,7 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
        }
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
-#endif
+#endif /* CONFIG_PPC32 */
 
 /*
  * Disable second function on K2-SATA, it's broken
index fcde070f7054dd4d341b86f9529693e4048985f0..b3abaaf61eb47fa589625ceb00e7c7ecf3d32bf8 100644 (file)
@@ -26,7 +26,7 @@ extern void pmac_pci_init(void);
 extern void pmac_nvram_update(void);
 extern unsigned char pmac_nvram_read_byte(int addr);
 extern void pmac_nvram_write_byte(int addr, unsigned char val);
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev);
 extern void pmac_pcibios_after_init(void);
 extern int of_show_percpuinfo(struct seq_file *m, int i);
 
index 02c533096627851363c3864232b53d130659ed8b..adad4e97638182ce31ef9733ba14c6fd7e1c709f 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>
@@ -94,7 +94,6 @@ extern struct machdep_calls pmac_md;
 #define DEFAULT_ROOT_DEVICE Root_SDA1  /* sda1 - slightly silly choice */
 
 #ifdef CONFIG_PPC64
-#include <asm/udbg.h>
 int sccdbg;
 #endif
 
@@ -613,9 +612,11 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
 
        /* We need to use normal PCI probing for the AGP bus,
         * since the device for the AGP bridge isn't in the tree.
+        * Same for the PCIe host on U4 and the HT host bridge.
         */
        if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
-                                 of_device_is_compatible(node, "u4-pcie")))
+                                 of_device_is_compatible(node, "u4-pcie") ||
+                                 of_device_is_compatible(node, "u3-ht")))
                return PCI_PROBE_NORMAL;
        return PCI_PROBE_DEVTREE;
 }
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 d1630a074acf6fb0e527bb4e900193914af662b6..5ad41189b494e030e9a6e943f81bb0653cabb40f 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/spu_priv1.h>
 #include <asm/lv1call.h>
 
+#include "../cell/spufs/spufs.h"
 #include "platform.h"
 
 /* spu_management_ops */
@@ -419,10 +420,34 @@ static int ps3_init_affinity(void)
        return 0;
 }
 
+/**
+ * ps3_enable_spu - Enable SPU run control.
+ *
+ * An outstanding enhancement for the PS3 would be to add a guard to check
+ * for incorrect access to the spu problem state when the spu context is
+ * disabled.  This check could be implemented with a flag added to the spu
+ * context that would inhibit mapping problem state pages, and a routine
+ * to unmap spu problem state pages.  When the spu is enabled with
+ * ps3_enable_spu() the flag would be set allowing pages to be mapped,
+ * and when the spu is disabled with ps3_disable_spu() the flag would be
+ * cleared and the mapped problem state pages would be unmapped.
+ */
+
+static void ps3_enable_spu(struct spu_context *ctx)
+{
+}
+
+static void ps3_disable_spu(struct spu_context *ctx)
+{
+       ctx->ops->runcntl_stop(ctx);
+}
+
 const struct spu_management_ops spu_management_ps3_ops = {
        .enumerate_spus = ps3_enumerate_spus,
        .create_spu = ps3_create_spu,
        .destroy_spu = ps3_destroy_spu,
+       .enable_spu = ps3_enable_spu,
+       .disable_spu = ps3_disable_spu,
        .init_affinity = ps3_init_affinity,
 };
 
@@ -505,8 +530,6 @@ static void mfc_sr1_set(struct spu *spu, u64 sr1)
        static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
                | MFC_STATE1_PROBLEM_STATE_MASK);
 
-       sr1 |= MFC_STATE1_MASTER_RUN_CONTROL_MASK;
-
        BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
 
        spu_pdata(spu)->cache.sr1 = sr1;
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 47f0e0857f0ecac871c87e28fddec3579bef9da9..5a5a19e40bb4587e80943991e8ebfc9621bbfd7b 100644 (file)
@@ -83,7 +83,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
 /* Must be called before pci_bus_add_devices */
 void
-pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+pcibios_fixup_new_pci_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
@@ -98,8 +98,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
                        /* Fill device archdata and setup iommu table */
                        pcibios_setup_new_device(dev);
 
-                       if(fix_bus)
-                               pcibios_fixup_device_resources(dev, bus);
                        pci_read_irq_line(dev);
                        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                                struct resource *r = &dev->resource[i];
@@ -132,8 +130,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
 
        pci_scan_child_bus(child_bus);
 
-       /* Fixup new pci devices without touching bus struct */
-       pcibios_fixup_new_pci_devices(child_bus, 0);
+       /* Fixup new pci devices */
+       pcibios_fixup_new_pci_devices(child_bus);
 
        /* Make the discovered devices available */
        pci_bus_add_devices(child_bus);
@@ -169,7 +167,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
                /* use ofdt-based probe */
                of_scan_bus(dn, bus);
                if (!list_empty(&bus->devices)) {
-                       pcibios_fixup_new_pci_devices(bus, 0);
+                       pcibios_fixup_new_pci_devices(bus);
                        pci_bus_add_devices(bus);
                        eeh_add_device_tree_late(bus);
                }
@@ -178,7 +176,7 @@ pcibios_add_pci_devices(struct pci_bus * bus)
                slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
                num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
                if (num) {
-                       pcibios_fixup_new_pci_devices(bus, 1);
+                       pcibios_fixup_new_pci_devices(bus);
                        pci_bus_add_devices(bus);
                        eeh_add_device_tree_late(bus);
                }
@@ -208,7 +206,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
                eeh_add_device_tree_early(dn);
 
        scan_phb(phb);
-       pcibios_fixup_new_pci_devices(phb->bus, 0);
+       pcibios_fixup_new_pci_devices(phb->bus);
        pci_bus_add_devices(phb->bus);
        eeh_add_device_tree_late(phb->bus);
 
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 66e7d68ffeb101c60425d6b054ebd348d593e2df..8f8dd9c3ca6b9dc499d7a2983d63770a9709a719 100644 (file)
@@ -87,19 +87,25 @@ static int ibm_int_off;
 /* Direct HW low level accessors */
 
 
-static inline unsigned int direct_xirr_info_get(int n_cpu)
+static inline unsigned int direct_xirr_info_get(void)
 {
-       return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
+       int cpu = smp_processor_id();
+
+       return in_be32(&xics_per_cpu[cpu]->xirr.word);
 }
 
-static inline void direct_xirr_info_set(int n_cpu, int value)
+static inline void direct_xirr_info_set(int value)
 {
-       out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
+       int cpu = smp_processor_id();
+
+       out_be32(&xics_per_cpu[cpu]->xirr.word, value);
 }
 
-static inline void direct_cppr_info(int n_cpu, u8 value)
+static inline void direct_cppr_info(u8 value)
 {
-       out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
+       int cpu = smp_processor_id();
+
+       out_8(&xics_per_cpu[cpu]->xirr.bytes[0], value);
 }
 
 static inline void direct_qirr_info(int n_cpu, u8 value)
@@ -111,7 +117,7 @@ static inline void direct_qirr_info(int n_cpu, u8 value)
 /* LPAR low level accessors */
 
 
-static inline unsigned int lpar_xirr_info_get(int n_cpu)
+static inline unsigned int lpar_xirr_info_get(void)
 {
        unsigned long lpar_rc;
        unsigned long return_value;
@@ -122,7 +128,7 @@ static inline unsigned int lpar_xirr_info_get(int n_cpu)
        return (unsigned int)return_value;
 }
 
-static inline void lpar_xirr_info_set(int n_cpu, int value)
+static inline void lpar_xirr_info_set(int value)
 {
        unsigned long lpar_rc;
        unsigned long val64 = value & 0xffffffff;
@@ -133,7 +139,7 @@ static inline void lpar_xirr_info_set(int n_cpu, int value)
                      val64);
 }
 
-static inline void lpar_cppr_info(int n_cpu, u8 value)
+static inline void lpar_cppr_info(u8 value)
 {
        unsigned long lpar_rc;
 
@@ -275,21 +281,19 @@ static unsigned int xics_startup(unsigned int virq)
 
 static void xics_eoi_direct(unsigned int virq)
 {
-       int cpu = smp_processor_id();
        unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
        iosync();
-       direct_xirr_info_set(cpu, (0xff << 24) | irq);
+       direct_xirr_info_set((0xff << 24) | irq);
 }
 
 
 static void xics_eoi_lpar(unsigned int virq)
 {
-       int cpu = smp_processor_id();
        unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
        iosync();
-       lpar_xirr_info_set(cpu, (0xff << 24) | irq);
+       lpar_xirr_info_set((0xff << 24) | irq);
 }
 
 static inline unsigned int xics_remap_irq(unsigned int vec)
@@ -312,16 +316,12 @@ static inline unsigned int xics_remap_irq(unsigned int vec)
 
 static unsigned int xics_get_irq_direct(void)
 {
-       unsigned int cpu = smp_processor_id();
-
-       return xics_remap_irq(direct_xirr_info_get(cpu));
+       return xics_remap_irq(direct_xirr_info_get());
 }
 
 static unsigned int xics_get_irq_lpar(void)
 {
-       unsigned int cpu = smp_processor_id();
-
-       return xics_remap_irq(lpar_xirr_info_get(cpu));
+       return xics_remap_irq(lpar_xirr_info_get());
 }
 
 #ifdef CONFIG_SMP
@@ -387,12 +387,12 @@ void xics_cause_IPI(int cpu)
 
 #endif /* CONFIG_SMP */
 
-static void xics_set_cpu_priority(int cpu, unsigned char cppr)
+static void xics_set_cpu_priority(unsigned char cppr)
 {
        if (firmware_has_feature(FW_FEATURE_LPAR))
-               lpar_cppr_info(cpu, cppr);
+               lpar_cppr_info(cppr);
        else
-               direct_cppr_info(cpu, cppr);
+               direct_cppr_info(cppr);
        iosync();
 }
 
@@ -440,9 +440,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
 
 void xics_setup_cpu(void)
 {
-       int cpu = smp_processor_id();
-
-       xics_set_cpu_priority(cpu, 0xff);
+       xics_set_cpu_priority(0xff);
 
        /*
         * Put the calling processor into the GIQ.  This is really only
@@ -783,7 +781,7 @@ void xics_teardown_cpu(int secondary)
        unsigned int ipi;
        struct irq_desc *desc;
 
-       xics_set_cpu_priority(cpu, 0);
+       xics_set_cpu_priority(0);
 
        /*
         * Clear IPI
@@ -824,10 +822,11 @@ void xics_teardown_cpu(int secondary)
 void xics_migrate_irqs_away(void)
 {
        int status;
-       unsigned int irq, virq, cpu = smp_processor_id();
+       int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
+       unsigned int irq, virq;
 
        /* Reject any interrupt that was queued to us... */
-       xics_set_cpu_priority(cpu, 0);
+       xics_set_cpu_priority(0);
 
        /* remove ourselves from the global interrupt queue */
        status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
@@ -835,7 +834,7 @@ void xics_migrate_irqs_away(void)
        WARN_ON(status < 0);
 
        /* Allow IPIs again... */
-       xics_set_cpu_priority(cpu, DEFAULT_PRIORITY);
+       xics_set_cpu_priority(DEFAULT_PRIORITY);
 
        for_each_irq(virq) {
                struct irq_desc *desc;
@@ -874,7 +873,7 @@ void xics_migrate_irqs_away(void)
                 * The irq has to be migrated only in the single cpu
                 * case.
                 */
-               if (xics_status[0] != get_hard_smp_processor_id(cpu))
+               if (xics_status[0] != hw_cpu)
                        goto unlock;
 
                printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
index db0ec3ba3ae2a96f1008544b50ea594280aefa29..9ffd809d29e218dea80039b60fbe245d9b515497 100644 (file)
@@ -21,9 +21,6 @@ extern void xics_cause_IPI(int cpu);
 extern  void xics_request_IPIs(void);
 extern void xics_migrate_irqs_away(void);
 
-/* first argument is ignored for now*/
-void pSeriesLP_cppr_info(int n_cpu, u8 value);
-
 struct xics_ipi_struct {
        volatile unsigned long value;
 } ____cacheline_aligned;
index 99a77d743d48c55643cfa3b59ddd09c3b65bf2ad..85cf8c60f0be0fa059bd4c318330efa70f2ad22a 100644 (file)
@@ -2,7 +2,7 @@ ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS                   += -mno-minimal-toc
 endif
 
-mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
+mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
 
 obj-$(CONFIG_PPC_MPC106)       += grackle.o
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 e802cb4eb69a5c575a8849147b1be7083568e9a7..c960a8b4965538a78d92bf7c2469f9f4ffed591d 100644 (file)
@@ -20,7 +20,7 @@ struct bcom_bd; /* defined later on ... */
 
 
 /* ======================================================================== */
-/* Generic task managment                                                   */
+/* Generic task management                                                   */
 /* ======================================================================== */
 
 /**
index f6a63780bbde5b3bcd7223cc34e0a85f6293f9a3..621bc6c1d4083601dcbfc24ebefdddb8c8e519f0 100644 (file)
@@ -240,6 +240,34 @@ void __init cpm_reset(void)
 #endif
 }
 
+static DEFINE_SPINLOCK(cmd_lock);
+
+#define MAX_CR_CMD_LOOPS        10000
+
+int cpm_command(u32 command, u8 opcode)
+{
+       int i, ret;
+       unsigned long flags;
+
+       if (command & 0xffffff0f)
+               return -EINVAL;
+
+       spin_lock_irqsave(&cmd_lock, flags);
+
+       ret = 0;
+       out_be16(&cpmp->cp_cpcr, command | CPM_CR_FLG | (opcode << 8));
+       for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+               if ((in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+                       goto out;
+
+       printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
+       ret = -EIO;
+out:
+       spin_unlock_irqrestore(&cmd_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(cpm_command);
+
 /* We used to do this earlier, but have to postpone as long as possible
  * to ensure the kernel VM is now running.
  */
@@ -408,7 +436,7 @@ EXPORT_SYMBOL(cpm_dpram_phys);
 #endif /* !CONFIG_PPC_CPM_NEW_BINDING */
 
 struct cpm_ioport16 {
-       __be16 dir, par, sor, dat, intr;
+       __be16 dir, par, odr_sor, dat, intr;
        __be16 res[3];
 };
 
@@ -438,6 +466,13 @@ static void cpm1_set_pin32(int port, int pin, int flags)
        else
                clrbits32(&iop->par, pin);
 
+       if (port == CPM_PORTB) {
+               if (flags & CPM_PIN_OPENDRAIN)
+                       setbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
+               else
+                       clrbits16(&mpc8xx_immr->im_cpm.cp_pbodr, pin);
+       }
+
        if (port == CPM_PORTE) {
                if (flags & CPM_PIN_SECONDARY)
                        setbits32(&iop->sor, pin);
@@ -471,11 +506,17 @@ static void cpm1_set_pin16(int port, int pin, int flags)
        else
                clrbits16(&iop->par, pin);
 
+       if (port == CPM_PORTA) {
+               if (flags & CPM_PIN_OPENDRAIN)
+                       setbits16(&iop->odr_sor, pin);
+               else
+                       clrbits16(&iop->odr_sor, pin);
+       }
        if (port == CPM_PORTC) {
                if (flags & CPM_PIN_SECONDARY)
-                       setbits16(&iop->sor, pin);
+                       setbits16(&iop->odr_sor, pin);
                else
-                       clrbits16(&iop->sor, pin);
+                       clrbits16(&iop->odr_sor, pin);
        }
 }
 
index c1d82403202084c5e39e7061f488b6113aafbf3e..f7188e2ba6696e21197dfbb5c9794f44306a8876 100644 (file)
@@ -82,6 +82,31 @@ void __init cpm2_reset(void)
        cpmp = &cpm2_immr->im_cpm;
 }
 
+static DEFINE_SPINLOCK(cmd_lock);
+
+#define MAX_CR_CMD_LOOPS        10000
+
+int cpm_command(u32 command, u8 opcode)
+{
+       int i, ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cmd_lock, flags);
+
+       ret = 0;
+       out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
+       for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
+               if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
+                       goto out;
+
+       printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
+       ret = -EIO;
+out:
+       spin_unlock_irqrestore(&cmd_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(cpm_command);
+
 /* Set a baud rate generator.  This needs lots of work.  There are
  * eight BRGs, which can be connected to the CPM channels or output
  * as clocks.  The BRGs are in two different block of internal
index 33df4c347ca7cb69cae3d8f945afb168695c011f..4b1d5120c1224690bb04f12d916af1abdfc3a4a7 100644 (file)
@@ -202,7 +202,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                        " bus 0\n", dev->full_name);
 
-       pci_assign_all_buses = 1;
+       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
@@ -222,7 +222,7 @@ 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 3ace7474809e00ba6d21be039e2d6dc21215b442..4baad80ab7316da61053dc7a3dd1a568497dcddd 100644 (file)
@@ -132,15 +132,18 @@ EXPORT_SYMBOL(get_baudrate);
 
 static int __init gfar_mdio_of_init(void)
 {
-       struct device_node *np;
-       unsigned int i;
+       struct device_node *np = NULL;
        struct platform_device *mdio_dev;
        struct resource res;
        int ret;
 
-       for (np = NULL, i = 0;
-            (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
-            i++) {
+       np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+
+       /* try the deprecated version */
+       if (!np)
+               np = of_find_compatible_node(np, "mdio", "gianfar");
+
+       if (np) {
                int k;
                struct device_node *child = NULL;
                struct gianfar_mdio_data mdio_data;
@@ -179,11 +182,13 @@ static int __init gfar_mdio_of_init(void)
                        goto unreg;
        }
 
+       of_node_put(np);
        return 0;
 
 unreg:
        platform_device_unregister(mdio_dev);
 err:
+       of_node_put(np);
        return ret;
 }
 
@@ -390,13 +395,11 @@ static void __init of_register_i2c_devices(struct device_node *adap_node,
 static int __init fsl_i2c_of_init(void)
 {
        struct device_node *np;
-       unsigned int i;
+       unsigned int i = 0;
        struct platform_device *i2c_dev;
        int ret;
 
-       for (np = NULL, i = 0;
-            (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
-            i++) {
+       for_each_compatible_node(np, NULL, "fsl-i2c") {
                struct resource r[2];
                struct fsl_i2c_platform_data i2c_data;
                const unsigned char *flags = NULL;
@@ -432,7 +435,7 @@ static int __init fsl_i2c_of_init(void)
                if (ret)
                        goto unreg;
 
-               of_register_i2c_devices(np, i);
+               of_register_i2c_devices(np, i++);
        }
 
        return 0;
index 11ad5622eb760bd71ea49139f6eb62b7c7a6bfb3..d502927644c68c69a1328c436c2030bed9349f1c 100644 (file)
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_controller *hose)
 {
        setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
        if (machine_is_compatible("PowerMac1,1"))
-               pci_assign_all_buses = 1;
+               ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
        if (machine_is_compatible("AAPL,PowerBook1998"))
                grackle_set_loop_snoop(hose, 1);
 #if 0  /* Disabled for now, HW problems ??? */
index 05a56e55804c3ab4395671b9bd2a4713972cbf20..7274750fd9c6fd32674d8d8da565cab3d5626c4a 100644 (file)
 #include "ipic.h"
 
 static struct ipic * primary_ipic;
+static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
 static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
+       [1] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_C,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 16,
+               .prio_mask = 0,
+       },
+       [2] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_C,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 17,
+               .prio_mask = 1,
+       },
+       [4] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_C,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 19,
+               .prio_mask = 3,
+       },
        [9] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
@@ -42,7 +63,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 0,
        },
        [10] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
@@ -50,15 +70,27 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 1,
        },
        [11] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
                .bit    = 26,
                .prio_mask = 2,
        },
+       [12] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_D,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 27,
+               .prio_mask = 3,
+       },
+       [13] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_D,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 28,
+               .prio_mask = 4,
+       },
        [14] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
@@ -66,7 +98,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 5,
        },
        [15] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
@@ -74,7 +105,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 6,
        },
        [16] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_D,
                .force  = IPIC_SIFCR_H,
@@ -82,7 +112,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 7,
        },
        [17] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SEFCR,
@@ -90,7 +120,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 5,
        },
        [18] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SEFCR,
@@ -98,7 +128,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 6,
        },
        [19] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SEFCR,
@@ -106,7 +136,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 7,
        },
        [20] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SEFCR,
@@ -114,7 +144,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 4,
        },
        [21] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SEFCR,
@@ -122,7 +152,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 5,
        },
        [22] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SEFCR,
@@ -130,7 +160,7 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 6,
        },
        [23] = {
-               .pend   = IPIC_SEPNR,
+               .ack    = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SEFCR,
@@ -138,7 +168,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 7,
        },
        [32] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -146,7 +175,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 0,
        },
        [33] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -154,7 +182,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 1,
        },
        [34] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -162,7 +189,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 2,
        },
        [35] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -170,7 +196,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 3,
        },
        [36] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -178,7 +203,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 4,
        },
        [37] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -186,7 +210,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 5,
        },
        [38] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
@@ -194,15 +217,48 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 6,
        },
        [39] = {
-               .pend   = IPIC_SIPNR_H,
                .mask   = IPIC_SIMSR_H,
                .prio   = IPIC_SIPRR_A,
                .force  = IPIC_SIFCR_H,
                .bit    = 7,
                .prio_mask = 7,
        },
+       [42] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_B,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 10,
+               .prio_mask = 2,
+       },
+       [44] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_B,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 12,
+               .prio_mask = 4,
+       },
+       [45] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_B,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 13,
+               .prio_mask = 5,
+       },
+       [46] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_B,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 14,
+               .prio_mask = 6,
+       },
+       [47] = {
+               .mask   = IPIC_SIMSR_H,
+               .prio   = IPIC_SIPRR_B,
+               .force  = IPIC_SIFCR_H,
+               .bit    = 15,
+               .prio_mask = 7,
+       },
        [48] = {
-               .pend   = IPIC_SEPNR,
                .mask   = IPIC_SEMSR,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SEFCR,
@@ -210,7 +266,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 4,
        },
        [64] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SIFCR_L,
@@ -218,7 +273,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 0,
        },
        [65] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SIFCR_L,
@@ -226,7 +280,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 1,
        },
        [66] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SIFCR_L,
@@ -234,7 +287,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 2,
        },
        [67] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_A,
                .force  = IPIC_SIFCR_L,
@@ -242,7 +294,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 3,
        },
        [68] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SIFCR_L,
@@ -250,7 +301,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 0,
        },
        [69] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SIFCR_L,
@@ -258,7 +308,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 1,
        },
        [70] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SIFCR_L,
@@ -266,7 +315,6 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 2,
        },
        [71] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = IPIC_SMPRR_B,
                .force  = IPIC_SIFCR_L,
@@ -274,91 +322,114 @@ static struct ipic_info ipic_info[] = {
                .prio_mask = 3,
        },
        [72] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 8,
        },
        [73] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 9,
        },
        [74] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 10,
        },
        [75] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 11,
        },
        [76] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 12,
        },
        [77] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 13,
        },
        [78] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 14,
        },
        [79] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 15,
        },
        [80] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 16,
        },
+       [81] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 17,
+       },
+       [82] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 18,
+       },
        [84] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 20,
        },
        [85] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 21,
        },
+       [86] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 22,
+       },
+       [87] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 23,
+       },
+       [88] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 24,
+       },
+       [89] = {
+               .mask   = IPIC_SIMSR_L,
+               .prio   = 0,
+               .force  = IPIC_SIFCR_L,
+               .bit    = 25,
+       },
        [90] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
                .bit    = 26,
        },
        [91] = {
-               .pend   = IPIC_SIPNR_L,
                .mask   = IPIC_SIMSR_L,
                .prio   = 0,
                .force  = IPIC_SIFCR_L,
@@ -412,6 +483,10 @@ static void ipic_mask_irq(unsigned int virq)
        temp &= ~(1 << (31 - ipic_info[src].bit));
        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
+       /* mb() can't guarantee that masking is finished.  But it does finish
+        * for nearly all cases. */
+       mb();
+
        spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
@@ -424,9 +499,13 @@ static void ipic_ack_irq(unsigned int virq)
 
        spin_lock_irqsave(&ipic_lock, flags);
 
-       temp = ipic_read(ipic->regs, ipic_info[src].pend);
+       temp = ipic_read(ipic->regs, ipic_info[src].ack);
        temp |= (1 << (31 - ipic_info[src].bit));
-       ipic_write(ipic->regs, ipic_info[src].pend, temp);
+       ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+       /* mb() can't guarantee that ack is finished.  But it does finish
+        * for nearly all cases. */
+       mb();
 
        spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -444,9 +523,13 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
        temp &= ~(1 << (31 - ipic_info[src].bit));
        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 
-       temp = ipic_read(ipic->regs, ipic_info[src].pend);
+       temp = ipic_read(ipic->regs, ipic_info[src].ack);
        temp |= (1 << (31 - ipic_info[src].bit));
-       ipic_write(ipic->regs, ipic_info[src].pend, temp);
+       ipic_write(ipic->regs, ipic_info[src].ack, temp);
+
+       /* mb() can't guarantee that ack is finished.  But it does finish
+        * for nearly all cases. */
+       mb();
 
        spin_unlock_irqrestore(&ipic_lock, flags);
 }
@@ -468,14 +551,22 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
                        flow_type);
                return -EINVAL;
        }
+       /* ipic supports only edge mode on external interrupts */
+       if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
+               printk(KERN_ERR "ipic: edge sense not supported on internal "
+                               "interrupts\n");
+               return -EINVAL;
+       }
 
        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
        desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
        if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
                desc->status |= IRQ_LEVEL;
                desc->handle_irq = handle_level_irq;
+               desc->chip = &ipic_level_irq_chip;
        } else {
                desc->handle_irq = handle_edge_irq;
+               desc->chip = &ipic_edge_irq_chip;
        }
 
        /* only EXT IRQ senses are programmable on ipic
@@ -500,7 +591,16 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
        return 0;
 }
 
-static struct irq_chip ipic_irq_chip = {
+/* level interrupts and edge interrupts have different ack operations */
+static struct irq_chip ipic_level_irq_chip = {
+       .typename       = " IPIC  ",
+       .unmask         = ipic_unmask_irq,
+       .mask           = ipic_mask_irq,
+       .mask_ack       = ipic_mask_irq,
+       .set_type       = ipic_set_irq_type,
+};
+
+static struct irq_chip ipic_edge_irq_chip = {
        .typename       = " IPIC  ",
        .unmask         = ipic_unmask_irq,
        .mask           = ipic_mask_irq,
@@ -519,13 +619,9 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq,
                         irq_hw_number_t hw)
 {
        struct ipic *ipic = h->host_data;
-       struct irq_chip *chip;
-
-       /* Default chip */
-       chip = &ipic->hc_irq;
 
        set_irq_chip_data(virq, ipic);
-       set_irq_chip_and_handler(virq, chip, handle_level_irq);
+       set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 
        /* Set default irq type */
        set_irq_type(virq, IRQ_TYPE_NONE);
@@ -584,7 +680,6 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
        ipic->regs = ioremap(res.start, res.end - res.start + 1);
 
        ipic->irqhost->host_data = ipic;
-       ipic->hc_irq = ipic_irq_chip;
 
        /* init hw */
        ipic_write(ipic->regs, IPIC_SICNR, 0x0);
@@ -593,6 +688,10 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
         * configure SICFR accordingly */
        if (flags & IPIC_SPREADMODE_GRP_A)
                temp |= SICFR_IPSA;
+       if (flags & IPIC_SPREADMODE_GRP_B)
+               temp |= SICFR_IPSB;
+       if (flags & IPIC_SPREADMODE_GRP_C)
+               temp |= SICFR_IPSC;
        if (flags & IPIC_SPREADMODE_GRP_D)
                temp |= SICFR_IPSD;
        if (flags & IPIC_SPREADMODE_MIX_A)
@@ -600,7 +699,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
        if (flags & IPIC_SPREADMODE_MIX_B)
                temp |= SICFR_MPSB;
 
-       ipic_write(ipic->regs, IPIC_SICNR, temp);
+       ipic_write(ipic->regs, IPIC_SICFR, temp);
 
        /* handle MCP route */
        temp = 0;
@@ -672,10 +771,12 @@ void ipic_set_highest_priority(unsigned int virq)
 
 void ipic_set_default_priority(void)
 {
-       ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
-       ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
-       ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
-       ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
+       ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
 }
 
 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
index bb309a501b2d475e036f8c18da88578b1617c9dc..9391c57b0c5115814b56c3c6a6b740e20455ddde 100644 (file)
 #define IPIC_IRQ_EXT7 23
 
 /* Default Priority Registers */
-#define IPIC_SIPRR_A_DEFAULT 0x05309770
-#define IPIC_SIPRR_D_DEFAULT 0x05309770
-#define IPIC_SMPRR_A_DEFAULT 0x05309770
-#define IPIC_SMPRR_B_DEFAULT 0x05309770
+#define IPIC_PRIORITY_DEFAULT 0x05309770
 
 /* System Global Interrupt Configuration Register */
 #define        SICFR_IPSA      0x00010000
+#define        SICFR_IPSB      0x00020000
+#define        SICFR_IPSC      0x00040000
 #define        SICFR_IPSD      0x00080000
 #define        SICFR_MPSA      0x00200000
 #define        SICFR_MPSB      0x00400000
@@ -45,13 +44,11 @@ struct ipic {
 
        /* The remapper for this IPIC */
        struct irq_host         *irqhost;
-
-       /* The "linux" controller struct */
-       struct irq_chip         hc_irq;
 };
 
 struct ipic_info {
-       u8      pend;           /* pending register offset from base */
+       u8      ack;            /* pending register offset from base if the irq
+                                  supports ack operation */
        u8      mask;           /* mask register offset from base */
        u8      prio;           /* priority register offset from base */
        u8      force;          /* force register offset from base */
index e073e246293d08fb44be9bf927eb4402e1331d18..7b49633a4bd0590960af399f67b70c41c7c5e841 100644 (file)
@@ -99,7 +99,7 @@ int __init mmio_nvram_init(void)
        nvram_addr = r.start;
        mmio_nvram_len = r.end - r.start + 1;
        if ( (!mmio_nvram_len) || (!nvram_addr) ) {
-               printk(KERN_WARNING "nvram: address or lenght is 0\n");
+               printk(KERN_WARNING "nvram: address or length is 0\n");
                ret = -EIO;
                goto out;
        }
index e47938899a9268c3e926979f7f15e73394810c3d..f74fe26b787e1c81b423e8359e1bdc0e8d0e6e8d 100644 (file)
@@ -612,12 +612,11 @@ static inline void mpic_eoi(struct mpic *mpic)
 }
 
 #ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
+static irqreturn_t mpic_ipi_action(int irq, void *data)
 {
-       struct mpic *mpic;
+       long ipi = (long)data;
 
-       mpic = mpic_find(irq, NULL);
-       smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]);
+       smp_message_recv(ipi);
 
        return IRQ_HANDLED;
 }
@@ -842,6 +841,24 @@ int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
        return 0;
 }
 
+void mpic_set_vector(unsigned int virq, unsigned int vector)
+{
+       struct mpic *mpic = mpic_from_irq(virq);
+       unsigned int src = mpic_irq_to_hw(virq);
+       unsigned int vecpri;
+
+       DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
+           mpic, virq, src, vector);
+
+       if (src >= mpic->irq_count)
+               return;
+
+       vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+       vecpri = vecpri & ~MPIC_INFO(VECPRI_VECTOR_MASK);
+       vecpri |= vector;
+       mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+}
+
 static struct irq_chip mpic_irq_chip = {
        .mask           = mpic_mask_irq,
        .unmask         = mpic_unmask_irq,
@@ -1230,6 +1247,8 @@ void __init mpic_init(struct mpic *mpic)
                mpic_u3msi_init(mpic);
        }
 
+       mpic_pasemi_msi_init(mpic);
+
        for (i = 0; i < mpic->num_sources; i++) {
                /* start with vector = source number, and masked */
                u32 vecpri = MPIC_VECPRI_MASK | i |
@@ -1457,7 +1476,7 @@ unsigned int mpic_get_irq(void)
 void mpic_request_ipis(void)
 {
        struct mpic *mpic = mpic_primary;
-       int i, err;
+       long i, err;
        static char *ipi_names[] = {
                "IPI0 (call function)",
                "IPI1 (reschedule)",
@@ -1472,14 +1491,14 @@ void mpic_request_ipis(void)
                unsigned int vipi = irq_create_mapping(mpic->irqhost,
                                                       mpic->ipi_vecs[0] + i);
                if (vipi == NO_IRQ) {
-                       printk(KERN_ERR "Failed to map IPI %d\n", i);
+                       printk(KERN_ERR "Failed to map IPI %ld\n", i);
                        break;
                }
                err = request_irq(vipi, mpic_ipi_action,
                                  IRQF_DISABLED|IRQF_PERCPU,
-                                 ipi_names[i], mpic);
+                                 ipi_names[i], (void *)i);
                if (err) {
-                       printk(KERN_ERR "Request of irq %d for IPI %d failed\n",
+                       printk(KERN_ERR "Request of irq %d for IPI %ld failed\n",
                               vipi, i);
                        break;
                }
index 1cb6bd841027d0f3a6b9d80e2fdd41778a159fdb..4783c6e9f30d0dae8a109deb982ae1f1402dafb7 100644 (file)
@@ -17,6 +17,7 @@ extern int mpic_msi_init_allocator(struct mpic *mpic);
 extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
 extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
 extern int mpic_u3msi_init(struct mpic *mpic);
+extern int mpic_pasemi_msi_init(struct mpic *mpic);
 #else
 static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
                                          irq_hw_number_t hwirq)
@@ -28,9 +29,15 @@ static inline int mpic_u3msi_init(struct mpic *mpic)
 {
        return -1;
 }
+
+static inline int mpic_pasemi_msi_init(struct mpic *mpic)
+{
+       return -1;
+}
 #endif
 
 extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern void mpic_set_vector(unsigned int virq, unsigned int vector);
 extern void mpic_end_irq(unsigned int irq);
 extern void mpic_mask_irq(unsigned int irq);
 extern void mpic_unmask_irq(unsigned int irq);
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
new file mode 100644 (file)
index 0000000..d6bfda3
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2007, Olof Johansson, PA Semi
+ *
+ * Based on arch/powerpc/sysdev/mpic_u3msi.c:
+ *
+ * Copyright 2006, Segher Boessenkool, IBM Corporation.
+ * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/msi.h>
+#include <asm/mpic.h>
+#include <asm/prom.h>
+#include <asm/hw_irq.h>
+#include <asm/ppc-pci.h>
+
+#include "mpic.h"
+
+/* Allocate 16 interrupts per device, to give an alignment of 16,
+ * since that's the size of the grouping w.r.t. affinity. If someone
+ * needs more than 32 MSI's down the road we'll have to rethink this,
+ * but it should be OK for now.
+ */
+#define ALLOC_CHUNK 16
+
+#define PASEMI_MSI_ADDR 0xfc080000
+
+/* A bit ugly, can we get this from the pci_dev somehow? */
+static struct mpic *msi_mpic;
+
+
+static void mpic_pasemi_msi_mask_irq(unsigned int irq)
+{
+       pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq);
+       mask_msi_irq(irq);
+       mpic_mask_irq(irq);
+}
+
+static void mpic_pasemi_msi_unmask_irq(unsigned int irq)
+{
+       pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq);
+       mpic_unmask_irq(irq);
+       unmask_msi_irq(irq);
+}
+
+static struct irq_chip mpic_pasemi_msi_chip = {
+       .shutdown       = mpic_pasemi_msi_mask_irq,
+       .mask           = mpic_pasemi_msi_mask_irq,
+       .unmask         = mpic_pasemi_msi_unmask_irq,
+       .eoi            = mpic_end_irq,
+       .set_type       = mpic_set_irq_type,
+       .set_affinity   = mpic_set_affinity,
+       .typename       = "PASEMI-MSI ",
+};
+
+static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+       if (type == PCI_CAP_ID_MSIX)
+               pr_debug("pasemi_msi: MSI-X untested, trying anyway\n");
+
+       return 0;
+}
+
+static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
+{
+       struct msi_desc *entry;
+
+       pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               if (entry->irq == NO_IRQ)
+                       continue;
+
+               set_irq_msi(entry->irq, NULL);
+               mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq),
+                                    ALLOC_CHUNK);
+               irq_dispose_mapping(entry->irq);
+       }
+
+       return;
+}
+
+static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+{
+       irq_hw_number_t hwirq;
+       unsigned int virq;
+       struct msi_desc *entry;
+       struct msi_msg msg;
+       u64 addr;
+
+       pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",
+                pdev, nvec, type);
+
+       msg.address_hi = 0;
+       msg.address_lo = PASEMI_MSI_ADDR;
+
+       list_for_each_entry(entry, &pdev->msi_list, list) {
+               /* Allocate 16 interrupts for now, since that's the grouping for
+                * affinity. This can be changed later if it turns out 32 is too
+                * few MSIs for someone, but restrictions will apply to how the
+                * sources can be changed independently.
+                */
+               hwirq = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK);
+               if (hwirq < 0) {
+                       pr_debug("pasemi_msi: failed allocating hwirq\n");
+                       return hwirq;
+               }
+
+               virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
+               if (virq == NO_IRQ) {
+                       pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq);
+                       mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK);
+                       return -ENOSPC;
+               }
+
+               /* Vector on MSI is really an offset, the hardware adds
+                * it to the value written at the magic address. So set
+                * it to 0 to remain sane.
+                */
+               mpic_set_vector(virq, 0);
+
+               set_irq_msi(virq, entry);
+               set_irq_chip(virq, &mpic_pasemi_msi_chip);
+               set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+
+               pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n",
+                         virq, hwirq, addr);
+
+               /* Likewise, the device writes [0...511] into the target
+                * register to generate MSI [512...1023]
+                */
+               msg.data = hwirq-0x200;
+               write_msi_msg(virq, &msg);
+       }
+
+       return 0;
+}
+
+int mpic_pasemi_msi_init(struct mpic *mpic)
+{
+       int rc;
+
+       if (!mpic->irqhost->of_node ||
+           !of_device_is_compatible(mpic->irqhost->of_node,
+                                    "pasemi,pwrficient-openpic"))
+               return -ENODEV;
+
+       rc = mpic_msi_init_allocator(mpic);
+       if (rc) {
+               pr_debug("pasemi_msi: Error allocating bitmap!\n");
+               return rc;
+       }
+
+       pr_debug("pasemi_msi: Registering PA Semi MPIC MSI callbacks\n");
+
+       msi_mpic = mpic;
+       WARN_ON(ppc_md.setup_msi_irqs);
+       ppc_md.setup_msi_irqs = pasemi_msi_setup_msi_irqs;
+       ppc_md.teardown_msi_irqs = pasemi_msi_teardown_msi_irqs;
+       ppc_md.msi_check_device = pasemi_msi_check_device;
+
+       return 0;
+}
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 3d57d3835b04e1fc2167893ed773fa8be4dcc83c..21e01061aca92735f8dd276824cf6a146dded2cd 100644 (file)
@@ -167,19 +167,20 @@ unsigned int get_brg_clk(void)
 
 /* Program the BRG to the given sampling rate and multiplier
  *
- * @brg: the BRG, 1-16
+ * @brg: the BRG, QE_BRG1 - QE_BRG16
  * @rate: the desired sampling rate
  * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or
  * GUMR_L[TDCR].  E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01,
  * then 'multiplier' should be 8.
- *
- * Also note that the value programmed into the BRGC register must be even.
  */
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
 {
        u32 divisor, tempval;
        u32 div16 = 0;
 
+       if ((brg < QE_BRG1) || (brg > QE_BRG16))
+               return -EINVAL;
+
        divisor = get_brg_clk() / (rate * multiplier);
 
        if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
@@ -196,8 +197,43 @@ void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier)
        tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
                QE_BRGC_ENABLE | div16;
 
-       out_be32(&qe_immr->brg.brgc[brg - 1], tempval);
+       out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
+
+       return 0;
+}
+EXPORT_SYMBOL(qe_setbrg);
+
+/* Convert a string to a QE clock source enum
+ *
+ * This function takes a string, typically from a property in the device
+ * tree, and returns the corresponding "enum qe_clock" value.
+*/
+enum qe_clock qe_clock_source(const char *source)
+{
+       unsigned int i;
+
+       if (strcasecmp(source, "none") == 0)
+               return QE_CLK_NONE;
+
+       if (strncasecmp(source, "brg", 3) == 0) {
+               i = simple_strtoul(source + 3, NULL, 10);
+               if ((i >= 1) && (i <= 16))
+                       return (QE_BRG1 - 1) + i;
+               else
+                       return QE_CLK_DUMMY;
+       }
+
+       if (strncasecmp(source, "clk", 3) == 0) {
+               i = simple_strtoul(source + 3, NULL, 10);
+               if ((i >= 1) && (i <= 24))
+                       return (QE_CLK1 - 1) + i;
+               else
+                       return QE_CLK_DUMMY;
+       }
+
+       return QE_CLK_DUMMY;
 }
+EXPORT_SYMBOL(qe_clock_source);
 
 /* Initialize SNUMs (thread serial numbers) according to
  * QE Module Control chapter, SNUM table
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 5255bd80aa6b2ec10fd7cb2c6aa5bd5d978368f7..3c453029f1c52826105c44fc91d934e99f6a29c3 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/nvram.h>
 #include <asm/xmon.h>
 #include <asm/ocp.h>
-#include <asm/prom.h>
 
 #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \
                      defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \
index b1f5b737c70deed904db4198e69a940f3c3000a6..731b40eacfdb8afd0548ae48350613b4acce268e 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/irq.h>
 #include <asm/immap_85xx.h>
 #include <asm/cpm2.h>
-#include <asm/mpc85xx.h>
 #include <asm/ppc_sys.h>
 
 #include <syslib/cpm2_pic.h>
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 1df3150f016eadb812c079f5724352ccc63c8ad3..8ed433e2a5c77a6d2f9c036b15960cb2a600ac0e 100644 (file)
@@ -1099,7 +1099,6 @@ prep_pib_init(void)
                                pci_write_config_byte(dev, 0x43, reg);
                        }
                }
-               pci_dev_put(dev);
        }
 
        if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND,
index e84d432c0657c9a022832b994317de363cf0ee4f..3b4fcca5d1e1dcc29eefc86c6cb970b2f79481d7 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 
index af35a316544a1a3308ce1cccff538a806fb066fb..f58149c03b0fcbe9fe326878ff3a84256aaf18c4 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 
index 4b7a3338e12252cd8a264ec2c67a8e869df31d75..2dd2dc5cd4045b2f82eee1cee9e74c9823225943 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
index 3f5be2c5ce99468ed0dc3586bbd5813f4851a29f..d42d4085dc818ed91eaf01ae5d7f4705d6dd6cb6 100644 (file)
@@ -376,7 +376,7 @@ ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
 
        down_write(&ocp_devices_sem);
        dev = __ocp_find_device(vendor, function, index);
-       list_del((struct list_head *)dev);
+       list_del(&dev->link);
        up_write(&ocp_devices_sem);
 
        DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
index ec466db52114202800a97ba462ad1e75f44bf79e..ea372914dd6eebbac9fd4855ce57d9c2b37bb120 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <syslib/ppc83xx_setup.h>
 #if defined(CONFIG_PCI)
-#include <asm/delay.h>
 #include <syslib/ppc83xx_pci.h>
 #endif
 
index e8619c750732ccdc7b926b6e69fdd05aab0f0e30..bce9a75c80e3ad38df4901cd131561b64b17dbad 100644 (file)
@@ -16,7 +16,7 @@ extern int cpm_get_irq(void);
  * the only interrupt controller.  Some boards, like the MBX and
  * Sandpoint have the 8259 as a secondary controller.  Depending
  * upon the processor type, the internal controller can have as
- * few as 16 interrups or as many as 64.  We could use  the
+ * few as 16 interrupts or as many as 64.  We could use  the
  * "clear_bit()" and "set_bit()" functions like other platforms,
  * but they are overkill for us.
  */
index 2d48018b71d93072216474f807fda2b2e8d4a55c..837183c24dfcff6072f0ae7949aabc5aeac907d6 100644 (file)
@@ -185,7 +185,7 @@ void platform_notify_map(const struct platform_notify_dev_map *map,
  */
 
 /*
-   Here we'll replace .name pointers with fixed-lenght strings
+   Here we'll replace .name pointers with fixed-length strings
    Hereby, this should be called *before* any func stuff triggeded.
  */
 void ppc_sys_device_initfunc(void)
index 8f0b953179fa9deffd1a69b2aff079641ba6ab81..9056fe58aaa15d3dcadee93026064d8c75a5eda6 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/sysrq.h>
 #include <linux/bitops.h>
 #include <asm/xmon.h>
-#include <asm/machdep.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
 #include <asm/delay.h>
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 5c742a526082484f41dbb1592d982a7d010c725f..5ae28f076d257be6129d07e8a16326585ebedc03 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/device.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
@@ -82,21 +83,11 @@ struct adb_driver *adb_controller;
 BLOCKING_NOTIFIER_HEAD(adb_client_list);
 static int adb_got_sleep;
 static int adb_inited;
-static pid_t adb_probe_task_pid;
 static DECLARE_MUTEX(adb_probe_mutex);
-static struct completion adb_probe_task_comp;
 static int sleepy_trackpad;
 static int autopoll_devs;
 int __adb_probe_sync;
 
-#ifdef CONFIG_PM_SLEEP
-static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
-static struct pmu_sleep_notifier adb_sleep_notifier = {
-       adb_notify_sleep,
-       SLEEP_LEVEL_ADB,
-};
-#endif
-
 static int adb_scan_bus(void);
 static int do_adb_reset_bus(void);
 static void adbdev_init(void);
@@ -134,16 +125,6 @@ static void printADBreply(struct adb_request *req)
 }
 #endif
 
-
-static __inline__ void adb_wait_ms(unsigned int ms)
-{
-       if (current->pid && adb_probe_task_pid &&
-         adb_probe_task_pid == current->pid)
-               msleep(ms);
-       else
-               mdelay(ms);
-}
-
 static int adb_scan_bus(void)
 {
        int i, highFree=0, noMovement;
@@ -248,13 +229,10 @@ static int adb_scan_bus(void)
 static int
 adb_probe_task(void *x)
 {
-       strcpy(current->comm, "kadbprobe");
-
        printk(KERN_INFO "adb: starting probe task...\n");
        do_adb_reset_bus();
        printk(KERN_INFO "adb: finished probe task...\n");
 
-       adb_probe_task_pid = 0;
        up(&adb_probe_mutex);
 
        return 0;
@@ -263,7 +241,7 @@ adb_probe_task(void *x)
 static void
 __adb_probe_task(struct work_struct *bullshit)
 {
-       adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL);
+       kthread_run(adb_probe_task, NULL, "kadbprobe");
 }
 
 static DECLARE_WORK(adb_reset_work, __adb_probe_task);
@@ -281,6 +259,36 @@ adb_reset_bus(void)
        return 0;
 }
 
+#ifdef CONFIG_PM
+/*
+ * notify clients before sleep
+ */
+static int adb_suspend(struct platform_device *dev, pm_message_t state)
+{
+       adb_got_sleep = 1;
+       /* We need to get a lock on the probe thread */
+       down(&adb_probe_mutex);
+       /* Stop autopoll */
+       if (adb_controller->autopoll)
+               adb_controller->autopoll(0);
+       blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
+
+       return 0;
+}
+
+/*
+ * reset bus after sleep
+ */
+static int adb_resume(struct platform_device *dev)
+{
+       adb_got_sleep = 0;
+       up(&adb_probe_mutex);
+       adb_reset_bus();
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 int __init adb_init(void)
 {
        struct adb_driver *driver;
@@ -313,15 +321,12 @@ int __init adb_init(void)
                printk(KERN_WARNING "Warning: no ADB interface detected\n");
                adb_controller = NULL;
        } else {
-#ifdef CONFIG_PM_SLEEP
-               pmu_register_sleep_notifier(&adb_sleep_notifier);
-#endif /* CONFIG_PM */
 #ifdef CONFIG_PPC
                if (machine_is_compatible("AAPL,PowerBook1998") ||
                        machine_is_compatible("PowerBook1,1"))
                        sleepy_trackpad = 1;
 #endif /* CONFIG_PPC */
-               init_completion(&adb_probe_task_comp);
+
                adbdev_init();
                adb_reset_bus();
        }
@@ -330,33 +335,6 @@ int __init adb_init(void)
 
 __initcall(adb_init);
 
-#ifdef CONFIG_PM
-/*
- * notify clients before sleep and reset bus afterwards
- */
-void
-adb_notify_sleep(struct pmu_sleep_notifier *self, int when)
-{
-       switch (when) {
-       case PBOOK_SLEEP_REQUEST:
-               adb_got_sleep = 1;
-               /* We need to get a lock on the probe thread */
-               down(&adb_probe_mutex);
-               /* Stop autopoll */
-               if (adb_controller->autopoll)
-                       adb_controller->autopoll(0);
-               blocking_notifier_call_chain(&adb_client_list,
-                       ADB_MSG_POWERDOWN, NULL);
-               break;
-       case PBOOK_WAKE:
-               adb_got_sleep = 0;
-               up(&adb_probe_mutex);
-               adb_reset_bus();
-               break;
-       }
-}
-#endif /* CONFIG_PM */
-
 static int
 do_adb_reset_bus(void)
 {
@@ -373,7 +351,7 @@ do_adb_reset_bus(void)
 
        if (sleepy_trackpad) {
                /* Let the trackpad settle down */
-               adb_wait_ms(500);
+               msleep(500);
        }
 
        down(&adb_handler_sem);
@@ -389,7 +367,7 @@ do_adb_reset_bus(void)
 
        if (sleepy_trackpad) {
                /* Let the trackpad settle down */
-               adb_wait_ms(1500);
+               msleep(1500);
        }
 
        if (!ret) {
@@ -413,41 +391,27 @@ adb_poll(void)
        adb_controller->poll();
 }
 
-static void
-adb_probe_wakeup(struct adb_request *req)
+static void adb_sync_req_done(struct adb_request *req)
 {
-       complete(&adb_probe_task_comp);
-}
+       struct completion *comp = req->arg;
 
-/* Static request used during probe */
-static struct adb_request adb_sreq;
-static unsigned long adb_sreq_lock; // Use semaphore ! */ 
+       complete(comp);
+}
 
 int
 adb_request(struct adb_request *req, void (*done)(struct adb_request *),
            int flags, int nbytes, ...)
 {
        va_list list;
-       int i, use_sreq;
+       int i;
        int rc;
+       struct completion comp;
 
        if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
                return -ENXIO;
        if (nbytes < 1)
                return -EINVAL;
-       if (req == NULL && (flags & ADBREQ_NOSEND))
-               return -EINVAL;
-       
-       if (req == NULL) {
-               if (test_and_set_bit(0,&adb_sreq_lock)) {
-                       printk("adb.c: Warning: contention on static request !\n");
-                       return -EPERM;
-               }
-               req = &adb_sreq;
-               flags |= ADBREQ_SYNC;
-               use_sreq = 1;
-       } else
-               use_sreq = 0;
+
        req->nbytes = nbytes+1;
        req->done = done;
        req->reply_expected = flags & ADBREQ_REPLY;
@@ -460,25 +424,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *),
        if (flags & ADBREQ_NOSEND)
                return 0;
 
-       /* Synchronous requests send from the probe thread cause it to
-        * block. Beware that the "done" callback will be overriden !
-        */
-       if ((flags & ADBREQ_SYNC) &&
-           (current->pid && adb_probe_task_pid &&
-           adb_probe_task_pid == current->pid)) {
-               req->done = adb_probe_wakeup;
-               rc = adb_controller->send_request(req, 0);
-               if (rc || req->complete)
-                       goto bail;
-               wait_for_completion(&adb_probe_task_comp);
-               rc = 0;
-               goto bail;
+       /* Synchronous requests block using an on-stack completion */
+       if (flags & ADBREQ_SYNC) {
+               WARN_ON(done);
+               req->done = adb_sync_req_done;
+               req->arg = &comp;
+               init_completion(&comp);
        }
 
-       rc = adb_controller->send_request(req, flags & ADBREQ_SYNC);
-bail:
-       if (use_sreq)
-               clear_bit(0, &adb_sreq_lock);
+       rc = adb_controller->send_request(req, 0);
+
+       if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
+               wait_for_completion(&comp);
 
        return rc;
 }
@@ -864,7 +821,29 @@ static const struct file_operations adb_fops = {
        .release        = adb_release,
 };
 
-static void
+static struct platform_driver adb_pfdrv = {
+       .driver = {
+               .name = "adb",
+       },
+#ifdef CONFIG_PM
+       .suspend = adb_suspend,
+       .resume = adb_resume,
+#endif
+};
+
+static struct platform_device adb_pfdev = {
+       .name = "adb",
+};
+
+static int __init
+adb_dummy_probe(struct platform_device *dev)
+{
+       if (dev == &adb_pfdev)
+               return 0;
+       return -ENODEV;
+}
+
+static void __init
 adbdev_init(void)
 {
        if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
@@ -876,4 +855,7 @@ adbdev_init(void)
        if (IS_ERR(adb_dev_class))
                return;
        class_device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+
+       platform_device_register(&adb_pfdev);
+       platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
 }
index 48d647abea460ce914168072012208690c4c57d5..192bef5c20b3df7803510e54ea5b06fc713799fb 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/ide.h>
+#include <linux/kthread.h>
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -35,7 +36,6 @@
 
 
 #define MB_DEBUG
-#define MB_IGNORE_SIGNALS
 
 #ifdef MB_DEBUG
 #define MBDBG(fmt, arg...)     printk(KERN_INFO fmt , ## arg)
@@ -622,12 +622,7 @@ static int media_bay_task(void *x)
 {
        int     i;
 
-       strcpy(current->comm, "media-bay");
-#ifdef MB_IGNORE_SIGNALS
-       sigfillset(&current->blocked);
-#endif
-
-       for (;;) {
+       while (!kthread_should_stop()) {
                for (i = 0; i < media_bay_count; ++i) {
                        down(&media_bays[i].lock);
                        if (!media_bays[i].sleeping)
@@ -636,9 +631,8 @@ static int media_bay_task(void *x)
                }
 
                msleep_interruptible(MB_POLL_DELAY);
-               if (signal_pending(current))
-                       return 0;
        }
+       return 0;
 }
 
 static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_device_id *match)
@@ -699,7 +693,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
 
        /* Startup kernel thread */
        if (i == 0)
-               kernel_thread(media_bay_task, NULL, CLONE_KERNEL);
+               kthread_run(media_bay_task, NULL, "media-bay");
 
        return 0;
 
index e43554e754a46f09bebf28732857fac8f2794441..6fadc9ac66b0c514d64486261397da80fc3b3cba 100644 (file)
 #include <linux/reboot.h>
 #include <linux/kmod.h>
 #include <linux/i2c.h>
+#include <linux/kthread.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -161,7 +162,7 @@ static struct slots_pid_state               slots_state;
 static int                             state;
 static int                             cpu_count;
 static int                             cpu_pid_type;
-static pid_t                           ctrl_task;
+static struct task_struct              *ctrl_task;
 static struct completion               ctrl_complete;
 static int                             critical_state;
 static int                             rackmac;
@@ -1779,8 +1780,6 @@ static int call_critical_overtemp(void)
  */
 static int main_control_loop(void *x)
 {
-       daemonize("kfand");
-
        DBG("main_control_loop started\n");
 
        down(&driver_lock);
@@ -1956,7 +1955,7 @@ static void start_control_loops(void)
 {
        init_completion(&ctrl_complete);
 
-       ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL);
+       ctrl_task = kthread_run(main_control_loop, NULL, "kfand");
 }
 
 /*
@@ -1964,7 +1963,7 @@ static void start_control_loops(void)
  */
 static void stop_control_loops(void)
 {
-       if (ctrl_task != 0)
+       if (ctrl_task)
                wait_for_completion(&ctrl_complete);
 }
 
index 5452da1bb1a5ab1cbf72a148fb81413f79734928..37224025f00eb5020c6a089dddafa0181e4bc8c6 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/kthread.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
@@ -61,8 +62,7 @@ I2C_CLIENT_INSMOD;
 
 static struct {
        volatile int            running;
-       struct completion       completion;
-       pid_t                   poll_task;
+       struct task_struct      *poll_task;
        
        struct semaphore        lock;
        struct of_device        *of_dev;
@@ -282,27 +282,27 @@ restore_regs( void )
        write_reg( x.fan, 0x00, x.r0, 1 );
 }
 
-static int
-control_loop( void *dummy )
+static int control_loop(void *dummy)
 {
-       daemonize("g4fand");
-
-       down( &x.lock );
+       down(&x.lock);
        setup_hardware();
+       up(&x.lock);
 
-       while( x.running ) {
-               up( &x.lock );
-
+       for (;;) {
                msleep_interruptible(8000);
-               
-               down( &x.lock );
+               if (kthread_should_stop())
+                       break;
+
+               down(&x.lock);
                poll_temp();
+               up(&x.lock);
        }
 
+       down(&x.lock);
        restore_regs();
-       up( &x.lock );
+       up(&x.lock);
 
-       complete_and_exit( &x.completion, 0 );
+       return 0;
 }
 
 
@@ -322,8 +322,7 @@ do_attach( struct i2c_adapter *adapter )
                ret = i2c_probe( adapter, &addr_data, &do_probe );
                if( x.thermostat && x.fan ) {
                        x.running = 1;
-                       init_completion( &x.completion );
-                       x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL );
+                       x.poll_task = kthread_run(control_loop, NULL, "g4fand");
                }
        }
        return ret;
@@ -339,7 +338,8 @@ do_detach( struct i2c_client *client )
        else {
                if( x.running ) {
                        x.running = 0;
-                       wait_for_completion( &x.completion );
+                       kthread_stop(x.poll_task);
+                       x.poll_task = NULL;
                }
                if( client == x.thermostat )
                        x.thermostat = NULL;
index 7e27071746e4582c54ae6b622b2160f36782778e..741a2e3f4fc6e34ce237beed4d1bebea7b0565b0 100644 (file)
@@ -22,7 +22,7 @@ static u8 bl_curve[FB_BACKLIGHT_LEVELS];
 
 static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
 {
-       unsigned int i, flat, count, range = (max - min);
+       int i, flat, count, range = (max - min);
 
        bl_curve[0] = off;
 
@@ -68,17 +68,11 @@ static int pmu_backlight_get_level_brightness(int level)
        return pmulevel;
 }
 
-static int pmu_backlight_update_status(struct backlight_device *bd)
+static int __pmu_backlight_update_status(struct backlight_device *bd)
 {
        struct adb_request req;
-       unsigned long flags;
        int level = bd->props.brightness;
 
-       spin_lock_irqsave(&pmu_backlight_lock, flags);
-
-       /* Don't update brightness when sleeping */
-       if (sleeping)
-               goto out;
 
        if (bd->props.power != FB_BLANK_UNBLANK ||
            bd->props.fb_blank != FB_BLANK_UNBLANK)
@@ -99,12 +93,23 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
                pmu_wait_complete(&req);
        }
 
-out:
-       spin_unlock_irqrestore(&pmu_backlight_lock, flags);
-
        return 0;
 }
 
+static int pmu_backlight_update_status(struct backlight_device *bd)
+{
+       unsigned long flags;
+       int rc = 0;
+
+       spin_lock_irqsave(&pmu_backlight_lock, flags);
+       /* Don't update brightness when sleeping */
+       if (!sleeping)
+               rc = __pmu_backlight_update_status(bd);
+       spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+       return rc;
+}
+
+
 static int pmu_backlight_get_brightness(struct backlight_device *bd)
 {
        return bd->props.brightness;
@@ -123,6 +128,16 @@ void pmu_backlight_set_sleep(int sleep)
 
        spin_lock_irqsave(&pmu_backlight_lock, flags);
        sleeping = sleep;
+       if (pmac_backlight) {
+               if (sleep) {
+                       struct adb_request req;
+
+                       pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+                                   PMU_POW_BACKLIGHT | PMU_POW_OFF);
+                       pmu_wait_complete(&req);
+               } else
+                       __pmu_backlight_update_status(pmac_backlight);
+       }
        spin_unlock_irqrestore(&pmu_backlight_lock, flags);
 }
 #endif /* CONFIG_PM */
@@ -148,8 +163,8 @@ void __init pmu_backlight_init()
 
        bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data);
        if (IS_ERR(bd)) {
-               printk("pmubl: Backlight registration failed\n");
-               goto error;
+               printk(KERN_ERR "PMU Backlight registration failed\n");
+               return;
        }
        bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
        pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
@@ -171,10 +186,5 @@ void __init pmu_backlight_init()
        bd->props.power = FB_BLANK_UNBLANK;
        backlight_update_status(bd);
 
-       printk("pmubl: Backlight initialized (%s)\n", name);
-
-       return;
-
-error:
-       return;
+       printk(KERN_INFO "PMU Backlight initialized (%s)\n", name);
 }
index 6123c70153d3d7db8504cc5eef67ecdc4a14d3a3..82ec12e0edd28389eedcae980a61505cbf0412b2 100644 (file)
  *
  * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
  * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ * Copyright (C) 2006-2007 Johannes Berg
  *
  * THIS DRIVER IS BECOMING A TOTAL MESS !
  *  - Cleanup atomically disabling reply to PMU events after
  *    a sleep or a freq. switch
- *  - Move sleep code out of here to pmac_pm, merge into new
- *    common PM infrastructure
- *  - Save/Restore PCI space properly
  *
  */
 #include <stdarg.h>
@@ -33,7 +31,6 @@
 #include <linux/adb.h>
 #include <linux/pmu.h>
 #include <linux/cuda.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
@@ -65,9 +62,7 @@
 #include "via-pmu-event.h"
 
 /* Some compile options */
-#undef SUSPEND_USES_PMU
-#define DEBUG_SLEEP
-#undef HACKED_PCI_SAVE
+#undef DEBUG_SLEEP
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR              154
@@ -152,12 +147,9 @@ static spinlock_t pmu_lock;
 static u8 pmu_intr_mask;
 static int pmu_version;
 static int drop_interrupts;
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 static int option_lid_wakeup = 1;
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
-#if (defined(CONFIG_PM_SLEEP)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
-static int sleep_in_progress;
-#endif
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
@@ -177,7 +169,6 @@ static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
 
 int __fake_sleep;
 int asleep;
-BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
 
 #ifdef CONFIG_ADB
 static int adb_dev_map;
@@ -224,7 +215,7 @@ extern void enable_kernel_fp(void);
 
 #ifdef DEBUG_SLEEP
 int pmu_polled_request(struct adb_request *req);
-int pmu_wink(struct adb_request *req);
+void pmu_blink(int n);
 #endif
 
 /*
@@ -875,7 +866,7 @@ proc_read_options(char *page, char **start, off_t off,
 {
        char *p = page;
 
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
        if (pmu_kind == PMU_KEYLARGO_BASED &&
            pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
                p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
@@ -916,7 +907,7 @@ proc_write_options(struct file *file, const char __user *buffer,
        *(val++) = 0;
        while(*val == ' ')
                val++;
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
        if (pmu_kind == PMU_KEYLARGO_BASED &&
            pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
                if (!strcmp(label, "lid_wakeup"))
@@ -1256,9 +1247,7 @@ void
 pmu_suspend(void)
 {
        unsigned long flags;
-#ifdef SUSPEND_USES_PMU
-       struct adb_request *req;
-#endif
+
        if (!via)
                return;
        
@@ -1276,17 +1265,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 +1289,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 */
@@ -1738,228 +1713,7 @@ pmu_present(void)
        return via != 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-
-static LIST_HEAD(sleep_notifiers);
-
-int
-pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
-{
-       struct list_head *list;
-       struct pmu_sleep_notifier *notifier;
-
-       for (list = sleep_notifiers.next; list != &sleep_notifiers;
-            list = list->next) {
-               notifier = list_entry(list, struct pmu_sleep_notifier, list);
-               if (n->priority > notifier->priority)
-                       break;
-       }
-       __list_add(&n->list, list->prev, list);
-       return 0;
-}
-EXPORT_SYMBOL(pmu_register_sleep_notifier);
-
-int
-pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
-{
-       if (n->list.next == 0)
-               return -ENOENT;
-       list_del(&n->list);
-       n->list.next = NULL;
-       return 0;
-}
-EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
-#endif /* CONFIG_PM_SLEEP */
-
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
-
-/* Sleep is broadcast last-to-first */
-static void broadcast_sleep(int when)
-{
-       struct list_head *list;
-       struct pmu_sleep_notifier *notifier;
-
-       for (list = sleep_notifiers.prev; list != &sleep_notifiers;
-            list = list->prev) {
-               notifier = list_entry(list, struct pmu_sleep_notifier, list);
-               notifier->notifier_call(notifier, when);
-       }
-}
-
-/* Wake is broadcast first-to-last */
-static void broadcast_wake(void)
-{
-       struct list_head *list;
-       struct pmu_sleep_notifier *notifier;
-
-       for (list = sleep_notifiers.next; list != &sleep_notifiers;
-            list = list->next) {
-               notifier = list_entry(list, struct pmu_sleep_notifier, list);
-               notifier->notifier_call(notifier, PBOOK_WAKE);
-       }
-}
-
-/*
- * This struct is used to store config register values for
- * PCI devices which may get powered off when we sleep.
- */
-static struct pci_save {
-#ifndef HACKED_PCI_SAVE
-       u16     command;
-       u16     cache_lat;
-       u16     intr;
-       u32     rom_address;
-#else
-       u32     config[16];
-#endif 
-} *pbook_pci_saves;
-static int pbook_npci_saves;
-
-static void
-pbook_alloc_pci_save(void)
-{
-       int npci;
-       struct pci_dev *pd = NULL;
-
-       npci = 0;
-       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-               ++npci;
-       }
-       if (npci == 0)
-               return;
-       pbook_pci_saves = (struct pci_save *)
-               kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
-       pbook_npci_saves = npci;
-}
-
-static void
-pbook_free_pci_save(void)
-{
-       if (pbook_pci_saves == NULL)
-               return;
-       kfree(pbook_pci_saves);
-       pbook_pci_saves = NULL;
-       pbook_npci_saves = 0;
-}
-
-static void
-pbook_pci_save(void)
-{
-       struct pci_save *ps = pbook_pci_saves;
-       struct pci_dev *pd = NULL;
-       int npci = pbook_npci_saves;
-       
-       if (ps == NULL)
-               return;
-
-       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-               if (npci-- == 0) {
-                       pci_dev_put(pd);
-                       return;
-               }
-#ifndef HACKED_PCI_SAVE
-               pci_read_config_word(pd, PCI_COMMAND, &ps->command);
-               pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
-               pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
-               pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
-#else
-               int i;
-               for (i=1;i<16;i++)
-                       pci_read_config_dword(pd, i<<4, &ps->config[i]);
-#endif
-               ++ps;
-       }
-}
-
-/* For this to work, we must take care of a few things: If gmac was enabled
- * during boot, it will be in the pci dev list. If it's disabled at this point
- * (and it will probably be), then you can't access it's config space.
- */
-static void
-pbook_pci_restore(void)
-{
-       u16 cmd;
-       struct pci_save *ps = pbook_pci_saves - 1;
-       struct pci_dev *pd = NULL;
-       int npci = pbook_npci_saves;
-       int j;
-
-       while ((pd = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-#ifdef HACKED_PCI_SAVE
-               int i;
-               if (npci-- == 0) {
-                       pci_dev_put(pd);
-                       return;
-               }
-               ps++;
-               for (i=2;i<16;i++)
-                       pci_write_config_dword(pd, i<<4, ps->config[i]);
-               pci_write_config_dword(pd, 4, ps->config[1]);
-#else
-               if (npci-- == 0)
-                       return;
-               ps++;
-               if (ps->command == 0)
-                       continue;
-               pci_read_config_word(pd, PCI_COMMAND, &cmd);
-               if ((ps->command & ~cmd) == 0)
-                       continue;
-               switch (pd->hdr_type) {
-               case PCI_HEADER_TYPE_NORMAL:
-                       for (j = 0; j < 6; ++j)
-                               pci_write_config_dword(pd,
-                                       PCI_BASE_ADDRESS_0 + j*4,
-                                       pd->resource[j].start);
-                       pci_write_config_dword(pd, PCI_ROM_ADDRESS,
-                               ps->rom_address);
-                       pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
-                               ps->cache_lat);
-                       pci_write_config_word(pd, PCI_INTERRUPT_LINE,
-                               ps->intr);
-                       pci_write_config_word(pd, PCI_COMMAND, ps->command);
-                       break;
-               }
-#endif 
-       }
-}
-
-#ifdef DEBUG_SLEEP
-/* N.B. This doesn't work on the 3400 */
-void 
-pmu_blink(int n)
-{
-       struct adb_request req;
-
-       memset(&req, 0, sizeof(req));
-
-       for (; n > 0; --n) {
-               req.nbytes = 4;
-               req.done = NULL;
-               req.data[0] = 0xee;
-               req.data[1] = 4;
-               req.data[2] = 0;
-               req.data[3] = 1;
-               req.reply[0] = ADB_RET_OK;
-               req.reply_len = 1;
-               req.reply_expected = 0;
-               pmu_polled_request(&req);
-               mdelay(50);
-               req.nbytes = 4;
-               req.done = NULL;
-               req.data[0] = 0xee;
-               req.data[1] = 4;
-               req.data[2] = 0;
-               req.data[3] = 0;
-               req.reply[0] = ADB_RET_OK;
-               req.reply_len = 1;
-               req.reply_expected = 0;
-               pmu_polled_request(&req);
-               mdelay(50);
-       }
-       mdelay(50);
-}
-#endif
-
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 /*
  * Put the powerbook to sleep.
  */
@@ -1994,134 +1748,6 @@ restore_via_state(void)
        out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-extern void pmu_backlight_set_sleep(int sleep);
-
-static int
-pmac_suspend_devices(void)
-{
-       int ret;
-
-       pm_prepare_console();
-       
-       /* Notify old-style device drivers */
-       broadcast_sleep(PBOOK_SLEEP_REQUEST);
-
-       /* Sync the disks. */
-       /* XXX It would be nice to have some way to ensure that
-        * nobody is dirtying any new buffers while we wait. That
-        * could be achieved using the refrigerator for processes
-        * that swsusp uses
-        */
-       sys_sync();
-
-       broadcast_sleep(PBOOK_SLEEP_NOW);
-
-       /* Send suspend call to devices, hold the device core's dpm_sem */
-       ret = device_suspend(PMSG_SUSPEND);
-       if (ret) {
-               broadcast_wake();
-               printk(KERN_ERR "Driver sleep failed\n");
-               return -EBUSY;
-       }
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       /* Tell backlight code not to muck around with the chip anymore */
-       pmu_backlight_set_sleep(1);
-#endif
-
-       /* Call platform functions marked "on sleep" */
-       pmac_pfunc_i2c_suspend();
-       pmac_pfunc_base_suspend();
-
-       /* Stop preemption */
-       preempt_disable();
-
-       /* Make sure the decrementer won't interrupt us */
-       asm volatile("mtdec %0" : : "r" (0x7fffffff));
-       /* Make sure any pending DEC interrupt occurring while we did
-        * the above didn't re-enable the DEC */
-       mb();
-       asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-       /* We can now disable MSR_EE. This code of course works properly only
-        * on UP machines... For SMP, if we ever implement sleep, we'll have to
-        * stop the "other" CPUs way before we do all that stuff.
-        */
-       local_irq_disable();
-
-       /* Broadcast power down irq
-        * This isn't that useful in most cases (only directly wired devices can
-        * use this but still... This will take care of sysdev's as well, so
-        * we exit from here with local irqs disabled and PIC off.
-        */
-       ret = device_power_down(PMSG_SUSPEND);
-       if (ret) {
-               wakeup_decrementer();
-               local_irq_enable();
-               preempt_enable();
-               device_resume();
-               broadcast_wake();
-               printk(KERN_ERR "Driver powerdown failed\n");
-               return -EBUSY;
-       }
-
-       /* Wait for completion of async requests */
-       while (!batt_req.complete)
-               pmu_poll();
-
-       /* Giveup the lazy FPU & vec so we don't have to back them
-        * up from the low level code
-        */
-       enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-       if (cpu_has_feature(CPU_FTR_ALTIVEC))
-               enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-       return 0;
-}
-
-static int
-pmac_wakeup_devices(void)
-{
-       mdelay(100);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-       /* Tell backlight code it can use the chip again */
-       pmu_backlight_set_sleep(0);
-#endif
-
-       /* Power back up system devices (including the PIC) */
-       device_power_up();
-
-       /* Force a poll of ADB interrupts */
-       adb_int_pending = 1;
-       via_pmu_interrupt(0, NULL);
-
-       /* Restart jiffies & scheduling */
-       wakeup_decrementer();
-
-       /* Re-enable local CPU interrupts */
-       local_irq_enable();
-       mdelay(10);
-       preempt_enable();
-
-       /* Call platform functions marked "on wake" */
-       pmac_pfunc_base_resume();
-       pmac_pfunc_i2c_resume();
-
-       /* Resume devices */
-       device_resume();
-
-       /* Notify old style drivers */
-       broadcast_wake();
-
-       pm_restore_console();
-
-       return 0;
-}
-
 #define        GRACKLE_PM      (1<<7)
 #define GRACKLE_DOZE   (1<<5)
 #define        GRACKLE_NAP     (1<<4)
@@ -2132,19 +1758,12 @@ static int powerbook_sleep_grackle(void)
        unsigned long save_l2cr;
        unsigned short pmcr1;
        struct adb_request req;
-       int ret;
        struct pci_dev *grackle;
 
        grackle = pci_get_bus_and_slot(0, 0);
        if (!grackle)
                return -ENODEV;
 
-       ret = pmac_suspend_devices();
-       if (ret) {
-               printk(KERN_ERR "Sleep rejected by devices\n");
-               return ret;
-       }
-       
        /* Turn off various things. Darwin does some retry tests here... */
        pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
        pmu_wait_complete(&req);
@@ -2207,8 +1826,6 @@ static int powerbook_sleep_grackle(void)
                        PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
        pmu_wait_complete(&req);
 
-       pmac_wakeup_devices();
-
        return 0;
 }
 
@@ -2218,7 +1835,6 @@ powerbook_sleep_Core99(void)
        unsigned long save_l2cr;
        unsigned long save_l3cr;
        struct adb_request req;
-       int ret;
        
        if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
                printk(KERN_ERR "Sleep mode not supported on this machine\n");
@@ -2228,12 +1844,6 @@ powerbook_sleep_Core99(void)
        if (num_online_cpus() > 1 || cpu_is_offline(0))
                return -EAGAIN;
 
-       ret = pmac_suspend_devices();
-       if (ret) {
-               printk(KERN_ERR "Sleep rejected by devices\n");
-               return ret;
-       }
-
        /* Stop environment and ADB interrupts */
        pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
        pmu_wait_complete(&req);
@@ -2304,45 +1914,33 @@ powerbook_sleep_Core99(void)
        /* Restore LPJ, cpufreq will adjust the cpu frequency */
        loops_per_jiffy /= 2;
 
-       pmac_wakeup_devices();
-
        return 0;
 }
 
 #define PB3400_MEM_CTRL                0xf8000000
 #define PB3400_MEM_CTRL_SLEEP  0x70
 
-static int
-powerbook_sleep_3400(void)
+static void __iomem *pb3400_mem_ctrl;
+
+static void powerbook_sleep_init_3400(void)
+{
+       /* map in the memory controller registers */
+       pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+       if (pb3400_mem_ctrl == NULL)
+               printk(KERN_WARNING "ioremap failed: sleep won't be possible");
+}
+
+static int powerbook_sleep_3400(void)
 {
-       int ret, i, x;
+       int i, x;
        unsigned int hid0;
-       unsigned long p;
+       unsigned long msr;
        struct adb_request sleep_req;
-       void __iomem *mem_ctrl;
        unsigned int __iomem *mem_ctrl_sleep;
 
-       /* first map in the memory controller registers */
-       mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
-       if (mem_ctrl == NULL) {
-               printk("powerbook_sleep_3400: ioremap failed\n");
+       if (pb3400_mem_ctrl == NULL)
                return -ENOMEM;
-       }
-       mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
-       /* Allocate room for PCI save */
-       pbook_alloc_pci_save();
-
-       ret = pmac_suspend_devices();
-       if (ret) {
-               pbook_free_pci_save();
-               iounmap(mem_ctrl);
-               printk(KERN_ERR "Sleep rejected by devices\n");
-               return ret;
-       }
-
-       /* Save the state of PCI config space for some slots */
-       pbook_pci_save();
+       mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
 
        /* Set the memory controller to keep the memory refreshed
           while we're asleep */
@@ -2357,41 +1955,34 @@ powerbook_sleep_3400(void)
 
        /* Ask the PMU to put us to sleep */
        pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-       while (!sleep_req.complete)
-               mb();
+       pmu_wait_complete(&sleep_req);
+       pmu_unlock();
 
-       pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+       pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
 
-       /* displacement-flush the L2 cache - necessary? */
-       for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
-               i = *(volatile int *)p;
        asleep = 1;
 
        /* Put the CPU into sleep mode */
        hid0 = mfspr(SPRN_HID0);
        hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
        mtspr(SPRN_HID0, hid0);
-       mtmsr(mfmsr() | MSR_POW | MSR_EE);
-       udelay(10);
+       local_irq_enable();
+       msr = mfmsr() | MSR_POW;
+       while (asleep) {
+               mb();
+               mtmsr(msr);
+               isync();
+       }
+       local_irq_disable();
 
        /* OK, we're awake again, start restoring things */
        out_be32(mem_ctrl_sleep, 0x3f);
-       pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-       pbook_pci_restore();
-       pmu_unlock();
-
-       /* wait for the PMU interrupt sequence to complete */
-       while (asleep)
-               mb();
-
-       pmac_wakeup_devices();
-       pbook_free_pci_save();
-       iounmap(mem_ctrl);
+       pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
 
        return 0;
 }
 
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
 /*
  * Support for /dev/pmu device
@@ -2548,7 +2139,6 @@ 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);
@@ -2562,10 +2152,96 @@ pmu_release(struct inode *inode, struct file *file)
 
                kfree(pp);
        }
-       unlock_kernel();
        return 0;
 }
 
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
+static void pmac_suspend_disable_irqs(void)
+{
+       /* Call platform functions marked "on sleep" */
+       pmac_pfunc_i2c_suspend();
+       pmac_pfunc_base_suspend();
+}
+
+static int powerbook_sleep(suspend_state_t state)
+{
+       int error = 0;
+
+       /* Wait for completion of async requests */
+       while (!batt_req.complete)
+               pmu_poll();
+
+       /* Giveup the lazy FPU & vec so we don't have to back them
+        * up from the low level code
+        */
+       enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+       if (cpu_has_feature(CPU_FTR_ALTIVEC))
+               enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+       switch (pmu_kind) {
+       case PMU_OHARE_BASED:
+               error = powerbook_sleep_3400();
+               break;
+       case PMU_HEATHROW_BASED:
+       case PMU_PADDINGTON_BASED:
+               error = powerbook_sleep_grackle();
+               break;
+       case PMU_KEYLARGO_BASED:
+               error = powerbook_sleep_Core99();
+               break;
+       default:
+               return -ENOSYS;
+       }
+
+       if (error)
+               return error;
+
+       mdelay(100);
+
+       return 0;
+}
+
+static void pmac_suspend_enable_irqs(void)
+{
+       /* Force a poll of ADB interrupts */
+       adb_int_pending = 1;
+       via_pmu_interrupt(0, NULL);
+
+       mdelay(10);
+
+       /* Call platform functions marked "on wake" */
+       pmac_pfunc_base_resume();
+       pmac_pfunc_i2c_resume();
+}
+
+static int pmu_sleep_valid(suspend_state_t state)
+{
+       return state == PM_SUSPEND_MEM
+               && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0);
+}
+
+static struct platform_suspend_ops pmu_pm_ops = {
+       .enter = powerbook_sleep,
+       .valid = pmu_sleep_valid,
+};
+
+static int register_pmu_pm_ops(void)
+{
+       if (pmu_kind == PMU_OHARE_BASED)
+               powerbook_sleep_init_3400();
+       ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs;
+       ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs;
+       suspend_set_ops(&pmu_pm_ops);
+
+       return 0;
+}
+
+device_initcall(register_pmu_pm_ops);
+#endif
+
 static int
 pmu_ioctl(struct inode * inode, struct file *filp,
                     u_int cmd, u_long arg)
@@ -2574,35 +2250,15 @@ pmu_ioctl(struct inode * inode, struct file *filp,
        int error = -EINVAL;
 
        switch (cmd) {
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
        case PMU_IOC_SLEEP:
                if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
-               if (sleep_in_progress)
-                       return -EBUSY;
-               sleep_in_progress = 1;
-               switch (pmu_kind) {
-               case PMU_OHARE_BASED:
-                       error = powerbook_sleep_3400();
-                       break;
-               case PMU_HEATHROW_BASED:
-               case PMU_PADDINGTON_BASED:
-                       error = powerbook_sleep_grackle();
-                       break;
-               case PMU_KEYLARGO_BASED:
-                       error = powerbook_sleep_Core99();
-                       break;
-               default:
-                       error = -ENOSYS;
-               }
-               sleep_in_progress = 0;
-               break;
+               return pm_suspend(PM_SUSPEND_MEM);
        case PMU_IOC_CAN_SLEEP:
-               if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+               if (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) < 0)
                        return put_user(0, argp);
                else
                        return put_user(1, argp);
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
 
 #ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
        /* Compatibility ioctl's for backlight */
@@ -2610,9 +2266,6 @@ pmu_ioctl(struct inode * inode, struct file *filp,
        {
                int brightness;
 
-               if (sleep_in_progress)
-                       return -EBUSY;
-
                brightness = pmac_backlight_get_legacy_brightness();
                if (brightness < 0)
                        return brightness;
@@ -2624,9 +2277,6 @@ pmu_ioctl(struct inode * inode, struct file *filp,
        {
                int brightness;
 
-               if (sleep_in_progress)
-                       return -EBUSY;
-
                error = get_user(brightness, argp);
                if (error)
                        return error;
@@ -2751,15 +2401,43 @@ pmu_polled_request(struct adb_request *req)
        local_irq_restore(flags);
        return 0;
 }
-#endif /* DEBUG_SLEEP */
 
+/* N.B. This doesn't work on the 3400 */
+void pmu_blink(int n)
+{
+       struct adb_request req;
 
-/* FIXME: This is a temporary set of callbacks to enable us
- * to do suspend-to-disk.
- */
+       memset(&req, 0, sizeof(req));
 
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+       for (; n > 0; --n) {
+               req.nbytes = 4;
+               req.done = NULL;
+               req.data[0] = 0xee;
+               req.data[1] = 4;
+               req.data[2] = 0;
+               req.data[3] = 1;
+               req.reply[0] = ADB_RET_OK;
+               req.reply_len = 1;
+               req.reply_expected = 0;
+               pmu_polled_request(&req);
+               mdelay(50);
+               req.nbytes = 4;
+               req.done = NULL;
+               req.data[0] = 0xee;
+               req.data[1] = 4;
+               req.data[2] = 0;
+               req.data[3] = 0;
+               req.reply[0] = ADB_RET_OK;
+               req.reply_len = 1;
+               req.reply_expected = 0;
+               pmu_polled_request(&req);
+               mdelay(50);
+       }
+       mdelay(50);
+}
+#endif /* DEBUG_SLEEP */
 
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 int pmu_sys_suspended;
 
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
@@ -2767,10 +2445,15 @@ static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
        if (state.event != PM_EVENT_SUSPEND || pmu_sys_suspended)
                return 0;
 
-       /* Suspend PMU event interrupts */
+       /* Suspend PMU event interrupts */\
        pmu_suspend();
-
        pmu_sys_suspended = 1;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+       /* Tell backlight code not to muck around with the chip anymore */
+       pmu_backlight_set_sleep(1);
+#endif
+
        return 0;
 }
 
@@ -2785,15 +2468,18 @@ static int pmu_sys_resume(struct sys_device *sysdev)
        pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
        pmu_wait_complete(&req);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+       /* Tell backlight code it can use the chip again */
+       pmu_backlight_set_sleep(0);
+#endif
        /* Resume PMU event interrupts */
        pmu_resume();
-
        pmu_sys_suspended = 0;
 
        return 0;
 }
 
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
 static struct sysdev_class pmu_sysclass = {
        set_kset_name("pmu"),
@@ -2804,10 +2490,10 @@ static struct sys_device device_pmu = {
 };
 
 static struct sysdev_driver driver_pmu = {
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
        .suspend        = &pmu_sys_suspend,
        .resume         = &pmu_sys_resume,
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 };
 
 static int __init init_pmu_sysfs(void)
@@ -2842,10 +2528,10 @@ EXPORT_SYMBOL(pmu_wait_complete);
 EXPORT_SYMBOL(pmu_suspend);
 EXPORT_SYMBOL(pmu_resume);
 EXPORT_SYMBOL(pmu_unlock);
-#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+#if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32)
 EXPORT_SYMBOL(pmu_enable_irled);
 EXPORT_SYMBOL(pmu_battery_count);
 EXPORT_SYMBOL(pmu_batteries);
 EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PM_SLEEP && CONFIG_PPC32 */
+#endif /* CONFIG_SUSPEND && CONFIG_PPC32 */
 
index da4efbca646e3b666fa7e9b2c947e2a8a66ab761..e36321152d504cf0f9a23b880f07e6afbba5b565 100644 (file)
 static inline int fcc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
        const struct fs_platform_info *fpi = fep->fpi;
-       int i;
-
-       W32(cpmp, cp_cpcr, fpi->cp_command | op | CPM_CR_FLG);
-       for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
-               if ((R32(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-                       return 0;
 
-       printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-              __FUNCTION__);
-       return 1;
+       return cpm_command(fpi->cp_command, op);
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
index 48f2f30059359f4a6a45e5d7b697fb33874c70d4..fe3d8a621c3355661d75f80a0b9b446ae25216a2 100644 (file)
  * Delay to wait for SCC reset command to complete (in us)
  */
 #define SCC_RESET_DELAY                50
-#define MAX_CR_CMD_LOOPS       10000
 
 static inline int scc_cr_cmd(struct fs_enet_private *fep, u32 op)
 {
        const struct fs_platform_info *fpi = fep->fpi;
-       int i;
-
-       W16(cpmp, cp_cpcr, fpi->cp_command | CPM_CR_FLG | (op << 8));
-       for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
-               if ((R16(cpmp, cp_cpcr) & CPM_CR_FLG) == 0)
-                       return 0;
 
-       printk(KERN_ERR "%s(): Not able to issue CPM command\n",
-               __FUNCTION__);
-       return 1;
+       return cpm_command(fpi->cp_command, op);
 }
 
 static int do_pd_setup(struct fs_enet_private *fep)
index abac7db3819eac943df7497b86735482a63170ca..8d456e379a86bd653bfaba993aa015b6ca9f8502 100644 (file)
@@ -3822,6 +3822,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        int err, ucc_num, max_speed = 0;
        const phandle *ph;
        const unsigned int *prop;
+       const char *sprop;
        const void *mac_addr;
        phy_interface_t phy_interface;
        static const int enet_to_speed[] = {
@@ -3854,10 +3855,56 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 
        ug_info->uf_info.ucc_num = ucc_num;
 
-       prop = of_get_property(np, "rx-clock", NULL);
-       ug_info->uf_info.rx_clock = *prop;
-       prop = of_get_property(np, "tx-clock", NULL);
-       ug_info->uf_info.tx_clock = *prop;
+       sprop = of_get_property(np, "rx-clock-name", NULL);
+       if (sprop) {
+               ug_info->uf_info.rx_clock = qe_clock_source(sprop);
+               if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) ||
+                   (ug_info->uf_info.rx_clock > QE_CLK24)) {
+                       printk(KERN_ERR
+                               "ucc_geth: invalid rx-clock-name property\n");
+                       return -EINVAL;
+               }
+       } else {
+               prop = of_get_property(np, "rx-clock", NULL);
+               if (!prop) {
+                       /* If both rx-clock-name and rx-clock are missing,
+                          we want to tell people to use rx-clock-name. */
+                       printk(KERN_ERR
+                               "ucc_geth: missing rx-clock-name property\n");
+                       return -EINVAL;
+               }
+               if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+                       printk(KERN_ERR
+                               "ucc_geth: invalid rx-clock propperty\n");
+                       return -EINVAL;
+               }
+               ug_info->uf_info.rx_clock = *prop;
+       }
+
+       sprop = of_get_property(np, "tx-clock-name", NULL);
+       if (sprop) {
+               ug_info->uf_info.tx_clock = qe_clock_source(sprop);
+               if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) ||
+                   (ug_info->uf_info.tx_clock > QE_CLK24)) {
+                       printk(KERN_ERR
+                               "ucc_geth: invalid tx-clock-name property\n");
+                       return -EINVAL;
+               }
+       } else {
+               prop = of_get_property(np, "rx-clock", NULL);
+               if (!prop) {
+                       printk(KERN_ERR
+                               "ucc_geth: mising tx-clock-name property\n");
+                       return -EINVAL;
+               }
+               if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) {
+                       printk(KERN_ERR
+                               "ucc_geth: invalid tx-clock property\n");
+                       return -EINVAL;
+               }
+               ug_info->uf_info.tx_clock = *prop;
+       }
+
        err = of_address_to_resource(np, 0, &res);
        if (err)
                return -EINVAL;
index b169b0e2647f72afefa42bb16430885a8a4d170f..191954bc8e5baf8df9d796226aee25d9e111b42f 100644 (file)
@@ -155,7 +155,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
            dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
                of_scan_pci_bridge(dn, dev);
 
-       pcibios_fixup_new_pci_devices(dev->subordinate,0);
+       pcibios_fixup_new_pci_devices(dev->subordinate);
 
        /* Claim new bus resources */
        pcibios_claim_one_bus(dev->bus);
index 52fb044bb79a917333788d033217016fefce868f..6ea0366e26ae68ab52f05c915c53058e4817942f 100644 (file)
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
-       u16 __iomem *cpcr = &cpmp->cp_cpcr;
-
-       out_be16(cpcr, port->command | (cmd << 8) | CPM_CR_FLG);
-       while (in_be16(cpcr) & CPM_CR_FLG)
-               ;
+       cpm_command(port->command, cmd);
 }
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
index 882dbc17d590bc700e5c6d8af6fa086314197924..def01582de5ccd6c121f6906ebd262de5a66c5df 100644 (file)
 #ifdef CONFIG_PPC_CPM_NEW_BINDING
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
-       cpm_cpm2_t __iomem *cp = cpm2_map(im_cpm);
-
-       out_be32(&cp->cp_cpcr, port->command | cmd | CPM_CR_FLG);
-       while (in_be32(&cp->cp_cpcr) & CPM_CR_FLG)
-               ;
-
-       cpm2_unmap(cp);
+       cpm_command(port->command, cmd);
 }
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
index 1311cefdfd30ffdea3ecf7628f50ed0db7f2ea0d..4b0e152060060c5ed53d2aa14fd0cf8896cdb1cc 100644 (file)
@@ -123,7 +123,7 @@ typedef struct      mem_ctlr {
 #define OR_G5LA                0x00000400      /* Output #GPL5 on #GPL_A5              */
 #define OR_G5LS                0x00000200      /* Drive #GPL high on falling edge of...*/
 #define OR_BI          0x00000100      /* Burst inhibit                        */
-#define OR_SCY_MSK     0x000000f0      /* Cycle Lenght in Clocks               */
+#define OR_SCY_MSK     0x000000f0      /* Cycle Length in Clocks               */
 #define OR_SCY_0_CLK   0x00000000      /* 0 clock cycles wait states           */
 #define OR_SCY_1_CLK   0x00000010      /* 1 clock cycles wait states           */
 #define OR_SCY_2_CLK   0x00000020      /* 2 clock cycles wait states           */
index 2ee59d7b335cd5ddfe2f00eb13655bd8baab4175..9e3b8648648c485fa5edd836c83e0095461516e5 100644 (file)
@@ -693,7 +693,7 @@ typedef struct risc_timer_pram {
 #define        CICR_SCC_SCC3           ((uint)0x00200000)      /* SCC3 @ SCCc */
 #define        CICR_SCB_SCC2           ((uint)0x00040000)      /* SCC2 @ SCCb */
 #define        CICR_SCA_SCC1           ((uint)0x00000000)      /* SCC1 @ SCCa */
-#define CICR_IRL_MASK          ((uint)0x0000e000)      /* Core interrrupt */
+#define CICR_IRL_MASK          ((uint)0x0000e000)      /* Core interrupt */
 #define CICR_HP_MASK           ((uint)0x00001f00)      /* Hi-pri int. */
 #define CICR_IEN               ((uint)0x00000080)      /* Int. enable */
 #define CICR_SPS               ((uint)0x00000001)      /* SCC Spread */
index 48df9f330e76a57d0a4608ec53e1c203b5356a92..fae83b137337287f675a2ad94c629ec05968410b 100644 (file)
@@ -10,5 +10,6 @@ int cpm_muram_free(unsigned long offset);
 unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size);
 void __iomem *cpm_muram_addr(unsigned long offset);
 dma_addr_t cpm_muram_dma(void __iomem *addr);
+int cpm_command(u32 command, u8 opcode);
 
 #endif
diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
new file mode 100644 (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 ff52013c0e2d79bf75202c8bc034d00f8287a92c..e974876e18d2c98c7239981c1c49b693a73b11a6 100644 (file)
@@ -87,6 +87,9 @@ static inline int dma_supported(struct device *dev, u64 mask)
        return dma_ops->dma_supported(dev, mask);
 }
 
+/* We have our own implementation of pci_set_dma_mask() */
+#define HAVE_ARCH_PCI_SET_DMA_MASK
+
 static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 {
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
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 0ad4e653d464bd48514c83bb6c263029cb88d83f..0f165e59c32689e90e78239f5e4da9515197f9f0 100644 (file)
@@ -89,14 +89,14 @@ struct ccsr_guts {
  * them.
  *
  * guts: Pointer to GUTS structure
- * co: The DMA controller (1 or 2)
+ * co: The DMA controller (0 or 1)
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
  */
 static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int device)
 {
-       unsigned int shift = 16 + (8 * (2 - co) + 2 * (3 - ch));
+       unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
 
        clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift);
 }
@@ -118,6 +118,27 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
 #define CCSR_GUTS_PMUXCR_DMA1_0                0x00000002
 #define CCSR_GUTS_PMUXCR_DMA1_3                0x00000001
 
+/*
+ * Set the DMA external control bits in the GUTS
+ *
+ * The DMA external control bits in the PMUXCR are only meaningful for
+ * channels 0 and 3.  Any other channels are ignored.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * value: the new value for the bit (0 or 1)
+ */
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+       unsigned int co, unsigned int ch, unsigned int value)
+{
+       if ((ch == 0) || (ch == 3)) {
+               unsigned int shift = 2 * (co + 1) - (ch & 1) - 1;
+
+               clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift);
+       }
+}
+
 #define CCSR_GUTS_CLKDVDR_PXCKEN       0x80000000
 #define CCSR_GUTS_CLKDVDR_SSICKEN      0x20000000
 #define CCSR_GUTS_CLKDVDR_PXCKINV      0x10000000
index e44cdfc8493a8f30a2b4a4644884c429f5b1f966..7be26f615755ad5a80c84aa3867facf781f3db03 100644 (file)
@@ -50,15 +50,16 @@ extern int check_legacy_ioport(unsigned long base_port);
 #define PCI_DRAM_OFFSET        pci_dram_offset
 #else
 #define _IO_BASE       pci_io_base
-#define _ISA_MEM_BASE  0
+#define _ISA_MEM_BASE  isa_mem_base
 #define PCI_DRAM_OFFSET        0
 #endif
 
 extern unsigned long isa_io_base;
-extern unsigned long isa_mem_base;
 extern unsigned long pci_io_base;
 extern unsigned long pci_dram_offset;
 
+extern resource_size_t isa_mem_base;
+
 #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_INDIRECT_IO)
 #error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits
 #endif
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 edec79dcb7c17b226ddb72814bd6005f52a616bb..8ff08be001461cad3e966c5daacf9feed5acc9fe 100644 (file)
 
 /* Flags when we init the IPIC */
 #define IPIC_SPREADMODE_GRP_A  0x00000001
-#define IPIC_SPREADMODE_GRP_D  0x00000002
-#define IPIC_SPREADMODE_MIX_A  0x00000004
-#define IPIC_SPREADMODE_MIX_B  0x00000008
-#define IPIC_DISABLE_MCP_OUT   0x00000010
-#define IPIC_IRQ0_MCP          0x00000020
+#define IPIC_SPREADMODE_GRP_B  0x00000002
+#define IPIC_SPREADMODE_GRP_C  0x00000004
+#define IPIC_SPREADMODE_GRP_D  0x00000008
+#define IPIC_SPREADMODE_MIX_A  0x00000010
+#define IPIC_SPREADMODE_MIX_B  0x00000020
+#define IPIC_DISABLE_MCP_OUT   0x00000040
+#define IPIC_IRQ0_MCP          0x00000080
 
 /* IPIC registers offsets */
 #define IPIC_SICFR     0x00    /* System Global Interrupt Configuration Register */
index 6ce2ce1e26909a0bc80bf84c772d6cc5338c4b77..8f5da7d772025e8b3eb7ece2d3d7137a77db36da 100644 (file)
@@ -78,7 +78,7 @@ extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
 /*
  * Close an Lp Event Path for a type and partition
- * returns 0 on sucess
+ * returns 0 on success
  */
 extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
index 6968f4300dca56e058fb8fd6cdb032630b53c3be..0872ec228c1e45d1e27c094f37a8c948823850bf 100644 (file)
@@ -204,6 +204,13 @@ struct machdep_calls {
        /*
         * optional PCI "hooks"
         */
+       /* Called in indirect_* to avoid touching devices */
+       int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
+
+       /* Called at then very end of pcibios_init() */
+       void (*pcibios_after_init)(void);
+
+#endif /* CONFIG_PPC32 */
 
        /* Called after PPC generic resource fixup to perform
           machine specific fixups */
@@ -212,18 +219,9 @@ struct machdep_calls {
        /* Called for each PCI bus in the system when it's probed */
        void (*pcibios_fixup_bus)(struct pci_bus *);
 
-       /* Called when pci_enable_device() is called (initial=0) or
-        * when a device with no assigned resource is found (initial=1).
-        * Returns 0 to allow assignment/enabling of the device. */
-       int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
-
-       /* Called in indirect_* to avoid touching devices */
-       int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char);
-
-       /* Called at then very end of pcibios_init() */
-       void (*pcibios_after_init)(void);
-
-#endif /* CONFIG_PPC32 */
+       /* Called when pci_enable_device() is called. Returns 0 to
+        * allow assignment/enabling of the device. */
+       int  (*pcibios_enable_device_hook)(struct pci_dev *);
 
        /* Called to shutdown machine specific hardware not already controlled
         * by other drivers.
@@ -253,6 +251,16 @@ struct machdep_calls {
         */
        void (*machine_kexec)(struct kimage *image);
 #endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_SUSPEND
+       /* These are called to disable and enable, respectively, IRQs when
+        * entering a suspend state.  If NULL, then the generic versions
+        * will be called.  The generic versions disable/enable the
+        * decrementer along with interrupts.
+        */
+       void (*suspend_disable_irqs)(void);
+       void (*suspend_enable_irqs)(void);
+#endif
 };
 
 extern void power4_idle(void);
@@ -326,5 +334,31 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal)
                ppc_md.log_error(buf, err_type, fatal);
 }
 
+#define __define_machine_initcall(mach,level,fn,id) \
+       static int __init __machine_initcall_##mach##_##fn(void) { \
+               if (machine_is(mach)) return fn(); \
+               return 0; \
+       } \
+       __define_initcall(level,__machine_initcall_##mach##_##fn,id);
+
+#define machine_core_initcall(mach,fn)         __define_machine_initcall(mach,"1",fn,1)
+#define machine_core_initcall_sync(mach,fn)    __define_machine_initcall(mach,"1s",fn,1s)
+#define machine_postcore_initcall(mach,fn)     __define_machine_initcall(mach,"2",fn,2)
+#define machine_postcore_initcall_sync(mach,fn)        __define_machine_initcall(mach,"2s",fn,2s)
+#define machine_arch_initcall(mach,fn)         __define_machine_initcall(mach,"3",fn,3)
+#define machine_arch_initcall_sync(mach,fn)    __define_machine_initcall(mach,"3s",fn,3s)
+#define machine_subsys_initcall(mach,fn)       __define_machine_initcall(mach,"4",fn,4)
+#define machine_subsys_initcall_sync(mach,fn)  __define_machine_initcall(mach,"4s",fn,4s)
+#define machine_fs_initcall(mach,fn)           __define_machine_initcall(mach,"5",fn,5)
+#define machine_fs_initcall_sync(mach,fn)      __define_machine_initcall(mach,"5s",fn,5s)
+#define machine_rootfs_initcall(mach,fn)       __define_machine_initcall(mach,"rootfs",fn,rootfs)
+#define machine_device_initcall(mach,fn)       __define_machine_initcall(mach,"6",fn,6)
+#define machine_device_initcall_sync(mach,fn)  __define_machine_initcall(mach,"6s",fn,6s)
+#define machine_late_initcall(mach,fn)         __define_machine_initcall(mach,"7",fn,7)
+#define machine_late_initcall_sync(mach,fn)    __define_machine_initcall(mach,"7s",fn,7s)
+
+void generic_suspend_disable_irqs(void);
+void generic_suspend_enable_irqs(void);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MACHDEP_H */
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 9877982508bf65753ec6a8c419b350067dd72069..4e7059cc6113f054fbaf8de634c2a9c05f785062 100644 (file)
@@ -10,6 +10,8 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
+#include <linux/errno.h>
+
 #define NVRW_CNT 0x20
 #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
 #define NVRAM_BLOCK_LEN 16
@@ -71,7 +73,16 @@ extern int nvram_clear_error_log(void);
 extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
 
 extern int pSeries_nvram_init(void);
+
+#ifdef CONFIG_MMIO_NVRAM
 extern int mmio_nvram_init(void);
+#else
+static inline int mmio_nvram_init(void)
+{
+       return -ENODEV;
+}
+#endif
+
 #endif /* __KERNEL__ */
 
 /* PowerMac specific nvram stuffs */
index 80e6fad28b4fdb7762d93cef14296c59b875a149..1bce5efe1de042f7ab891f8bdf20fc57d56b77fb 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,
@@ -26,7 +32,7 @@ extern struct of_device *of_platform_device_create(struct device_node *np,
 #define OF_NO_DEEP_PROBE ((struct of_device_id *)-1)
 
 extern int of_platform_bus_probe(struct device_node *root,
-                                struct of_device_id *matches,
+                                const struct of_device_id *matches,
                                 struct device *parent);
 
 extern struct of_device *of_find_device_by_phandle(phandle ph);
index d8bdc79db12e2767b1dec66cf74a530975fb8f49..9b16d3b171699f41c00af244bb4034fb873f3b06 100644 (file)
@@ -1,15 +1,42 @@
 #ifndef _ASM_POWERPC_PCI_BRIDGE_H
 #define _ASM_POWERPC_PCI_BRIDGE_H
 #ifdef __KERNEL__
-
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
 
-#ifndef CONFIG_PPC64
-
 struct device_node;
-struct pci_controller;
+
+extern unsigned int ppc_pci_flags;
+enum {
+       /* Force re-assigning all resources (ignore firmware
+        * setup completely)
+        */
+       PPC_PCI_REASSIGN_ALL_RSRC       = 0x00000001,
+
+       /* Re-assign all bus numbers */
+       PPC_PCI_REASSIGN_ALL_BUS        = 0x00000002,
+
+       /* Do not try to assign, just use existing setup */
+       PPC_PCI_PROBE_ONLY              = 0x00000004,
+
+       /* Don't bother with ISA alignment unless the bridge has
+        * ISA forwarding enabled
+        */
+       PPC_PCI_CAN_SKIP_ISA_ALIGN      = 0x00000008,
+
+       /* Enable domain numbers in /proc */
+       PPC_PCI_ENABLE_PROC_DOMAINS     = 0x00000010,
+       /* ... except for domain 0 */
+       PPC_PCI_COMPAT_DOMAIN_0         = 0x00000020,
+};
+
 
 /*
  * Structure of a PCI controller (host bridge)
@@ -17,26 +44,41 @@ struct pci_controller;
 struct pci_controller {
        struct pci_bus *bus;
        char is_dynamic;
-       void *arch_data;
+#ifdef CONFIG_PPC64
+       int node;
+#endif
+       struct device_node *dn;
        struct list_head list_node;
        struct device *parent;
 
        int first_busno;
        int last_busno;
+#ifndef CONFIG_PPC64
        int self_busno;
+#endif
 
        void __iomem *io_base_virt;
+#ifdef CONFIG_PPC64
+       void *io_base_alloc;
+#endif
        resource_size_t io_base_phys;
+#ifndef CONFIG_PPC64
+       resource_size_t pci_io_size;
+#endif
 
        /* Some machines (PReP) have a non 1:1 mapping of
         * the PCI memory space in the CPU bus space
         */
        resource_size_t pci_mem_offset;
+#ifdef CONFIG_PPC64
+       unsigned long pci_io_size;
+#endif
 
        struct pci_ops *ops;
-       volatile unsigned int __iomem *cfg_addr;
-       volatile void __iomem *cfg_data;
+       unsigned int __iomem *cfg_addr;
+       void __iomem *cfg_data;
 
+#ifndef CONFIG_PPC64
        /*
         * Used for variants of PCI indirect handling and possible quirks:
         *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
@@ -51,21 +93,30 @@ 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 +132,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 +155,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 +180,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 +190,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 +228,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);
 
 extern int pcibios_remove_root_bus(struct pci_controller *phb);
 
@@ -270,20 +271,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 +297,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 7b11765c6865f31157dd30c6ee91ba5c1ecc9ad0..a05a942b1c2573d4dae0ba35e2bbf24d6b3d2f14 100644 (file)
@@ -36,11 +36,10 @@ struct pci_dev;
 
 /*
  * Set this to 1 if you want the kernel to re-assign all PCI
- * bus numbers
+ * bus numbers (don't do that on ppc64 yet !)
  */
-extern int pci_assign_all_buses;
-#define pcibios_assign_all_busses()    (pci_assign_all_buses)
-
+#define pcibios_assign_all_busses()            (ppc_pci_flags & \
+                                        PPC_PCI_REASSIGN_ALL_BUS)
 #define pcibios_scan_all_fns(a, b)     0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
@@ -95,9 +94,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 #define get_pci_dma_ops()      NULL
 #endif
 
-/* Decide whether to display the domain number in /proc */
-extern int pci_proc_domain(struct pci_bus *bus);
-
 #else /* 32-bit */
 
 #ifdef CONFIG_PCI
@@ -109,17 +105,14 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
        *strategy_parameter = ~0UL;
 }
 #endif
-
-/* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
-       return 0;
-}
-
 #endif /* CONFIG_PPC64 */
 
 extern int pci_domain_nr(struct pci_bus *bus);
 
+/* Decide whether to display the domain number in /proc */
+extern int pci_proc_domain(struct pci_bus *bus);
+
+
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
@@ -199,13 +192,12 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
        return root;
 }
 
-extern void pcibios_fixup_device_resources(struct pci_dev *dev,
-                       struct pci_bus *bus);
-
 extern void pcibios_setup_new_device(struct pci_dev *dev);
 
 extern void pcibios_claim_one_bus(struct pci_bus *b);
 
+extern void pcibios_resource_survey(void);
+
 extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
 
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
@@ -229,5 +221,8 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
                                 const struct resource *rsrc,
                                 resource_size_t *start, resource_size_t *end);
 
+extern void pcibios_do_bus_setup(struct pci_bus *bus);
+extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
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 925e2d384bb327e1dff9d3177dee37e38c932084..78b7b0d494c0b353ea67659a969a20b84b3bfb86 100644 (file)
@@ -202,6 +202,10 @@ static inline unsigned long of_read_ulong(const u32 *cell, int size)
  */
 extern u64 of_translate_address(struct device_node *np, const u32 *addr);
 
+/* Translate a DMA address from device space to CPU space */
+extern u64 of_translate_dma_address(struct device_node *dev,
+                                   const u32 *in_addr);
+
 /* Extract an address from a device, returns the region size and
  * the address space flags too. The PCI version uses a BAR number
  * instead of an absolute index
index 0dabe46a29d20ac7e1e9a9a85001261eb34220b5..a24b7b14958fc5361e1680653f8d37c15babbd60 100644 (file)
 #define MEM_PART_SECONDARY     1
 #define MEM_PART_MURAM         2
 
+/* Clocks and BRGs */
+enum qe_clock {
+       QE_CLK_NONE = 0,
+       QE_BRG1,                /* Baud Rate Generator 1 */
+       QE_BRG2,                /* Baud Rate Generator 2 */
+       QE_BRG3,                /* Baud Rate Generator 3 */
+       QE_BRG4,                /* Baud Rate Generator 4 */
+       QE_BRG5,                /* Baud Rate Generator 5 */
+       QE_BRG6,                /* Baud Rate Generator 6 */
+       QE_BRG7,                /* Baud Rate Generator 7 */
+       QE_BRG8,                /* Baud Rate Generator 8 */
+       QE_BRG9,                /* Baud Rate Generator 9 */
+       QE_BRG10,               /* Baud Rate Generator 10 */
+       QE_BRG11,               /* Baud Rate Generator 11 */
+       QE_BRG12,               /* Baud Rate Generator 12 */
+       QE_BRG13,               /* Baud Rate Generator 13 */
+       QE_BRG14,               /* Baud Rate Generator 14 */
+       QE_BRG15,               /* Baud Rate Generator 15 */
+       QE_BRG16,               /* Baud Rate Generator 16 */
+       QE_CLK1,                /* Clock 1 */
+       QE_CLK2,                /* Clock 2 */
+       QE_CLK3,                /* Clock 3 */
+       QE_CLK4,                /* Clock 4 */
+       QE_CLK5,                /* Clock 5 */
+       QE_CLK6,                /* Clock 6 */
+       QE_CLK7,                /* Clock 7 */
+       QE_CLK8,                /* Clock 8 */
+       QE_CLK9,                /* Clock 9 */
+       QE_CLK10,               /* Clock 10 */
+       QE_CLK11,               /* Clock 11 */
+       QE_CLK12,               /* Clock 12 */
+       QE_CLK13,               /* Clock 13 */
+       QE_CLK14,               /* Clock 14 */
+       QE_CLK15,               /* Clock 15 */
+       QE_CLK16,               /* Clock 16 */
+       QE_CLK17,               /* Clock 17 */
+       QE_CLK18,               /* Clock 18 */
+       QE_CLK19,               /* Clock 19 */
+       QE_CLK20,               /* Clock 20 */
+       QE_CLK21,               /* Clock 21 */
+       QE_CLK22,               /* Clock 22 */
+       QE_CLK23,               /* Clock 23 */
+       QE_CLK24,               /* Clock 24 */
+       QE_CLK_DUMMY
+};
+
 /* Export QE common operations */
 extern void qe_reset(void);
 extern int par_io_init(struct device_node *np);
@@ -38,7 +84,8 @@ extern int par_io_data_set(u8 port, u8 pin, u8 val);
 
 /* QE internal API */
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
-void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier);
+enum qe_clock qe_clock_source(const char *source);
+int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
 unsigned long qe_muram_alloc(int size, int align);
@@ -129,52 +176,6 @@ enum comm_dir {
        COMM_DIR_RX_AND_TX = 3
 };
 
-/* Clocks and BRGs */
-enum qe_clock {
-       QE_CLK_NONE = 0,
-       QE_BRG1,                /* Baud Rate Generator 1 */
-       QE_BRG2,                /* Baud Rate Generator 2 */
-       QE_BRG3,                /* Baud Rate Generator 3 */
-       QE_BRG4,                /* Baud Rate Generator 4 */
-       QE_BRG5,                /* Baud Rate Generator 5 */
-       QE_BRG6,                /* Baud Rate Generator 6 */
-       QE_BRG7,                /* Baud Rate Generator 7 */
-       QE_BRG8,                /* Baud Rate Generator 8 */
-       QE_BRG9,                /* Baud Rate Generator 9 */
-       QE_BRG10,               /* Baud Rate Generator 10 */
-       QE_BRG11,               /* Baud Rate Generator 11 */
-       QE_BRG12,               /* Baud Rate Generator 12 */
-       QE_BRG13,               /* Baud Rate Generator 13 */
-       QE_BRG14,               /* Baud Rate Generator 14 */
-       QE_BRG15,               /* Baud Rate Generator 15 */
-       QE_BRG16,               /* Baud Rate Generator 16 */
-       QE_CLK1,                /* Clock 1 */
-       QE_CLK2,                /* Clock 2 */
-       QE_CLK3,                /* Clock 3 */
-       QE_CLK4,                /* Clock 4 */
-       QE_CLK5,                /* Clock 5 */
-       QE_CLK6,                /* Clock 6 */
-       QE_CLK7,                /* Clock 7 */
-       QE_CLK8,                /* Clock 8 */
-       QE_CLK9,                /* Clock 9 */
-       QE_CLK10,               /* Clock 10 */
-       QE_CLK11,               /* Clock 11 */
-       QE_CLK12,               /* Clock 12 */
-       QE_CLK13,               /* Clock 13 */
-       QE_CLK14,               /* Clock 14 */
-       QE_CLK15,               /* Clock 15 */
-       QE_CLK16,               /* Clock 16 */
-       QE_CLK17,               /* Clock 17 */
-       QE_CLK18,               /* Clock 18 */
-       QE_CLK19,               /* Clock 19 */
-       QE_CLK20,               /* Clock 20 */
-       QE_CLK21,               /* Clock 21 */
-       QE_CLK22,               /* Clock 22 */
-       QE_CLK23,               /* Clock 23 */
-       QE_CLK24,               /* Clock 24 */
-       QE_CLK_DUMMY,
-};
-
 /* QE CMXUCR Registers.
  * There are two UCCs represented in each of the four CMXUCR registers.
  * These values are for the UCC in the LSBs
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 8fdc2b47afb9889d08030a5952ae655d4ce85553..d3e8dd0fc738c6611b2410a4b6b18371c6a4aaf3 100644 (file)
 #define SPRN_SPEFSCR   0x200   /* SPE & Embedded FP Status & Control */
 #define SPRN_BBEAR     0x201   /* Branch Buffer Entry Address Register */
 #define SPRN_BBTAR     0x202   /* Branch Buffer Target Address Register */
+#define SPRN_ATB       0x20E   /* Alternate Time Base */
+#define SPRN_ATBL      0x20E   /* Alternate Time Base Lower */
+#define SPRN_ATBU      0x20F   /* Alternate Time Base Upper */
 #define SPRN_IVOR32    0x210   /* Interrupt Vector Offset Register 32 */
 #define SPRN_IVOR33    0x211   /* Interrupt Vector Offset Register 33 */
 #define SPRN_IVOR34    0x212   /* Interrupt Vector Offset Register 34 */
 #define SPRN_IVOR35    0x213   /* Interrupt Vector Offset Register 35 */
+#define SPRN_IVOR36    0x214   /* Interrupt Vector Offset Register 36 */
+#define SPRN_IVOR37    0x215   /* Interrupt Vector Offset Register 37 */
 #define SPRN_MCSRR0    0x23A   /* Machine Check Save and Restore Register 0 */
 #define SPRN_MCSRR1    0x23B   /* Machine Check Save and Restore Register 1 */
 #define SPRN_MCSR      0x23C   /* Machine Check Status Register */
 #define SPRN_MCAR      0x23D   /* Machine Check Address Register */
 #define SPRN_DSRR0     0x23E   /* Debug Save and Restore Register 0 */
 #define SPRN_DSRR1     0x23F   /* Debug Save and Restore Register 1 */
+#define SPRN_SPRG8     0x25C   /* Special Purpose Register General 8 */
+#define SPRN_SPRG9     0x25D   /* Special Purpose Register General 9 */
 #define SPRN_MAS0      0x270   /* MMU Assist Register 0 */
 #define SPRN_MAS1      0x271   /* MMU Assist Register 1 */
 #define SPRN_MAS2      0x272   /* MMU Assist Register 2 */
 #define SPRN_MAS4      0x274   /* MMU Assist Register 4 */
 #define SPRN_MAS5      0x275   /* MMU Assist Register 5 */
 #define SPRN_MAS6      0x276   /* MMU Assist Register 6 */
-#define SPRN_MAS7      0x3b0   /* MMU Assist Register 7 */
 #define SPRN_PID1      0x279   /* Process ID Register 1 */
 #define SPRN_PID2      0x27A   /* Process ID Register 2 */
 #define SPRN_TLB0CFG   0x2B0   /* TLB 0 Config Register */
 #define SPRN_TLB1CFG   0x2B1   /* TLB 1 Config Register */
+#define SPRN_EPR       0x2BE   /* External Proxy Register */
 #define SPRN_CCR1      0x378   /* Core Configuration Register 1 */
 #define SPRN_ZPR       0x3B0   /* Zone Protection Register (40x) */
+#define SPRN_MAS7      0x3B0   /* MMU Assist Register 7 */
 #define SPRN_MMUCR     0x3B2   /* MMU Control Register */
 #define SPRN_CCR0      0x3B3   /* Core Configuration Register 0 */
+#define SPRN_EPLC      0x3B3   /* External Process ID Load Context */
+#define SPRN_EPSC      0x3B4   /* External Process ID Store Context */
 #define SPRN_SGR       0x3B9   /* Storage Guarded Register */
 #define SPRN_DCWR      0x3BA   /* Data Cache Write-thru Register */
 #define SPRN_SLER      0x3BB   /* Little-endian real mode */
 #define SPRN_L1CSR0    0x3F2   /* L1 Cache Control and Status Register 0 */
 #define SPRN_L1CSR1    0x3F3   /* L1 Cache Control and Status Register 1 */
 #define SPRN_PIT       0x3DB   /* Programmable Interval Timer */
+#define SPRN_BUCSR     0x3F5   /* Branch Unit Control and Status */
 #define SPRN_DCCR      0x3FA   /* Data Cache Cacheability Register */
 #define SPRN_ICCR      0x3FB   /* Instruction Cache Cacheability Register */
 #define SPRN_SVR       0x3FF   /* System Version Register */
 #define ESR_IMCB       0x20000000      /* Instr. Machine Check - Bus error */
 #define ESR_IMCT       0x10000000      /* Instr. Machine Check - Timeout */
 #define ESR_PIL                0x08000000      /* Program Exception - Illegal */
-#define ESR_PPR                0x04000000      /* Program Exception - Priveleged */
+#define ESR_PPR                0x04000000      /* Program Exception - Privileged */
 #define ESR_PTR                0x02000000      /* Program Exception - Trap */
 #define ESR_FP         0x01000000      /* Floating Point Operation */
 #define ESR_DST                0x00800000      /* Storage Exception - Data miss */
index e49f644ca63a18e9bfc491ff326a7d5b5b61d501..7ae2753da565d6435c05b8d0e9ff505ae94fa928 100644 (file)
@@ -22,7 +22,7 @@
  * Partition info commands
  *
  * These commands are used to retrieve the sdb-partition-XX datas from
- * the SMU. The lenght is always 2. First byte is the subcommand code
+ * the SMU. The length is always 2. First byte is the subcommand code
  * and second byte is the partition ID.
  *
  * The reply is 6 bytes:
  * Power supply control
  *
  * The "sub" command is an ASCII string in the data, the
- * data lenght is that of the string.
+ * data length is that of the string.
  *
  * The VSLEW command can be used to get or set the voltage slewing.
- *  - lenght 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
+ *  - length 5 (only "VSLEW") : it returns "DONE" and 3 bytes of
  *    reply at data offset 6, 7 and 8.
- *  - lenght 8 ("VSLEWxyz") has 3 additional bytes appended, and is
+ *  - length 8 ("VSLEWxyz") has 3 additional bytes appended, and is
  *    used to set the voltage slewing point. The SMU replies with "DONE"
  * I yet have to figure out their exact meaning of those 3 bytes in
  * both cases. They seem to be:
  */
 #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 -
@@ -564,13 +688,13 @@ struct smu_user_cmd_hdr
 
        __u8            cmd;                    /* SMU command byte */
        __u8            pad[3];                 /* padding */
-       __u32           data_len;               /* Lenght of data following */
+       __u32           data_len;               /* Length of data following */
 };
 
 struct smu_user_reply_hdr
 {
        __u32           status;                 /* Command status */
-       __u32           reply_len;              /* Lenght of data follwing */
+       __u32           reply_len;              /* Length of data follwing */
 };
 
 #endif /*  _SMU_H */
index b1accce77bb5a84a52a5f3b165bff1350137770e..5ca30e2e26399cce10f6f62ad30f01329e59c212 100644 (file)
 
 struct spu_context;
 struct spu_runqueue;
+struct spu_lscsa;
 struct device_node;
 
 enum spu_utilization_state {
@@ -145,7 +146,6 @@ struct spu {
        void (* ibox_callback)(struct spu *spu);
        void (* stop_callback)(struct spu *spu);
        void (* mfc_callback)(struct spu *spu);
-       void (* dma_callback)(struct spu *spu, int type);
 
        char irq_c0[8];
        char irq_c1[8];
@@ -196,10 +196,11 @@ struct cbe_spu_info {
 extern struct cbe_spu_info cbe_spu_info[];
 
 void spu_init_channels(struct spu *spu);
-int spu_irq_class_0_bottom(struct spu *spu);
-int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+               void *code, int code_size);
+
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);
 #else
@@ -210,6 +211,7 @@ static inline void crash_register_spus(struct list_head *list)
 
 extern void spu_invalidate_slbs(struct spu *spu);
 extern void spu_associate_mm(struct spu *spu, struct mm_struct *mm);
+int spu_64k_pages_available(void);
 
 /* Calls from the memory management to the SPU */
 struct mm_struct;
@@ -278,6 +280,8 @@ void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
 int spu_add_sysdev_attr_group(struct attribute_group *attrs);
 void spu_remove_sysdev_attr_group(struct attribute_group *attrs);
 
+int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
+               unsigned long dsisr, unsigned *flt);
 
 /*
  * Notifier blocks:
@@ -299,7 +303,7 @@ int spu_switch_event_register(struct notifier_block * n);
 int spu_switch_event_unregister(struct notifier_block * n);
 
 /*
- * This defines the Local Store, Problem Area and Privlege Area of an SPU.
+ * This defines the Local Store, Problem Area and Privilege Area of an SPU.
  */
 
 union mfc_tag_size_class_cmd {
@@ -520,8 +524,24 @@ struct spu_priv1 {
 #define CLASS2_ENABLE_SPU_STOP_INTR                    0x2L
 #define CLASS2_ENABLE_SPU_HALT_INTR                    0x4L
 #define CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR  0x8L
+#define CLASS2_ENABLE_MAILBOX_THRESHOLD_INTR           0x10L
        u8  pad_0x118_0x140[0x28];                              /* 0x118 */
        u64 int_stat_RW[3];                                     /* 0x140 */
+#define CLASS0_DMA_ALIGNMENT_INTR                      0x1L
+#define CLASS0_INVALID_DMA_COMMAND_INTR                        0x2L
+#define CLASS0_SPU_ERROR_INTR                          0x4L
+#define CLASS0_INTR_MASK                               0x7L
+#define CLASS1_SEGMENT_FAULT_INTR                      0x1L
+#define CLASS1_STORAGE_FAULT_INTR                      0x2L
+#define CLASS1_LS_COMPARE_SUSPEND_ON_GET_INTR          0x4L
+#define CLASS1_LS_COMPARE_SUSPEND_ON_PUT_INTR          0x8L
+#define CLASS1_INTR_MASK                               0xfL
+#define CLASS2_MAILBOX_INTR                            0x1L
+#define CLASS2_SPU_STOP_INTR                           0x2L
+#define CLASS2_SPU_HALT_INTR                           0x4L
+#define CLASS2_SPU_DMA_TAG_GROUP_COMPLETE_INTR         0x8L
+#define CLASS2_MAILBOX_THRESHOLD_INTR                  0x10L
+#define CLASS2_INTR_MASK                               0x1fL
        u8  pad_0x158_0x180[0x28];                              /* 0x158 */
        u64 int_route_RW;                                       /* 0x180 */
 
index e87794d5d4eadc75513bcd9a5e0708e3cefb439c..0ab6bff86078e955dd10c3da1c282fe29773f33f 100644 (file)
@@ -194,7 +194,7 @@ struct spu_priv1_collapsed {
 };
 
 /*
- * struct spu_priv2_collapsed - condensed priviliged 2 area, w/o pads.
+ * struct spu_priv2_collapsed - condensed privileged 2 area, w/o pads.
  */
 struct spu_priv2_collapsed {
        u64 slb_index_W;
@@ -254,20 +254,11 @@ struct spu_state {
        u64 spu_chnldata_RW[32];
        u32 spu_mailbox_data[4];
        u32 pu_mailbox_data[1];
-       u64 dar, dsisr;
+       u64 dar, dsisr, class_0_pending;
        unsigned long suspend_time;
        spinlock_t register_lock;
 };
 
-extern int spu_init_csa(struct spu_state *csa);
-extern void spu_fini_csa(struct spu_state *csa);
-extern int spu_save(struct spu_state *prev, struct spu *spu);
-extern int spu_restore(struct spu_state *new, struct spu *spu);
-extern int spu_switch(struct spu_state *prev, struct spu_state *new,
-                     struct spu *spu);
-extern int spu_alloc_lscsa(struct spu_state *csa);
-extern void spu_free_lscsa(struct spu_state *csa);
-
 #endif /* !__SPU__ */
 #endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
index 0f37c7c908207ae1d65c374f41f371308bbeef19..25020a34ce7fd47b6478a272b6969af4e74981aa 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/types.h>
 
 struct spu;
+struct spu_context;
 
 /* access to priv1 registers */
 
@@ -178,6 +179,8 @@ struct spu_management_ops {
        int (*enumerate_spus)(int (*fn)(void *data));
        int (*create_spu)(struct spu *spu, void *data);
        int (*destroy_spu)(struct spu *spu);
+       void (*enable_spu)(struct spu_context *ctx);
+       void (*disable_spu)(struct spu_context *ctx);
        int (*init_affinity)(void);
 };
 
@@ -207,6 +210,18 @@ spu_init_affinity (void)
        return spu_management_ops->init_affinity();
 }
 
+static inline void
+spu_enable_spu (struct spu_context *ctx)
+{
+       spu_management_ops->enable_spu(ctx);
+}
+
+static inline void
+spu_disable_spu (struct spu_context *ctx)
+{
+       spu_management_ops->disable_spu(ctx);
+}
+
 /*
  * The declarations folowing are put here for convenience
  * and only intended to be used by the platform setup code.
index 1311cefdfd30ffdea3ecf7628f50ed0db7f2ea0d..4b0e152060060c5ed53d2aa14fd0cf8896cdb1cc 100644 (file)
@@ -123,7 +123,7 @@ typedef struct      mem_ctlr {
 #define OR_G5LA                0x00000400      /* Output #GPL5 on #GPL_A5              */
 #define OR_G5LS                0x00000200      /* Drive #GPL high on falling edge of...*/
 #define OR_BI          0x00000100      /* Burst inhibit                        */
-#define OR_SCY_MSK     0x000000f0      /* Cycle Lenght in Clocks               */
+#define OR_SCY_MSK     0x000000f0      /* Cycle Length in Clocks               */
 #define OR_SCY_0_CLK   0x00000000      /* 0 clock cycles wait states           */
 #define OR_SCY_1_CLK   0x00000010      /* 1 clock cycles wait states           */
 #define OR_SCY_2_CLK   0x00000020      /* 2 clock cycles wait states           */
index 397248705e0ed88060f7a76e1ef4adef617b34f1..462abb185f07b8e9b34eb0356e9f5a8c3330559f 100644 (file)
@@ -681,7 +681,7 @@ typedef struct risc_timer_pram {
 #define        CICR_SCC_SCC3           ((uint)0x00200000)      /* SCC3 @ SCCc */
 #define        CICR_SCB_SCC2           ((uint)0x00040000)      /* SCC2 @ SCCb */
 #define        CICR_SCA_SCC1           ((uint)0x00000000)      /* SCC1 @ SCCa */
-#define CICR_IRL_MASK          ((uint)0x0000e000)      /* Core interrrupt */
+#define CICR_IRL_MASK          ((uint)0x0000e000)      /* Core interrupt */
 #define CICR_HP_MASK           ((uint)0x00001f00)      /* Hi-pri int. */
 #define CICR_IEN               ((uint)0x00000080)      /* Int. enable */
 #define CICR_SPS               ((uint)0x00000001)      /* SCC Spread */
index 82948ed2744a78f7f29e2b4423bed318b71c72af..4cad45a055dd8c319a114a29bafdd53b869a01ee 100644 (file)
 #define ESR_IMCB       0x20000000      /* Instr. Machine Check - Bus error */
 #define ESR_IMCT       0x10000000      /* Instr. Machine Check - Timeout */
 #define ESR_PIL                0x08000000      /* Program Exception - Illegal */
-#define ESR_PPR                0x04000000      /* Program Exception - Priveleged */
+#define ESR_PPR                0x04000000      /* Program Exception - Privileged */
 #define ESR_PTR                0x02000000      /* Program Exception - Trap */
 #define ESR_FP         0x01000000      /* Floating Point Operation */
 #define ESR_DST                0x00800000      /* Storage Exception - Data miss */
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);
index b7824c21535487a0b8d7a9a16b504c7ad42b0399..4c5f65392d36e832be841716eee2ebd752723f59 100644 (file)
@@ -159,41 +159,7 @@ extern void pmu_unlock(void);
 extern int pmu_present(void);
 extern int pmu_get_model(void);
 
-#ifdef CONFIG_PM
-/*
- * Stuff for putting the powerbook to sleep and waking it again.
- *
- */
-#include <linux/list.h>
-
-struct pmu_sleep_notifier
-{
-       void (*notifier_call)(struct pmu_sleep_notifier *self, int when);
-       int priority;
-       struct list_head list;
-};
-
-/* Code values for calling sleep/wakeup handlers
- */
-#define PBOOK_SLEEP_REQUEST    1
-#define PBOOK_SLEEP_NOW                2
-#define PBOOK_WAKE             3
-
-/* priority levels in notifiers */
-#define SLEEP_LEVEL_VIDEO      100     /* Video driver (first wake) */
-#define SLEEP_LEVEL_MEDIABAY   90      /* Media bay driver */
-#define SLEEP_LEVEL_BLOCK      80      /* IDE, SCSI */
-#define SLEEP_LEVEL_NET                70      /* bmac, gmac */
-#define SLEEP_LEVEL_MISC       60      /* Anything else */
-#define SLEEP_LEVEL_USERLAND   55      /* Reserved for apm_emu */
-#define SLEEP_LEVEL_ADB                50      /* ADB (async) */
-#define SLEEP_LEVEL_SOUND      40      /* Sound driver (blocking) */
-
-/* special register notifier functions */
-int pmu_register_sleep_notifier(struct pmu_sleep_notifier* notifier);
-int pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* notifier);
-
-#endif /* CONFIG_PM */
+extern void pmu_backlight_set_sleep(int sleep);
 
 #define PMU_MAX_BATTERIES      2