summary refs log tree commit diff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c12
-rw-r--r--arch/alpha/kernel/osf_sys.c2
-rw-r--r--arch/alpha/kernel/signal.c2
-rw-r--r--arch/arm/Kconfig103
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boot/compressed/head-at91rm9200.S12
-rw-r--r--arch/arm/boot/compressed/head.S4
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/dmabounce.c67
-rw-r--r--arch/arm/common/sharpsl_pm.c28
-rw-r--r--arch/arm/common/uengine.c58
-rw-r--r--arch/arm/configs/ateb9200_defconfig1312
-rw-r--r--arch/arm/configs/carmeva_defconfig723
-rw-r--r--arch/arm/configs/kafa_defconfig884
-rw-r--r--arch/arm/configs/kb9202_defconfig780
-rw-r--r--arch/arm/configs/lpd270_defconfig963
-rw-r--r--arch/arm/configs/lpd7a400_defconfig135
-rw-r--r--arch/arm/configs/lpd7a404_defconfig430
-rw-r--r--arch/arm/configs/netx_defconfig926
-rw-r--r--arch/arm/configs/pnx4008_defconfig2072
-rw-r--r--arch/arm/configs/s3c2410_defconfig76
-rw-r--r--arch/arm/kernel/entry-armv.S24
-rw-r--r--arch/arm/kernel/entry-common.S2
-rw-r--r--arch/arm/kernel/irq.c8
-rw-r--r--arch/arm/kernel/iwmmxt.S4
-rw-r--r--arch/arm/kernel/process.c85
-rw-r--r--arch/arm/kernel/signal.c228
-rw-r--r--arch/arm/kernel/time.c24
-rw-r--r--arch/arm/mach-at91rm9200/Kconfig12
-rw-r--r--arch/arm/mach-at91rm9200/Makefile17
-rw-r--r--arch/arm/mach-at91rm9200/board-carmeva.c131
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c45
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c32
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c59
-rw-r--r--arch/arm/mach-at91rm9200/board-eb9200.c130
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c49
-rw-r--r--arch/arm/mach-at91rm9200/board-kafa.c116
-rw-r--r--arch/arm/mach-at91rm9200/board-kb9202.c125
-rw-r--r--arch/arm/mach-at91rm9200/clock.c126
-rw-r--r--arch/arm/mach-at91rm9200/common.c19
-rw-r--r--arch/arm/mach-at91rm9200/devices.c406
-rw-r--r--arch/arm/mach-at91rm9200/generic.h7
-rw-r--r--arch/arm/mach-at91rm9200/gpio.c89
-rw-r--r--arch/arm/mach-at91rm9200/irq.c44
-rw-r--r--arch/arm/mach-at91rm9200/pm.c225
-rw-r--r--arch/arm/mach-at91rm9200/time.c57
-rw-r--r--arch/arm/mach-ep93xx/Makefile2
-rw-r--r--arch/arm/mach-ep93xx/clock.c156
-rw-r--r--arch/arm/mach-ep93xx/core.c33
-rw-r--r--arch/arm/mach-ep93xx/gesbc9312.c24
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c23
-rw-r--r--arch/arm/mach-imx/dma.c65
-rw-r--r--arch/arm/mach-ixp2000/core.c4
-rw-r--r--arch/arm/mach-ixp23xx/core.c5
-rw-r--r--arch/arm/mach-ixp23xx/espresso.c22
-rw-r--r--arch/arm/mach-ixp23xx/ixdp2351.c22
-rw-r--r--arch/arm/mach-ixp23xx/roadrunner.c22
-rw-r--r--arch/arm/mach-ixp4xx/common.c2
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c41
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c48
-rw-r--r--arch/arm/mach-lh7a40x/Kconfig5
-rw-r--r--arch/arm/mach-lh7a40x/Makefile19
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c200
-rw-r--r--arch/arm/mach-lh7a40x/clcd.c241
-rw-r--r--arch/arm/mach-lh7a40x/clocks.c199
-rw-r--r--arch/arm/mach-lh7a40x/common.h1
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a404.c17
-rw-r--r--arch/arm/mach-lh7a40x/lcd-panel.h346
-rw-r--r--arch/arm/mach-lh7a40x/ssp-cpld.c343
-rw-r--r--arch/arm/mach-lh7a40x/time.c4
-rw-r--r--arch/arm/mach-netx/Kconfig24
-rw-r--r--arch/arm/mach-netx/Makefile15
-rw-r--r--arch/arm/mach-netx/Makefile.boot2
-rw-r--r--arch/arm/mach-netx/fb.c114
-rw-r--r--arch/arm/mach-netx/fb.h24
-rw-r--r--arch/arm/mach-netx/generic.c193
-rw-r--r--arch/arm/mach-netx/generic.h24
-rw-r--r--arch/arm/mach-netx/nxdb500.c210
-rw-r--r--arch/arm/mach-netx/nxdkn.c103
-rw-r--r--arch/arm/mach-netx/nxeb500hmi.c187
-rw-r--r--arch/arm/mach-netx/pfifo.c68
-rw-r--r--arch/arm/mach-netx/time.c88
-rw-r--r--arch/arm/mach-netx/xc.c255
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c11
-rw-r--r--arch/arm/mach-pnx4008/Makefile12
-rw-r--r--arch/arm/mach-pnx4008/Makefile.boot4
-rw-r--r--arch/arm/mach-pnx4008/clock.c983
-rw-r--r--arch/arm/mach-pnx4008/clock.h43
-rw-r--r--arch/arm/mach-pnx4008/core.c207
-rw-r--r--arch/arm/mach-pnx4008/dma.c1109
-rw-r--r--arch/arm/mach-pnx4008/gpio.c330
-rw-r--r--arch/arm/mach-pnx4008/irq.c121
-rw-r--r--arch/arm/mach-pnx4008/pm.c184
-rw-r--r--arch/arm/mach-pnx4008/serial.c69
-rw-r--r--arch/arm/mach-pnx4008/sleep.S196
-rw-r--r--arch/arm/mach-pnx4008/time.c141
-rw-r--r--arch/arm/mach-pxa/Kconfig1
-rw-r--r--arch/arm/mach-pxa/Makefile2
-rw-r--r--arch/arm/mach-pxa/corgi.c25
-rw-r--r--arch/arm/mach-pxa/corgi_pm.c23
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c42
-rw-r--r--arch/arm/mach-pxa/lubbock.c84
-rw-r--r--arch/arm/mach-pxa/poodle.c108
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c7
-rw-r--r--arch/arm/mach-pxa/spitz.c25
-rw-r--r--arch/arm/mach-pxa/spitz_pm.c15
-rw-r--r--arch/arm/mach-pxa/tosa.c26
-rw-r--r--arch/arm/mach-s3c2410/Kconfig54
-rw-r--r--arch/arm/mach-s3c2410/Makefile20
-rw-r--r--arch/arm/mach-s3c2410/clock.c249
-rw-r--r--arch/arm/mach-s3c2410/clock.h13
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.c65
-rw-r--r--arch/arm/mach-s3c2410/cpu.c114
-rw-r--r--arch/arm/mach-s3c2410/cpu.h9
-rw-r--r--arch/arm/mach-s3c2410/devs.c78
-rw-r--r--arch/arm/mach-s3c2410/devs.h8
-rw-r--r--arch/arm/mach-s3c2410/irq.c57
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c52
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-nexcoder.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-osiris.c5
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2413.c126
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c2
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c2
-rw-r--r--arch/arm/mach-s3c2410/pm-simtec.c3
-rw-r--r--arch/arm/mach-s3c2410/pm.c4
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-clock.c271
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-gpio.c13
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c108
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.h2
-rw-r--r--arch/arm/mach-s3c2410/s3c2412-clock.c711
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.c195
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.h29
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c4
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-irq.c77
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c234
-rw-r--r--arch/arm/mach-s3c2410/s3c2442-clock.c171
-rw-r--r--arch/arm/mach-s3c2410/s3c2442.c52
-rw-r--r--arch/arm/mach-s3c2410/s3c2442.h17
-rw-r--r--arch/arm/mach-s3c2410/s3c244x-irq.c142
-rw-r--r--arch/arm/mach-s3c2410/s3c244x.c184
-rw-r--r--arch/arm/mach-s3c2410/s3c244x.h25
-rw-r--r--arch/arm/mach-s3c2410/sleep.S2
-rw-r--r--arch/arm/mm/Kconfig10
-rw-r--r--arch/arm/nwfpe/fpmodule.c25
-rw-r--r--arch/arm/plat-omap/timer32k.c3
-rw-r--r--arch/arm/vfp/Makefile5
-rw-r--r--arch/arm/vfp/vfphw.S4
-rw-r--r--arch/arm/vfp/vfpmodule.c71
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/frv_ksyms.c18
-rw-r--r--arch/frv/kernel/irq-routing.c8
-rw-r--r--arch/frv/kernel/irq.c6
-rw-r--r--arch/frv/kernel/pm.c40
-rw-r--r--arch/frv/kernel/process.c2
-rw-r--r--arch/frv/kernel/setup.c2
-rw-r--r--arch/frv/kernel/signal.c22
-rw-r--r--arch/frv/kernel/sys_frv.c2
-rw-r--r--arch/frv/kernel/sysctl.c4
-rw-r--r--arch/frv/kernel/uaccess.c6
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c10
-rw-r--r--arch/frv/mm/kmap.c6
-rw-r--r--arch/h8300/kernel/signal.c2
-rw-r--r--arch/i386/Kconfig7
-rw-r--r--arch/i386/kernel/acpi/boot.c10
-rw-r--r--arch/i386/kernel/acpi/processor.c2
-rw-r--r--arch/i386/kernel/acpi/sleep.c19
-rw-r--r--arch/i386/kernel/acpi/wakeup.S11
-rw-r--r--arch/i386/kernel/apic.c4
-rw-r--r--arch/i386/kernel/apm.c39
-rw-r--r--arch/i386/kernel/cpu/common.c2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c291
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c30
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c266
-rw-r--r--arch/i386/kernel/cpu/cyrix.c9
-rw-r--r--arch/i386/kernel/cpu/proc.c2
-rw-r--r--arch/i386/kernel/i387.c2
-rw-r--r--arch/i386/kernel/i8259.c4
-rw-r--r--arch/i386/kernel/io_apic.c31
-rw-r--r--arch/i386/kernel/irq.c4
-rw-r--r--arch/i386/kernel/kprobes.c2
-rw-r--r--arch/i386/kernel/microcode.c73
-rw-r--r--arch/i386/kernel/setup.c106
-rw-r--r--arch/i386/kernel/srat.c19
-rw-r--r--arch/i386/kernel/syscall_table.S1
-rw-r--r--arch/i386/kernel/traps.c11
-rw-r--r--arch/i386/kernel/vmlinux.lds.S7
-rw-r--r--arch/i386/lib/usercopy.c137
-rw-r--r--arch/i386/mm/fault.c21
-rw-r--r--arch/i386/mm/init.c3
-rw-r--r--arch/i386/mm/pageattr.c8
-rw-r--r--arch/i386/pci/common.c1
-rw-r--r--arch/i386/pci/i386.c9
-rw-r--r--arch/i386/pci/irq.c15
-rw-r--r--arch/i386/pci/mmconfig.c9
-rw-r--r--arch/i386/pci/pci.h1
-rw-r--r--arch/i386/power/cpu.c2
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/Makefile2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c4
-rw-r--r--arch/ia64/kernel/acpi.c32
-rw-r--r--arch/ia64/kernel/asm-offsets.c16
-rw-r--r--arch/ia64/kernel/efi.c156
-rw-r--r--arch/ia64/kernel/efi_stub.S2
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/entry.h1
-rw-r--r--arch/ia64/kernel/irq_ia64.c19
-rw-r--r--arch/ia64/kernel/mca_asm.S28
-rw-r--r--arch/ia64/kernel/perfmon.c10
-rw-r--r--arch/ia64/kernel/sal.c6
-rw-r--r--arch/ia64/kernel/setup.c1
-rw-r--r--arch/ia64/kernel/uncached.c200
-rw-r--r--arch/ia64/mm/init.c2
-rw-r--r--arch/ia64/mm/ioremap.c27
-rw-r--r--arch/ia64/pci/pci.c19
-rw-r--r--arch/ia64/sn/kernel/io_init.c9
-rw-r--r--arch/ia64/sn/kernel/irq.c142
-rw-r--r--arch/ia64/sn/kernel/setup.c4
-rw-r--r--arch/ia64/sn/kernel/sn2/cache.c15
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c50
-rw-r--r--arch/ia64/sn/pci/pci_dma.c10
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c62
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c8
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c69
-rw-r--r--arch/m68k/kernel/entry.S4
-rw-r--r--arch/m68k/kernel/ints.c6
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/traps.c8
-rw-r--r--arch/m68k/lib/Makefile4
-rw-r--r--arch/m68k/lib/uaccess.c222
-rw-r--r--arch/m68k/mac/config.c13
-rw-r--r--arch/m68k/mac/macints.c1
-rw-r--r--arch/m68k/mac/via.c17
-rw-r--r--arch/m68k/mm/motorola.c12
-rw-r--r--arch/m68k/mm/sun3mmu.c5
-rw-r--r--arch/m68knommu/kernel/signal.c2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/sysirix.c12
-rw-r--r--arch/parisc/hpux/sys_hpux.c10
-rw-r--r--arch/parisc/kernel/signal.c2
-rw-r--r--arch/powerpc/Kconfig53
-rw-r--r--arch/powerpc/Kconfig.debug13
-rw-r--r--arch/powerpc/Makefile1
-rw-r--r--arch/powerpc/boot/Makefile4
-rw-r--r--arch/powerpc/boot/main.c27
-rw-r--r--arch/powerpc/boot/prom.h7
-rw-r--r--arch/powerpc/configs/cell_defconfig34
-rw-r--r--arch/powerpc/configs/mpc85xx_cds_defconfig846
-rw-r--r--arch/powerpc/configs/mpc8641_hpcn_defconfig921
-rw-r--r--arch/powerpc/configs/pmac32_defconfig204
-rw-r--r--arch/powerpc/configs/pseries_defconfig75
-rw-r--r--arch/powerpc/kernel/align.c189
-rw-r--r--arch/powerpc/kernel/asm-offsets.c5
-rw-r--r--arch/powerpc/kernel/cpu_setup_6xx.S2
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S17
-rw-r--r--arch/powerpc/kernel/cputable.c137
-rw-r--r--arch/powerpc/kernel/crash.c13
-rw-r--r--arch/powerpc/kernel/crash_dump.c11
-rw-r--r--arch/powerpc/kernel/entry_64.S2
-rw-r--r--arch/powerpc/kernel/fpu.S6
-rw-r--r--arch/powerpc/kernel/head_32.S14
-rw-r--r--arch/powerpc/kernel/head_64.S29
-rw-r--r--arch/powerpc/kernel/iomap.c2
-rw-r--r--arch/powerpc/kernel/iommu.c23
-rw-r--r--arch/powerpc/kernel/irq.c29
-rw-r--r--arch/powerpc/kernel/lparcfg.c4
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c99
-rw-r--r--arch/powerpc/kernel/misc_32.S2
-rw-r--r--arch/powerpc/kernel/misc_64.S5
-rw-r--r--arch/powerpc/kernel/nvram_64.c2
-rw-r--r--arch/powerpc/kernel/pci_32.c7
-rw-r--r--arch/powerpc/kernel/pci_64.c62
-rw-r--r--arch/powerpc/kernel/pci_direct_iommu.c18
-rw-r--r--arch/powerpc/kernel/pci_dn.c6
-rw-r--r--arch/powerpc/kernel/pci_iommu.c41
-rw-r--r--arch/powerpc/kernel/proc_ppc64.c2
-rw-r--r--arch/powerpc/kernel/process.c55
-rw-r--r--arch/powerpc/kernel/prom.c145
-rw-r--r--arch/powerpc/kernel/prom_init.c120
-rw-r--r--arch/powerpc/kernel/prom_parse.c25
-rw-r--r--arch/powerpc/kernel/ptrace.c2
-rw-r--r--arch/powerpc/kernel/rtas-rtc.c30
-rw-r--r--arch/powerpc/kernel/rtas.c108
-rw-r--r--arch/powerpc/kernel/rtas_flash.c25
-rw-r--r--arch/powerpc/kernel/rtas_pci.c4
-rw-r--r--arch/powerpc/kernel/setup-common.c20
-rw-r--r--arch/powerpc/kernel/setup.h3
-rw-r--r--arch/powerpc/kernel/setup_32.c18
-rw-r--r--arch/powerpc/kernel/setup_64.c31
-rw-r--r--arch/powerpc/kernel/signal_32.c23
-rw-r--r--arch/powerpc/kernel/signal_64.c16
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/kernel/systbl.S311
-rw-r--r--arch/powerpc/kernel/time.c67
-rw-r--r--arch/powerpc/kernel/traps.c8
-rw-r--r--arch/powerpc/kernel/udbg.c7
-rw-r--r--arch/powerpc/kernel/vdso.c57
-rw-r--r--arch/powerpc/kernel/vector.S4
-rw-r--r--arch/powerpc/kernel/vio.c344
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S5
-rw-r--r--arch/powerpc/lib/Makefile5
-rw-r--r--arch/powerpc/lib/bitops.c150
-rw-r--r--arch/powerpc/mm/hash_low_32.S34
-rw-r--r--arch/powerpc/mm/hash_low_64.S31
-rw-r--r--arch/powerpc/mm/hash_native_64.c2
-rw-r--r--arch/powerpc/mm/hash_utils_64.c84
-rw-r--r--arch/powerpc/mm/lmb.c43
-rw-r--r--arch/powerpc/mm/mem.c6
-rw-r--r--arch/powerpc/mm/mmu_context_32.c2
-rw-r--r--arch/powerpc/mm/mmu_context_64.c3
-rw-r--r--arch/powerpc/mm/numa.c8
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c16
-rw-r--r--arch/powerpc/mm/slb.c32
-rw-r--r--arch/powerpc/mm/slb_low.S17
-rw-r--r--arch/powerpc/mm/stab.c4
-rw-r--r--arch/powerpc/mm/tlb_32.c6
-rw-r--r--arch/powerpc/mm/tlb_64.c5
-rw-r--r--arch/powerpc/oprofile/Kconfig1
-rw-r--r--arch/powerpc/oprofile/Makefile4
-rw-r--r--arch/powerpc/oprofile/common.c6
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c37
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig9
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c359
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.h43
-rw-r--r--arch/powerpc/platforms/86xx/Kconfig36
-rw-r--r--arch/powerpc/platforms/86xx/Makefile10
-rw-r--r--arch/powerpc/platforms/86xx/mpc8641_hpcn.h54
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx.h28
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_hpcn.c326
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_pcie.c173
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c117
-rw-r--r--arch/powerpc/platforms/86xx/pci.c325
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig9
-rw-r--r--arch/powerpc/platforms/cell/Makefile23
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c128
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h129
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c40
-rw-r--r--arch/powerpc/platforms/cell/iommu.c18
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c104
-rw-r--r--arch/powerpc/platforms/cell/pervasive.h37
-rw-r--r--arch/powerpc/platforms/cell/ras.c112
-rw-r--r--arch/powerpc/platforms/cell/ras.h9
-rw-r--r--arch/powerpc/platforms/cell/setup.c14
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c179
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c314
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1.c133
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.c159
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile14
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c67
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c36
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped1122
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped922
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c48
-rw-r--r--arch/powerpc/platforms/iseries/Makefile6
-rw-r--r--arch/powerpc/platforms/iseries/call_pci.h19
-rw-r--r--arch/powerpc/platforms/iseries/dt.c615
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c46
-rw-r--r--arch/powerpc/platforms/iseries/iommu.h35
-rw-r--r--arch/powerpc/platforms/iseries/irq.c7
-rw-r--r--arch/powerpc/platforms/iseries/irq.h2
-rw-r--r--arch/powerpc/platforms/iseries/mf.c9
-rw-r--r--arch/powerpc/platforms/iseries/pci.c347
-rw-r--r--arch/powerpc/platforms/iseries/setup.c271
-rw-r--r--arch/powerpc/platforms/iseries/setup.h2
-rw-r--r--arch/powerpc/platforms/iseries/vio.c131
-rw-r--r--arch/powerpc/platforms/maple/pci.c3
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_32.c2
-rw-r--r--arch/powerpc/platforms/powermac/feature.c2
-rw-r--r--arch/powerpc/platforms/powermac/pci.c3
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c14
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/Makefile5
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c2
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c55
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c50
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c182
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c6
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c6
-rw-r--r--arch/powerpc/platforms/pseries/setup.c6
-rw-r--r--arch/powerpc/platforms/pseries/vio.c274
-rw-r--r--arch/powerpc/platforms/pseries/xics.c25
-rw-r--r--arch/powerpc/sysdev/Makefile4
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c66
-rw-r--r--arch/powerpc/sysdev/mpic.c20
-rw-r--r--arch/ppc/Kconfig4
-rw-r--r--arch/ppc/boot/lib/Makefile2
-rw-r--r--arch/ppc/mm/init.c2
-rw-r--r--arch/ppc/mm/mmu_context.c2
-rw-r--r--arch/ppc/mm/tlb.c6
-rw-r--r--arch/ppc/platforms/4xx/Kconfig2
-rw-r--r--arch/ppc/platforms/4xx/cpci405.c139
-rw-r--r--arch/ppc/platforms/4xx/cpci405.h30
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c9
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c6
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Makefile2
-rw-r--r--arch/s390/hypfs/Makefile7
-rw-r--r--arch/s390/hypfs/hypfs.h30
-rw-r--r--arch/s390/hypfs/hypfs_diag.c696
-rw-r--r--arch/s390/hypfs/hypfs_diag.h16
-rw-r--r--arch/s390/hypfs/inode.c491
-rw-r--r--arch/sh64/kernel/signal.c2
-rw-r--r--arch/sparc/kernel/Makefile2
-rw-r--r--arch/sparc/kernel/ebus.c185
-rw-r--r--arch/sparc/kernel/ioport.c131
-rw-r--r--arch/sparc/kernel/of_device.c268
-rw-r--r--arch/sparc/kernel/pcic.c11
-rw-r--r--arch/sparc/kernel/prom.c474
-rw-r--r--arch/sparc/kernel/setup.c36
-rw-r--r--arch/sparc/kernel/smp.c36
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c1
-rw-r--r--arch/sparc/kernel/sun4c_irq.c3
-rw-r--r--arch/sparc/kernel/sun4d_irq.c12
-rw-r--r--arch/sparc/kernel/sun4m_irq.c8
-rw-r--r--arch/sparc/kernel/sun4m_smp.c9
-rw-r--r--arch/sparc/mm/init.c2
-rw-r--r--arch/sparc/mm/iommu.c3
-rw-r--r--arch/sparc64/Kconfig4
-rw-r--r--arch/sparc64/defconfig39
-rw-r--r--arch/sparc64/kernel/Makefile2
-rw-r--r--arch/sparc64/kernel/auxio.c109
-rw-r--r--arch/sparc64/kernel/central.c127
-rw-r--r--arch/sparc64/kernel/chmc.c69
-rw-r--r--arch/sparc64/kernel/devices.c224
-rw-r--r--arch/sparc64/kernel/ebus.c197
-rw-r--r--arch/sparc64/kernel/entry.S13
-rw-r--r--arch/sparc64/kernel/irq.c1035
-rw-r--r--arch/sparc64/kernel/isa.c183
-rw-r--r--arch/sparc64/kernel/of_device.c279
-rw-r--r--arch/sparc64/kernel/pci.c93
-rw-r--r--arch/sparc64/kernel/pci_common.c227
-rw-r--r--arch/sparc64/kernel/pci_impl.h3
-rw-r--r--arch/sparc64/kernel/pci_psycho.c187
-rw-r--r--arch/sparc64/kernel/pci_sabre.c294
-rw-r--r--arch/sparc64/kernel/pci_schizo.c363
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c192
-rw-r--r--arch/sparc64/kernel/power.c113
-rw-r--r--arch/sparc64/kernel/prom.c650
-rw-r--r--arch/sparc64/kernel/sbus.c114
-rw-r--r--arch/sparc64/kernel/setup.c4
-rw-r--r--arch/sparc64/kernel/smp.c41
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c7
-rw-r--r--arch/sparc64/kernel/sun4v_ivec.S15
-rw-r--r--arch/sparc64/kernel/time.c402
-rw-r--r--arch/sparc64/kernel/traps.c22
-rw-r--r--arch/sparc64/kernel/ttable.S10
-rw-r--r--arch/sparc64/kernel/unaligned.c9
-rw-r--r--arch/sparc64/mm/init.c52
-rw-r--r--arch/sparc64/solaris/fs.c4
-rw-r--r--arch/sparc64/solaris/misc.c34
-rw-r--r--arch/um/Kconfig.debug1
-rw-r--r--arch/um/kernel/physmem.c2
-rw-r--r--arch/um/kernel/time_kern.c2
-rw-r--r--arch/um/sys-ppc/misc.S6
-rw-r--r--arch/v850/kernel/signal.c2
-rw-r--r--arch/x86_64/Kconfig6
-rw-r--r--arch/x86_64/ia32/ia32entry.S1
-rw-r--r--arch/x86_64/kernel/acpi/Makefile1
-rw-r--r--arch/x86_64/kernel/acpi/processor.c72
-rw-r--r--arch/x86_64/kernel/acpi/sleep.c7
-rw-r--r--arch/x86_64/kernel/apic.c2
-rw-r--r--arch/x86_64/kernel/i387.c2
-rw-r--r--arch/x86_64/kernel/setup.c95
-rw-r--r--arch/x86_64/mm/srat.c33
-rw-r--r--arch/x86_64/pci/mmconfig.c13
-rw-r--r--arch/xtensa/Kconfig4
-rw-r--r--arch/xtensa/boot/lib/Makefile2
-rw-r--r--arch/xtensa/kernel/entry.S2
-rw-r--r--arch/xtensa/kernel/signal.c12
480 files changed, 34699 insertions, 8807 deletions
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 2b245ad731ee..d3848c5b0d2b 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -53,10 +53,6 @@ extern void __divqu (void);
 extern void __remqu (void);
 
 EXPORT_SYMBOL(alpha_mv);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
-EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(screen_info);
 EXPORT_SYMBOL(perf_irq);
 EXPORT_SYMBOL(callback_getenv);
@@ -68,19 +64,13 @@ EXPORT_SYMBOL(alpha_using_srm);
 
 /* platform dependent support */
 EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
@@ -122,11 +112,9 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s);
 
 /* In-kernel system calls.  */
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_dup);
 EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(execve);
 EXPORT_SYMBOL(sys_setsid);
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 31afe3d91ac6..e15dcf4f3dcd 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -244,7 +244,7 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
 	      unsigned long bufsiz)
 {
 	struct kstatfs linux_stat;
-	int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
+	int error = vfs_statfs(dentry, &linux_stat);
 	if (!error)
 		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
 	return error;	
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 2e45e8604e32..741da0945dc4 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -375,7 +375,7 @@ give_sigsegv:
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void __user *)((sp - frame_size) & -32ul);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 08b7cc900cae..1b7e5c2e90ef 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -93,15 +93,49 @@ choice
 	prompt "ARM system type"
 	default ARCH_VERSATILE
 
+config ARCH_AAEC2000
+	bool "Agilent AAEC-2000 based"
+	select ARM_AMBA
+	help
+	  This enables support for systems based on the Agilent AAEC-2000
+
+config ARCH_INTEGRATOR
+	bool "ARM Ltd. Integrator family"
+	select ARM_AMBA
+	select ICST525
+	help
+	  Support for ARM's Integrator platform.
+
+config ARCH_REALVIEW
+	bool "ARM Ltd. RealView family"
+	select ARM_AMBA
+	select ICST307
+	help
+	  This enables support for ARM Ltd RealView boards.
+
+config ARCH_VERSATILE
+	bool "ARM Ltd. Versatile family"
+	select ARM_AMBA
+	select ARM_VIC
+	select ICST307
+	help
+	  This enables support for ARM Ltd Versatile board.
+
+config ARCH_AT91RM9200
+	bool "Atmel AT91RM9200"
+	help
+	  Say Y here if you intend to run this kernel on an Atmel
+	  AT91RM9200-based board.
+
 config ARCH_CLPS7500
-	bool "Cirrus-CL-PS7500FE"
+	bool "Cirrus CL-PS7500FE"
 	select TIMER_ACORN
 	select ISA
 	help
 	  Support for the Cirrus Logic PS7500FE system-on-a-chip.
 
 config ARCH_CLPS711X
-	bool "CLPS711x/EP721x-based"
+	bool "Cirrus Logic CLPS711x/EP721x-based"
 	help
 	  Support for Cirrus Logic 711x/721x based boards.
 
@@ -135,12 +169,22 @@ config ARCH_FOOTBRIDGE
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
-config ARCH_INTEGRATOR
-	bool "Integrator"
-	select ARM_AMBA
-	select ICST525
+config ARCH_NETX
+	bool "Hilscher NetX based"
+	select ARM_VIC
 	help
-	  Support for ARM's Integrator platform.
+	  This enables support for systems based on the Hilscher NetX Soc
+
+config ARCH_H720X
+	bool "Hynix HMS720x-based"
+	select ISA_DMA_API
+	help
+	  This enables support for systems based on the Hynix HMS720x
+
+config ARCH_IMX
+	bool "IMX"
+	help
+	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
 config ARCH_IOP3XX
 	bool "IOP3xx-based"
@@ -178,6 +222,11 @@ config ARCH_L7200
 	  If you have any questions or comments about the Linux kernel port
 	  to this board, send e-mail to <sjhill@cotw.com>.
 
+config ARCH_PNX4008
+	bool "Philips Nexperia PNX4008 Mobile"
+	help
+	  This enables support for Philips PNX4008 mobile platform.
+
 config ARCH_PXA
 	bool "PXA2xx-based"
 	select ARCH_MTD_XIP
@@ -232,44 +281,6 @@ config ARCH_OMAP
 	help
 	  Support for TI's OMAP platform (OMAP1 and OMAP2).
 
-config ARCH_VERSATILE
-	bool "Versatile"
-	select ARM_AMBA
-	select ARM_VIC
-	select ICST307
-	help
-	  This enables support for ARM Ltd Versatile board.
-
-config ARCH_REALVIEW
-	bool "RealView"
-	select ARM_AMBA
-	select ICST307
-	help
-	  This enables support for ARM Ltd RealView boards.
-
-config ARCH_IMX
-	bool "IMX"
-	help
-	  Support for Motorola's i.MX family of processors (MX1, MXL).
-
-config ARCH_H720X
-	bool "Hynix-HMS720x-based"
-	select ISA_DMA_API
-	help
-	  This enables support for systems based on the Hynix HMS720x
-
-config ARCH_AAEC2000
-	bool "Agilent AAEC-2000 based"
-	select ARM_AMBA
-	help
-	  This enables support for systems based on the Agilent AAEC-2000
-
-config ARCH_AT91RM9200
-	bool "AT91RM9200"
-	help
-	  Say Y here if you intend to run this kernel on an Atmel
-	  AT91RM9200-based board.
-
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -314,6 +325,8 @@ source "arch/arm/mach-realview/Kconfig"
 
 source "arch/arm/mach-at91rm9200/Kconfig"
 
+source "arch/arm/mach-netx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6f8e84c1c1f2..282b14e2f464 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -116,6 +116,8 @@ endif
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
  machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
  machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
+ machine-$(CONFIG_ARCH_NETX)       := netx
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S
index 2119ea62b547..57a3b163b2cb 100644
--- a/arch/arm/boot/compressed/head-at91rm9200.S
+++ b/arch/arm/boot/compressed/head-at91rm9200.S
@@ -49,6 +49,18 @@
 		cmp	r7, r3
 		beq	99f
 
+		@ Embest ATEB9200 : 923
+		mov	r3,	#(MACH_TYPE_ATEB9200 & 0xff)
+		orr	r3, r3,	#(MACH_TYPE_ATEB9200 & 0xff00)
+		cmp	r7, r3
+		beq	99f
+
+		@ Sperry-Sun KAFA : 662
+		mov	r3,	#(MACH_TYPE_KAFA & 0xff)
+		orr	r3, r3,	#(MACH_TYPE_KAFA & 0xff00)
+		cmp	r7, r3
+		beq	99f
+
 		@ Unknown board, use the AT91RM9200DK board
 		@ mov	r7, #MACH_TYPE_AT91RM9200
 		mov	r7,	#(MACH_TYPE_AT91RM9200DK & 0xff)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index b56f5e691d65..23016f6aa645 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -605,8 +605,8 @@ proc_types:
 		b	__armv4_mmu_cache_off
 		b	__armv4_mmu_cache_flush
 
-		.word	0x00070000		@ ARMv6
-		.word	0x000f0000
+		.word	0x0007b000		@ ARMv6
+		.word	0x0007f000
 		b	__armv4_mmu_cache_on
 		b	__armv4_mmu_cache_off
 		b	__armv6_mmu_cache_flush
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 847e3e6356c6..e1289a256ce5 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
 obj-$(CONFIG_SHARPSL_PM)	+= sharpsl_pm.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
+obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 7971d0dc6892..5b7c26395b44 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -77,6 +77,8 @@ struct dmabounce_device_info {
 #endif
 	struct dmabounce_pool	small;
 	struct dmabounce_pool	large;
+
+	rwlock_t lock;
 };
 
 static LIST_HEAD(dmabounce_devs);
@@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 	struct safe_buffer *buf;
 	struct dmabounce_pool *pool;
 	struct device *dev = device_info->dev;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
 		__func__, ptr, size, dir);
@@ -163,8 +166,12 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 		print_alloc_stats(device_info);
 #endif
 
+	write_lock_irqsave(&device_info->lock, flags);
+
 	list_add(&buf->node, &device_info->safe_buffers);
 
+	write_unlock_irqrestore(&device_info->lock, flags);
+
 	return buf;
 }
 
@@ -172,22 +179,32 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 static inline struct safe_buffer *
 find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 {
-	struct safe_buffer *b;
+	struct safe_buffer *b = NULL;
+	unsigned long flags;
+
+	read_lock_irqsave(&device_info->lock, flags);
 
 	list_for_each_entry(b, &device_info->safe_buffers, node)
 		if (b->safe_dma_addr == safe_dma_addr)
-			return b;
+			break;
 
-	return NULL;
+	read_unlock_irqrestore(&device_info->lock, flags);
+	return b;
 }
 
 static inline void
 free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
 {
+	unsigned long flags;
+
 	dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
 
+	write_lock_irqsave(&device_info->lock, flags);
+
 	list_del(&buf->node);
 
+	write_unlock_irqrestore(&device_info->lock, flags);
+
 	if (buf->pool)
 		dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
 	else
@@ -396,7 +413,6 @@ dma_addr_t
 dma_map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	dma_addr_t dma_addr;
 
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -404,12 +420,8 @@ dma_map_single(struct device *dev, void *ptr, size_t size,
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	dma_addr = map_single(dev, ptr, size, dir);
 
-	local_irq_restore(flags);
-
 	return dma_addr;
 }
 
@@ -424,25 +436,18 @@ void
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	unmap_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 int
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -450,8 +455,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		struct page *page = sg->page;
 		unsigned int offset = sg->offset;
@@ -462,8 +465,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 			map_single(dev, ptr, length, dir);
 	}
 
-	local_irq_restore(flags);
-
 	return nents;
 }
 
@@ -471,7 +472,6 @@ void
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -479,55 +479,38 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		unmap_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
 				enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
-	local_irq_save(flags);
-
 	sync_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
 				enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
-	local_irq_save(flags);
-
 	sync_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -535,23 +518,18 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		sync_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -559,16 +537,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		sync_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 static int
@@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
 
 	device_info->dev = dev;
 	INIT_LIST_HEAD(&device_info->safe_buffers);
+	rwlock_init(&device_info->lock);
 
 #ifdef STATS
 	device_info->total_allocs = 0;
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 3cd8c9ee4510..045e37e07330 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -49,13 +49,6 @@
 #define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
 #define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
 
-#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
-#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
-#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
-#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
-#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
-#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
-
 /*
  * Prototypes
  */
@@ -82,12 +75,13 @@ DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
 static int get_percentage(int voltage)
 {
 	int i = sharpsl_pm.machinfo->bat_levels - 1;
+	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
 	struct battery_thresh *thresh;
 
 	if (sharpsl_pm.charge_mode == CHRG_ON)
-		thresh=sharpsl_pm.machinfo->bat_levels_acin;
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
 	else
-		thresh=sharpsl_pm.machinfo->bat_levels_noac;
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
 
 	while (i > 0 && (voltage > thresh[i].voltage))
 		i--;
@@ -131,7 +125,7 @@ static void sharpsl_battery_thread(void *private_)
 	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
 
 	/* Corgi cannot confirm when battery fully charged so periodically kick! */
-	if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON)
+	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
 			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
 		schedule_work(&toggle_charger);
 
@@ -166,11 +160,11 @@ static void sharpsl_battery_thread(void *private_)
 			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
 			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
 		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
-			corgibl_limit_intensity(1);
+			sharpsl_pm.machinfo->backlight_limit(1);
 			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
 		}
 	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
-		corgibl_limit_intensity(0);
+		sharpsl_pm.machinfo->backlight_limit(0);
 		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
 	}
 
@@ -418,7 +412,7 @@ static int sharpsl_check_battery_temp(void)
 	val = get_select_val(buff);
 
 	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
-	if (val > SHARPSL_CHARGE_ON_TEMP)
+	if (val > sharpsl_pm.machinfo->charge_on_temp)
 		return -1;
 
 	return 0;
@@ -450,7 +444,7 @@ static int sharpsl_check_battery_voltage(void)
 	val = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
 
-	if (val < SHARPSL_CHARGE_ON_VOLT)
+	if (val < sharpsl_pm.machinfo->charge_on_volt)
 		return -1;
 
 	return 0;
@@ -468,7 +462,7 @@ static int sharpsl_ac_check(void)
 	temp = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
 
-	if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) {
+	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
 		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
 		return -1;
 	}
@@ -627,8 +621,8 @@ static int sharpsl_fatal_check(void)
 	temp = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
 
-	if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) ||
-			(!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT)))
+	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
+			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
 		return -1;
 	return 0;
 }
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c
index a1310b71004e..dfca596a9a27 100644
--- a/arch/arm/common/uengine.c
+++ b/arch/arm/common/uengine.c
@@ -18,10 +18,26 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <asm/hardware.h>
-#include <asm/arch/ixp2000-regs.h>
+#include <asm/arch/hardware.h>
 #include <asm/hardware/uengine.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_ARCH_IXP2000)
+#define IXP_UENGINE_CSR_VIRT_BASE	IXP2000_UENGINE_CSR_VIRT_BASE
+#define IXP_PRODUCT_ID			IXP2000_PRODUCT_ID
+#define IXP_MISC_CONTROL		IXP2000_MISC_CONTROL
+#define IXP_RESET1			IXP2000_RESET1
+#else
+#if defined(CONFIG_ARCH_IXP23XX)
+#define IXP_UENGINE_CSR_VIRT_BASE	IXP23XX_UENGINE_CSR_VIRT_BASE
+#define IXP_PRODUCT_ID			IXP23XX_PRODUCT_ID
+#define IXP_MISC_CONTROL		IXP23XX_MISC_CONTROL
+#define IXP_RESET1			IXP23XX_RESET1
+#else
+#error unknown platform
+#endif
+#endif
+
 #define USTORE_ADDRESS			0x000
 #define USTORE_DATA_LOWER		0x004
 #define USTORE_DATA_UPPER		0x008
@@ -43,7 +59,7 @@ u32 ixp2000_uengine_mask;
 
 static void *ixp2000_uengine_csr_area(int uengine)
 {
-	return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
+	return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
 }
 
 /*
@@ -91,8 +107,13 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write);
 
 void ixp2000_uengine_reset(u32 uengine_mask)
 {
-	ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
-	ixp2000_reg_wrb(IXP2000_RESET1, 0);
+	u32 value;
+
+	value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
+
+	uengine_mask &= ixp2000_uengine_mask;
+	ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
+	ixp2000_reg_wrb(IXP_RESET1, value);
 }
 EXPORT_SYMBOL(ixp2000_uengine_reset);
 
@@ -235,11 +256,12 @@ static int check_ixp_type(struct ixp2000_uengine_code *c)
 	u32 product_id;
 	u32 rev;
 
-	product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID);
+	product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
 	if (((product_id >> 16) & 0x1f) != 0)
 		return 0;
 
 	switch ((product_id >> 8) & 0xff) {
+#ifdef CONFIG_ARCH_IXP2000
 	case 0:		/* IXP2800 */
 		if (!(c->cpu_model_bitmask & 4))
 			return 0;
@@ -254,6 +276,14 @@ static int check_ixp_type(struct ixp2000_uengine_code *c)
 		if (!(c->cpu_model_bitmask & 2))
 			return 0;
 		break;
+#endif
+
+#ifdef CONFIG_ARCH_IXP23XX
+	case 4:		/* IXP23xx */
+		if (!(c->cpu_model_bitmask & 0x3f0))
+			return 0;
+		break;
+#endif
 
 	default:
 		return 0;
@@ -432,7 +462,8 @@ static int __init ixp2000_uengine_init(void)
 	/*
 	 * Determine number of microengines present.
 	 */
-	switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) {
+	switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
+#ifdef CONFIG_ARCH_IXP2000
 	case 0:		/* IXP2800 */
 	case 1:		/* IXP2850 */
 		ixp2000_uengine_mask = 0x00ff00ff;
@@ -441,10 +472,17 @@ static int __init ixp2000_uengine_init(void)
 	case 2:		/* IXP2400 */
 		ixp2000_uengine_mask = 0x000f000f;
 		break;
+#endif
+
+#ifdef CONFIG_ARCH_IXP23XX
+	case 4:		/* IXP23xx */
+		ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
+		break;
+#endif
 
 	default:
 		printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
-			(unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID));
+			(unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
 		ixp2000_uengine_mask = 0x00000000;
 		break;
 	}
@@ -457,15 +495,15 @@ static int __init ixp2000_uengine_init(void)
 	/*
 	 * Synchronise timestamp counters across all microengines.
 	 */
-	value = ixp2000_reg_read(IXP2000_MISC_CONTROL);
-	ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80);
+	value = ixp2000_reg_read(IXP_MISC_CONTROL);
+	ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
 	for (uengine = 0; uengine < 32; uengine++) {
 		if (ixp2000_uengine_mask & (1 << uengine)) {
 			ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
 			ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
 		}
 	}
-	ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80);
+	ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
 
 	return 0;
 }
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
new file mode 100644
index 000000000000..69c39e098743
--- /dev/null
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -0,0 +1,1312 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:53:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+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=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE 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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+CONFIG_MACH_ATEB9200=y
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=m
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# 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_NET_DIVERT 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_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 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_MAX6875 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 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_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D 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
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP2101=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_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_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=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# 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_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# 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=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# 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
+# CONFIG_9P_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=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# 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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC 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_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig
new file mode 100644
index 000000000000..5ccd29a7c1fb
--- /dev/null
+++ b/arch/arm/configs/carmeva_defconfig
@@ -0,0 +1,723 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue Jun 14 12:05:24 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+CONFIG_MACH_CARMEVA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP 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=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_NET_DIVERT 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
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+CONFIG_ARM_AT91_ETHER_RMII=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE 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_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+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 is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC 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_DES=y
+# 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_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
new file mode 100644
index 000000000000..51ded20e3f64
--- /dev/null
+++ b/arch/arm/configs/kafa_defconfig
@@ -0,0 +1,884 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:54:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+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
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+CONFIG_MACH_KAFA=y
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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_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=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=32
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=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_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 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_MAX6875 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# 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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# 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_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# 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=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC 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_DES=y
+# 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_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig
new file mode 100644
index 000000000000..fee4f566452e
--- /dev/null
+++ b/arch/arm/configs/kb9202_defconfig
@@ -0,0 +1,780 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc2
+# Sun Aug 14 19:26:59 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+CONFIG_MACH_KB9200=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10000000
+CONFIG_ZBOOT_ROM_BSS=0x20040000
+CONFIG_ZBOOT_ROM=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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 is not set
+# 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_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER 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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_AT91_SPI is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY 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_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_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_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
new file mode 100644
index 000000000000..d08bbe59483a
--- /dev/null
+++ b/arch/arm/configs/lpd270_defconfig
@@ -0,0 +1,963 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-git2
+# Wed Jun 21 22:20:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE 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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+CONFIG_MACH_LOGICPD_PXA270=y
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_PXA27x=y
+CONFIG_IWMMXT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+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_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# 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
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=y
+CONFIG_SND_PXA2XX_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS 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 is not set
+# 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_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_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN 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 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig
index 67eaa26c2647..bf9cf9c6d2df 100644
--- a/arch/arm/configs/lpd7a400_defconfig
+++ b/arch/arm/configs/lpd7a400_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:06:33 2005
+# Linux kernel version: 2.6.12
+# Thu Nov  3 14:15:32 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -36,6 +37,8 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
@@ -71,6 +74,7 @@ CONFIG_BASE_SMALL=0
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
@@ -84,6 +88,7 @@ CONFIG_ARCH_LH7A40X=y
 CONFIG_MACH_LPD7A400=y
 # CONFIG_MACH_LPD7A404 is not set
 CONFIG_ARCH_LH7A400=y
+CONFIG_LPD7A40X_CPLD_SSP=y
 # CONFIG_LH7A40X_CONTIGMEM is not set
 # CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set
 
@@ -110,6 +115,8 @@ CONFIG_ARM_THUMB=y
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -119,6 +126,7 @@ CONFIG_ARM_THUMB=y
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 CONFIG_PREEMPT=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_ALIGNMENT_TRAP=y
@@ -175,7 +183,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -217,7 +225,10 @@ CONFIG_MTD_CFI_UTIL=y
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_EDB7312 is not set
 
@@ -254,7 +265,6 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Block devices
 #
-# 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
@@ -288,13 +298,15 @@ CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -302,7 +314,37 @@ CONFIG_IDE_GENERIC=y
 #
 # SCSI device support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# 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 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
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -331,7 +373,6 @@ CONFIG_NET=y
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -438,13 +479,10 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -453,7 +491,13 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADS7843_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADS7843_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -461,7 +505,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -479,6 +522,8 @@ CONFIG_HW_CONSOLE=y
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -510,7 +555,6 @@ CONFIG_RTC=y
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -534,18 +578,73 @@ CONFIG_RTC=y
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig
index 208d591ebfce..3a57be32e849 100644
--- a/arch/arm/configs/lpd7a404_defconfig
+++ b/arch/arm/configs/lpd7a404_defconfig
@@ -1,52 +1,58 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:14:08 2005
+# Linux kernel version: 2.6.16
+# Thu Mar 23 17:50:31 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
@@ -54,6 +60,23 @@ CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 
 #
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # System Type
 #
 # CONFIG_ARCH_CLPS7500 is not set
@@ -71,11 +94,15 @@ CONFIG_BASE_SMALL=0
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # LH7A40X Implementations
@@ -110,6 +137,7 @@ CONFIG_ARM_THUMB=y
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -120,7 +148,18 @@ CONFIG_ARM_THUMB=y
 # Kernel Features
 #
 CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_AEABI is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -154,6 +193,84 @@ CONFIG_BINFMT_ELF=y
 # Power management options
 #
 # CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -168,6 +285,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
@@ -175,7 +297,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -186,6 +308,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -211,15 +334,18 @@ CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -243,6 +369,11 @@ CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -254,7 +385,6 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Block devices
 #
-# 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
@@ -262,16 +392,7 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -291,12 +412,13 @@ CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -304,6 +426,7 @@ CONFIG_IDE_GENERIC=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -315,6 +438,7 @@ CONFIG_SCSI=y
 # CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -329,10 +453,12 @@ CONFIG_SCSI=y
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -344,6 +470,7 @@ CONFIG_SCSI=y
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -354,70 +481,8 @@ CONFIG_SCSI=y
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP 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_NET_DIVERT 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
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -425,11 +490,17 @@ CONFIG_NETDEVICES=y
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -456,6 +527,8 @@ CONFIG_SMC91X=y
 # 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
 
 #
 # ISDN subsystem
@@ -470,10 +543,13 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -482,7 +558,13 @@ CONFIG_INPUT=y
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADC_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADC_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -490,7 +572,6 @@ CONFIG_INPUT=y
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -508,6 +589,8 @@ CONFIG_HW_CONSOLE=y
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -533,13 +616,13 @@ CONFIG_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -547,10 +630,33 @@ CONFIG_RTC=y
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -563,18 +669,83 @@ CONFIG_RTC=y
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE is not set
+# CONFIG_FB_ARMCLCD_HITACHI is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
@@ -595,6 +766,7 @@ CONFIG_USB_DEVICEFS=y
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
@@ -603,16 +775,19 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -621,22 +796,32 @@ CONFIG_USB_STORAGE_DATAFAB=y
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -686,16 +871,33 @@ CONFIG_USB_MON=y
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
 # USB Gadget Support
 #
-# CONFIG_USB_GADGET is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_LH7=y
+CONFIG_USB_LH7=y
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=y
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
 
 #
 # MMC/SD Card support
@@ -707,6 +909,7 @@ CONFIG_USB_MON=y
 #
 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
@@ -716,17 +919,17 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_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_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
@@ -749,12 +952,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -769,8 +971,8 @@ CONFIG_RAMFS=y
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -787,12 +989,14 @@ CONFIG_CRAMFS=y
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # 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_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -801,6 +1005,7 @@ CONFIG_SUNRPC=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -820,6 +1025,7 @@ CONFIG_MSDOS_PARTITION=y
 # 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
 
 #
@@ -875,19 +1081,24 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
@@ -912,6 +1123,7 @@ CONFIG_DEBUG_ERRORS=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig
new file mode 100644
index 000000000000..61115a773382
--- /dev/null
+++ b/arch/arm/configs/netx_defconfig
@@ -0,0 +1,926 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc6
+# Tue Jun  6 15:26:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE 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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_NETX=y
+
+#
+# NetX Implementations
+#
+CONFIG_MACH_NXDKN=y
+CONFIG_MACH_NXDB500=y
+CONFIG_MACH_NXEB500HMI=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySMX0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+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 is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_NET_NETX=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_NETX=y
+CONFIG_SERIAL_NETX_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=m
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_NETX=m
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# 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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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_SYSFS=y
+CONFIG_TMPFS=y
+# 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_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN 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=y
+# 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_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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
new file mode 100644
index 000000000000..8a078d479d57
--- /dev/null
+++ b/arch/arm/configs/pnx4008_defconfig
@@ -0,0 +1,2072 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc1
+# Thu Apr  6 17:05:58 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=m
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE 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"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_PNX4008=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+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=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=m
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=y
+CONFIG_ATM_CLIP=y
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_NET_DIVERT is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_BAYCOM_EPP=m
+CONFIG_YAM=m
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+# CONFIG_TOIM3232_DONGLE is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+# CONFIG_BT_HCIBPA10X is not set
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+# CONFIG_IEEE80211_CRYPT_WEP is not set
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLKMTD=m
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+CONFIG_PCMCIA_RAYCS=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+CONFIG_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+CONFIG_SYNCLINK_SYNCPPP=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW_ETH=y
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+CONFIG_HDLC_X25=y
+CONFIG_DLCI=m
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_SHAPER=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+CONFIG_ISDN_PPP_BSDCOMP=m
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_ISDN_X25=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+# CONFIG_HISAX_NO_SENDCOMPLETE is not set
+# CONFIG_HISAX_NO_LLC is not set
+# CONFIG_HISAX_NO_KEYPAD is not set
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+# CONFIG_HISAX_HFC4S8S is not set
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+# CONFIG_ISDN_DRV_GIGASET is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_TSDEV=m
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+# CONFIG_JOYSTICK_TWIDJOY is not set
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+CONFIG_SX=m
+CONFIG_RIO=m
+CONFIG_RIO_OLDPCI=y
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_NVRAM=m
+CONFIG_DTLK=m
+CONFIG_R3964=m
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ISA=m
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_SENSORS_MAX6875 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
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS9490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ASB100=m
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_F71805F is not set
+CONFIG_SENSORS_FSCHER=m
+# CONFIG_SENSORS_FSCPOS is not set
+CONFIG_SENSORS_GL518SM=m
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+# CONFIG_SENSORS_LM92 is not set
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SMSC47M1=m
+# CONFIG_SENSORS_SMSC47B397 is not set
+CONFIG_SENSORS_W83781D=m
+# CONFIG_SENSORS_W83792D is not set
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+# CONFIG_DVB_CX24123 is not set
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+# CONFIG_DVB_S5H1420 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+# CONFIG_DVB_ZL10353 is not set
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terresterial DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_TVMIXER=m
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_CS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_TI is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+# CONFIG_USB_UEAGLEATM is not set
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_DUMMY_HCD=y
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS_FS=m
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+# CONFIG_NCPFS_SMALLDOS is not set
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
+CONFIG_ACORN_PARTITION_ICS=y
+# CONFIG_ACORN_PARTITION_ADFS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+CONFIG_SECURITY_ROOTPLUG=m
+CONFIG_SECURITY_SECLVL=m
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3cec29d56c8e..e17661380096 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 20:36:02 2006
+# Linux kernel version: 2.6.17
+# Tue Jun 20 18:57:01 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -27,6 +29,7 @@ CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -42,10 +45,6 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -57,7 +56,6 @@ CONFIG_OBSOLETE_INTERMODULE=y
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -65,6 +63,7 @@ CONFIG_KMOD=y
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -92,6 +91,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -106,6 +106,8 @@ CONFIG_ARCH_S3C2410=y
 # CONFIG_ARCH_H720X is not set
 # CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_NETX is not set
 
 #
 # S3C24XX Implementations
@@ -116,14 +118,19 @@ CONFIG_ARCH_BAST=y
 CONFIG_BAST_PC104_IRQ=y
 CONFIG_ARCH_H1940=y
 CONFIG_MACH_N30=y
+CONFIG_MACH_SMDK=y
 CONFIG_ARCH_SMDK2410=y
 CONFIG_ARCH_S3C2440=y
+CONFIG_SMDK2440_CPU2440=y
+CONFIG_SMDK2440_CPU2442=y
 CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
 CONFIG_MACH_OTOM=y
 CONFIG_MACH_NEXCODER_2440=y
 CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C244X=y
 CONFIG_CPU_S3C2440=y
+CONFIG_CPU_S3C2442=y
 
 #
 # S3C2410 Boot
@@ -251,12 +258,15 @@ CONFIG_IP_PNP_BOOTP=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_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -360,7 +370,6 @@ CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -385,7 +394,6 @@ CONFIG_MTD_BAST_MAXSIZE=4
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -694,7 +702,6 @@ CONFIG_S3C2410_WATCHDOG=y
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 CONFIG_S3C2410_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -743,9 +750,7 @@ CONFIG_SENSORS_EEPROM=m
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -807,18 +812,29 @@ CONFIG_SENSORS_LM85=m
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -828,6 +844,7 @@ CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -863,6 +880,7 @@ CONFIG_FONT_8x16=y
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -915,9 +933,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -931,15 +947,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -984,17 +991,6 @@ CONFIG_USB_MON=y
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
 
 #
 # MMC/SD Card support
@@ -1002,6 +998,12 @@ CONFIG_USB_MON=y
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1052,7 +1054,6 @@ CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1193,6 +1194,7 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index ab8e600c18c8..86c92523a346 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -20,6 +20,7 @@
 #include <asm/glue.h>
 #include <asm/vfpmacros.h>
 #include <asm/arch/entry-macro.S>
+#include <asm/thread_notify.h>
 
 #include "entry-header.S"
 
@@ -560,10 +561,8 @@ ENTRY(__switch_to)
 	add	ip, r1, #TI_CPU_SAVE
 	ldr	r3, [r2, #TI_TP_VALUE]
 	stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
-#ifndef CONFIG_MMU
-	add	r2, r2, #TI_CPU_DOMAIN
-#else
-	ldr	r6, [r2, #TI_CPU_DOMAIN]!
+#ifdef CONFIG_MMU
+	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
 #if __LINUX_ARM_ARCH__ >= 6
 #ifdef CONFIG_CPU_32v6K
@@ -585,21 +584,20 @@ ENTRY(__switch_to)
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r6, c3, c0, 0		@ Set domain register
 #endif
-#ifdef CONFIG_VFP
-	@ Always disable VFP so we can lazily save/restore the old
-	@ state. This occurs in the context of the previous thread.
-	VFPFMRX	r4, FPEXC
-	bic	r4, r4, #FPEXC_ENABLE
-	VFPFMXR	FPEXC, r4
-#endif
 #if defined(CONFIG_IWMMXT)
 	bl	iwmmxt_task_switch
 #elif defined(CONFIG_CPU_XSCALE)
-	add	r4, r2, #40			@ cpu_context_save->extra
+	add	r4, r2, #TI_CPU_DOMAIN + 40	@ cpu_context_save->extra
 	ldmib	r4, {r4, r5}
 	mar	acc0, r4, r5
 #endif
-	ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	r0, r5
+	ldmia	r4, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
 	__INIT
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index dbcb11a31f78..b5bcebca1cd6 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -271,7 +271,7 @@ ENTRY(sys_call_table)
 @ r8 = syscall table
 		.type	sys_syscall, #function
 sys_syscall:
-		eor	scno, r0, #__NR_OABI_SYSCALL_BASE
+		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
 		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
 		cmpne	scno, #NR_syscalls	@ check range
 		stmloia	sp, {r5, r6}		@ shuffle args
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2d5896b36181..ec20f8935e8b 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -52,7 +52,7 @@
  */
 #define MAX_IRQ_CNT	100000
 
-static int noirqdebug;
+static int noirqdebug __read_mostly;
 static volatile unsigned long irq_err_count;
 static DEFINE_SPINLOCK(irq_controller_lock);
 static LIST_HEAD(irq_pending);
@@ -81,7 +81,7 @@ irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs)
 
 void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
 {
-	irq_err_count += 1;
+	irq_err_count++;
 	printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
 }
 
@@ -342,10 +342,10 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 
 #ifdef CONFIG_NO_IDLE_HZ
 	if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
-		write_seqlock(&xtime_lock);
+		spin_lock(&system_timer->dyn_tick->lock);
 		if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
 			system_timer->dyn_tick->handler(irq, 0, regs);
-		write_sequnlock(&xtime_lock);
+		spin_unlock(&system_timer->dyn_tick->lock);
 	}
 #endif
 
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index 24c7b0477a09..a3bae95e536c 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -273,7 +273,7 @@ ENTRY(iwmmxt_task_restore)
  *
  * r0 = previous task_struct pointer (must be preserved)
  * r1 = previous thread_info pointer
- * r2 = next thread_info.cpu_domain pointer (must be preserved)
+ * r2 = next thread_info pointer (must be preserved)
  *
  * Called only from __switch_to with task preemption disabled.
  * No need to care about preserving r4 and above.
@@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch)
 	bne	1f				@ yes: block them for next task
 
 	ldr	r5, =concan_owner
-	add	r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area
+	add	r6, r2, #TI_IWMMXT_STATE	@ get next task Concan save area
 	ldr	r5, [r5]			@ get current Concan owner
 	teq	r5, r6				@ next task owns it?
 	movne	pc, lr				@ no: leave Concan disabled
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 7df6e1aaa323..e1c77ee885a7 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,10 +28,12 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/elfcore.h>
+#include <linux/pm.h>
 
 #include <asm/leds.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/thread_notify.h>
 #include <asm/uaccess.h>
 #include <asm/mach/time.h>
 
@@ -71,8 +73,36 @@ static int __init hlt_setup(char *__unused)
 __setup("nohlt", nohlt_setup);
 __setup("hlt", hlt_setup);
 
+void arm_machine_restart(char mode)
+{
+	/*
+	 * Clean and disable cache, and turn off interrupts
+	 */
+	cpu_proc_fin();
+
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot(mode);
+
+	/*
+	 * Now call the architecture specific reboot code.
+	 */
+	arch_reset(mode);
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 * Tell the user!
+	 */
+	mdelay(1000);
+	printk("Reboot failed -- System halted\n");
+	while (1);
+}
+
 /*
- * The following aren't currently used.
+ * Function pointers to optional machine specific functions
  */
 void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
@@ -80,6 +110,10 @@ EXPORT_SYMBOL(pm_idle);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
+void (*arm_pm_restart)(char str) = arm_machine_restart;
+EXPORT_SYMBOL_GPL(arm_pm_restart);
+
+
 /*
  * This is our default idle handler.  We need to disable
  * interrupts here to ensure we don't miss a wakeup call.
@@ -151,33 +185,9 @@ void machine_power_off(void)
 		pm_power_off();
 }
 
-
 void machine_restart(char * __unused)
 {
-	/*
-	 * Clean and disable cache, and turn off interrupts
-	 */
-	cpu_proc_fin();
-
-	/*
-	 * Tell the mm system that we are going to reboot -
-	 * we may need it to insert some 1:1 mappings so that
-	 * soft boot works.
-	 */
-	setup_mm_for_reboot(reboot_mode);
-
-	/*
-	 * Now call the architecture specific reboot code.
-	 */
-	arch_reset(reboot_mode);
-
-	/*
-	 * Whoops - the architecture was unable to reboot.
-	 * Tell the user!
-	 */
-	mdelay(1000);
-	printk("Reboot failed -- System halted\n");
-	while (1);
+	arm_pm_restart(reboot_mode);
 }
 
 void __show_regs(struct pt_regs *regs)
@@ -329,13 +339,9 @@ void exit_thread(void)
 {
 }
 
-static void default_fp_init(union fp_state *fp)
-{
-	memset(fp, 0, sizeof(union fp_state));
-}
+ATOMIC_NOTIFIER_HEAD(thread_notify_head);
 
-void (*fp_init)(union fp_state *) = default_fp_init;
-EXPORT_SYMBOL(fp_init);
+EXPORT_SYMBOL_GPL(thread_notify_head);
 
 void flush_thread(void)
 {
@@ -344,22 +350,21 @@ void flush_thread(void)
 
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+	memset(&thread->fpstate, 0, sizeof(union fp_state));
+
+	thread_notify(THREAD_NOTIFY_FLUSH, thread);
 #if defined(CONFIG_IWMMXT)
 	iwmmxt_task_release(thread);
 #endif
-	fp_init(&thread->fpstate);
-#if defined(CONFIG_VFP)
-	vfp_flush_thread(&thread->vfpstate);
-#endif
 }
 
 void release_thread(struct task_struct *dead_task)
 {
-#if defined(CONFIG_VFP)
-	vfp_release_thread(&task_thread_info(dead_task)->vfpstate);
-#endif
+	struct thread_info *thread = task_thread_info(dead_task);
+
+	thread_notify(THREAD_NOTIFY_RELEASE, thread);
 #if defined(CONFIG_IWMMXT)
-	iwmmxt_task_release(task_thread_info(dead_task));
+	iwmmxt_task_release(thread);
 #endif
 }
 
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a0cd0a90a10d..1ce05ec086c6 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 
 #ifdef CONFIG_IWMMXT
 
-/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
-#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
-#define IWMMXT_MAGIC0		0x12ef842a
-#define IWMMXT_MAGIC1		0x1c07ca71
-
-struct iwmmxt_sigframe {
-	unsigned long	magic0;
-	unsigned long	magic1;
-	unsigned long	storage[0x98/4];
-};
-
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
 	char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 	/* the iWMMXt context must be 64 bit aligned */
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
-	kframe->magic0 = IWMMXT_MAGIC0;
-	kframe->magic1 = IWMMXT_MAGIC1;
+	kframe->magic = IWMMXT_MAGIC;
+	kframe->size = IWMMXT_STORAGE_SIZE;
 	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	if (__copy_from_user(kframe, frame, sizeof(*frame)))
 		return -1;
-	if (kframe->magic0 != IWMMXT_MAGIC0 ||
-	    kframe->magic1 != IWMMXT_MAGIC1)
+	if (kframe->magic != IWMMXT_MAGIC ||
+	    kframe->size != IWMMXT_STORAGE_SIZE)
 		return -1;
 	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
 	return 0;
@@ -177,70 +166,61 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 #endif
 
 /*
- * Auxiliary signal frame.  This saves stuff like FP state.
- * The layout of this structure is not part of the user ABI.
- */
-struct aux_sigframe {
-#ifdef CONFIG_IWMMXT
-	struct iwmmxt_sigframe	iwmmxt;
-#endif
-#ifdef CONFIG_VFP
-	union vfp_state		vfp;
-#endif
-};
-
-/*
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  */
 struct sigframe {
-	struct sigcontext sc;
-	unsigned long extramask[_NSIG_WORDS-1];
+	struct ucontext uc;
 	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 
 struct rt_sigframe {
-	struct siginfo __user *pinfo;
-	void __user *puc;
 	struct siginfo info;
-	struct ucontext uc;
-	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
+	struct sigframe sig;
 };
 
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-		   struct aux_sigframe __user *aux)
+static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 {
-	int err = 0;
+	struct aux_sigframe __user *aux;
+	sigset_t set;
+	int err;
 
-	__get_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__get_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__get_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__get_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__get_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__get_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__get_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__get_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__get_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__get_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__get_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__get_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__get_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__get_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__get_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__get_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		spin_lock_irq(&current->sighand->siglock);
+		current->blocked = set;
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
 
 	err |= !valid_user_regs(regs);
 
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= restore_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
-//		err |= vfp_restore_state(&aux->vfp);
+//		err |= vfp_restore_state(&sf->aux.vfp);
 #endif
 
 	return err;
@@ -249,7 +229,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	sigset_t set;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -266,19 +245,8 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.oldmask)
-	    || (_NSIG_WORDS > 1
-	        && __copy_from_user(&set.sig[1], &frame->extramask,
-				    sizeof(frame->extramask))))
-		goto badframe;
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->sc, &frame->aux))
+	if (restore_sigframe(regs, frame))
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
@@ -297,7 +265,6 @@ badframe:
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	sigset_t set;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -314,19 +281,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto badframe;
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
+	if (restore_sigframe(regs, &frame->sig))
 		goto badframe;
 
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
+	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
@@ -343,42 +302,46 @@ badframe:
 }
 
 static int
-setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux,
-		 struct pt_regs *regs, unsigned long mask)
+setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 {
+	struct aux_sigframe __user *aux;
 	int err = 0;
 
-	__put_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__put_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__put_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__put_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__put_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__put_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__put_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__put_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__put_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__put_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__put_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__put_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__put_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__put_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__put_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__put_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
-
-	__put_user_error(current->thread.trap_no, &sc->trap_no, err);
-	__put_user_error(current->thread.error_code, &sc->error_code, err);
-	__put_user_error(current->thread.address, &sc->fault_address, err);
-	__put_user_error(mask, &sc->oldmask, err);
-
+	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
+
+	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
+	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
+	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= preserve_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
-//		err |= vfp_save_state(&aux->vfp);
+//		err |= vfp_save_state(&sf->aux.vfp);
 #endif
+	__put_user_error(0, &aux->end_magic, err);
 
 	return err;
 }
@@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
 	if (!frame)
 		return 1;
 
-	err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);
-
-	if (_NSIG_WORDS > 1) {
-		err |= __copy_to_user(frame->extramask, &set->sig[1],
-				      sizeof(frame->extramask));
-	}
+	/*
+	 * Set uc.uc_flags to a value which sc.trap_no would never have.
+	 */
+	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
 
+	err |= setup_sigframe(frame, regs, set);
 	if (err == 0)
 		err = setup_return(regs, ka, frame->retcode, frame, usig);
 
@@ -511,25 +473,20 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	if (!frame)
 		return 1;
 
-	__put_user_error(&frame->info, &frame->pinfo, err);
-	__put_user_error(&frame->uc, &frame->puc, err);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
-	__put_user_error(0, &frame->uc.uc_flags, err);
-	__put_user_error(NULL, &frame->uc.uc_link, err);
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
 
 	memset(&stack, 0, sizeof(stack));
 	stack.ss_sp = (void __user *)current->sas_ss_sp;
 	stack.ss_flags = sas_ss_flags(regs->ARM_sp);
 	stack.ss_size = current->sas_ss_size;
-	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
-
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
-				regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
 
+	err |= setup_sigframe(&frame->sig, regs, set);
 	if (err == 0)
-		err = setup_return(regs, ka, frame->retcode, frame, usig);
+		err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
 
 	if (err == 0) {
 		/*
@@ -538,7 +495,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
 		 */
 		regs->ARM_r1 = (unsigned long)&frame->info;
-		regs->ARM_r2 = (unsigned long)&frame->uc;
+		regs->ARM_r2 = (unsigned long)&frame->sig.uc;
 	}
 
 	return err;
@@ -665,17 +622,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 	if (syscall) {
 		if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
 			if (thumb_mode(regs)) {
-				regs->ARM_r7 = __NR_restart_syscall;
+				regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
 				regs->ARM_pc -= 2;
 			} else {
+#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
+				regs->ARM_r7 = __NR_restart_syscall;
+				regs->ARM_pc -= 4;
+#else
 				u32 __user *usp;
+				u32 swival = __NR_restart_syscall;
 
 				regs->ARM_sp -= 12;
 				usp = (u32 __user *)regs->ARM_sp;
 
+				/*
+				 * Either we supports OABI only, or we have
+				 * EABI with the OABI compat layer enabled.
+				 * In the later case we don't know if user
+				 * space is EABI or not, and if not we must
+				 * not clobber r7.  Always using the OABI
+				 * syscall solves that issue and works for
+				 * all those cases.
+				 */
+				swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
+
 				put_user(regs->ARM_pc, &usp[0]);
 				/* swi __NR_restart_syscall */
-				put_user(0xef000000 | __NR_restart_syscall, &usp[1]);
+				put_user(0xef000000 | swival, &usp[1]);
 				/* ldr	pc, [sp], #12 */
 				put_user(0xe49df00c, &usp[2]);
 
@@ -683,6 +656,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 						   (unsigned long)(usp + 3));
 
 				regs->ARM_pc = regs->ARM_sp + 4;
+#endif
 			}
 		}
 		if (regs->ARM_r0 == -ERESTARTNOHAND ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index d6bd435a6857..9c12d4fefbd3 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -379,7 +379,7 @@ static int timer_dyn_tick_enable(void)
 	int ret = -ENODEV;
 
 	if (dyn_tick) {
-		write_seqlock_irqsave(&xtime_lock, flags);
+		spin_lock_irqsave(&dyn_tick->lock, flags);
 		ret = 0;
 		if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
 			ret = dyn_tick->enable();
@@ -387,7 +387,7 @@ static int timer_dyn_tick_enable(void)
 			if (ret == 0)
 				dyn_tick->state |= DYN_TICK_ENABLED;
 		}
-		write_sequnlock_irqrestore(&xtime_lock, flags);
+		spin_unlock_irqrestore(&dyn_tick->lock, flags);
 	}
 
 	return ret;
@@ -400,7 +400,7 @@ static int timer_dyn_tick_disable(void)
 	int ret = -ENODEV;
 
 	if (dyn_tick) {
-		write_seqlock_irqsave(&xtime_lock, flags);
+		spin_lock_irqsave(&dyn_tick->lock, flags);
 		ret = 0;
 		if (dyn_tick->state & DYN_TICK_ENABLED) {
 			ret = dyn_tick->disable();
@@ -408,7 +408,7 @@ static int timer_dyn_tick_disable(void)
 			if (ret == 0)
 				dyn_tick->state &= ~DYN_TICK_ENABLED;
 		}
-		write_sequnlock_irqrestore(&xtime_lock, flags);
+		spin_unlock_irqrestore(&dyn_tick->lock, flags);
 	}
 
 	return ret;
@@ -422,15 +422,20 @@ static int timer_dyn_tick_disable(void)
 void timer_dyn_reprogram(void)
 {
 	struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
-	unsigned long next, seq;
+	unsigned long next, seq, flags;
 
-	if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) {
+	if (!dyn_tick)
+		return;
+
+	spin_lock_irqsave(&dyn_tick->lock, flags);
+	if (dyn_tick->state & DYN_TICK_ENABLED) {
 		next = next_timer_interrupt();
 		do {
 			seq = read_seqbegin(&xtime_lock);
-			dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+			dyn_tick->reprogram(next - jiffies);
 		} while (read_seqretry(&xtime_lock, seq));
 	}
+	spin_unlock_irqrestore(&dyn_tick->lock, flags);
 }
 
 static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
@@ -499,5 +504,10 @@ void __init time_init(void)
 	if (system_timer->offset == NULL)
 		system_timer->offset = dummy_gettimeoffset;
 	system_timer->init();
+
+#ifdef CONFIG_NO_IDLE_HZ
+	if (system_timer->dyn_tick)
+		system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
+#endif
 }
 
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig
index 4b7218fc3eb1..1ab5b7828318 100644
--- a/arch/arm/mach-at91rm9200/Kconfig
+++ b/arch/arm/mach-at91rm9200/Kconfig
@@ -40,6 +40,18 @@ config MACH_KB9200
 	help
 	  Select this if you are using KwikByte's KB920x board
 
+config MACH_ATEB9200
+	bool "Embest's ATEB9200"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Embest's ATEB9200 board
+
+config MACH_KAFA
+	bool "Sperry-Sun KAFA board"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Sperry-Sun's KAFA board
+
 
 comment "AT91RM9200 Feature Selections"
 
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index ef88c4128edc..81ebc6684ad2 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -7,22 +7,31 @@ obj-m		:=
 obj-n		:=
 obj-		:=
 
+obj-$(CONFIG_PM)		+= pm.o
+
 # Board-specific support
 obj-$(CONFIG_ARCH_AT91RM9200DK)	+= board-dk.o
 obj-$(CONFIG_MACH_AT91RM9200EK)	+= board-ek.o
 obj-$(CONFIG_MACH_CSB337)	+= board-csb337.o
 obj-$(CONFIG_MACH_CSB637)	+= board-csb637.o
-#obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
-#obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
+obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o
+obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o
 
 # LEDs support
 led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
 led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
 led-$(CONFIG_MACH_CSB337)	+= leds.o
 led-$(CONFIG_MACH_CSB637)	+= leds.o
-#led-$(CONFIG_MACH_KB9200)	+= leds.o
-#led-$(CONFIG_MACH_KAFA)	+= leds.o
+led-$(CONFIG_MACH_KB9200)	+= leds.o
+led-$(CONFIG_MACH_KAFA)		+= leds.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # VGA support
 #obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o
+
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o += -DDEBUG
+endif
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
new file mode 100644
index 000000000000..2c138b542ebe
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-carmeva.c
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-carmeva.c
+ *
+ *  Copyright (c) 2005 Peer Georgi
+ *  		       Conitec Datasystems
+ *
+ * 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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init carmeva_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata carmeva_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init carmeva_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 20.000 MHz crystal */
+	at91_clock_init(20000000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&carmeva_uart_config);
+}
+
+static struct at91_eth_data __initdata carmeva_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata carmeva_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata carmeva_udc_data = {
+	.vbus_pin	= AT91_PIN_PD12,
+	.pullup_pin	= AT91_PIN_PD9,
+};
+
+/* FIXME: user dependend */
+// static struct at91_cf_data __initdata carmeva_cf_data = {
+//	.det_pin	= AT91_PIN_PB0,
+//	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+// };
+
+static struct at91_mmc_data __initdata carmeva_mmc_data = {
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init carmeva_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&carmeva_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&carmeva_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&carmeva_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+//	at91_add_device_cf(&carmeva_cf_data);
+	/* SPI */
+//	at91_add_device_spi(NULL, 0);
+	/* MMC */
+	at91_add_device_mmc(&carmeva_mmc_data);
+}
+
+MACHINE_START(CARMEVA, "Carmeva")
+	/* Maintainer: Conitec Datasystems */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= carmeva_map_io,
+	.init_irq	= carmeva_init_irq,
+	.init_machine	= carmeva_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index f45104ceea8f..e94645d77f7a 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -34,9 +35,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -54,32 +55,24 @@ static void __init csb337_init_irq(void)
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define CSB337_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define CSB337_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata csb337_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init csb337_map_io(void)
 {
-	int serial[AT91_NR_UART] = CSB337_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
 	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = CSB337_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb337_uart_config);
 }
 
 static struct at91_eth_data __initdata csb337_eth_data = {
@@ -118,17 +111,31 @@ static struct at91_mmc_data __initdata csb337_mmc_data = {
 	.wp_pin		= AT91_PIN_PD6,
 };
 
+static struct spi_board_info csb337_spi_devices[] = {
+	{	/* CAN controller */
+		.modalias	= "sak82c900",
+		.chip_select	= 0,
+		.max_speed_hz	= 6 * 1000 * 1000,
+	},
+};
+
 static void __init csb337_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&csb337_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&csb337_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb337_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
 	/* Compact Flash */
 	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
 	at91_add_device_cf(&csb337_cf_data);
+	/* SPI */
+	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
 	/* MMC */
 	at91_add_device_mmc(&csb337_mmc_data);
 }
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index f2c2d6e79bc6..67d5f7786cdb 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -34,9 +34,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -54,14 +54,14 @@ static void __init csb637_init_irq(void)
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define CSB637_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define CSB637_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata csb637_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init csb637_map_io(void)
 {
-	int serial[AT91_NR_UART] = CSB637_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 3.6864 MHz crystal */
@@ -70,16 +70,8 @@ static void __init csb637_map_io(void)
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = CSB637_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb637_uart_config);
 }
 
 static struct at91_eth_data __initdata csb637_eth_data = {
@@ -98,12 +90,18 @@ static struct at91_udc_data __initdata csb637_udc_data = {
 
 static void __init csb637_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&csb637_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&csb637_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb637_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
 }
 
 MACHINE_START(CSB637, "Cogent CSB637")
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 2d7200ed66ed..48d7390fa584 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -37,9 +38,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -57,14 +58,14 @@ static void __init dk_init_irq(void)
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define DK_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define DK_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata dk_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init dk_map_io(void)
 {
-	int serial[AT91_NR_UART] = DK_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 18.432 MHz crystal */
@@ -73,16 +74,8 @@ static void __init dk_map_io(void)
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = DK_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (at91_serial_map[i] >= 0)
-			at91_register_uart(i, at91_serial_map[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&dk_uart_config);
 }
 
 static struct at91_eth_data __initdata dk_eth_data = {
@@ -111,16 +104,48 @@ static struct at91_mmc_data __initdata dk_mmc_data = {
 	.wire4		= 1,
 };
 
+static struct spi_board_info dk_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+	{	/* UR6HCPS2-SP40 PS2-to-SPI adapter */
+		.modalias	= "ur6hcps2",
+		.chip_select	= 1,
+		.max_speed_hz	= 250 *  1000,
+	},
+	{	/* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
+		.modalias	= "tlv1504",
+		.chip_select	= 2,
+		.max_speed_hz	= 20 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	}
+#endif
+};
+
 static void __init dk_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&dk_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&dk_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&dk_udc_data);
+	at91_set_multi_drive(dk_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
 	/* Compact Flash */
 	at91_add_device_cf(&dk_cf_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
 	/* DataFlash card */
 	at91_set_gpio_output(AT91_PIN_PB7, 0);
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
new file mode 100644
index 000000000000..a3e2df968a66
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-eb9200.c
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-eb9200.c
+ *
+ *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
+ *  by Andrew Patrikalakis
+ *
+ * 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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init eb9200_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata eb9200_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init eb9200_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 18.432 MHz crystal */
+	at91_clock_init(18432000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&eb9200_uart_config);
+}
+
+static struct at91_eth_data __initdata eb9200_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata eb9200_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata eb9200_udc_data = {
+	.vbus_pin	= AT91_PIN_PD4,
+	.pullup_pin	= AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata eb9200_cf_data = {
+	.det_pin	= AT91_PIN_PB0,
+	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+};
+
+static struct at91_mmc_data __initdata eb9200_mmc_data = {
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init eb9200_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&eb9200_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&eb9200_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&eb9200_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+	at91_add_device_cf(&eb9200_cf_data);
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+	/* MMC */
+	/* only supports 1 or 4 bit interface, not wired through to SPI */
+	at91_add_device_mmc(&eb9200_mmc_data);
+}
+
+MACHINE_START(ATEB9200, "Embest ATEB9200")
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= eb9200_map_io,
+	.init_irq	= eb9200_init_irq,
+	.init_machine	= eb9200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index 80d90f5135a1..72202ed830ad 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -37,9 +38,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -57,14 +58,14 @@ static void __init ek_init_irq(void)
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define EK_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define EK_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init ek_map_io(void)
 {
-	int serial[AT91_NR_UART] = EK_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 18.432 MHz crystal */
@@ -73,16 +74,8 @@ static void __init ek_map_io(void)
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = EK_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
 }
 
 static struct at91_eth_data __initdata ek_eth_data = {
@@ -106,14 +99,36 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
 	.wp_pin		= AT91_PIN_PA17,
 };
 
+static struct spi_board_info ek_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#endif
+};
+
 static void __init ek_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&ek_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
+	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
 	/* DataFlash card */
 	at91_set_gpio_output(AT91_PIN_PB22, 0);
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
new file mode 100644
index 000000000000..bf760c5e0c46
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-kafa.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kafa.c
+ *
+ *  Copyright (C) 2006 Sperry-Sun
+ *
+ * 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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kafa_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kafa_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 0, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kafa_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 18.432 MHz crystal */
+	at91_clock_init(18432000);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kafa_uart_config);
+}
+
+static struct at91_eth_data __initdata kafa_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kafa_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kafa_udc_data = {
+	.vbus_pin	= AT91_PIN_PB6,
+	.pullup_pin	= AT91_PIN_PB7,
+};
+
+static void __init kafa_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kafa_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kafa_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kafa_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KAFA, "Sperry-Sun KAFA")
+	/* Maintainer: Sergei Sharonov */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kafa_map_io,
+	.init_irq	= kafa_init_irq,
+	.init_machine	= kafa_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
new file mode 100644
index 000000000000..f06d2b54cc9a
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-kb9202.c
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kb9202.c
+ *
+ *  Copyright (c) 2005 kb_admin
+ *  		       KwikByte, 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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kb9202_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kb9202_uart_config = {
+	.console_tty	= 0,					/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 4, 0, 1, -1, -1 }			/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kb9202_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 10 MHz crystal */
+	at91_clock_init(10000000);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kb9202_uart_config);
+}
+
+static struct at91_eth_data __initdata kb9202_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PB29,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kb9202_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kb9202_udc_data = {
+	.vbus_pin	= AT91_PIN_PB24,
+	.pullup_pin	= AT91_PIN_PB22,
+};
+
+static struct at91_mmc_data __initdata kb9202_mmc_data = {
+	.det_pin	= AT91_PIN_PB2,
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init kb9202_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kb9202_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kb9202_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kb9202_udc_data);
+	/* MMC */
+	at91_add_device_mmc(&kb9202_mmc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KB9200, "KB920x")
+	/* Maintainer: KwikByte, Inc. */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kb9202_map_io,
+	.init_irq	= kb9202_init_irq,
+	.init_machine	= kb9202_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
index 8b95467c6d61..edc2cc837ae6 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -27,12 +27,10 @@
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/arch/board.h>		/* for master clock global */
+#include <asm/hardware.h>
 
 #include "generic.h"
 
-#undef	DEBUG
 
 /*
  * There's a lot more which can be done with clocks, including cpufreq
@@ -41,7 +39,9 @@
  */
 
 struct clk {
-	const char	*name;
+	const char	*name;		/* unique clock name */
+	const char	*function;	/* function of the clock */
+	struct device	*dev;		/* device associated with function */
 	unsigned long	rate_hz;
 	struct clk	*parent;
 	u32		pmc_mask;
@@ -71,15 +71,14 @@ static struct clk clk32k = {
 };
 static struct clk main_clk = {
 	.name		= "main",
-	.pmc_mask	= 1 << 0,	/* in PMC_SR */
-	.users		= 1,
+	.pmc_mask	= AT91_PMC_MOSCS,	/* in PMC_SR */
 	.id		= 1,
 	.primary	= 1,
 };
 static struct clk plla = {
 	.name		= "plla",
 	.parent		= &main_clk,
-	.pmc_mask	= 1 << 1,	/* in PMC_SR */
+	.pmc_mask	= AT91_PMC_LOCKA,	/* in PMC_SR */
 	.id		= 2,
 	.primary	= 1,
 	.pll		= 1,
@@ -105,7 +104,7 @@ static void pllb_mode(struct clk *clk, int is_on)
 static struct clk pllb = {
 	.name		= "pllb",
 	.parent		= &main_clk,
-	.pmc_mask	= 1 << 2,	/* in PMC_SR */
+	.pmc_mask	= AT91_PMC_LOCKB,	/* in PMC_SR */
 	.mode		= pllb_mode,
 	.id		= 3,
 	.primary	= 1,
@@ -177,8 +176,7 @@ static struct clk pck3 = {
  */
 static struct clk mck = {
 	.name		= "mck",
-	.pmc_mask	= 1 << 3,	/* in PMC_SR */
-	.users		= 1,		/* (must be) always on */
+	.pmc_mask	= AT91_PMC_MCKRDY,	/* in PMC_SR */
 };
 
 static void pmc_periph_mode(struct clk *clk, int is_on)
@@ -249,6 +247,30 @@ static struct clk spi_clk = {
 	.pmc_mask	= 1 << AT91_ID_SPI,
 	.mode		= pmc_periph_mode,
 };
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOA,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOB,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOC,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioD_clk = {
+	.name		= "pioD_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOD,
+	.mode		= pmc_periph_mode,
+};
 
 static struct clk *const clock_list[] = {
 	/* four primary clocks -- MUST BE FIRST! */
@@ -279,21 +301,46 @@ static struct clk *const clock_list[] = {
 	&udc_clk,
 	&twi_clk,
 	&spi_clk,
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&pioD_clk,
 	// ssc0..ssc2
 	// tc0..tc5
+	// irq0..irq6
 	&ohci_clk,
 	&ether_clk,
 };
 
 
+/*
+ * Associate a particular clock with a function (eg, "uart") and device.
+ * The drivers can then request the same 'function' with several different
+ * devices and not care about which clock name to use.
+ */
+void __init at91_clock_associate(const char *id, struct device *dev, const char *func)
+{
+	struct clk *clk = clk_get(NULL, id);
+
+	if (!dev || !clk || !IS_ERR(clk_get(dev, func)))
+		return;
+
+	clk->function = func;
+	clk->dev = dev;
+}
+
 /* clocks are all static for now; no refcounting necessary */
 struct clk *clk_get(struct device *dev, const char *id)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-		if (strcmp(id, clock_list[i]->name) == 0)
-			return clock_list[i];
+		struct clk *clk = clock_list[i];
+
+		if (strcmp(id, clk->name) == 0)
+			return clk;
+		if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
+			return clk;
 	}
 
 	return ERR_PTR(-ENOENT);
@@ -593,6 +640,30 @@ fail:
 	return 0;
 }
 
+
+/*
+ * Several unused clocks may be active.  Turn them off.
+ */
+static void at91_periphclk_reset(void)
+{
+	unsigned long reg;
+	int i;
+
+	reg = at91_sys_read(AT91_PMC_PCSR);
+
+	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
+		struct clk	*clk = clock_list[i];
+
+		if (clk->mode != pmc_periph_mode)
+			continue;
+
+		if (clk->users > 0)
+			reg &= ~clk->pmc_mask;
+	}
+
+	at91_sys_write(AT91_PMC_PCDR, reg);
+}
+
 int __init at91_clock_init(unsigned long main_clock)
 {
 	unsigned tmp, freq, mckr;
@@ -626,7 +697,6 @@ int __init at91_clock_init(unsigned long main_clock)
 	 */
 	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
 	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-	at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP));
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP);
 	at91_sys_write(AT91_CKGR_PLLBR, 0);
 	at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP);
@@ -640,19 +710,18 @@ int __init at91_clock_init(unsigned long main_clock)
 	 */
 	mckr = at91_sys_read(AT91_PMC_MCKR);
 	mck.parent = clock_list[mckr & AT91_PMC_CSS];
-	mck.parent->users++;
 	freq = mck.parent->rate_hz;
 	freq /= (1 << ((mckr >> 2) & 3));		/* prescale */
 	mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));	/* mdiv */
 
+	/* MCK and CPU clock are "always on" */
+	clk_enable(&mck);
+
 	printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
 		freq / 1000000, (unsigned) mck.rate_hz / 1000000,
 		(unsigned) main_clock / 1000000,
 		((unsigned) main_clock % 1000000) / 1000);
 
-	/* FIXME get rid of master_clock global */
-	at91_master_clock = mck.rate_hz;
-
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
 	/* establish PCK0..PCK3 parentage */
 	for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
@@ -663,19 +732,28 @@ int __init at91_clock_init(unsigned long main_clock)
 			continue;
 
 		pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-		parent = clock_list[pckr & 3];
+		parent = clock_list[pckr & AT91_PMC_CSS];
 		clk->parent = parent;
 		clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+
+		if (clk->users == 0) {
+			/* not being used, so switch it off */
+			at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+		}
 	}
 #else
-	/* disable unused clocks */
+	/* disable all programmable clocks */
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
-#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+#endif
 
-	/* FIXME several unused clocks may still be active...  provide
-	 * a CONFIG option to turn off all unused clocks at some point
-	 * before driver init starts.
-	 */
+	/* enable the PIO clocks */
+	clk_enable(&pioA_clk);
+	clk_enable(&pioB_clk);
+	clk_enable(&pioC_clk);
+	clk_enable(&pioD_clk);
+
+	/* disable all other unused peripheral clocks */
+	at91_periphclk_reset();
 
 	return 0;
 }
diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c
index 3848fd2d5596..e836f8537a1d 100644
--- a/arch/arm/mach-at91rm9200/common.c
+++ b/arch/arm/mach-at91rm9200/common.c
@@ -16,7 +16,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
+#include "generic.h"
 
 static struct map_desc at91rm9200_io_desc[] __initdata = {
 	{
@@ -94,6 +95,11 @@ static struct map_desc at91rm9200_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(AT91_BASE_TCB0),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_SRAM_VIRT_BASE,
+		.pfn		= __phys_to_pfn(AT91_SRAM_BASE),
+		.length		= AT91_SRAM_SIZE,
+		.type		= MT_DEVICE,
 	},
 };
 
@@ -102,14 +108,3 @@ void __init at91rm9200_map_io(void)
 	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 }
 
-
-unsigned long at91_master_clock;
-
-EXPORT_SYMBOL(at91_master_clock);
-
-
-int at91_serial_map[AT91_NR_UART];
-int at91_console_port;
-
-EXPORT_SYMBOL(at91_serial_map);
-EXPORT_SYMBOL(at91_console_port);
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index bfe47bd6e50c..1cf85d231baa 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -16,9 +16,15 @@
 #include <linux/config.h>
 #include <linux/platform_device.h>
 
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
-#include <asm/arch/pio.h>
+#include <asm/arch/gpio.h>
 
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
 
 /* --------------------------------------------------------------------
  *  USB Host
@@ -28,7 +34,7 @@
 static u64 ohci_dmamask = 0xffffffffUL;
 static struct at91_usbh_data usbh_data;
 
-static struct resource at91_usbh_resource[] = {
+static struct resource at91_usbh_resources[] = {
 	[0] = {
 		.start	= AT91_UHP_BASE,
 		.end	= AT91_UHP_BASE + SZ_1M - 1,
@@ -42,15 +48,15 @@ static struct resource at91_usbh_resource[] = {
 };
 
 static struct platform_device at91rm9200_usbh_device = {
-	.name		= "at91rm9200-ohci",
+	.name		= "at91_ohci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &ohci_dmamask,
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &usbh_data,
 	},
-	.resource	= at91_usbh_resource,
-	.num_resources	= ARRAY_SIZE(at91_usbh_resource),
+	.resource	= at91_usbh_resources,
+	.num_resources	= ARRAY_SIZE(at91_usbh_resources),
 };
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -74,11 +80,16 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
 static struct at91_udc_data udc_data;
 
 static struct resource at91_udc_resources[] = {
-	{
+	[0] = {
 		.start	= AT91_BASE_UDP,
 		.end	= AT91_BASE_UDP + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91_ID_UDP,
+		.end	= AT91_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device at91rm9200_udc_device = {
@@ -100,10 +111,8 @@ void __init at91_add_device_udc(struct at91_udc_data *data)
 		at91_set_gpio_input(data->vbus_pin, 0);
 		at91_set_deglitch(data->vbus_pin, 1);
 	}
-	if (data->pullup_pin) {
+	if (data->pullup_pin)
 		at91_set_gpio_output(data->pullup_pin, 0);
-		at91_set_multi_drive(data->pullup_pin, 1);
-	}
 
 	udc_data = *data;
 	platform_device_register(&at91rm9200_udc_device);
@@ -197,7 +206,7 @@ static struct at91_cf_data cf_data;
 static struct resource at91_cf_resources[] = {
 	[0] = {
 		.start	= AT91_CF_BASE,
-		/* ties up CS4, CS5, and CS6 */
+		/* ties up CS4, CS5 and CS6 */
 		.end	= AT91_CF_BASE + (0x30000000 - 1),
 		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
 	},
@@ -231,6 +240,12 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
 		at91_set_gpio_output(data->vcc_pin, 0);
 	at91_set_gpio_output(data->rst_pin, 0);
 
+	/* force poweron defaults for these pins ... */
+	at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
+	at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
+	at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
+	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
+
 	cf_data = *data;
 	platform_device_register(&at91rm9200_cf_device);
 }
@@ -319,6 +334,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
 void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
 #endif
 
+
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -400,22 +416,110 @@ void __init at91_add_device_i2c(void) {}
 
 
 /* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource at91_spi_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_SPI,
+		.end	= AT91_BASE_SPI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SPI,
+		.end	= AT91_ID_SPI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_spi_device = {
+	.name		= "at91_spi",
+	.id		= 0,
+	.dev		= {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= at91_spi_resources,
+	.num_resources	= ARRAY_SIZE(at91_spi_resources),
+};
+
+static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+
+	at91_set_A_periph(AT91_PIN_PA0, 0);	/* MISO */
+	at91_set_A_periph(AT91_PIN_PA1, 0);	/* MOSI */
+	at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPCK */
+
+	/* Enable SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else
+			cs_pin = at91_spi_standard_cs[devices[i].chip_select];
+
+#ifdef CONFIG_SPI_AT91_MANUAL_CS
+		at91_set_gpio_output(cs_pin, 1);
+#else
+		at91_set_A_periph(cs_pin, 0);
+#endif
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+	at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi");
+	platform_device_register(&at91rm9200_spi_device);
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
  *  RTC
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE)
 static struct platform_device at91rm9200_rtc_device = {
 	.name		= "at91_rtc",
 	.id		= -1,
 	.num_resources	= 0,
 };
 
-void __init at91_add_device_rtc(void)
+static void __init at91_add_device_rtc(void)
 {
 	platform_device_register(&at91rm9200_rtc_device);
 }
 #else
-void __init at91_add_device_rtc(void) {}
+static void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Watchdog
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE)
+static struct platform_device at91rm9200_wdt_device = {
+	.name		= "at91_wdt",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_watchdog(void)
+{
+	platform_device_register(&at91rm9200_wdt_device);
+}
+#else
+static void __init at91_add_device_watchdog(void) {}
 #endif
 
 
@@ -429,13 +533,281 @@ u8 at91_leds_timer;
 
 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
 {
-	at91_leds_cpu   = cpu_led;
-	at91_leds_timer = timer_led;
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
 }
-
 #else
 void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
 #endif
 
 
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_AT91)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+};
+
+static struct platform_device at91rm9200_dbgu_device = {
+	.name		= "at91_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA30, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PA31, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US0,
+		.end	= AT91_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US0,
+		.end	= AT91_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart0_device = {
+	.name		= "at91_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA17, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PA18, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PA20, 0);		/* CTS0 */
+
+	/*
+	 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
+	 *  We need to drive the pin manually.  Default is off (RTS is active low).
+	 */
+	at91_set_gpio_output(AT91_PIN_PA21, 1);
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US1,
+		.end	= AT91_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US1,
+		.end	= AT91_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart1_device = {
+	.name		= "at91_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB18, 0);		/* RI1 */
+	at91_set_A_periph(AT91_PIN_PB19, 0);		/* DTR1 */
+	at91_set_A_periph(AT91_PIN_PB20, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PB21, 0);		/* RXD1 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD1 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);		/* CTS1 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);		/* DSR1 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US2,
+		.end	= AT91_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US2,
+		.end	= AT91_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart2_device = {
+	.name		= "at91_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA22, 0);		/* RXD2 */
+	at91_set_A_periph(AT91_PIN_PA23, 1);		/* TXD2 */
+}
+
+static struct resource uart3_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US3,
+		.end	= AT91_BASE_US3 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US3,
+		.end	= AT91_ID_US3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart3_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart3_device = {
+	.name		= "at91_usart",
+	.id		= 4,
+	.dev		= {
+				.platform_data	= &uart3_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart3_resources,
+	.num_resources	= ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+	at91_set_B_periph(AT91_PIN_PA5, 1);		/* TXD3 */
+	at91_set_B_periph(AT91_PIN_PA6, 0);		/* RXD3 */
+}
+
+struct platform_device *at91_uarts[AT91_NR_UART];	/* the UARTs to use */
+struct platform_device *at91_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91rm9200_uart0_device;
+				at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91rm9200_uart1_device;
+				at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91rm9200_uart2_device;
+				at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_usart3_pins();
+				at91_uarts[i] = &at91rm9200_uart3_device;
+				at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
+				break;
+			case 4:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91rm9200_dbgu_device;
+				at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < AT91_NR_UART)
+		at91_default_console_device = at91_uarts[config->console_tty];
+	if (!at91_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < AT91_NR_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
 /* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	at91_add_device_rtc();
+	at91_add_device_watchdog();
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
index 9bd541eba0a0..f0d969d7d874 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91rm9200/generic.h
@@ -16,3 +16,10 @@ extern struct sys_timer at91rm9200_timer;
 extern void __init at91rm9200_map_io(void);
 
 extern int __init at91_clock_init(unsigned long main_clock);
+struct device;
+extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
+
+ /* Power Management */
+extern void at91_irq_suspend(void);
+extern void at91_irq_resume(void);
+
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 5ab46274e1a3..83c34747087b 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -16,7 +16,7 @@
 
 #include <asm/io.h>
 #include <asm/mach/irq.h>
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 #include <asm/arch/gpio.h>
 
 static const u32 pio_controller_offset[4] = {
@@ -213,6 +213,84 @@ EXPORT_SYMBOL(at91_get_gpio_value);
 
 /*--------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PM
+
+static u32 wakeups[BGA_GPIO_BANKS];
+static u32 backups[BGA_GPIO_BANKS];
+
+static int gpio_irq_set_wake(unsigned pin, unsigned state)
+{
+	unsigned	mask = pin_to_mask(pin);
+
+	pin -= PIN_BASE;
+	pin /= 32;
+
+	if (unlikely(pin >= BGA_GPIO_BANKS))
+		return -EINVAL;
+
+	if (state)
+		wakeups[pin] |= mask;
+	else
+		wakeups[pin] &= ~mask;
+
+	return 0;
+}
+
+void at91_gpio_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < BGA_GPIO_BANKS; i++) {
+		u32 pio = pio_controller_offset[i];
+
+		/*
+		 * Note: drivers should have disabled GPIO interrupts that
+		 * aren't supposed to be wakeup sources.
+		 * But that is not much good on ARM.....  disable_irq() does
+		 * not update the hardware immediately, so the hardware mask
+		 * (IMR) has the wrong value (not current, too much is
+		 * permitted).
+		 *
+		 * Our workaround is to disable all non-wakeup IRQs ...
+		 * which is exactly what correct drivers asked for in the
+		 * first place!
+		 */
+		backups[i] = at91_sys_read(pio + PIO_IMR);
+		at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]);
+		at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]);
+
+		if (!wakeups[i]) {
+			disable_irq_wake(AT91_ID_PIOA + i);
+			at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i));
+		} else {
+			enable_irq_wake(AT91_ID_PIOA + i);
+#ifdef CONFIG_PM_DEBUG
+			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
+#endif
+		}
+	}
+}
+
+void at91_gpio_resume(void)
+{
+	int i;
+
+	for (i = 0; i < BGA_GPIO_BANKS; i++) {
+		at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]);
+		at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]);
+	}
+
+	at91_sys_write(AT91_PMC_PCER,
+			  (1 << AT91_ID_PIOA)
+			| (1 << AT91_ID_PIOB)
+			| (1 << AT91_ID_PIOC)
+			| (1 << AT91_ID_PIOD));
+}
+
+#else
+#define gpio_irq_set_wake	NULL
+#endif
+
 
 /* Several AIC controller irqs are dispatched through this GPIO handler.
  * To use any AT91_PIN_* as an externally triggered IRQ, first call
@@ -252,6 +330,7 @@ static struct irqchip gpio_irqchip = {
 	.mask		= gpio_irq_mask,
 	.unmask		= gpio_irq_unmask,
 	.set_type	= gpio_irq_type,
+	.set_wake	= gpio_irq_set_wake,
 };
 
 static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)
@@ -266,6 +345,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs
 	/* temporarily mask (level sensitive) parent IRQ */
 	desc->chip->ack(irq);
 	for (;;) {
+		/* reading ISR acks the pending (edge triggered) GPIO interrupt */
 		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
 		if (!isr)
 			break;
@@ -315,15 +395,16 @@ void __init at91_gpio_irq_setup(unsigned banks)
 		set_irq_chipdata(id, controller);
 
 		for (i = 0; i < 32; i++, pin++) {
+			/*
+			 * Can use the "simple" and not "edge" handler since it's
+			 * shorter, and the AIC handles interupts sanely.
+			 */
 			set_irq_chip(pin, &gpio_irqchip);
 			set_irq_handler(pin, do_simple_IRQ);
 			set_irq_flags(pin, IRQF_VALID);
 		}
 
 		set_irq_chained_handler(id, gpio_irq_handler);
-
-		/* enable the PIO peripheral clock */
-		at91_sys_write(AT91_PMC_PCER, 1 << id);
 	}
 	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks);
 }
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
index cb62bc83a1dd..70f4d7ac1533 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -92,10 +92,6 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type)
 {
 	unsigned int smr, srctype;
 
-	/* change triggering only for FIQ and external IRQ0..IRQ6 */
-	if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ))
-		return -EINVAL;
-
 	switch (type) {
 	case IRQT_HIGH:
 		srctype = AT91_AIC_SRCTYPE_HIGH;
@@ -104,9 +100,13 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type)
 		srctype = AT91_AIC_SRCTYPE_RISING;
 		break;
 	case IRQT_LOW:
+		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_LOW;
 		break;
 	case IRQT_FALLING:
+		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_FALLING;
 		break;
 	default:
@@ -118,11 +118,47 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type)
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static u32 wakeups;
+static u32 backups;
+
+static int at91rm9200_irq_set_wake(unsigned irq, unsigned value)
+{
+	if (unlikely(irq >= 32))
+		return -EINVAL;
+
+	if (value)
+		wakeups |= (1 << irq);
+	else
+		wakeups &= ~(1 << irq);
+
+	return 0;
+}
+
+void at91_irq_suspend(void)
+{
+	backups = at91_sys_read(AT91_AIC_IMR);
+	at91_sys_write(AT91_AIC_IDCR, backups);
+	at91_sys_write(AT91_AIC_IECR, wakeups);
+}
+
+void at91_irq_resume(void)
+{
+	at91_sys_write(AT91_AIC_IDCR, wakeups);
+	at91_sys_write(AT91_AIC_IECR, backups);
+}
+
+#else
+#define at91rm9200_irq_set_wake	NULL
+#endif
+
 static struct irqchip at91rm9200_irq_chip = {
 	.ack		= at91rm9200_mask_irq,
 	.mask		= at91rm9200_mask_irq,
 	.unmask		= at91rm9200_unmask_irq,
 	.set_type	= at91rm9200_irq_type,
+	.set_wake	= at91rm9200_irq_set_wake,
 };
 
 /*
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c
new file mode 100644
index 000000000000..47e5480feb7e
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/pm.c
@@ -0,0 +1,225 @@
+/*
+ * arch/arm/mach-at91rm9200/pm.c
+ * AT91 Power Management
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * 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/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+static int at91_pm_valid_state(suspend_state_t state)
+{
+	switch (state) {
+		case PM_SUSPEND_ON:
+		case PM_SUSPEND_STANDBY:
+		case PM_SUSPEND_MEM:
+			return 1;
+
+		default:
+			return 0;
+	}
+}
+
+
+static suspend_state_t target_state;
+
+/*
+ * Called after processes are frozen, but before we shutdown devices.
+ */
+static int at91_pm_prepare(suspend_state_t state)
+{
+	target_state = state;
+	return 0;
+}
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+static int at91_pm_verify_clocks(void)
+{
+	unsigned long scsr;
+	int i;
+
+	scsr = at91_sys_read(AT91_PMC_SCSR);
+
+	/* USB must not be using PLLB */
+	if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) {
+		pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+		return 0;
+	}
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
+	for (i = 0; i < 4; i++) {
+		u32 css;
+
+		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+			continue;
+
+		css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		if (css != AT91_PMC_CSS_SLOW) {
+			pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+			return 0;
+		}
+	}
+#endif
+
+	return 1;
+}
+
+/*
+ * Call this from platform driver suspend() to see how deeply to suspend.
+ * For example, some controllers (like OHCI) need one of the PLL clocks
+ * in order to act as a wakeup source, and those are not available when
+ * going into slow clock mode.
+ *
+ * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
+ * the very same problem (but not using at91 main_clk), and it'd be better
+ * to add one generic API rather than lots of platform-specific ones.
+ */
+int at91_suspend_entering_slow_clock(void)
+{
+	return (target_state == PM_SUSPEND_MEM);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+
+static void (*slow_clock)(void);
+
+
+
+static int at91_pm_enter(suspend_state_t state)
+{
+	at91_gpio_suspend();
+	at91_irq_suspend();
+
+	pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+			/* remember all the always-wake irqs */
+			(at91_sys_read(AT91_PMC_PCSR)
+					| (1 << AT91_ID_FIQ)
+					| (1 << AT91_ID_SYS)
+					| (1 << AT91_ID_IRQ0)
+					| (1 << AT91_ID_IRQ1)
+					| (1 << AT91_ID_IRQ2)
+					| (1 << AT91_ID_IRQ3)
+					| (1 << AT91_ID_IRQ4)
+					| (1 << AT91_ID_IRQ5)
+					| (1 << AT91_ID_IRQ6))
+				& at91_sys_read(AT91_AIC_IMR),
+			state);
+
+	switch (state) {
+		/*
+		 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
+		 * drivers must suspend more deeply:  only the master clock
+		 * controller may be using the main oscillator.
+		 */
+		case PM_SUSPEND_MEM:
+			/*
+			 * Ensure that clocks are in a valid state.
+			 */
+			if (!at91_pm_verify_clocks())
+				goto error;
+
+			/*
+			 * Enter slow clock mode by switching over to clk32k and
+			 * turning off the main oscillator; reverse on wakeup.
+			 */
+			if (slow_clock) {
+				slow_clock();
+				break;
+			} else {
+				/* DEVELOPMENT ONLY */
+				pr_info("AT91: PM - no slow clock mode yet ...\n");
+				/* FALLTHROUGH leaving master clock alone */
+			}
+
+		/*
+		 * STANDBY mode has *all* drivers suspended; ignores irqs not
+		 * marked as 'wakeup' event sources; and reduces DRAM power.
+		 * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
+		 * nothing fancy done with main or cpu clocks.
+		 */
+		case PM_SUSPEND_STANDBY:
+			/*
+			 * NOTE: the Wait-for-Interrupt instruction needs to be
+			 * in icache so the SDRAM stays in self-refresh mode until
+			 * the wakeup IRQ occurs.
+			 */
+			asm("b 1f; .align 5; 1:");
+			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
+			at91_sys_write(AT91_SDRAMC_SRR, 1);	/* self-refresh mode */
+			/* fall though to next state */
+
+		case PM_SUSPEND_ON:
+			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+			break;
+
+		default:
+			pr_debug("AT91: PM - bogus suspend state %d\n", state);
+			goto error;
+	}
+
+	pr_debug("AT91: PM - wakeup %08x\n",
+			at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+error:
+	target_state = PM_SUSPEND_ON;
+	at91_irq_resume();
+	at91_gpio_resume();
+	return 0;
+}
+
+
+static struct pm_ops at91_pm_ops ={
+	.pm_disk_mode	= 0,
+	.valid		= at91_pm_valid_state,
+	.prepare	= at91_pm_prepare,
+	.enter		= at91_pm_enter,
+};
+
+static int __init at91_pm_init(void)
+{
+	printk("AT91: Power Management\n");
+
+#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+	/* REVISIT allocations of SRAM should be dynamically managed.
+	 * FIQ handlers and other components will want SRAM/TCM too...
+	 */
+	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
+#endif
+
+	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
+	at91_sys_write(AT91_SDRAMC_LPR, 0);
+
+	pm_set_ops(&at91_pm_ops);
+
+	return 0;
+}
+arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c
index 7ffcf443b99f..fc2d7d5e4637 100644
--- a/arch/arm/mach-at91rm9200/time.c
+++ b/arch/arm/mach-at91rm9200/time.c
@@ -31,6 +31,8 @@
 #include <asm/irq.h>
 #include <asm/mach/time.h>
 
+static unsigned long last_crtr;
+
 /*
  * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
  *  necessary to read it twice (with the same value) to ensure accuracy.
@@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeoffset(void)
 {
 	unsigned long elapsed;
 
-	elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV;
+	elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
 
 	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
 }
@@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeoffset(void)
  */
 static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	unsigned long rtar;
-
 	if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) {	/* This is a shared interrupt */
 		write_seqlock(&xtime_lock);
 
-		while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) {
+		while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
 			timer_tick(regs);
-			rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV;
-			at91_sys_write(AT91_ST_RTAR, rtar);
+			last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
 		}
 
 		write_sequnlock(&xtime_lock);
@@ -87,10 +86,24 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r
 
 static struct irqaction at91rm9200_timer_irq = {
 	.name		= "at91_tick",
-	.flags		= SA_SHIRQ | SA_INTERRUPT,
+	.flags		= SA_SHIRQ | SA_INTERRUPT | SA_TIMER,
 	.handler	= at91rm9200_timer_interrupt
 };
 
+void at91rm9200_timer_reset(void)
+{
+	last_crtr = 0;
+
+	/* Real time counter incremented every 30.51758 microseconds */
+	at91_sys_write(AT91_ST_RTMR, 1);
+
+	/* Set Period Interval timer */
+	at91_sys_write(AT91_ST_PIMR, LATCH);
+
+	/* Enable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
 /*
  * Set up timer interrupt.
  */
@@ -100,28 +113,30 @@ void __init at91rm9200_timer_init(void)
 	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 	(void) at91_sys_read(AT91_ST_SR);	/* Clear any pending interrupts */
 
-	/*
-	 * Make IRQs happen for the system timer.
-	 */
+	/* Make IRQs happen for the system timer */
 	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
 
-	/* Set initial alarm to 0 */
-	at91_sys_write(AT91_ST_RTAR, 0);
-
-	/* Real time counter incremented every 30.51758 microseconds */
-	at91_sys_write(AT91_ST_RTMR, 1);
-
-	/* Set Period Interval timer */
-	at91_sys_write(AT91_ST_PIMR, LATCH);
-
 	/* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
 	tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
 
-	/* Enable Period Interval Timer interrupt */
-	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+	/* Initialize and enable the timer interrupt */
+	at91rm9200_timer_reset();
+}
+
+#ifdef CONFIG_PM
+static void at91rm9200_timer_suspend(void)
+{
+	/* disable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
 }
+#else
+#define at91rm9200_timer_suspend	NULL
+#endif
 
 struct sys_timer at91rm9200_timer = {
 	.init		= at91rm9200_timer_init,
 	.offset		= at91rm9200_gettimeoffset,
+	.suspend	= at91rm9200_timer_suspend,
+	.resume		= at91rm9200_timer_reset,
 };
+
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 5393af989e94..05a48a21038e 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for the linux kernel.
 #
-obj-y			:= core.o
+obj-y			:= core.o clock.o
 obj-m			:=
 obj-n			:=
 obj-			:=
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
new file mode 100644
index 000000000000..08ad782c1649
--- /dev/null
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -0,0 +1,156 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.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 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <asm/div64.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+struct clk {
+	char		*name;
+	unsigned long	rate;
+	int		users;
+	u32		enable_reg;
+	u32		enable_mask;
+};
+
+static struct clk clk_pll1 = {
+	.name		= "pll1",
+};
+static struct clk clk_f = {
+	.name		= "fclk",
+};
+static struct clk clk_h = {
+	.name		= "hclk",
+};
+static struct clk clk_p = {
+	.name		= "pclk",
+};
+static struct clk clk_pll2 = {
+	.name		= "pll2",
+};
+static struct clk clk_usb_host = {
+	.name		= "usb_host",
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= EP93XX_SYSCON_CLOCK_USH_EN,
+};
+
+
+static struct clk *clocks[] = {
+	&clk_pll1,
+	&clk_f,
+	&clk_h,
+	&clk_p,
+	&clk_pll2,
+	&clk_usb_host,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		if (!strcmp(clocks[i]->name, id))
+			return clocks[i];
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (!clk->users++ && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value | clk->enable_mask, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (!--clk->users && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value & ~clk->enable_mask, clk->enable_reg);
+	}
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+	unsigned long long rate;
+	int i;
+
+	rate = 14745600;
+	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
+	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
+	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
+	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
+		rate >>= 1;
+
+	return (unsigned long)rate;
+}
+
+void ep93xx_clock_init(void)
+{
+	u32 value;
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
+	if (!(value & 0x00800000)) {			/* PLL1 bypassed?  */
+		clk_pll1.rate = 14745600;
+	} else {
+		clk_pll1.rate = calc_pll_rate(value);
+	}
+	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
+	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */
+		clk_pll2.rate = 14745600;
+	} else if (value & 0x00040000) {		/* PLL2 enabled?  */
+		clk_pll2.rate = calc_pll_rate(value);
+	} else {
+		clk_pll2.rate = 0;
+	}
+	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+	printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+		clk_f.rate / 1000000, clk_h.rate / 1000000,
+		clk_p.rate / 1000000);
+}
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index dcd417625389..1fe73c0a9d01 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -103,7 +103,8 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	write_seqlock(&xtime_lock);
 
 	__raw_writel(1, EP93XX_TIMER1_CLEAR);
-	while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time
+	while ((signed long)
+		(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
 						>= TIMER4_TICKS_PER_JIFFY) {
 		last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
 		timer_tick(regs);
@@ -124,7 +125,7 @@ static void __init ep93xx_timer_init(void)
 {
 	/* Enable periodic HZ timer.  */
 	__raw_writel(0x48, EP93XX_TIMER1_CONTROL);
-	__raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD);
+	__raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
 	__raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
 
 	/* Enable lost jiffy timer.  */
@@ -432,10 +433,37 @@ static struct platform_device ep93xx_rtc_device = {
 };
 
 
+static struct resource ep93xx_ohci_resources[] = {
+	[0] = {
+		.start	= EP93XX_USB_PHYS_BASE,
+		.end	= EP93XX_USB_PHYS_BASE + 0x0fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EP93XX_USB,
+		.end	= IRQ_EP93XX_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ep93xx_ohci_device = {
+	.name		= "ep93xx-ohci",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= (void *)0xffffffff,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
+	.resource	= ep93xx_ohci_resources,
+};
+
+
 void __init ep93xx_init_devices(void)
 {
 	unsigned int v;
 
+	ep93xx_clock_init();
+
 	/*
 	 * Disallow access to MaverickCrunch initially.
 	 */
@@ -449,4 +477,5 @@ void __init ep93xx_init_devices(void)
 	amba_device_register(&uart3_device, &iomem_resource);
 
 	platform_device_register(&ep93xx_rtc_device);
+	platform_device_register(&ep93xx_ohci_device);
 }
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index d18fcb1a2f1b..47cc6c8b7c79 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -16,16 +16,38 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+static struct physmap_flash_data gesbc9312_flash_data = {
+	.width		= 4,
+};
+
+static struct resource gesbc9312_flash_resource = {
+	.start		= 0x60000000,
+	.end		= 0x60800000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gesbc9312_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &gesbc9312_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gesbc9312_flash_resource,
+};
+
 static void __init gesbc9312_init_machine(void)
 {
 	ep93xx_init_devices();
-	physmap_configure(0x60000000, 0x00800000, 4, NULL);
+	platform_device_register(&gesbc9312_flash);
 }
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index e24566b88a78..6e5a56cd5ae8 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
 #include <linux/m48t86.h>
@@ -111,6 +112,26 @@ static void __init ts72xx_map_io(void)
 	}
 }
 
+static struct physmap_flash_data ts72xx_flash_data = {
+	.width		= 1,
+};
+
+static struct resource ts72xx_flash_resource = {
+	.start		= TS72XX_NOR_PHYS_BASE,
+	.end		= TS72XX_NOR_PHYS_BASE + 0x01000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ts72xx_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ts72xx_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ts72xx_flash_resource,
+};
+
 static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
 {
 	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
@@ -141,7 +162,7 @@ static void __init ts72xx_init_machine(void)
 {
 	ep93xx_init_devices();
 	if (board_is_ts7200())
-		physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+		platform_device_register(&ts72xx_flash);
 	platform_device_register(&ts72xx_rtc_device);
 }
 
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 4ca51dcf13ac..36578871ecc8 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -15,6 +15,9 @@
  *             Changed to support scatter gather DMA
  *             by taking Russell's code from RiscPC
  *
+ *  2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Corrected error handling code.
+ *
  */
 
 #undef DEBUG
@@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
 int
 imx_dma_setup_handlers(imx_dmach_t dma_ch,
 		       void (*irq_handler) (int, void *, struct pt_regs *),
-		       void (*err_handler) (int, void *, struct pt_regs *),
+		       void (*err_handler) (int, void *, struct pt_regs *, int),
 		       void *data)
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
@@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
 	int i, disr = DISR;
 	struct imx_dma_channel *channel;
 	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
+	int errcode;
 
-	DISR = disr;
+	DISR = disr & err_mask;
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
-		channel = &imx_dma_channels[i];
-
-		if ((err_mask & 1 << i) && channel->name
-		    && channel->err_handler) {
-			channel->err_handler(i, channel->data, regs);
+		if(!(err_mask & (1 << i)))
 			continue;
-		}
-
-		imx_dma_channels[i].sg = NULL;
+		channel = &imx_dma_channels[i];
+		errcode = 0;
 
 		if (DBTOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Burst timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DBTOSR |= (1 << i);
+			DBTOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_BURST;
 		}
 		if (DRTOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Request timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DRTOSR |= (1 << i);
+			DRTOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_REQUEST;
 		}
 		if (DSESR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Transfer timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DSESR |= (1 << i);
+			DSESR = (1 << i);
+			errcode |= IMX_DMA_ERR_TRANSFER;
 		}
 		if (DBOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Buffer overflow timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DBOSR |= (1 << i);
+			DBOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_BUFFER;
 		}
+
+		/*
+		 * The cleaning of @sg field would be questionable
+		 * there, because its value can help to compute
+		 * remaining/transfered bytes count in the handler
+		 */
+		/*imx_dma_channels[i].sg = NULL;*/
+
+		if (channel->name && channel->err_handler) {
+			channel->err_handler(i, channel->data, regs, errcode);
+			continue;
+		}
+
+		imx_dma_channels[i].sg = NULL;
+
+		printk(KERN_WARNING
+		       "DMA timeout on channel %d (%s) -%s%s%s%s\n",
+		       i, channel->name,
+		       errcode&IMX_DMA_ERR_BURST?    " burst":"",
+		       errcode&IMX_DMA_ERR_REQUEST?  " request":"",
+		       errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
+		       errcode&IMX_DMA_ERR_BUFFER?   " buffer":"");
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 6e8d504aca55..ebe4391dd7f9 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -211,7 +211,8 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	/* clear timer 1 */
 	ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
 
-	while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
+	while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr)
+							>= ticks_per_jiffy) {
 		timer_tick(regs);
 		next_jiffy_time -= ticks_per_jiffy;
 	}
@@ -301,6 +302,7 @@ void gpio_line_config(int line, int direction)
 	}
 	local_irq_restore(flags);
 }
+EXPORT_SYMBOL(gpio_line_config);
 
 
 /*************************************************************************
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
index affd1d5d7440..051e3d70026e 100644
--- a/arch/arm/mach-ixp23xx/core.c
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -334,7 +334,7 @@ void __init ixp23xx_init_irq(void)
 /*************************************************************************
  * Timer-tick functions for IXP23xx
  *************************************************************************/
-#define CLOCK_TICKS_PER_USEC	CLOCK_TICK_RATE / (USEC_PER_SEC)
+#define CLOCK_TICKS_PER_USEC	(CLOCK_TICK_RATE / USEC_PER_SEC)
 
 static unsigned long next_jiffy_time;
 
@@ -353,7 +353,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Clear Pending Interrupt by writing '1' to it */
 	*IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
-	while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) {
+	while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) {
 		timer_tick(regs);
 		next_jiffy_time += LATCH;
 	}
@@ -439,5 +439,6 @@ static struct platform_device *ixp23xx_devices[] __initdata = {
 
 void __init ixp23xx_sys_init(void)
 {
+	*IXP23XX_EXP_UNIT_FUSE |= 0xf;
 	platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
 }
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index bf688c128630..dc5e489c70bc 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -53,9 +53,29 @@ static int __init espresso_pci_init(void)
 };
 subsys_initcall(espresso_pci_init);
 
+static struct physmap_flash_data espresso_flash_data = {
+	.width		= 2,
+};
+
+static struct resource espresso_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x92000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device espresso_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &espresso_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &espresso_flash_resource,
+};
+
 static void __init espresso_init(void)
 {
-	physmap_configure(0x90000000, 0x02000000, 2, NULL);
+	platform_device_register(&espresso_flash);
 
 	/*
 	 * Mark flash as writeable.
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index 00146c35daac..535b334ee045 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -298,9 +298,29 @@ static void __init ixdp2351_map_io(void)
 	iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
 }
 
+static struct physmap_flash_data ixdp2351_flash_data = {
+	.width		= 1,
+};
+
+static struct resource ixdp2351_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x94000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2351_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ixdp2351_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2351_flash_resource,
+};
+
 static void __init ixdp2351_init(void)
 {
-	physmap_configure(0x90000000, 0x04000000, 1, NULL);
+	platform_device_register(&ixdp2351_flash);
 
 	/*
 	 * Mark flash as writeable
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index 43c14e740794..b9f5d13fcfe1 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -137,9 +137,29 @@ static int __init roadrunner_pci_init(void)
 
 subsys_initcall(roadrunner_pci_init);
 
+static struct physmap_flash_data roadrunner_flash_data = {
+	.width		= 2,
+};
+
+static struct resource roadrunner_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x94000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device roadrunner_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &roadrunner_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &roadrunner_flash_resource,
+};
+
 static void __init roadrunner_init(void)
 {
-	physmap_configure(0x90000000, 0x04000000, 2, NULL);
+	platform_device_register(&roadrunner_flash);
 
 	/*
 	 * Mark flash as writeable
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 00b761ff0f9c..bf25a76e9bdf 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -276,7 +276,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs
 	/*
 	 * Catch up with the real idea of time
 	 */
-	while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) {
+	while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
 		timer_tick(regs);
 		last_jiffy_time += LATCH;
 	}
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index a3b4c6ac5708..9a31444d9214 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/leds.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -37,6 +38,36 @@ static struct platform_device nas100d_flash = {
 	.resource		= &nas100d_flash_resource,
 };
 
+#ifdef CONFIG_LEDS_IXP4XX
+static struct resource nas100d_led_resources[] = {
+	{
+		.name		= "wlan",   /* green led */
+		.start		= 0,
+		.end		= 0,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "ready",  /* blue power led (off is flashing!) */
+		.start		= 15,
+		.end		= 15,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "disk",   /* yellow led */
+		.start		= 3,
+		.end		= 3,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+};
+
+static struct platform_device nas100d_leds = {
+	.name			= "IXP4XX-GPIO-LED",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(nas100d_led_resources),
+	.resource		= nas100d_led_resources,
+};
+#endif
+
 static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
 	.sda_pin		= NAS100D_SDA_PIN,
 	.scl_pin		= NAS100D_SCL_PIN,
@@ -95,7 +126,9 @@ static struct platform_device nas100d_uart = {
 static struct platform_device *nas100d_devices[] __initdata = {
 	&nas100d_i2c_controller,
 	&nas100d_flash,
-	&nas100d_uart,
+#ifdef CONFIG_LEDS_IXP4XX
+	&nas100d_leds,
+#endif
 };
 
 static void nas100d_power_off(void)
@@ -122,6 +155,12 @@ static void __init nas100d_init(void)
 
 	pm_power_off = nas100d_power_off;
 
+	/* This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nas100d_uart);
+
 	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
 }
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 55411f21d838..749a337494d3 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -7,6 +7,7 @@
  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
  *
  * Author: Mark Rakes <mrakes at mac.com>
+ * Author: Rod Whitby <rod@whitby.id.au>
  * Maintainers: http://www.nslu2-linux.org/
  *
  * Fixed missing init_time in MACHINE_START kas11 10/22/04
@@ -16,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/leds.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -43,6 +45,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
 	.scl_pin		= NSLU2_SCL_PIN,
 };
 
+#ifdef CONFIG_LEDS_IXP4XX
+static struct resource nslu2_led_resources[] = {
+	{
+		.name		= "ready",  /* green led */
+		.start		= NSLU2_LED_GRN,
+		.end		= NSLU2_LED_GRN,
+		.flags		= IXP4XX_GPIO_HIGH,
+	},
+	{
+		.name		= "status", /* red led */
+		.start		= NSLU2_LED_RED,
+		.end		= NSLU2_LED_RED,
+		.flags		= IXP4XX_GPIO_HIGH,
+	},
+	{
+		.name		= "disk-1",
+		.start		= NSLU2_LED_DISK1,
+		.end		= NSLU2_LED_DISK1,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "disk-2",
+		.start		= NSLU2_LED_DISK2,
+		.end		= NSLU2_LED_DISK2,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+};
+
+static struct platform_device nslu2_leds = {
+	.name			= "IXP4XX-GPIO-LED",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(nslu2_led_resources),
+	.resource		= nslu2_led_resources,
+};
+#endif
+
 static struct platform_device nslu2_i2c_controller = {
 	.name			= "IXP4XX-I2C",
 	.id			= 0,
@@ -102,8 +140,10 @@ static struct platform_device nslu2_uart = {
 static struct platform_device *nslu2_devices[] __initdata = {
 	&nslu2_i2c_controller,
 	&nslu2_flash,
-	&nslu2_uart,
 	&nslu2_beeper,
+#ifdef CONFIG_LEDS_IXP4XX
+	&nslu2_leds,
+#endif
 };
 
 static void nslu2_power_off(void)
@@ -127,6 +167,12 @@ static void __init nslu2_init(void)
 
 	pm_power_off = nslu2_power_off;
 
+	/* This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nslu2_uart);
+
 	platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
 }
 
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
index 8a17867a6a24..558a34f53b1c 100644
--- a/arch/arm/mach-lh7a40x/Kconfig
+++ b/arch/arm/mach-lh7a40x/Kconfig
@@ -14,6 +14,7 @@ config MACH_LPD7A400
 	bool "LPD7A400 Card Engine"
 	select ARCH_LH7A400
 #	select IDE_POLL
+	select HAS_TOUCHSCREEN_ADS7843_LH7
 	help
 	  Say Y here if you are using Logic Product Development's
 	  LPD7A400 CardEngine.  For the time being, the LPD7A400 and
@@ -23,6 +24,7 @@ config MACH_LPD7A404
 	bool "LPD7A404 Card Engine"
 	select ARCH_LH7A404
 #	select IDE_POLL
+	select HAS_TOUCHSCREEN_ADC_LH7
 	help
 	  Say Y here if you are using Logic Product Development's
 	  LPD7A404 CardEngine. For the time being, the LPD7A400 and
@@ -34,6 +36,9 @@ config ARCH_LH7A400
 config ARCH_LH7A404
 	bool
 
+config LPD7A40X_CPLD_SSP
+	bool
+
 config LH7A40X_CONTIGMEM
 	bool "Disable NUMA Support"
 	depends on ARCH_LH7A40X
diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
index e90512dbc2d6..94b8615fb3c3 100644
--- a/arch/arm/mach-lh7a40x/Makefile
+++ b/arch/arm/mach-lh7a40x/Makefile
@@ -4,11 +4,14 @@
 
 # Object file lists.
 
-obj-y			:= time.o
-obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
-
-obj-m			:=
-obj-n			:=
-obj-			:=
+obj-y				:= time.o clocks.o
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_MACH_KEV7A400)	+= arch-kev7a400.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A400)	+= arch-lpd7a40x.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A404)	+= arch-lpd7a40x.o irq-lh7a404.o
+obj-$(CONFIG_LPD7A40X_CPLD_SSP)	+= ssp-cpld.o
+obj-$(CONFIG_FB_ARMCLCD)	+= clcd.o
+
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 12e23277c5ea..c0e6854289f1 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -23,6 +23,28 @@
 
 #include "common.h"
 
+#define CPLD_INT_NETHERNET	(1<<0)
+#define CPLD_INTMASK_ETHERNET	(1<<2)
+#if defined (CONFIG_MACH_LPD7A400)
+# define CPLD_INT_NTOUCH		(1<<1)
+# define CPLD_INTMASK_TOUCH	(1<<3)
+# define CPLD_INT_PEN		(1<<4)
+# define CPLD_INTMASK_PEN	(1<<4)
+# define CPLD_INT_PIRQ		(1<<4)
+#endif
+#define CPLD_INTMASK_CPLD	(1<<7)
+#define CPLD_INT_CPLD		(1<<6)
+
+#define CPLD_CONTROL_SWINT		(1<<7) /* Disable all CPLD IRQs */
+#define CPLD_CONTROL_OCMSK		(1<<6) /* Mask USB1 connect IRQ */
+#define CPLD_CONTROL_PDRV		(1<<5) /* PCC_nDRV high */
+#define CPLD_CONTROL_USB1C		(1<<4) /* USB1 connect IRQ active */
+#define CPLD_CONTROL_USB1P		(1<<3) /* USB1 power disable */
+#define CPLD_CONTROL_AWKP		(1<<2) /* Auto-wakeup disabled  */
+#define CPLD_CONTROL_LCD_ENABLE		(1<<1) /* LCD Vee enable */
+#define CPLD_CONTROL_WRLAN_NENABLE	(1<<0) /* SMC91x power disable */
+
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= CPLD00_PHYS,
@@ -48,12 +70,12 @@ static struct platform_device smc91x_device = {
 static struct resource lh7a40x_usbclient_resources[] = {
 	[0] = {
 		.start	= USB_PHYS,
-		.end	= (USB_PHYS + 0xFF),
+		.end	= (USB_PHYS + PAGE_SIZE),
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_USBINTR,
-		.end	= IRQ_USBINTR,
+		.start	= IRQ_USB,
+		.end	= IRQ_USB,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -61,7 +83,8 @@ static struct resource lh7a40x_usbclient_resources[] = {
 static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
 
 static struct platform_device lh7a40x_usbclient_device = {
-	.name		= "lh7a40x_udc",
+//	.name		= "lh7a40x_udc",
+	.name		= "lh7-udc",
 	.id		= 0,
 	.dev		= {
 		.dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -101,7 +124,7 @@ static struct platform_device lh7a404_usbhost_device = {
 
 #endif
 
-static struct platform_device *lpd7a40x_devs[] __initdata = {
+static struct platform_device* lpd7a40x_devs[] __initdata = {
 	&smc91x_device,
 	&lh7a40x_usbclient_device,
 #if defined (CONFIG_ARCH_LH7A404)
@@ -113,29 +136,52 @@ extern void lpd7a400_map_io (void);
 
 static void __init lpd7a40x_init (void)
 {
-	CPLD_CONTROL |=     (1<<6); /* Mask USB1 connection IRQ */
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL |= 0
+		| CPLD_CONTROL_SWINT /* Disable software interrupt */
+		| CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
 	CPLD_CONTROL &= ~(0
-			  | (1<<1) /* Disable LCD */
-			  | (1<<0) /* Enable WLAN */
+			  | CPLD_CONTROL_LCD_ENABLE	/* Disable LCD */
+			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
 		);
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	CPLD_CONTROL &= ~(0
+			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
+		);
+#endif
 
 	platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
+#if defined (CONFIG_FB_ARMCLCD)
+        lh7a40x_clcd_init ();
+#endif
 }
 
 static void lh7a40x_ack_cpld_irq (u32 irq)
 {
-	/* CPLD doesn't have ack capability */
+	/* CPLD doesn't have ack capability, but some devices may */
+
+#if defined (CPLD_INTMASK_TOUCH)
+	/* The touch control *must* mask the the interrupt because the
+	 * interrupt bit is read by the driver to determine if the pen
+	 * is still down. */
+	if (irq == IRQ_TOUCH)
+		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
+#endif
 }
 
 static void lh7a40x_mask_cpld_irq (u32 irq)
 {
 	switch (irq) {
 	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
+		CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
 		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
+#if defined (IRQ_TOUCH)
+	case IRQ_TOUCH:
+		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
 		break;
+#endif
 	}
 }
 
@@ -143,11 +189,13 @@ static void lh7a40x_unmask_cpld_irq (u32 irq)
 {
 	switch (irq) {
 	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
+		CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
 		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
+#if defined (IRQ_TOUCH)
+	case IRQ_TOUCH:
+		CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
 		break;
+#endif
 	}
 }
 
@@ -164,11 +212,13 @@ static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
 
 	desc->chip->ack (irq);
 
-	if ((mask & 0x1) == 0)	/* WLAN */
+	if ((mask & (1<<0)) == 0)	/* WLAN */
 		IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
 
-	if ((mask & 0x2) == 0)	/* Touch */
-		IRQ_DISPATCH (IRQ_LPD7A400_TS);
+#if defined (IRQ_TOUCH)
+	if ((mask & (1<<1)) == 0)	/* Touch */
+		IRQ_DISPATCH (IRQ_TOUCH);
+#endif
 
 	desc->chip->unmask (irq); /* Level-triggered need this */
 }
@@ -204,9 +254,21 @@ void __init lh7a40x_init_board_irq (void)
 
 		/* Then, configure CPLD interrupt */
 
-	CPLD_INTERRUPTS	=   0x9c; /* Disable all CPLD interrupts */
+			/* Disable all CPLD interrupts */
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_INTERRUPTS	= CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
+		| CPLD_INTMASK_ETHERNET;
+	/* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
+               and 4 is uncefined. */
+	// (1<<7)|(1<<4)|(1<<3)|(1<<2);
+#endif
+#if defined (CONFIG_MACH_LPD7A404)
+	CPLD_INTERRUPTS	= CPLD_INTMASK_ETHERNET;
+	/* *** FIXME: don't know why we need 6 and 5, neither is defined. */
+	// (1<<6)|(1<<5)|(1<<3);
+#endif
 	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */
+	GPIO_INTTYPE1	&= ~(1 << pinCPLD); /* Level triggered */
 	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
 	barrier ();
 	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
@@ -216,7 +278,7 @@ void __init lh7a40x_init_board_irq (void)
 	for (irq = IRQ_BOARD_START;
 	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
 		set_irq_chip (irq, &lpd7a40x_cpld_chip);
-		set_irq_handler (irq, do_edge_IRQ);
+		set_irq_handler (irq, do_level_IRQ);
 		set_irq_flags (irq, IRQF_VALID);
 	}
 
@@ -226,91 +288,109 @@ void __init lh7a40x_init_board_irq (void)
 				 lpd7a40x_cpld_handler);
 }
 
-static struct map_desc lpd7a400_io_desc[] __initdata = {
+static struct map_desc lpd7a40x_io_desc[] __initdata = {
 	{
-		.virtual	=     IO_VIRT,
+		.virtual	= IO_VIRT,
 		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= 	    IO_SIZE,
+		.length		= IO_SIZE,
 		.type		= MT_DEVICE
-	}, {	/* Mapping added to work around chip select problems */
+	},
+	{	/* Mapping added to work around chip select problems */
 		.virtual	= IOBARRIER_VIRT,
 		.pfn		= __phys_to_pfn(IOBARRIER_PHYS),
 		.length		= IOBARRIER_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CF_VIRT,
 		.pfn		= __phys_to_pfn(CF_PHYS),
-		.length		= 	CF_SIZE,
+		.length		= CF_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD02_VIRT,
 		.pfn		= __phys_to_pfn(CPLD02_PHYS),
-		.length		= 	CPLD02_SIZE,
+		.length		= CPLD02_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD06_VIRT,
 		.pfn		= __phys_to_pfn(CPLD06_PHYS),
-		.length		= 	CPLD06_SIZE,
+		.length		= CPLD06_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD08_VIRT,
+		.pfn		= __phys_to_pfn(CPLD08_PHYS),
+		.length		= CPLD08_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD08_VIRT,
 		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= 	CPLD08_SIZE,
+		.length		= CPLD08_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
+		.virtual	= CPLD0A_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0A_PHYS),
+		.length		= CPLD0A_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
 		.virtual	= CPLD0C_VIRT,
 		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
-		.length		= 	CPLD0C_SIZE,
+		.length		= CPLD0C_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD0E_VIRT,
 		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
-		.length		= 	CPLD0E_SIZE,
+		.length		= CPLD0E_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD10_VIRT,
 		.pfn		= __phys_to_pfn(CPLD10_PHYS),
-		.length		= 	CPLD10_SIZE,
+		.length		= CPLD10_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD12_VIRT,
 		.pfn		= __phys_to_pfn(CPLD12_PHYS),
-		.length		= 	CPLD12_SIZE,
+		.length		= CPLD12_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD14_VIRT,
 		.pfn		= __phys_to_pfn(CPLD14_PHYS),
-		.length		= 	CPLD14_SIZE,
+		.length		= CPLD14_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD16_VIRT,
 		.pfn		= __phys_to_pfn(CPLD16_PHYS),
-		.length		= 	CPLD16_SIZE,
+		.length		= CPLD16_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD18_VIRT,
 		.pfn		= __phys_to_pfn(CPLD18_PHYS),
-		.length		= 	CPLD18_SIZE,
+		.length		= CPLD18_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CPLD1A_VIRT,
 		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
-		.length		= 	CPLD1A_SIZE,
+		.length		= CPLD1A_SIZE,
 		.type		= MT_DEVICE
 	},
-	/* This mapping is redundant since the smc driver performs another. */
-/*	{ CPLD00_VIRT,  CPLD00_PHYS,	CPLD00_SIZE,	MT_DEVICE }, */
 };
 
 void __init
-lpd7a400_map_io(void)
+lpd7a40x_map_io(void)
 {
-	iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc));
-
-		/* Fixup (improve) Static Memory Controller settings */
-	SMC_BCR0 = 0x200039af;	/* Boot Flash */
-	SMC_BCR6 = 0x1000fbe0;	/* CPLD */
-	SMC_BCR7 = 0x1000b2c2;	/* Compact Flash */
+	iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
 }
 
 #ifdef CONFIG_MACH_LPD7A400
@@ -320,7 +400,7 @@ MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
 	.phys_io	= 0x80000000,
 	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a400_map_io,
+	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a400_init_irq,
 	.timer		= &lh7a40x_timer,
 	.init_machine	= lpd7a40x_init,
@@ -335,7 +415,7 @@ MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
 	.phys_io	= 0x80000000,
 	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a400_map_io,
+	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a404_init_irq,
 	.timer		= &lh7a40x_timer,
 	.init_machine	= lpd7a40x_init,
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644
index 000000000000..93751fee793d
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clcd.c
@@ -0,0 +1,241 @@
+/*
+ *  arch/arm/mach-lh7a40x/clcd.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+
+//#include <linux/module.h>
+//#include <linux/time.h>
+//#include <asm/hardware.h>
+
+//#include <asm/mach/time.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#define HRTFTC_HRSETUP		__REG(HRTFTC_PHYS + 0x00)
+#define HRTFTC_HRCON		__REG(HRTFTC_PHYS + 0x04)
+#define HRTFTC_HRTIMING1	__REG(HRTFTC_PHYS + 0x08)
+#define HRTFTC_HRTIMING2	__REG(HRTFTC_PHYS + 0x0c)
+
+#define ALI_SETUP		__REG(ALI_PHYS + 0x00)
+#define ALI_CONTROL		__REG(ALI_PHYS + 0x04)
+#define ALI_TIMING1		__REG(ALI_PHYS + 0x08)
+#define ALI_TIMING2		__REG(ALI_PHYS + 0x0c)
+
+#include "lcd-panel.h"
+
+static void lh7a40x_clcd_disable (struct clcd_fb *fb)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL &= ~(1<<1);	/* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	GPIO_PCD  &= ~(1<<3);		/* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+	HRTFTC_HRSETUP &= ~(1<<13);	/* Disable HRTFT controller */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+	ALI_SETUP &= ~(1<<13);		/* Disable ALI */
+#endif
+}
+
+static void lh7a40x_clcd_enable (struct clcd_fb *fb)
+{
+	struct clcd_panel_extra* extra
+		= (struct clcd_panel_extra*) fb->board_data;
+
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL |= (1<<1);		/* Enable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	GPIO_PCDD &= ~(1<<3);		/* Enable LCD Vee */
+	GPIO_PCD  |=  (1<<3);
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+
+	if (extra) {
+		HRTFTC_HRSETUP
+			= (1 << 13)
+			| ((fb->fb.var.xres - 1) << 4)
+			| 0xc
+			| (extra->hrmode ? 1 : 0);
+		HRTFTC_HRCON
+			= ((extra->clsen ? 1 : 0) << 1)
+			| ((extra->spsen ? 1 : 0) << 0);
+		HRTFTC_HRTIMING1
+			= (extra->pcdel << 8)
+			| (extra->revdel << 4)
+			| (extra->lpdel << 0);
+		HRTFTC_HRTIMING2
+			= (extra->spldel << 9)
+			| (extra->pc2del << 0);
+	}
+	else
+		HRTFTC_HRSETUP
+			= (1 << 13)
+			| 0xc;
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+
+	if (extra) {
+		ALI_SETUP
+			= (1 << 13)
+			| ((fb->fb.var.xres - 1) << 4)
+			| 0xc
+			| (extra->hrmode ? 1 : 0);
+		ALI_CONTROL
+			= ((extra->clsen ? 1 : 0) << 1)
+			| ((extra->spsen ? 1 : 0) << 0);
+		ALI_TIMING1
+			= (extra->pcdel << 8)
+			| (extra->revdel << 4)
+			| (extra->lpdel << 0);
+		ALI_TIMING2
+			= (extra->spldel << 9)
+			| (extra->pc2del << 0);
+	}
+	else
+		ALI_SETUP
+			= (1 << 13)
+			| 0xc;
+#endif
+
+}
+
+#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
+
+static int lh7a40x_clcd_setup (struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+	u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
+			     *(lcd_panel.bpp/8));
+
+	fb->panel = &lcd_panel;
+
+		/* Enforce the sync polarity defaults */
+	if (!(fb->panel->tim2 & TIM2_IHS))
+		fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (!(fb->panel->tim2 & TIM2_IVS))
+		fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+#if defined (HAS_LCD_PANEL_EXTRA)
+	fb->board_data = &lcd_panel_extra;
+#endif
+
+	fb->fb.screen_base
+		= dma_alloc_writecombine (&fb->dev->dev, len,
+					  &dma, GFP_KERNEL);
+	printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
+		fb->fb.screen_base, (void*) dma, len,
+		(void*) io_p2v (CLCDC_PHYS));
+	printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
+
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+#if defined (USE_RGB555)
+	fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
+#endif
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = len;
+
+		/* Drive PE4 high to prevent CPLD crash */
+	GPIO_PEDD |= (1<<4);
+	GPIO_PED  |= (1<<4);
+
+	GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
+
+//	fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
+//	fb->fb.fbops->fb_set_par (&fb->fb);
+
+	return 0;
+}
+
+static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+				     fb->fb.screen_base,
+				     fb->fb.fix.smem_start,
+				     fb->fb.fix.smem_len);
+}
+
+static void lh7a40x_clcd_remove (struct clcd_fb *fb)
+{
+	dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
+			       fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_platform_data = {
+	.name		= "lh7a40x FB",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.enable		= lh7a40x_clcd_enable,
+	.setup		= lh7a40x_clcd_setup,
+	.mmap		= lh7a40x_clcd_mmap,
+	.remove		= lh7a40x_clcd_remove,
+	.disable	= lh7a40x_clcd_disable,
+};
+
+#define IRQ_CLCDC (IRQ_LCDINTR)
+
+#define AMBA_DEVICE(name,busid,base,plat,pid)			\
+static struct amba_device name##_device = {			\
+	.dev = {						\
+		.coherent_dma_mask = ~0,			\
+		.bus_id	= busid,				\
+		.platform_data = plat,				\
+		},						\
+	.res = {						\
+		.start	= base##_PHYS,				\
+		.end	= (base##_PHYS) + (4*1024) - 1,		\
+		.flags	= IORESOURCE_MEM,			\
+		},						\
+	.dma_mask	= ~0,					\
+	.irq		= { IRQ_##base, },			\
+	/* .dma		= base##_DMA,*/				\
+	.periphid = pid,					\
+}
+
+AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
+
+static struct amba_device *amba_devs[] __initdata = {
+	&clcd_device,
+};
+
+void __init lh7a40x_clcd_init (void)
+{
+	int i;
+	int result;
+	printk ("CLCD: registering amba devices\n");
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		result = amba_device_register(d, &iomem_resource);
+		printk ("  %d -> %d\n", i ,result);
+	}
+}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
new file mode 100644
index 000000000000..2291afe9f23e
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clocks.c
@@ -0,0 +1,199 @@
+/* arch/arm/mach-lh7a40x/clocks.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <asm/hardware.h>
+#include <asm/arch/clocks.h>
+#include <linux/err.h>
+
+struct module;
+struct icst525_params;
+
+struct clk {
+	struct list_head node;
+	unsigned long rate;
+	struct module *owner;
+	const char *name;
+//	void *data;
+//	const struct icst525_params *params;
+//	void (*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+/* ----- */
+
+#define MAINDIV1(c)	(((c) >>  7) & 0x0f)
+#define MAINDIV2(c)	(((c) >> 11) & 0x1f)
+#define PS(c)		(((c) >> 18) & 0x03)
+#define PREDIV(c)	(((c) >>  2) & 0x1f)
+#define HCLKDIV(c)	(((c) >>  0) & 0x02)
+#define PCLKDIV(c)	(((c) >> 16) & 0x03)
+
+unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
+{
+	return fclkfreq_get ()/1000;
+}
+EXPORT_SYMBOL(cpufreq_get);
+
+unsigned int fclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	unsigned int gclk
+		= XTAL_IN
+		/ (1 << PS(clkset))
+		* (MAINDIV1(clkset) + 2)
+		/ (PREDIV(clkset)   + 2)
+		* (MAINDIV2(clkset) + 2)
+		;
+	return gclk;
+}
+
+unsigned int hclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
+
+	return hclk;
+}
+
+unsigned int pclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	int pclkdiv = PCLKDIV(clkset);
+	unsigned int pclk;
+	if (pclkdiv == 0x3)
+		pclkdiv = 0x2;
+	pclk = hclkfreq_get () / (1 << pclkdiv);
+
+	return pclk;
+}
+
+/* ----- */
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get (struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *clk = ERR_PTR(-ENOENT);
+
+	down (&clocks_sem);
+	list_for_each_entry (p, &clocks, node) {
+		if (strcmp (id, p->name) == 0
+		    && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up (&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put (struct clk *clk)
+{
+	module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable (struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use (struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate (struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate (struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate (struct clk *clk, unsigned long rate)
+{
+	int ret = -EIO;
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+#if 0
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+	.name	= "KMIREFCLK",
+	.rate	= 24000000,
+};
+
+static struct clk uart_clk = {
+	.name	= "UARTCLK",
+	.rate	= 24000000,
+};
+
+static struct clk mmci_clk = {
+	.name	= "MCLK",
+	.rate	= 33000000,
+};
+#endif
+
+static struct clk clcd_clk = {
+	.name	= "CLCDCLK",
+	.rate	= 0,
+};
+
+int clk_register (struct clk *clk)
+{
+	down (&clocks_sem);
+	list_add (&clk->node, &clocks);
+	up (&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister (struct clk *clk)
+{
+	down (&clocks_sem);
+	list_del (&clk->node);
+	up (&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init (void)
+{
+	clk_register(&clcd_clk);
+	return 0;
+}
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index ea8de7e3ab1b..18e8bb4eb202 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -12,6 +12,7 @@ extern struct sys_timer lh7a40x_timer;
 
 extern void lh7a400_init_irq (void);
 extern void lh7a404_init_irq (void);
+extern void lh7a40x_clcd_init (void);
 extern void lh7a40x_init_board_irq (void);
 
 #define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
index e902e3d87da4..2685a81454d2 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -28,13 +28,17 @@
 
 static unsigned char irq_pri_vic1[] = {
 #if defined (USE_PRIORITIES)
-IRQ_GPIO3INTR,
+	IRQ_GPIO3INTR,			/* CPLD */
+	IRQ_DMAM2P4, IRQ_DMAM2P5,	/* AC97 */
 #endif
 };
 static unsigned char irq_pri_vic2[] = {
 #if defined (USE_PRIORITIES)
-	IRQ_T3UI, IRQ_GPIO7INTR,
+	IRQ_T3UI,			/* Timer */
+	IRQ_GPIO7INTR,			/* CPLD */
 	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
+	IRQ_LCDINTR,			/* LCD */
+	IRQ_TSCINTR,			/* ADC/Touchscreen */
 #endif
 };
 
@@ -98,10 +102,19 @@ static struct irqchip lh7a404_gpio_vic2_chip = {
 
   /* IRQ initialization */
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+extern void* branch_irq_lh7a400;
+#endif
+
 void __init lh7a404_init_irq (void)
 {
 	int irq;
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+#define NOP 0xe1a00000			/* mov r0, r0 */
+	branch_irq_lh7a400 = NOP;
+#endif
+
 	VIC1_INTENCLR = 0xffffffff;
 	VIC2_INTENCLR = 0xffffffff;
 	VIC1_INTSEL = 0;		/* All IRQs */
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
new file mode 100644
index 000000000000..4fb2efc4950f
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/lcd-panel.h
@@ -0,0 +1,346 @@
+/* lcd-panel.h
+     $Id$
+
+   written by Marc Singer
+   18 Jul 2005
+
+   Copyright (C) 2005 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   Only one panel may be defined at a time.
+
+   The pixel clock is calculated to be no greater than the target.
+
+   Each timing value is accompanied by a specification comment.
+
+     UNITS/MIN/TYP/MAX
+
+   Most of the units will be in clocks.
+
+   USE_RGB555
+
+     Define this macro to configure the AMBA LCD controller to use an
+     RGB555 encoding for the pels instead of the normal RGB565.
+
+   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
+
+     These boards are best approximated by 555 for all panels.  Some
+     can use an extra low-order bit of blue in bit 16 of the color
+     value, but we don't have a way to communicate this non-linear
+     mapping to the kernel.
+
+*/
+
+#if !defined (__LCD_PANEL_H__)
+#    define   __LCD_PANEL_H__
+
+#if defined (MACH_LPD79520)\
+ || defined (MACH_LPD79524)\
+ || defined (MACH_LPD7A400)\
+ || defined (MACH_LPD7A404)
+# define USE_RGB555
+#endif
+
+struct clcd_panel_extra {
+	unsigned int hrmode;
+	unsigned int clsen;
+	unsigned int spsen;
+	unsigned int pcdel;
+	unsigned int revdel;
+	unsigned int lpdel;
+	unsigned int spldel;
+	unsigned int pc2del;
+};
+
+#define NS_TO_CLOCK(ns,c)	((((ns)*((c)/1000) + (1000000 - 1))/1000000))
+#define CLOCK_TO_DIV(e,c)	(((c) + (e) - 1)/(e))
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+
+	/* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
+	/* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
+
+#define PIX_CLOCK_TARGET	(6800000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "3.5in QVGA (LQ035Q7DB02)",
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 16,
+		.right_margin	= 21,
+		.upper_margin	= 8,			// line/8/8/8
+		.lower_margin	= 5,
+		.hsync_len	= 61,
+		.vsync_len	= NS_TO_CLOCK (60, PIX_CLOCK),
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#define HAS_LCD_PANEL_EXTRA
+
+static struct clcd_panel_extra lcd_panel_extra = {
+	.hrmode = 1,
+	.clsen = 1,
+	.spsen = 1,
+	.pcdel = 8,
+	.revdel = 7,
+	.lpdel = 13,
+	.spldel = 77,
+	.pc2del = 208,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
+
+	/* Logic Product Development LCD 5.7" QVGA -10 */
+	/* Sharp PN LQ057Q3DC02 */
+	/* QVGA mode, V/Q=LOW */
+
+/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
+ * based on the datasheet.
+
+    Timing0	TIMING1		TIMING2		CONTROL
+    0x140A0C4C	0x080504EF	0x013F380D	0x00000829
+    HBP= 20	VBP=  8		BCD=  0
+    HFP= 10	VFP=  5		CPL=319
+    HSW= 12	VSW=  1		IOE=  0
+    PPL= 19	LPP=239		IPC=  1
+				IHS=  1
+				IVS=  1
+				ACB=  0
+				CSEL= 0
+				PCD= 13
+
+ */
+
+/* The full horozontal cycle (Th) is clock/360/400/450. */
+/* The full vertical   cycle (Tv) is line/251/262/280. */
+
+#define PIX_CLOCK_TARGET	(6300000) /* -/6.3/7 MHz */
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "5.7in QVGA (LQ057Q3DC02)",
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 11,
+		.right_margin	= 400-11-320-2,
+		.upper_margin	= 7,			// line/7/7/7
+		.lower_margin	= 262-7-240-2,
+		.hsync_len	= 2,			// clk/2/96/200
+		.vsync_len	= 2,			// line/2/-/34
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
+
+	/* Logic Product Development LCD 6.4" VGA -10 */
+	/* Sharp PN LQ64D343 */
+
+/* The full horozontal cycle (Th) is clock/750/800/900. */
+/* The full vertical   cycle (Tv) is line/515/525/560. */
+
+#define PIX_CLOCK_TARGET	(28330000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "6.4in QVGA (LQ64D343)",
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 32,
+		.right_margin	= 800-32-640-96,
+		.upper_margin	= 32,			// line/34/34/34
+		.lower_margin	= 540-32-480-2,
+		.hsync_len	= 96,			// clk/2/96/200
+		.vsync_len	= 2,			// line/2/-/34
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
+
+	/* Logic Product Development LCD 10.4" VGA -10 */
+	/* Sharp PN LQ10D368 */
+
+#define PIX_CLOCK_TARGET	(28330000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "10.4in VGA (LQ10D368)",
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 21,
+		.right_margin	= 15,
+		.upper_margin	= 34,
+		.lower_margin	= 5,
+		.hsync_len	= 96,
+		.vsync_len	= 16,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
+
+	/* Logic Product Development LCD 12.1" SVGA -10 */
+	/* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
+
+/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
+ * target clock frequency range of 35MHz to 42MHz. */
+
+/* If the target pixel clock is substantially lower than the panel
+ * spec, this is done to prevent the LCD display from glitching when
+ * the CPU is under load.  A pixel clock higher than 25MHz
+ * (empirically determined) will compete with the CPU for bus cycles
+ * for the Ethernet chip.  However, even a pixel clock of 10MHz
+ * competes with Compact Flash interface during some operations
+ * (fdisk, e2fsck).  And, at that speed the display may have a visible
+ * flicker. */
+
+/* The full horozontal cycle (Th) is clock/832/1056/1395. */
+
+#define PIX_CLOCK_TARGET	(20000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "12.1in SVGA (LQ121S1DG41)",
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 89,		// ns/5/-/(1/PIX_CLOCK)-10
+		.right_margin	= 1056-800-89-128,
+		.upper_margin	= 23,		// line/23/23/23
+		.lower_margin	= 44,
+		.hsync_len	= 128,		// clk/2/128/200
+		.vsync_len	= 4,		// line/2/4/6
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_HITACHI
+
+	/* Hitachi*/
+	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET	(49000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "Hitachi 800x480",
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 128,
+		.vsync_len	= 2,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+
+#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
+
+	/* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
+	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET	(10000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "7.0in Wide (A070VW01)",
+		.xres		= 480,
+		.yres		= 234,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 30,
+		.right_margin	= 25,
+		.upper_margin	= 14,
+		.lower_margin	= 12,
+		.hsync_len	= 100,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#undef NS_TO_CLOCK
+#undef CLOCK_TO_DIV
+
+#endif  /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
new file mode 100644
index 000000000000..a10830186dac
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/ssp-cpld.c
@@ -0,0 +1,343 @@
+/* arch/arm/mach-lh7a40x/ssp-cpld.c
+ *
+ *  Copyright (C) 2004,2005 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ * SSP/SPI driver for the CardEngine CPLD.
+ *
+ */
+
+/* NOTES
+   -----
+
+   o *** This driver is cribbed from the 7952x implementation.
+	 Some comments may not apply.
+
+   o This driver contains sufficient logic to control either the
+     serial EEPROMs or the audio codec.  It is included in the kernel
+     to support the codec.  The EEPROMs are really the responsibility
+     of the boot loader and should probably be left alone.
+
+   o The code must be augmented to cope with multiple, simultaneous
+     clients.
+     o The audio codec writes to the codec chip whenever playback
+       starts.
+     o The touchscreen driver writes to the ads chip every time it
+       samples.
+     o The audio codec must write 16 bits, but the touch chip writes
+       are 8 bits long.
+     o We need to be able to keep these configurations separate while
+       simultaneously active.
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+//#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+//#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+
+//#define TALK
+
+#if defined (TALK)
+#define PRINTK(f...)		printk (f)
+#else
+#define PRINTK(f...)		do {} while (0)
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+# define CPLD_SPID		__REGP16(CPLD06_VIRT) /* SPI data */
+# define CPLD_SPIC		__REGP16(CPLD08_VIRT) /* SPI control */
+# define CPLD_SPIC_CS_CODEC	(1<<0)
+# define CPLD_SPIC_CS_TOUCH	(1<<1)
+# define CPLD_SPIC_WRITE	(0<<2)
+# define CPLD_SPIC_READ		(1<<2)
+# define CPLD_SPIC_DONE		(1<<3) /* r/o */
+# define CPLD_SPIC_LOAD		(1<<4)
+# define CPLD_SPIC_START	(1<<4)
+# define CPLD_SPIC_LOADED	(1<<5) /* r/o */
+#endif
+
+#define CPLD_SPI		__REGP16(CPLD0A_VIRT) /* SPI operation */
+#define CPLD_SPI_CS_EEPROM	(1<<3)
+#define CPLD_SPI_SCLK		(1<<2)
+#define CPLD_SPI_TX_SHIFT	(1)
+#define CPLD_SPI_TX		(1<<CPLD_SPI_TX_SHIFT)
+#define CPLD_SPI_RX_SHIFT	(0)
+#define CPLD_SPI_RX		(1<<CPLD_SPI_RX_SHIFT)
+
+/* *** FIXME: these timing values are substantially larger than the
+   *** chip requires. We may implement an nsleep () function. */
+#define T_SKH	1		/* Clock time high (us) */
+#define T_SKL	1		/* Clock time low (us) */
+#define T_CS	1		/* Minimum chip select low time (us)  */
+#define T_CSS	1		/* Minimum chip select setup time (us)  */
+#define T_DIS	1		/* Data setup time (us) */
+
+	 /* EEPROM SPI bits */
+#define P_START		(1<<9)
+#define P_WRITE		(1<<7)
+#define P_READ		(2<<7)
+#define P_ERASE		(3<<7)
+#define P_EWDS		(0<<7)
+#define P_WRAL		(0<<7)
+#define P_ERAL		(0<<7)
+#define P_EWEN		(0<<7)
+#define P_A_EWDS	(0<<5)
+#define P_A_WRAL	(1<<5)
+#define P_A_ERAL	(2<<5)
+#define P_A_EWEN	(3<<5)
+
+struct ssp_configuration {
+	int device;
+	int mode;
+	int speed;
+	int frame_size_write;
+	int frame_size_read;
+};
+
+static struct ssp_configuration ssp_configuration;
+static spinlock_t ssp_lock;
+
+static void enable_cs (void)
+{
+	switch (ssp_configuration.device) {
+	case DEVICE_EEPROM:
+		CPLD_SPI |= CPLD_SPI_CS_EEPROM;
+		break;
+	}
+	udelay (T_CSS);
+}
+
+static void disable_cs (void)
+{
+	switch (ssp_configuration.device) {
+	case DEVICE_EEPROM:
+		CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
+		break;
+	}
+	udelay (T_CS);
+}
+
+static void pulse_clock (void)
+{
+	CPLD_SPI |=  CPLD_SPI_SCLK;
+	udelay (T_SKH);
+	CPLD_SPI &= ~CPLD_SPI_SCLK;
+	udelay (T_SKL);
+}
+
+
+/* execute_spi_command
+
+   sends an spi command to a device.  It first sends cwrite bits from
+   v.  If cread is greater than zero it will read cread bits
+   (discarding the leading 0 bit) and return them.  If cread is less
+   than zero it will check for completetion status and return 0 on
+   success or -1 on timeout.  If cread is zero it does nothing other
+   than sending the command.
+
+   On the LPD7A400, we can only read or write multiples of 8 bits on
+   the codec and the touch screen device.  Here, we round up.
+
+*/
+
+static int execute_spi_command (int v, int cwrite, int cread)
+{
+	unsigned long l = 0;
+
+#if defined (CONFIG_MACH_LPD7A400)
+	/* The codec and touch devices cannot be bit-banged.  Instead,
+	 * the CPLD provides an eight-bit shift register and a crude
+	 * interface.  */
+	if (   ssp_configuration.device == DEVICE_CODEC
+	    || ssp_configuration.device == DEVICE_TOUCH) {
+		int select = 0;
+
+		PRINTK ("spi(%d %d.%d) 0x%04x",
+			ssp_configuration.device, cwrite, cread,
+			v);
+#if defined (TALK)
+		if (ssp_configuration.device == DEVICE_CODEC)
+			PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
+#endif
+		PRINTK ("\n");
+
+		if (ssp_configuration.device == DEVICE_CODEC)
+			select = CPLD_SPIC_CS_CODEC;
+		if (ssp_configuration.device == DEVICE_TOUCH)
+			select = CPLD_SPIC_CS_TOUCH;
+		if (cwrite) {
+			for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
+				CPLD_SPID = (v >> (8*cwrite)) & 0xff;
+				CPLD_SPIC = select | CPLD_SPIC_LOAD;
+				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+					;
+				CPLD_SPIC = select;
+				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+					;
+			}
+			v = 0;
+		}
+		if (cread) {
+			mdelay (2);	/* *** FIXME: required by ads7843? */
+			v = 0;
+			for (cread = (cread + 7)/8; cread-- > 0;) {
+				CPLD_SPID = 0;
+				CPLD_SPIC = select | CPLD_SPIC_READ
+					| CPLD_SPIC_START;
+				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+					;
+				CPLD_SPIC = select | CPLD_SPIC_READ;
+				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+					;
+				v = (v << 8) | CPLD_SPID;
+			}
+		}
+		return v;
+	}
+#endif
+
+	PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
+		v & 0x1ff, (v >> 9) & 0x7f);
+
+	enable_cs ();
+
+	v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
+	while (cwrite--) {
+		CPLD_SPI
+			= (CPLD_SPI & ~CPLD_SPI_TX)
+			| ((v >> cwrite) & CPLD_SPI_TX);
+		udelay (T_DIS);
+		pulse_clock ();
+	}
+
+	if (cread < 0) {
+		int delay = 10;
+		disable_cs ();
+		udelay (1);
+		enable_cs ();
+
+		l = -1;
+		do {
+			if (CPLD_SPI & CPLD_SPI_RX) {
+				l = 0;
+				break;
+			}
+		} while (udelay (1), --delay);
+	}
+	else
+	/* We pulse the clock before the data to skip the leading zero. */
+		while (cread-- > 0) {
+			pulse_clock ();
+			l = (l<<1)
+				| (((CPLD_SPI & CPLD_SPI_RX)
+				    >> CPLD_SPI_RX_SHIFT) & 0x1);
+		}
+
+	disable_cs ();
+	return l;
+}
+
+static int ssp_init (void)
+{
+	spin_lock_init (&ssp_lock);
+	memset (&ssp_configuration, 0, sizeof (ssp_configuration));
+	return 0;
+}
+
+
+/* ssp_chip_select
+
+   drops the chip select line for the CPLD shift-register controlled
+   devices.  It doesn't enable chip
+
+*/
+
+static void ssp_chip_select (int enable)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+	int select;
+
+	if (ssp_configuration.device == DEVICE_CODEC)
+		select = CPLD_SPIC_CS_CODEC;
+	else if (ssp_configuration.device == DEVICE_TOUCH)
+		select = CPLD_SPIC_CS_TOUCH;
+	else
+		return;
+
+	if (enable)
+		CPLD_SPIC = select;
+	else
+		CPLD_SPIC = 0;
+#endif
+}
+
+static void ssp_acquire (void)
+{
+	spin_lock (&ssp_lock);
+}
+
+static void ssp_release (void)
+{
+	ssp_chip_select (0);	/* just in case */
+	spin_unlock (&ssp_lock);
+}
+
+static int ssp_configure (int device, int mode, int speed,
+			   int frame_size_write, int frame_size_read)
+{
+	ssp_configuration.device		= device;
+	ssp_configuration.mode			= mode;
+	ssp_configuration.speed			= speed;
+	ssp_configuration.frame_size_write	= frame_size_write;
+	ssp_configuration.frame_size_read	= frame_size_read;
+
+	return 0;
+}
+
+static int ssp_read (void)
+{
+	return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
+}
+
+static int ssp_write (u16 data)
+{
+	execute_spi_command (data, ssp_configuration.frame_size_write, 0);
+	return 0;
+}
+
+static int ssp_write_read (u16 data)
+{
+	return execute_spi_command (data, ssp_configuration.frame_size_write,
+				    ssp_configuration.frame_size_read);
+}
+
+struct ssp_driver lh7a40x_cpld_ssp_driver = {
+	.init		= ssp_init,
+	.acquire	= ssp_acquire,
+	.release	= ssp_release,
+	.configure	= ssp_configure,
+	.chip_select	= ssp_chip_select,
+	.read		= ssp_read,
+	.write		= ssp_write,
+	.write_read	= ssp_write_read,
+};
+
+
+MODULE_AUTHOR("Marc Singer");
+MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index be377e331f25..ef9af375fcc4 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -1,4 +1,4 @@
-/* 
+/*
  *  arch/arm/mach-lh7a40x/time.c
  *
  *  Copyright (C) 2004 Logic Product Development
@@ -57,7 +57,7 @@ static struct irqaction lh7a40x_timer_irq = {
 	.handler	= lh7a40x_timer_interrupt,
 };
 
-static void __init lh7a40x_timer_init(void)
+static void __init lh7a40x_timer_init (void)
 {
 				/* Stop/disable all timers */
 	TIMER_CONTROL1 = 0;
diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig
new file mode 100644
index 000000000000..3d90ef19be2b
--- /dev/null
+++ b/arch/arm/mach-netx/Kconfig
@@ -0,0 +1,24 @@
+menu "NetX Implementations"
+	depends on ARCH_NETX
+
+config MACH_NXDKN
+	bool "Enable Hilscher nxdkn Eval Board support"
+	depends on ARCH_NETX
+	help
+	  Board support for the Hilscher NetX Eval Board
+
+config MACH_NXDB500
+	bool "Enable Hilscher nxdb500 Eval Board support"
+	depends on ARCH_NETX
+	select ARM_AMBA
+	help
+	  Board support for the Hilscher nxdb500 Eval Board
+
+config MACH_NXEB500HMI
+	bool "Enable Hilscher nxeb500hmi Eval Board support"
+	depends on ARCH_NETX
+	select ARM_AMBA
+	help
+	  Board support for the Hilscher nxeb500hmi Eval Board
+
+endmenu
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile
new file mode 100644
index 000000000000..18785ff37657
--- /dev/null
+++ b/arch/arm/mach-netx/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+# Object file lists.
+
+obj-y			+= time.o generic.o pfifo.o xc.o
+
+# Specific board support
+obj-$(CONFIG_MACH_NXDKN) += nxdkn.o
+obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o
+obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
new file mode 100644
index 000000000000..b81cf6aff0ac
--- /dev/null
+++ b/arch/arm/mach-netx/Makefile.boot
@@ -0,0 +1,2 @@
+    zreladdr-y			:= 0x80008000
+
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
new file mode 100644
index 000000000000..ef0ab6115c0b
--- /dev/null
+++ b/arch/arm/mach-netx/fb.c
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-netx/fb.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/device.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/arch/netx-regs.h>
+#include <asm/hardware.h>
+
+struct clk {};
+
+static struct clk fb_clk;
+
+static struct clcd_panel *netx_panel;
+
+void netx_clcd_enable(struct clcd_fb *fb)
+{
+}
+
+int netx_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel = netx_panel;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= 1024*1024;
+
+	return 0;
+}
+
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+				     fb->fb.screen_base,
+				     fb->fb.fix.smem_start,
+				     fb->fb.fix.smem_len);
+}
+
+void netx_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	return &fb_clk;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+static struct amba_device fb_device = {
+	.dev		= {
+		.bus_id	= "fb",
+		.coherent_dma_mask = ~0,
+	},
+	.res		= {
+		.start	= 0x00104000,
+		.end	= 0x00104fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= { NETX_IRQ_LCD, NO_IRQ },
+	.periphid	= 0x10112400,
+};
+
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel)
+{
+	netx_panel = panel;
+	fb_device.dev.platform_data = board;
+	return amba_device_register(&fb_device, &iomem_resource);
+}
diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h
new file mode 100644
index 000000000000..4919cf33a5f3
--- /dev/null
+++ b/arch/arm/mach-netx/fb.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/fb.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+void netx_clcd_enable(struct clcd_fb *fb);
+int netx_clcd_setup(struct clcd_fb *fb);
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
+void netx_clcd_remove(struct clcd_fb *fb);
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
new file mode 100644
index 000000000000..af0b13534cfd
--- /dev/null
+++ b/arch/arm/mach-netx/generic.c
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-netx/generic.c
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/vic.h>
+#include <asm/io.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/mach/irq.h>
+
+static struct map_desc netx_io_desc[] __initdata = {
+	{
+		.virtual        = NETX_IO_VIRT,
+		.pfn            = __phys_to_pfn(NETX_IO_PHYS),
+		.length         = NETX_IO_SIZE,
+		.type           = MT_DEVICE
+	}
+};
+
+void __init netx_map_io(void)
+{
+	iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
+}
+
+static struct resource netx_rtc_resources[] = {
+	[0] = {
+		.start	= 0x00101200,
+		.end	= 0x00101220,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device netx_rtc_device = {
+	.name		= "netx-rtc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_rtc_resources),
+	.resource	= netx_rtc_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_rtc_device,
+};
+
+#if 0
+#define DEBUG_IRQ(fmt...)	printk(fmt)
+#else
+#define DEBUG_IRQ(fmt...)	while (0) {}
+#endif
+
+static void
+netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
+	unsigned int stat;
+
+	stat = ((readl(NETX_DPMAS_INT_EN) &
+		readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
+
+	desc = irq_desc + NETX_IRQ_HIF_CHAINED(0);
+
+	while (stat) {
+		if (stat & 1) {
+			DEBUG_IRQ("handling irq %d\n", irq);
+			desc_handle_irq(irq, desc, regs);
+		}
+		irq++;
+		desc++;
+		stat >>= 1;
+	}
+}
+
+static int
+netx_hif_irq_type(unsigned int _irq, unsigned int type)
+{
+	unsigned int val, irq;
+
+	val = readl(NETX_DPMAS_IF_CONF1);
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+
+	if (type & __IRQT_RISEDGE) {
+		DEBUG_IRQ("rising edges\n");
+		val |= (1 << 26) << irq;
+	}
+	if (type & __IRQT_FALEDGE) {
+		DEBUG_IRQ("falling edges\n");
+		val &= ~((1 << 26) << irq);
+	}
+	if (type & __IRQT_LOWLVL) {
+		DEBUG_IRQ("low level\n");
+		val &= ~((1 << 26) << irq);
+	}
+	if (type & __IRQT_HIGHLVL) {
+		DEBUG_IRQ("high level\n");
+		val |= (1 << 26) << irq;
+	}
+
+	writel(val, NETX_DPMAS_IF_CONF1);
+
+	return 0;
+}
+
+static void
+netx_hif_ack_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
+
+	val = readl(NETX_DPMAS_INT_EN);
+	val &= ~((1 << 24) << irq);
+	writel(val, NETX_DPMAS_INT_EN);
+
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_mask_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	val = readl(NETX_DPMAS_INT_EN);
+	val &= ~((1 << 24) << irq);
+	writel(val, NETX_DPMAS_INT_EN);
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_unmask_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	val = readl(NETX_DPMAS_INT_EN);
+	val |= (1 << 24) << irq;
+	writel(val, NETX_DPMAS_INT_EN);
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static struct irqchip netx_hif_chip = {
+	.ack = netx_hif_ack_irq,
+	.mask = netx_hif_mask_irq,
+	.unmask = netx_hif_unmask_irq,
+	.set_type = netx_hif_irq_type,
+};
+
+void __init netx_init_irq(void)
+{
+	int irq;
+
+	vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+
+	for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
+		set_irq_chip(irq, &netx_hif_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
+	set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
+}
+
+static int __init netx_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(netx_init);
+
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
new file mode 100644
index 000000000000..ede2d35341c3
--- /dev/null
+++ b/arch/arm/mach-netx/generic.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/generic.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+extern void __init netx_map_io(void);
+extern void __init netx_init_irq(void);
+
+struct sys_timer;
+extern struct sys_timer netx_timer;
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
new file mode 100644
index 000000000000..e4a133d62846
--- /dev/null
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-netx/nxdb500.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+	.mode		= {
+		.name		= "QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 187617,
+		.left_margin	= 6,
+		.right_margin	= 26,
+		.upper_margin	= 0,
+		.lower_margin	= 6,
+		.hsync_len	= 6,
+		.vsync_len	= 1,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		=  16,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	var->green.length = 5;
+	var->green.msb_right = 0;
+
+	return clcdfb_check(fb, var);
+}
+
+static int nxdb500_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned int val;
+
+	fb->fb.var.green.length = 5;
+	fb->fb.var.green.msb_right = 0;
+
+	/* enable asic control */
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(3, NETX_SYSTEM_IOC_CR);
+
+	val = readl(NETX_PIO_OUTPIO);
+	writel(val | 1, NETX_PIO_OUTPIO);
+
+	val = readl(NETX_PIO_OEPIO);
+	writel(val | 1, NETX_PIO_OEPIO);
+	return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "netX",
+	.check		= nxdb500_check,
+	.decode		= clcdfb_decode,
+	.enable		= netx_clcd_enable,
+	.setup		= nxdb500_clcd_setup,
+	.mmap		= netx_clcd_mmap,
+	.remove		= netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct resource netx_uart1_resources[] = {
+	[0] = {
+		.start	= 0x00100A40,
+		.end	= 0x00100A7F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART1),
+		.end	= (NETX_IRQ_UART1),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart1_device = {
+	.name		= "netx-uart",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(netx_uart1_resources),
+	.resource	= netx_uart1_resources,
+};
+
+static struct resource netx_uart2_resources[] = {
+	[0] = {
+		.start	= 0x00100A80,
+		.end	= 0x00100ABF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART2),
+		.end	= (NETX_IRQ_UART2),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart2_device = {
+	.name		= "netx-uart",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(netx_uart2_resources),
+	.resource	= netx_uart2_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_eth0_device,
+	&netx_eth1_device,
+	&netx_uart0_device,
+	&netx_uart1_device,
+	&netx_uart2_device,
+};
+
+static void __init nxdb500_init(void)
+{
+	netx_fb_init(&clcd_data, &qvga);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDB500, "Hilscher nxdb500")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxdb500_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
new file mode 100644
index 000000000000..7e26c42d1ac7
--- /dev/null
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -0,0 +1,103 @@
+/*
+ * arch/arm/mach-netx/nxdkn.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device nxdkn_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device nxdkn_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&nxdkn_eth0_device,
+	&nxdkn_eth1_device,
+	&netx_uart0_device,
+};
+
+static void __init nxdkn_init(void)
+{
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDKN, "Hilscher nxdkn")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxdkn_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
new file mode 100644
index 000000000000..53e10a9849f9
--- /dev/null
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -0,0 +1,187 @@
+/*
+ * arch/arm/mach-netx/nxeb500hmi.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+	.mode		= {
+		.name		= "QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 187617,
+		.left_margin	= 6,
+		.right_margin	= 26,
+		.upper_margin	= 0,
+		.lower_margin	= 6,
+		.hsync_len	= 6,
+		.vsync_len	= 1,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		=  16,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	var->green.length = 5;
+	var->green.msb_right = 0;
+
+	return clcdfb_check(fb, var);
+}
+
+static int nxeb500hmi_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned int val;
+
+	fb->fb.var.green.length = 5;
+	fb->fb.var.green.msb_right = 0;
+
+	/* enable asic control */
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(3, NETX_SYSTEM_IOC_CR);
+
+	/* GPIO 14 is used for display enable on newer boards */
+	writel(9, NETX_GPIO_CFG(14));
+
+	val = readl(NETX_PIO_OUTPIO);
+	writel(val | 1, NETX_PIO_OUTPIO);
+
+	val = readl(NETX_PIO_OEPIO);
+	writel(val | 1, NETX_PIO_OEPIO);
+	return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "netX",
+	.check		= nxeb500hmi_check,
+	.decode		= clcdfb_decode,
+	.enable		= netx_clcd_enable,
+	.setup		= nxeb500hmi_clcd_setup,
+	.mmap		= netx_clcd_mmap,
+	.remove		= netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_cf_resources[] = {
+	[0] = {
+		.start	= 0x20000000,
+		.end	= 0x25ffffff,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	},
+};
+
+static struct platform_device netx_cf_device = {
+	.name		= "netx-cf",
+	.id		= 0,
+	.resource	= netx_cf_resources,
+	.num_resources	= ARRAY_SIZE(netx_cf_resources),
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_eth0_device,
+	&netx_eth1_device,
+	&netx_cf_device,
+	&netx_uart0_device,
+};
+
+static void __init nxeb500hmi_init(void)
+{
+	netx_fb_init(&clcd_data, &qvga);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxeb500hmi_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c
new file mode 100644
index 000000000000..44dea61a9de4
--- /dev/null
+++ b/arch/arm/mach-netx/pfifo.c
@@ -0,0 +1,68 @@
+/*
+ * arch/arm/mach-netx/pfifo.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/pfifo.h>
+
+static DEFINE_MUTEX(pfifo_lock);
+
+static unsigned int pfifo_used = 0;
+
+int pfifo_request(unsigned int pfifo_mask)
+{
+	int err = 0;
+	unsigned int val;
+
+	mutex_lock(&pfifo_lock);
+
+	if (pfifo_mask & pfifo_used) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	pfifo_used |= pfifo_mask;
+
+	val = readl(NETX_PFIFO_RESET);
+	writel(val | pfifo_mask, NETX_PFIFO_RESET);
+	writel(val, NETX_PFIFO_RESET);
+
+out:
+	mutex_unlock(&pfifo_lock);
+	return err;
+}
+
+void pfifo_free(unsigned int pfifo_mask)
+{
+	mutex_lock(&pfifo_lock);
+	pfifo_used &= ~pfifo_mask;
+	mutex_unlock(&pfifo_lock);
+}
+
+EXPORT_SYMBOL(pfifo_push);
+EXPORT_SYMBOL(pfifo_pop);
+EXPORT_SYMBOL(pfifo_fill_level);
+EXPORT_SYMBOL(pfifo_empty);
+EXPORT_SYMBOL(pfifo_request);
+EXPORT_SYMBOL(pfifo_free);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
new file mode 100644
index 000000000000..edfbdf40c600
--- /dev/null
+++ b/arch/arm/mach-netx/time.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-netx/time.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+#include <asm/arch/netx-regs.h>
+
+/*
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long netx_gettimeoffset(void)
+{
+	return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100;
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	timer_tick(regs);
+	write_sequnlock(&xtime_lock);
+
+	/* acknowledge interrupt */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+	return IRQ_HANDLED;
+}
+
+
+static struct irqaction netx_timer_irq = {
+	.name           = "NetX Timer Tick",
+	.flags          = SA_INTERRUPT | SA_TIMER,
+	.handler        = netx_timer_interrupt,
+};
+
+/*
+ * Set up timer interrupt
+ */
+static void __init netx_timer_init(void)
+{
+	/* disable timer initially */
+	writel(0, NETX_GPIO_COUNTER_CTRL(0));
+
+	/* Reset the timer value to zero */
+	writel(0, NETX_GPIO_COUNTER_CURRENT(0));
+
+	writel(LATCH, NETX_GPIO_COUNTER_MAX(0));
+
+	/* acknowledge interrupt */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+	/* Enable the interrupt in the specific timer register and start timer */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE);
+	writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN,
+		NETX_GPIO_COUNTER_CTRL(0));
+
+	setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
+}
+
+struct sys_timer netx_timer = {
+	.init           = netx_timer_init,
+	.offset         = netx_gettimeoffset,
+};
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
new file mode 100644
index 000000000000..172a058ddd66
--- /dev/null
+++ b/arch/arm/mach-netx/xc.c
@@ -0,0 +1,255 @@
+/*
+ * arch/arm/mach-netx/xc.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <linux/init.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+
+#include <asm/arch/xc.h>
+
+static DEFINE_MUTEX(xc_lock);
+
+static int xc_in_use = 0;
+
+struct fw_desc {
+	unsigned int ofs;
+	unsigned int size;
+	unsigned int patch_ofs;
+	unsigned int patch_entries;
+};
+
+struct fw_header {
+	unsigned int magic;
+	unsigned int type;
+	unsigned int version;
+	unsigned int reserved[5];
+	struct fw_desc fw_desc[3];
+} __attribute__ ((packed));
+
+int xc_stop(struct xc *x)
+{
+	writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+	writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+	writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+	return 0;
+}
+
+int xc_start(struct xc *x)
+{
+	writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+	writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+	writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+	return 0;
+}
+
+int xc_running(struct xc *x)
+{
+	return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC)
+	    || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC)
+	    || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ?
+		0 : 1;
+}
+
+int xc_reset(struct xc *x)
+{
+	writel(0, x->xpec_base + NETX_XPEC_PC_OFS);
+	return 0;
+}
+
+static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size)
+{
+	if (adr >= NETX_PA_XMAC(x->no) &&
+	    adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE)
+		return 0;
+
+	if (adr >= NETX_PA_XPEC(x->no) &&
+	    adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE)
+		return 0;
+
+	dev_err(x->dev, "Illegal pointer in firmware found. aborting\n");
+
+	return -1;
+}
+
+static int xc_patch(struct xc *x, void *patch, int count)
+{
+	unsigned int val, adr;
+	unsigned int *data = patch;
+
+	int i;
+	for (i = 0; i < count; i++) {
+		adr = *data++;
+		val = *data++;
+		if (xc_check_ptr(x, adr, 4) < 0)
+			return -EINVAL;
+
+		writel(val, (void __iomem *)io_p2v(adr));
+	}
+	return 0;
+}
+
+int xc_request_firmware(struct xc *x)
+{
+	int ret;
+	char name[16];
+	const struct firmware *fw;
+	struct fw_header *head;
+	unsigned int size;
+	int i;
+	void *src;
+	unsigned long dst;
+
+	sprintf(name, "xc%d.bin", x->no);
+
+	ret = request_firmware(&fw, name, x->dev);
+
+	if (ret < 0) {
+		dev_err(x->dev, "request_firmware failed\n");
+		return ret;
+	}
+
+	head = (struct fw_header *)fw->data;
+	if (head->magic != 0x4e657458) {
+		if (head->magic == 0x5874654e) {
+			dev_err(x->dev,
+			    "firmware magic is 'XteN'. Endianess problems?\n");
+			ret = -ENODEV;
+			goto exit_release_firmware;
+		}
+		dev_err(x->dev, "unrecognized firmware magic 0x%08x\n",
+			head->magic);
+		ret = -ENODEV;
+		goto exit_release_firmware;
+	}
+
+	x->type = head->type;
+	x->version = head->version;
+
+	ret = -EINVAL;
+
+	for (i = 0; i < 3; i++) {
+		src = fw->data + head->fw_desc[i].ofs;
+		dst = *(unsigned int *)src;
+		src += sizeof (unsigned int);
+		size = head->fw_desc[i].size - sizeof (unsigned int);
+
+		if (xc_check_ptr(x, dst, size))
+			goto exit_release_firmware;
+
+		memcpy((void *)io_p2v(dst), src, size);
+
+		src = fw->data + head->fw_desc[i].patch_ofs;
+		size = head->fw_desc[i].patch_entries;
+		ret = xc_patch(x, src, size);
+		if (ret < 0)
+			goto exit_release_firmware;
+	}
+
+	ret = 0;
+
+      exit_release_firmware:
+	release_firmware(fw);
+
+	return ret;
+}
+
+struct xc *request_xc(int xcno, struct device *dev)
+{
+	struct xc *x = NULL;
+
+	mutex_lock(&xc_lock);
+
+	if (xcno > 3)
+		goto exit;
+	if (xc_in_use & (1 << xcno))
+		goto exit;
+
+	x = kmalloc(sizeof (struct xc), GFP_KERNEL);
+	if (!x)
+		goto exit;
+
+	if (!request_mem_region
+	    (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name))
+		goto exit_free;
+
+	if (!request_mem_region
+	    (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name))
+		goto exit_release_1;
+
+	if (!request_mem_region
+	    (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name))
+		goto exit_release_2;
+
+	x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
+	x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno));
+	x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+	if (!x->sram_base)
+		goto exit_release_3;
+
+	x->irq = NETX_IRQ_XPEC(xcno);
+
+	x->no = xcno;
+	x->dev = dev;
+
+	xc_in_use |= (1 << xcno);
+
+	goto exit;
+
+      exit_release_3:
+	release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+      exit_release_2:
+	release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+      exit_release_1:
+	release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+      exit_free:
+	kfree(x);
+	x = NULL;
+      exit:
+	mutex_unlock(&xc_lock);
+	return x;
+}
+
+void free_xc(struct xc *x)
+{
+	int xcno = x->no;
+
+	mutex_lock(&xc_lock);
+
+	iounmap(x->sram_base);
+	release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+	release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+	release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+	xc_in_use &= ~(1 << x->no);
+	kfree(x);
+
+	mutex_unlock(&xc_lock);
+}
+
+EXPORT_SYMBOL(free_xc);
+EXPORT_SYMBOL(request_xc);
+EXPORT_SYMBOL(xc_request_firmware);
+EXPORT_SYMBOL(xc_reset);
+EXPORT_SYMBOL(xc_running);
+EXPORT_SYMBOL(xc_start);
+EXPORT_SYMBOL(xc_stop);
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 6178f046f128..73df32aac4c4 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -84,6 +84,15 @@ static struct omap_board_config_kernel ams_delta_config[] = {
 	{ OMAP_TAG_UART,	&ams_delta_uart_config },
 };
 
+static struct platform_device ams_delta_led_device = {
+	.name	= "ams-delta-led",
+	.id	= -1
+};
+
+static struct platform_device *ams_delta_devices[] __initdata = {
+	&ams_delta_led_device,
+};
+
 static void __init ams_delta_init(void)
 {
 	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
@@ -94,6 +103,8 @@ static void __init ams_delta_init(void)
 
 	/* Clear latch2 (NAND, LCD, modem enable) */
 	ams_delta_latch2_write(~0, 0);
+
+	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 }
 
 static void __init ams_delta_map_io(void)
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
new file mode 100644
index 000000000000..b457ca0a431a
--- /dev/null
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y			:= core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
new file mode 100644
index 000000000000..44c7117e20dd
--- /dev/null
+++ b/arch/arm/mach-pnx4008/Makefile.boot
@@ -0,0 +1,4 @@
+   zreladdr-y		:= 0x80008000
+params_phys-y		:= 0x80000100
+initrd_phys-y		:= 0x80800000
+
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
new file mode 100644
index 000000000000..f582ed2ec43c
--- /dev/null
+++ b/arch/arm/mach-pnx4008/clock.c
@@ -0,0 +1,983 @@
+/*
+ * arch/arm/mach-pnx4008/clock.c
+ *
+ * Clock control driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ * Generic clock management functions are partially based on:
+ *  linux/arch/arm/mach-omap/clock.c
+ *
+ * 2005-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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include "clock.h"
+
+/*forward declaration*/
+static struct clk per_ck;
+static struct clk hclk_ck;
+static struct clk ck_1MHz;
+static struct clk ck_13MHz;
+static struct clk ck_pll1;
+static int local_set_rate(struct clk *clk, u32 rate);
+
+static inline void clock_lock(void)
+{
+	local_irq_disable();
+}
+
+static inline void clock_unlock(void)
+{
+	local_irq_enable();
+}
+
+static void propagate_rate(struct clk *clk)
+{
+	struct clk *tmp_clk;
+
+	tmp_clk = clk;
+	while (tmp_clk->propagate_next) {
+		tmp_clk = tmp_clk->propagate_next;
+		local_set_rate(tmp_clk, tmp_clk->user_rate);
+	}
+}
+
+static inline void clk_reg_disable(struct clk *clk)
+{
+	if (clk->enable_reg)
+		__raw_writel(__raw_readl(clk->enable_reg) &
+			     ~(1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_enable(struct clk *clk)
+{
+	if (clk->enable_reg)
+		__raw_writel(__raw_readl(clk->enable_reg) |
+			     (1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_disable1(struct clk *clk)
+{
+	if (clk->enable_reg1)
+		__raw_writel(__raw_readl(clk->enable_reg1) &
+			     ~(1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static inline void clk_reg_enable1(struct clk *clk)
+{
+	if (clk->enable_reg1)
+		__raw_writel(__raw_readl(clk->enable_reg1) |
+			     (1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static int clk_wait_for_pll_lock(struct clk *clk)
+{
+	int i;
+	i = 0;
+	while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ;	/*wait for PLL to lock */
+
+	if (!(__raw_readl(clk->scale_reg) & 1)) {
+		printk(KERN_ERR
+		       "%s ERROR: failed to lock, scale reg data: %x\n",
+		       clk->name, __raw_readl(clk->scale_reg));
+		return -1;
+	}
+	return 0;
+}
+
+static int switch_to_dirty_13mhz(struct clk *clk)
+{
+	int i;
+	int ret;
+	u32 tmp_reg;
+
+	ret = 0;
+
+	if (!clk->rate)
+		clk_reg_enable1(clk);
+
+	tmp_reg = __raw_readl(clk->parent_switch_reg);
+	/*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
+	if (!(tmp_reg & 1)) {
+		tmp_reg |= (1 << 1);	/* Trigger switch to 13'MHz (dirty) clock */
+		__raw_writel(tmp_reg, clk->parent_switch_reg);
+		i = 0;
+		while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13'MHz selection status */
+
+		if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
+			printk(KERN_ERR
+			       "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
+			       clk->name, __raw_readl(clk->parent_switch_reg));
+			ret = -1;
+		}
+	}
+
+	if (!clk->rate)
+		clk_reg_disable1(clk);
+
+	return ret;
+}
+
+static int switch_to_clean_13mhz(struct clk *clk)
+{
+	int i;
+	int ret;
+	u32 tmp_reg;
+
+	ret = 0;
+
+	if (!clk->rate)
+		clk_reg_enable1(clk);
+
+	tmp_reg = __raw_readl(clk->parent_switch_reg);
+	/*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
+	if (tmp_reg & 1) {
+		tmp_reg &= ~(1 << 1);	/* Trigger switch to 13MHz (clean) clock */
+		__raw_writel(tmp_reg, clk->parent_switch_reg);
+		i = 0;
+		while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13MHz selection status */
+
+		if (__raw_readl(clk->parent_switch_reg) & 1) {
+			printk(KERN_ERR
+			       "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
+			       clk->name, __raw_readl(clk->parent_switch_reg));
+			ret = -1;
+		}
+	}
+
+	if (!clk->rate)
+		clk_reg_disable1(clk);
+
+	return ret;
+}
+
+static int set_13MHz_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -EINVAL;
+
+	if (parent == &ck_13MHz)
+		ret = switch_to_clean_13mhz(clk);
+	else if (parent == &ck_pll1)
+		ret = switch_to_dirty_13mhz(clk);
+
+	return ret;
+}
+
+#define PLL160_MIN_FCCO 156000
+#define PLL160_MAX_FCCO 320000
+
+/*
+ * Calculate pll160 settings.
+ * Possible input: up to 320MHz with step of clk->parent->rate.
+ * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
+ * Ignored paths: "feedback" (bit 13 set), "div-by-N".
+ * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
+ * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
+ * Please refer to PNX4008 IC manual for details.
+ */
+
+static int pll160_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp_reg, tmp_m, tmp_2p, i;
+	u32 parent_rate;
+	int ret = -EINVAL;
+
+	parent_rate = clk->parent->rate;
+
+	if (!parent_rate)
+		goto out;
+
+	/* set direct run for ARM or disable output for others  */
+	clk_reg_disable(clk);
+
+	/* disable source input as well (ignored for ARM) */
+	clk_reg_disable1(clk);
+
+	tmp_reg = __raw_readl(clk->scale_reg);
+	tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
+	__raw_writel(tmp_reg, clk->scale_reg);
+
+	rate -= rate % parent_rate;	/*round down the input */
+
+	if (rate > PLL160_MAX_FCCO)
+		rate = PLL160_MAX_FCCO;
+
+	if (!rate) {
+		clk->rate = 0;
+		ret = 0;
+		goto out;
+	}
+
+	clk_reg_enable1(clk);
+	tmp_reg = __raw_readl(clk->scale_reg);
+
+	if (rate == parent_rate) {
+		/*enter direct bypass mode */
+		tmp_reg |= ((1 << 14) | (1 << 15));
+		__raw_writel(tmp_reg, clk->scale_reg);
+		clk->rate = parent_rate;
+		clk_reg_enable(clk);
+		ret = 0;
+		goto out;
+	}
+
+	i = 0;
+	for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
+		if (rate * tmp_2p >= PLL160_MIN_FCCO)
+			break;
+		i++;
+	}
+
+	if (tmp_2p > 1)
+		tmp_reg |= ((i - 1) << 11);
+	else
+		tmp_reg |= (1 << 14);	/*direct mode, no divide */
+
+	tmp_m = rate * tmp_2p;
+	tmp_m /= parent_rate;
+
+	tmp_reg |= (tmp_m - 1) << 1;	/*calculate M */
+	tmp_reg |= (1 << 16);	/*power up PLL */
+	__raw_writel(tmp_reg, clk->scale_reg);
+
+	if (clk_wait_for_pll_lock(clk) < 0) {
+		clk_reg_disable(clk);
+		clk_reg_disable1(clk);
+
+		tmp_reg = __raw_readl(clk->scale_reg);
+		tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
+		__raw_writel(tmp_reg, clk->scale_reg);
+		clk->rate = 0;
+		ret = -EFAULT;
+		goto out;
+	}
+
+	clk->rate = (tmp_m * parent_rate) / tmp_2p;
+
+	if (clk->flags & RATE_PROPAGATES)
+		propagate_rate(clk);
+
+	clk_reg_enable(clk);
+	ret = 0;
+
+out:
+	return ret;
+}
+
+/*configure PER_CLK*/
+static int per_clk_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(clk->scale_reg);
+	tmp &= ~(0x1f << 2);
+	tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
+	__raw_writel(tmp, clk->scale_reg);
+	clk->rate = rate;
+	return 0;
+}
+
+/*configure HCLK*/
+static int hclk_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp;
+	tmp = __raw_readl(clk->scale_reg);
+	tmp = tmp & ~0x3;
+	switch (rate) {
+	case 1:
+		break;
+	case 2:
+		tmp |= 1;
+		break;
+	case 4:
+		tmp |= 2;
+		break;
+	}
+
+	__raw_writel(tmp, clk->scale_reg);
+	clk->rate = rate;
+	return 0;
+}
+
+static u32 hclk_round_rate(struct clk *clk, u32 rate)
+{
+	switch (rate) {
+	case 1:
+	case 4:
+		return rate;
+	}
+	return 2;
+}
+
+static u32 per_clk_round_rate(struct clk *clk, u32 rate)
+{
+	return CLK_RATE_13MHZ;
+}
+
+static int on_off_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_enable(clk);
+		clk->rate = 1;
+	} else {
+		clk_reg_disable(clk);
+		clk->rate = 0;
+	}
+	return 0;
+}
+
+static int on_off_inv_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		clk->rate = 1;
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+	}
+	return 0;
+}
+
+static u32 on_off_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? 1 : 0);
+}
+
+static u32 pll4_round_rate(struct clk *clk, u32 rate)
+{
+	if (rate > CLK_RATE_208MHZ)
+		rate = CLK_RATE_208MHZ;
+	if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
+		rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
+	return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
+}
+
+static u32 pll3_round_rate(struct clk *clk, u32 rate)
+{
+	if (rate > CLK_RATE_208MHZ)
+		rate = CLK_RATE_208MHZ;
+	return (rate - rate % CLK_RATE_13MHZ);
+}
+
+static u32 pll5_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? CLK_RATE_48MHZ : 0);
+}
+
+static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? CLK_RATE_13MHZ : 0);
+}
+
+static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		udelay(500);
+		clk->rate = CLK_RATE_13MHZ;
+		ck_1MHz.rate = CLK_RATE_1MHZ;
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+		ck_1MHz.rate = 0;
+	}
+	return 0;
+}
+
+static int pll1_set_rate(struct clk *clk, u32 rate)
+{
+#if 0 /* doesn't work on some boards, probably a HW BUG */
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		if (!clk_wait_for_pll_lock(clk)) {
+			clk->rate = CLK_RATE_13MHZ;
+		} else {
+			clk_reg_enable(clk);
+			clk->rate = 0;
+		}
+
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+	}
+#endif
+	return 0;
+}
+
+/* Clock sources */
+
+static struct clk osc_13MHz = {
+	.name = "osc_13MHz",
+	.flags = FIXED_RATE,
+	.rate = CLK_RATE_13MHZ,
+};
+
+static struct clk ck_13MHz = {
+	.name = "ck_13MHz",
+	.parent = &osc_13MHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &ck_13MHz_round_rate,
+	.set_rate = &ck_13MHz_set_rate,
+	.enable_reg = OSC13CTRL_REG,
+	.enable_shift = 0,
+	.rate = CLK_RATE_13MHZ,
+};
+
+static struct clk osc_32KHz = {
+	.name = "osc_32KHz",
+	.flags = FIXED_RATE,
+	.rate = CLK_RATE_32KHZ,
+};
+
+/*attached to PLL5*/
+static struct clk ck_1MHz = {
+	.name = "ck_1MHz",
+	.flags = FIXED_RATE | PARENT_SET_RATE,
+	.parent = &ck_13MHz,
+};
+
+/* PLL1 (397) - provides 13' MHz clock */
+static struct clk ck_pll1 = {
+	.name = "ck_pll1",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &ck_13MHz_round_rate,
+	.set_rate = &pll1_set_rate,
+	.enable_reg = PLLCTRL_REG,
+	.enable_shift = 1,
+	.scale_reg = PLLCTRL_REG,
+	.rate = CLK_RATE_13MHZ,
+};
+
+/* CPU/Bus PLL */
+static struct clk ck_pll4 = {
+	.name = "ck_pll4",
+	.parent = &ck_pll1,
+	.flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
+	.propagate_next = &per_ck,
+	.round_rate = &pll4_round_rate,
+	.set_rate = &pll160_set_rate,
+	.rate = CLK_RATE_208MHZ,
+	.scale_reg = HCLKPLLCTRL_REG,
+	.enable_reg = PWRCTRL_REG,
+	.enable_shift = 2,
+	.parent_switch_reg = SYSCLKCTRL_REG,
+	.set_parent = &set_13MHz_parent,
+};
+
+/* USB PLL */
+static struct clk ck_pll5 = {
+	.name = "ck_pll5",
+	.parent = &ck_1MHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &pll5_round_rate,
+	.set_rate = &pll160_set_rate,
+	.scale_reg = USBCTRL_REG,
+	.enable_reg = USBCTRL_REG,
+	.enable_shift = 18,
+	.enable_reg1 = USBCTRL_REG,
+	.enable_shift1 = 17,
+};
+
+/* XPERTTeak DSP PLL */
+static struct clk ck_pll3 = {
+	.name = "ck_pll3",
+	.parent = &ck_pll1,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &pll3_round_rate,
+	.set_rate = &pll160_set_rate,
+	.scale_reg = DSPPLLCTRL_REG,
+	.enable_reg = DSPCLKCTRL_REG,
+	.enable_shift = 3,
+	.enable_reg1 = DSPCLKCTRL_REG,
+	.enable_shift1 = 2,
+	.parent_switch_reg = DSPCLKCTRL_REG,
+	.set_parent = &set_13MHz_parent,
+};
+
+static struct clk hclk_ck = {
+	.name = "hclk_ck",
+	.parent = &ck_pll4,
+	.flags = PARENT_SET_RATE,
+	.set_rate = &hclk_set_rate,
+	.round_rate = &hclk_round_rate,
+	.scale_reg = HCLKDIVCTRL_REG,
+	.rate = 2,
+	.user_rate = 2,
+};
+
+static struct clk per_ck = {
+	.name = "per_ck",
+	.parent = &ck_pll4,
+	.flags = FIXED_RATE,
+	.propagate_next = &hclk_ck,
+	.set_rate = &per_clk_set_rate,
+	.round_rate = &per_clk_round_rate,
+	.scale_reg = HCLKDIVCTRL_REG,
+	.rate = CLK_RATE_13MHZ,
+	.user_rate = CLK_RATE_13MHZ,
+};
+
+static struct clk m2hclk_ck = {
+	.name = "m2hclk_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_inv_set_rate,
+	.rate = 1,
+	.enable_shift = 6,
+	.enable_reg = PWRCTRL_REG,
+};
+
+static struct clk vfp9_ck = {
+	.name = "vfp9_ck",
+	.parent = &ck_pll4,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 4,
+	.enable_reg = VFP9CLKCTRL_REG,
+};
+
+static struct clk keyscan_ck = {
+	.name = "keyscan_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = KEYCLKCTRL_REG,
+};
+
+static struct clk touch_ck = {
+	.name = "touch_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = TSCLKCTRL_REG,
+};
+
+static struct clk pwm1_ck = {
+	.name = "pwm1_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk pwm2_ck = {
+	.name = "pwm2_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 2,
+	.enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk jpeg_ck = {
+	.name = "jpeg_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = JPEGCLKCTRL_REG,
+};
+
+static struct clk ms_ck = {
+	.name = "ms_ck",
+	.parent = &ck_pll4,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 5,
+	.enable_reg = MSCTRL_REG,
+};
+
+static struct clk dum_ck = {
+	.name = "dum_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = DUMCLKCTRL_REG,
+};
+
+static struct clk flash_ck = {
+	.name = "flash_ck",
+	.parent = &hclk_ck,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,	/* Only MLC clock supported */
+	.enable_reg = FLASHCLKCTRL_REG,
+};
+
+static struct clk i2c0_ck = {
+	.name = "i2c0_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c1_ck = {
+	.name = "i2c1_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,
+	.enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c2_ck = {
+	.name = "i2c2_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 2,
+	.enable_reg = USB_OTG_CLKCTRL_REG,
+};
+
+static struct clk spi0_ck = {
+	.name = "spi0_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = SPICTRL_REG,
+};
+
+static struct clk spi1_ck = {
+	.name = "spi1_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 4,
+	.enable_reg = SPICTRL_REG,
+};
+
+static struct clk dma_ck = {
+	.name = "dma_ck",
+	.parent = &hclk_ck,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = DMACLKCTRL_REG,
+};
+
+static struct clk uart3_ck = {
+	.name = "uart3_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 0,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart4_ck = {
+	.name = "uart4_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart5_ck = {
+	.name = "uart5_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 2,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart6_ck = {
+	.name = "uart6_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 3,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+/* These clocks are visible outside this module
+ * and can be initialized
+ */
+static struct clk *onchip_clks[] = {
+	&ck_13MHz,
+	&ck_pll1,
+	&ck_pll4,
+	&ck_pll5,
+	&ck_pll3,
+	&vfp9_ck,
+	&m2hclk_ck,
+	&hclk_ck,
+	&dma_ck,
+	&flash_ck,
+	&dum_ck,
+	&keyscan_ck,
+	&pwm1_ck,
+	&pwm2_ck,
+	&jpeg_ck,
+	&ms_ck,
+	&touch_ck,
+	&i2c0_ck,
+	&i2c1_ck,
+	&i2c2_ck,
+	&spi0_ck,
+	&spi1_ck,
+	&uart3_ck,
+	&uart4_ck,
+	&uart5_ck,
+	&uart6_ck,
+};
+
+static int local_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
+	    && clk->user_rate)
+		ret = clk->set_rate(clk, clk->user_rate);
+	return ret;
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+	if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
+		clk->set_rate(clk, 0);
+}
+
+static void local_clk_unuse(struct clk *clk)
+{
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		local_clk_disable(clk);
+		if (clk->parent)
+			local_clk_unuse(clk->parent);
+	}
+}
+
+static int local_clk_use(struct clk *clk)
+{
+	int ret = 0;
+	if (clk->usecount++ == 0) {
+		if (clk->parent)
+			ret = local_clk_use(clk->parent);
+
+		if (ret != 0) {
+			clk->usecount--;
+			goto out;
+		}
+
+		ret = local_clk_enable(clk);
+
+		if (ret != 0 && clk->parent) {
+			local_clk_unuse(clk->parent);
+			clk->usecount--;
+		}
+	}
+out:
+	return ret;
+}
+
+static int local_set_rate(struct clk *clk, u32 rate)
+{
+	int ret = -EINVAL;
+	if (clk->set_rate) {
+
+		if (clk->user_rate == clk->rate && clk->parent->rate) {
+			/* if clock enabled or rate not set */
+			clk->user_rate = clk->round_rate(clk, rate);
+			ret = clk->set_rate(clk, clk->user_rate);
+		} else
+			clk->user_rate = clk->round_rate(clk, rate);
+		ret = 0;
+	}
+	return ret;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	if (clk->flags & FIXED_RATE)
+		goto out;
+
+	clock_lock();
+	if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
+
+		clk->user_rate = clk->round_rate(clk, rate);
+		/* parent clock needs to be refreshed
+		   for the setting to take effect */
+	} else {
+		ret = local_set_rate(clk, rate);
+	}
+	ret = 0;
+	clock_unlock();
+
+out:
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *clk = ERR_PTR(-ENOENT);
+	struct clk **clkp;
+
+	clock_lock();
+	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     clkp++) {
+		if (strcmp(id, (*clkp)->name) == 0
+		    && try_module_get((*clkp)->owner)) {
+			clk = (*clkp);
+			break;
+		}
+	}
+	clock_unlock();
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	clock_lock();
+	if (clk && !IS_ERR(clk))
+		module_put(clk->owner);
+	clock_unlock();
+}
+EXPORT_SYMBOL(clk_put);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long ret;
+	clock_lock();
+	ret = clk->rate;
+	clock_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	clock_lock();
+	ret = local_clk_use(clk);
+	clock_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	clock_lock();
+	local_clk_unuse(clk);
+	clock_unlock();
+}
+
+EXPORT_SYMBOL(clk_disable);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	long ret;
+	clock_lock();
+	if (clk->round_rate)
+		ret = clk->round_rate(clk, rate);
+	else
+		ret = clk->rate;
+	clock_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -ENODEV;
+	if (!clk->set_parent)
+		goto out;
+
+	clock_lock();
+	ret = clk->set_parent(clk, parent);
+	if (!ret)
+		clk->parent = parent;
+	clock_unlock();
+
+out:
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_set_parent);
+
+static int __init clk_init(void)
+{
+	struct clk **clkp;
+
+	/* Disable autoclocking, as it doesn't seem to work */
+	__raw_writel(0xff, AUTOCLK_CTRL);
+
+	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     clkp++) {
+		if (((*clkp)->flags & NEEDS_INITIALIZATION)
+		    && ((*clkp)->set_rate)) {
+			(*clkp)->user_rate = (*clkp)->rate;
+			local_set_rate((*clkp), (*clkp)->user_rate);
+			if ((*clkp)->set_parent)
+				(*clkp)->set_parent((*clkp), (*clkp)->parent);
+		}
+		pr_debug("%s: clock %s, rate %ld\n",
+			__FUNCTION__, (*clkp)->name, (*clkp)->rate);
+	}
+
+	local_clk_use(&ck_pll4);
+
+	/* if ck_13MHz is not used, disable it. */
+	if (ck_13MHz.usecount == 0)
+		local_clk_disable(&ck_13MHz);
+
+	/* Disable autoclocking */
+	__raw_writeb(0xff, AUTOCLK_CTRL);
+
+	return 0;
+}
+
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h
new file mode 100644
index 000000000000..cd58f372cfd0
--- /dev/null
+++ b/arch/arm/mach-pnx4008/clock.h
@@ -0,0 +1,43 @@
+/*
+ * arch/arm/mach-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - internal header file
+ *
+ * Author: Vitaly Wool <source@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.
+ */
+#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
+#define __ARCH_ARM_PNX4008_CLOCK_H__
+
+struct clk {
+	struct list_head node;
+	struct module *owner;
+	const char *name;
+	struct clk *parent;
+	struct clk *propagate_next;
+	u32 rate;
+	u32 user_rate;
+	s8 usecount;
+	u32 flags;
+	u32 scale_reg;
+	u8 enable_shift;
+	u32 enable_reg;
+	u8 enable_shift1;
+	u32 enable_reg1;
+	u32 parent_switch_reg;
+	 u32(*round_rate) (struct clk *, u32);
+	int (*set_rate) (struct clk *, u32);
+	int (*set_parent) (struct clk * clk, struct clk * parent);
+};
+
+/* Flags */
+#define RATE_PROPAGATES      (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE      (1<<2)
+#define FIXED_RATE           (1<<3)
+
+#endif
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
new file mode 100644
index 000000000000..ba91daad64fb
--- /dev/null
+++ b/arch/arm/mach-pnx4008/core.c
@@ -0,0 +1,207 @@
+/*
+ * arch/arm/mach-pnx4008/core.c
+ *
+ * PNX4008 core startup code
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev,
+ * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dma.h>
+
+struct resource spipnx_0_resources[] = {
+	{
+		.start = PNX4008_SPI1_BASE,
+		.end = PNX4008_SPI1_BASE + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = PER_SPI1_REC_XMIT,
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = SPI1_INT,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.flags = 0,
+	},
+};
+
+struct resource spipnx_1_resources[] = {
+	{
+		.start = PNX4008_SPI2_BASE,
+		.end = PNX4008_SPI2_BASE + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = PER_SPI2_REC_XMIT,
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = SPI2_INT,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+	{
+		.modalias	= "m25p80",
+		.max_speed_hz	= 1000000,
+		.bus_num	= 1,
+		.chip_select	= 0,
+	},
+};
+
+static struct platform_device spipnx_1 = {
+	.name = "spipnx",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(spipnx_0_resources),
+	.resource = spipnx_0_resources,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+		},
+};
+
+static struct platform_device spipnx_2 = {
+	.name = "spipnx",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(spipnx_1_resources),
+	.resource = spipnx_1_resources,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+		},
+};
+
+static struct plat_serial8250_port platform_serial_ports[] = {
+	{
+		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
+		.mapbase = (unsigned long)PNX4008_UART5_BASE,
+		.irq = IIR5_INT,
+		.uartclk = PNX4008_UART_CLK,
+		.regshift = 2,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+	},
+	{
+		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
+		.mapbase = (unsigned long)PNX4008_UART3_BASE,
+		.irq = IIR3_INT,
+		.uartclk = PNX4008_UART_CLK,
+		.regshift = 2,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+	 },
+	{}
+};
+
+static struct platform_device serial_device = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = &platform_serial_ports,
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&spipnx_1,
+	&spipnx_2,
+	&serial_device,
+};
+
+
+extern void pnx4008_uart_init(void);
+
+static void __init pnx4008_init(void)
+{
+	/*disable all START interrupt sources,
+	   and clear all START interrupt flags */
+	__raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
+	__raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+	/* Switch on the UART clocks */
+	pnx4008_uart_init();
+}
+
+static struct map_desc pnx4008_io_desc[] __initdata = {
+	{
+		.virtual 	= IO_ADDRESS(PNX4008_IRAM_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_IRAM_BASE),
+		.length		= SZ_64K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
+		.length		= SZ_1M - SZ_128K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
+		.length		= SZ_128K * 3,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
+		.length		= SZ_1M,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_AHB2FAB_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_AHB2FAB_BASE),
+		.length		= SZ_1M,
+		.type 		= MT_DEVICE,
+	},
+};
+
+void __init pnx4008_map_io(void)
+{
+	iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
+}
+
+extern struct sys_timer pnx4008_timer;
+
+MACHINE_START(PNX4008, "Philips PNX4008")
+	/* Maintainer: MontaVista Software Inc. */
+	.phys_io 		= 0x40090000,
+	.io_pg_offst 		= (0xf4090000 >> 18) & 0xfffc,
+	.boot_params		= 0x80000100,
+	.map_io 		= pnx4008_map_io,
+	.init_irq 		= pnx4008_init_irq,
+	.init_machine 		= pnx4008_init,
+	.timer 			= &pnx4008_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
new file mode 100644
index 000000000000..981aa9dcdede
--- /dev/null
+++ b/arch/arm/mach-pnx4008/dma.c
@@ -0,0 +1,1109 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/dma.c
+ *
+ *  PNX4008 DMA registration and IRQ dispatching
+ *
+ *  Author:	Vitaly Wool
+ *  Copyright:	MontaVista Software Inc. (c) 2005
+ *
+ *  Based on the code from Nicolas Pitre
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/mach/dma.h>
+#include <asm/arch/clock.h>
+
+static struct dma_channel {
+	char *name;
+	void (*irq_handler) (int, int, void *, struct pt_regs *);
+	void *data;
+	struct pnx4008_dma_ll *ll;
+	u32 ll_dma;
+	void *target_addr;
+	int target_id;
+} dma_channels[MAX_DMA_CHANNELS];
+
+static struct ll_pool {
+	void *vaddr;
+	void *cur;
+	dma_addr_t dma_addr;
+	int count;
+} ll_pool;
+
+static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED;
+
+struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma)
+{
+	struct pnx4008_dma_ll *ll = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ll_lock, flags);
+	if (ll_pool.count > 4) { /* can give one more */
+		ll = *(struct pnx4008_dma_ll **) ll_pool.cur;
+		*ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr);
+		*(void **)ll_pool.cur = **(void ***)ll_pool.cur;
+		memset(ll, 0, sizeof(*ll));
+		ll_pool.count--;
+	}
+	spin_unlock_irqrestore(&ll_lock, flags);
+
+	return ll;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry);
+
+void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma)
+{
+	unsigned long flags;
+
+	if (ll) {
+		if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) {
+			printk(KERN_ERR "Trying to free entry not allocated by DMA\n");
+			BUG();
+		}
+
+		if (ll->flags & DMA_BUFFER_ALLOCATED)
+			ll->free(ll->alloc_data);
+
+		spin_lock_irqsave(&ll_lock, flags);
+		*(long *)ll = *(long *)ll_pool.cur;
+		*(long *)ll_pool.cur = (long)ll;
+		ll_pool.count++;
+		spin_unlock_irqrestore(&ll_lock, flags);
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry);
+
+void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll)
+{
+	struct pnx4008_dma_ll *ptr;
+	u32 dma;
+
+	while (ll) {
+		dma = ll->next_dma;
+		ptr = ll->next;
+		pnx4008_free_ll_entry(ll, ll_dma);
+
+		ll_dma = dma;
+		ll = ptr;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll);
+
+static int dma_channels_requested = 0;
+
+static inline void dma_increment_usage(void)
+{
+	if (!dma_channels_requested++) {
+		struct clk *clk = clk_get(0, "dma_ck");
+		if (!IS_ERR(clk)) {
+			clk_set_rate(clk, 1);
+			clk_put(clk);
+		}
+		pnx4008_config_dma(-1, -1, 1);
+	}
+}
+static inline void dma_decrement_usage(void)
+{
+	if (!--dma_channels_requested) {
+		struct clk *clk = clk_get(0, "dma_ck");
+		if (!IS_ERR(clk)) {
+			clk_set_rate(clk, 0);
+			clk_put(clk);
+		}
+		pnx4008_config_dma(-1, -1, 0);
+
+	}
+}
+
+static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void pnx4008_dma_lock(void)
+{
+	spin_lock_irq(&dma_lock);
+}
+
+static inline void pnx4008_dma_unlock(void)
+{
+	spin_unlock_irq(&dma_lock);
+}
+
+#define VALID_CHANNEL(c)	(((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
+
+int pnx4008_request_channel(char *name, int ch,
+			    void (*irq_handler) (int, int, void *,
+						 struct pt_regs *), void *data)
+{
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name || (ch != -1 && !VALID_CHANNEL(ch)))
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+
+	/* try grabbing a DMA channel with the requested priority */
+	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+		if (!dma_channels[i].name && (ch == -1 || ch == i)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		dma_increment_usage();
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].data = data;
+		dma_channels[i].ll = NULL;
+		dma_channels[i].ll_dma = 0;
+	} else {
+		printk(KERN_WARNING "No more available DMA channels for %s\n",
+		       name);
+		i = -ENODEV;
+	}
+
+	pnx4008_dma_unlock();
+	return i;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_request_channel);
+
+void pnx4008_free_channel(int ch)
+{
+	if (!dma_channels[ch].name) {
+		printk(KERN_CRIT
+		       "%s: trying to free channel %d which is already freed\n",
+		       __FUNCTION__, ch);
+		return;
+	}
+
+	pnx4008_dma_lock();
+	pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
+	dma_channels[ch].ll = NULL;
+	dma_decrement_usage();
+
+	dma_channels[ch].name = NULL;
+	pnx4008_dma_unlock();
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_channel);
+
+int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable)
+{
+	unsigned long dma_cfg = __raw_readl(DMAC_CONFIG);
+
+	switch (ahb_m1_be) {
+	case 0:
+		dma_cfg &= ~(1 << 1);
+		break;
+	case 1:
+		dma_cfg |= (1 << 1);
+		break;
+	default:
+		break;
+	}
+
+	switch (ahb_m2_be) {
+	case 0:
+		dma_cfg &= ~(1 << 2);
+		break;
+	case 1:
+		dma_cfg |= (1 << 2);
+		break;
+	default:
+		break;
+	}
+
+	switch (enable) {
+	case 0:
+		dma_cfg &= ~(1 << 0);
+		break;
+	case 1:
+		dma_cfg |= (1 << 0);
+		break;
+	default:
+		break;
+	}
+
+	pnx4008_dma_lock();
+	__raw_writel(dma_cfg, DMAC_CONFIG);
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_dma);
+
+int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl,
+			     unsigned long *ctrl)
+{
+	int i = 0, dbsize, sbsize, err = 0;
+
+	if (!ctrl || !ch_ctrl) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	*ctrl = 0;
+
+	switch (ch_ctrl->tc_mask) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 31);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+
+	switch (ch_ctrl->cacheable) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 30);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->bufferable) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 29);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->priv_mode) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 28);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->di) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 27);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->si) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 26);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->dest_ahb1) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 25);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->src_ahb1) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 24);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->dwidth) {
+	case WIDTH_BYTE:
+		*ctrl &= ~(7 << 21);
+		break;
+	case WIDTH_HWORD:
+		*ctrl &= ~(7 << 21);
+		*ctrl |= (1 << 21);
+		break;
+	case WIDTH_WORD:
+		*ctrl &= ~(7 << 21);
+		*ctrl |= (2 << 21);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->swidth) {
+	case WIDTH_BYTE:
+		*ctrl &= ~(7 << 18);
+		break;
+	case WIDTH_HWORD:
+		*ctrl &= ~(7 << 18);
+		*ctrl |= (1 << 18);
+		break;
+	case WIDTH_WORD:
+		*ctrl &= ~(7 << 18);
+		*ctrl |= (2 << 18);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	dbsize = ch_ctrl->dbsize;
+	while (!(dbsize & 1)) {
+		i++;
+		dbsize >>= 1;
+	}
+	if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) {
+		err = -EINVAL;
+		goto out;
+	} else if (i > 1)
+		i--;
+	*ctrl &= ~(7 << 15);
+	*ctrl |= (i << 15);
+
+	sbsize = ch_ctrl->sbsize;
+	while (!(sbsize & 1)) {
+		i++;
+		sbsize >>= 1;
+	}
+	if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) {
+		err = -EINVAL;
+		goto out;
+	} else if (i > 1)
+		i--;
+	*ctrl &= ~(7 << 12);
+	*ctrl |= (i << 12);
+
+	if (ch_ctrl->tr_size > 0x7ff) {
+		err = -E2BIG;
+		goto out;
+	}
+	*ctrl &= ~0x7ff;
+	*ctrl |= ch_ctrl->tr_size & 0x7ff;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control);
+
+int pnx4008_dma_parse_control(unsigned long ctrl,
+			      struct pnx4008_dma_ch_ctrl * ch_ctrl)
+{
+	int err = 0;
+
+	if (!ch_ctrl) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	ch_ctrl->tr_size = ctrl & 0x7ff;
+	ctrl >>= 12;
+
+	ch_ctrl->sbsize = 1 << (ctrl & 7);
+	if (ch_ctrl->sbsize > 1)
+		ch_ctrl->sbsize <<= 1;
+	ctrl >>= 3;
+
+	ch_ctrl->dbsize = 1 << (ctrl & 7);
+	if (ch_ctrl->dbsize > 1)
+		ch_ctrl->dbsize <<= 1;
+	ctrl >>= 3;
+
+	switch (ctrl & 7) {
+	case 0:
+		ch_ctrl->swidth = WIDTH_BYTE;
+		break;
+	case 1:
+		ch_ctrl->swidth = WIDTH_HWORD;
+		break;
+	case 2:
+		ch_ctrl->swidth = WIDTH_WORD;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	ctrl >>= 3;
+
+	switch (ctrl & 7) {
+	case 0:
+		ch_ctrl->dwidth = WIDTH_BYTE;
+		break;
+	case 1:
+		ch_ctrl->dwidth = WIDTH_HWORD;
+		break;
+	case 2:
+		ch_ctrl->dwidth = WIDTH_WORD;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	ctrl >>= 3;
+
+	ch_ctrl->src_ahb1 = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->dest_ahb1 = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->si = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->di = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->priv_mode = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->bufferable = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->cacheable = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->tc_mask = ctrl & 1;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control);
+
+int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg,
+			    unsigned long *cfg)
+{
+	int err = 0;
+
+	if (!cfg || !ch_cfg) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	*cfg = 0;
+
+	switch (ch_cfg->halt) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 18);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->active) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 17);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->lock) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 16);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->itc) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 15);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->ie) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 14);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->flow_cntrl) {
+	case FC_MEM2MEM_DMA:
+		*cfg &= ~(7 << 11);
+		break;
+	case FC_MEM2PER_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (1 << 11);
+		break;
+	case FC_PER2MEM_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (2 << 11);
+		break;
+	case FC_PER2PER_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (3 << 11);
+		break;
+	case FC_PER2PER_DPER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (4 << 11);
+		break;
+	case FC_MEM2PER_PER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (5 << 11);
+		break;
+	case FC_PER2MEM_PER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (6 << 11);
+		break;
+	case FC_PER2PER_SPER:
+		*cfg |= (7 << 11);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	*cfg &= ~(0x1f << 6);
+	*cfg |= ((ch_cfg->dest_per & 0x1f) << 6);
+
+	*cfg &= ~(0x1f << 1);
+	*cfg |= ((ch_cfg->src_per & 0x1f) << 1);
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config);
+
+int pnx4008_dma_parse_config(unsigned long cfg,
+			     struct pnx4008_dma_ch_config * ch_cfg)
+{
+	int err = 0;
+
+	if (!ch_cfg) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	cfg >>= 1;
+
+	ch_cfg->src_per = cfg & 0x1f;
+	cfg >>= 5;
+
+	ch_cfg->dest_per = cfg & 0x1f;
+	cfg >>= 5;
+
+	switch (cfg & 7) {
+	case 0:
+		ch_cfg->flow_cntrl = FC_MEM2MEM_DMA;
+		break;
+	case 1:
+		ch_cfg->flow_cntrl = FC_MEM2PER_DMA;
+		break;
+	case 2:
+		ch_cfg->flow_cntrl = FC_PER2MEM_DMA;
+		break;
+	case 3:
+		ch_cfg->flow_cntrl = FC_PER2PER_DMA;
+		break;
+	case 4:
+		ch_cfg->flow_cntrl = FC_PER2PER_DPER;
+		break;
+	case 5:
+		ch_cfg->flow_cntrl = FC_MEM2PER_PER;
+		break;
+	case 6:
+		ch_cfg->flow_cntrl = FC_PER2MEM_PER;
+		break;
+	case 7:
+		ch_cfg->flow_cntrl = FC_PER2PER_SPER;
+	}
+	cfg >>= 3;
+
+	ch_cfg->ie = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->itc = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->lock = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->active = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->halt = cfg & 1;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config);
+
+void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config,
+				  struct pnx4008_dma_ch_ctrl * ctrl)
+{
+	int new_len = ctrl->tr_size, num_entries = 0;
+	int old_len = new_len;
+	int src_width, dest_width, count = 1;
+
+	switch (ctrl->swidth) {
+	case WIDTH_BYTE:
+		src_width = 1;
+		break;
+	case WIDTH_HWORD:
+		src_width = 2;
+		break;
+	case WIDTH_WORD:
+		src_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	switch (ctrl->dwidth) {
+	case WIDTH_BYTE:
+		dest_width = 1;
+		break;
+	case WIDTH_HWORD:
+		dest_width = 2;
+		break;
+	case WIDTH_WORD:
+		dest_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	while (new_len > 0x7FF) {
+		num_entries++;
+		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+	}
+	if (num_entries != 0) {
+		struct pnx4008_dma_ll *ll = NULL;
+		config->ch_ctrl &= ~0x7ff;
+		config->ch_ctrl |= new_len;
+		if (!config->is_ll) {
+			config->is_ll = 1;
+			while (num_entries) {
+				if (!ll) {
+					config->ll =
+					    pnx4008_alloc_ll_entry(&config->
+								   ll_dma);
+					ll = config->ll;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    config->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = config->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    config->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = config->dest_addr;
+				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+		} else {
+			struct pnx4008_dma_ll *ll_old = config->ll;
+			unsigned long ll_dma_old = config->ll_dma;
+			while (num_entries) {
+				if (!ll) {
+					config->ll =
+					    pnx4008_alloc_ll_entry(&config->
+								   ll_dma);
+					ll = config->ll;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    config->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = config->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    config->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = config->dest_addr;
+				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+			ll->next_dma = ll_dma_old;
+			ll->next = ll_old;
+		}
+		/* adjust last length/tc */
+		ll->ch_ctrl = config->ch_ctrl & (~0x7ff);
+		ll->ch_ctrl |= old_len - new_len * (count - 1);
+		config->ch_ctrl &= 0x7fffffff;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry);
+
+void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll,
+				struct pnx4008_dma_ch_ctrl * ctrl)
+{
+	int new_len = ctrl->tr_size, num_entries = 0;
+	int old_len = new_len;
+	int src_width, dest_width, count = 1;
+
+	switch (ctrl->swidth) {
+	case WIDTH_BYTE:
+		src_width = 1;
+		break;
+	case WIDTH_HWORD:
+		src_width = 2;
+		break;
+	case WIDTH_WORD:
+		src_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	switch (ctrl->dwidth) {
+	case WIDTH_BYTE:
+		dest_width = 1;
+		break;
+	case WIDTH_HWORD:
+		dest_width = 2;
+		break;
+	case WIDTH_WORD:
+		dest_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	while (new_len > 0x7FF) {
+		num_entries++;
+		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+	}
+	if (num_entries != 0) {
+		struct pnx4008_dma_ll *ll = NULL;
+		cur_ll->ch_ctrl &= ~0x7ff;
+		cur_ll->ch_ctrl |= new_len;
+		if (!cur_ll->next) {
+			while (num_entries) {
+				if (!ll) {
+					cur_ll->next =
+					    pnx4008_alloc_ll_entry(&cur_ll->
+								   next_dma);
+					ll = cur_ll->next;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    cur_ll->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = cur_ll->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    cur_ll->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = cur_ll->dest_addr;
+				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+		} else {
+			struct pnx4008_dma_ll *ll_old = cur_ll->next;
+			unsigned long ll_dma_old = cur_ll->next_dma;
+			while (num_entries) {
+				if (!ll) {
+					cur_ll->next =
+					    pnx4008_alloc_ll_entry(&cur_ll->
+								   next_dma);
+					ll = cur_ll->next;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    cur_ll->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = cur_ll->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    cur_ll->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = cur_ll->dest_addr;
+				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+
+			ll->next_dma = ll_dma_old;
+			ll->next = ll_old;
+		}
+		/* adjust last length/tc */
+		ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff);
+		ll->ch_ctrl |= old_len - new_len * (count - 1);
+		cur_ll->ch_ctrl &= 0x7fffffff;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry);
+
+int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config)
+{
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	__raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch));
+	__raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch));
+
+	if (config->is_ll)
+		__raw_writel(config->ll_dma, DMAC_Cx_LLI(ch));
+	else
+		__raw_writel(0, DMAC_Cx_LLI(ch));
+
+	__raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch));
+	__raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_channel);
+
+int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config)
+{
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch));
+
+	config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch));
+	config->is_ll = config->ll_dma ? 1 : 0;
+
+	config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch));
+	config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_channel_get_config);
+
+int pnx4008_dma_ch_enable(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	ch_cfg |= 1;
+	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable);
+
+int pnx4008_dma_ch_disable(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	ch_cfg &= ~1;
+	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable);
+
+int pnx4008_dma_ch_enabled(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return ch_cfg & 1;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i;
+	unsigned long dint = __raw_readl(DMAC_INT_STAT);
+	unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT);
+	unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT);
+	unsigned long i_bit;
+
+	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+		i_bit = 1 << i;
+		if (dint & i_bit) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			if (channel->name && channel->irq_handler) {
+				int cause = 0;
+
+				if (eint & i_bit)
+					cause |= DMA_ERR_INT;
+				if (tcint & i_bit)
+					cause |= DMA_TC_INT;
+				channel->irq_handler(i, cause, channel->data,
+						     regs);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel
+				 */
+				printk(KERN_WARNING
+				       "spurious IRQ for DMA channel %d\n", i);
+			}
+			if (tcint & i_bit)
+				__raw_writel(i_bit, DMAC_INT_TC_CLEAR);
+			if (eint & i_bit)
+				__raw_writel(i_bit, DMAC_INT_ERR_CLEAR);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init pnx4008_dma_init(void)
+{
+	int ret, i;
+
+	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+		goto out;
+	}
+
+	ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll);
+	ll_pool.cur = ll_pool.vaddr =
+	    dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll),
+			       &ll_pool.dma_addr, GFP_KERNEL);
+
+	if (!ll_pool.vaddr) {
+		ret = -ENOMEM;
+		free_irq(DMA_INT, NULL);
+		goto out;
+	}
+
+	for (i = 0; i < ll_pool.count - 1; i++) {
+		void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll);
+		*addr = (void *)addr + sizeof(struct pnx4008_dma_ll);
+	}
+	*(long *)(ll_pool.vaddr +
+		  (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) =
+	    (long)ll_pool.vaddr;
+
+	__raw_writel(1, DMAC_CONFIG);
+
+out:
+	return ret;
+}
+arch_initcall(pnx4008_dma_init);
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
new file mode 100644
index 000000000000..e1ce050d8fe0
--- /dev/null
+++ b/arch/arm/mach-pnx4008/gpio.c
@@ -0,0 +1,330 @@
+/*
+ * arch/arm/mach-pnx4008/gpio.c
+ *
+ * PNX4008 GPIO driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (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 <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/gpio.h>
+
+/* register definitions */
+#define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
+
+#define PIO_INP_STATE	(0x00U)
+#define PIO_OUTP_SET	(0x04U)
+#define PIO_OUTP_CLR	(0x08U)
+#define PIO_OUTP_STATE	(0x0CU)
+#define PIO_DRV_SET	(0x10U)
+#define PIO_DRV_CLR	(0x14U)
+#define PIO_DRV_STATE	(0x18U)
+#define PIO_SDINP_STATE	(0x1CU)
+#define PIO_SDOUTP_SET	(0x20U)
+#define PIO_SDOUTP_CLR	(0x24U)
+#define PIO_MUX_SET	(0x28U)
+#define PIO_MUX_CLR	(0x2CU)
+#define PIO_MUX_STATE	(0x30U)
+
+static inline void gpio_lock(void)
+{
+	local_irq_disable();
+}
+
+static inline void gpio_unlock(void)
+{
+	local_irq_enable();
+}
+
+/* Inline functions */
+static inline int gpio_read_bit(u32 reg, int gpio)
+{
+	u32 bit, val;
+	int ret = -EFAULT;
+
+	if (gpio < 0)
+		goto out;
+
+	bit = GPIO_BIT(gpio);
+	if (bit) {
+		val = __raw_readl(PIO_VA_BASE + reg);
+		ret = (val & bit) ? 1 : 0;
+	}
+out:
+	return ret;
+}
+
+static inline int gpio_set_bit(u32 reg, int gpio)
+{
+	u32 bit, val;
+	int ret = -EFAULT;
+
+	if (gpio < 0)
+		goto out;
+
+	bit = GPIO_BIT(gpio);
+	if (bit) {
+		val = __raw_readl(PIO_VA_BASE + reg);
+		val |= bit;
+		__raw_writel(val, PIO_VA_BASE + reg);
+		ret = 0;
+	}
+out:
+	return ret;
+}
+
+/* Very simple access control, bitmap for allocated/free */
+static unsigned long access_map[4];
+#define INP_INDEX	0
+#define OUTP_INDEX	1
+#define GPIO_INDEX	2
+#define MUX_INDEX	3
+
+/*GPIO to Input Mapping */
+static short gpio_to_inp_map[32] = {
+	-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, 10, 11, 12, 13, 14, 24, -1
+};
+
+/*GPIO to Mux Mapping */
+static short gpio_to_mux_map[32] = {
+	-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, 0, 1, 4, 5, -1
+};
+
+/*Output to Mux Mapping */
+static short outp_to_mux_map[32] = {
+	-1, -1, -1, 6, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, 2, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int pnx4008_gpio_register_pin(unsigned short pin)
+{
+	unsigned long bit = GPIO_BIT(pin);
+	int ret = -EBUSY;	/* Already in use */
+
+	gpio_lock();
+
+	if (GPIO_ISBID(pin)) {
+		if (access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] |= bit;
+
+	} else if (GPIO_ISRAM(pin)) {
+		if (access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] |= bit;
+
+	} else if (GPIO_ISMUX(pin)) {
+		if (access_map[MUX_INDEX] & bit)
+			goto out;
+		access_map[MUX_INDEX] |= bit;
+
+	} else if (GPIO_ISOUT(pin)) {
+		if (access_map[OUTP_INDEX] & bit)
+			goto out;
+		access_map[OUTP_INDEX] |= bit;
+
+	} else if (GPIO_ISIN(pin)) {
+		if (access_map[INP_INDEX] & bit)
+			goto out;
+		access_map[INP_INDEX] |= bit;
+	} else
+		goto out;
+	ret = 0;
+
+out:
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_register_pin);
+
+int pnx4008_gpio_unregister_pin(unsigned short pin)
+{
+	unsigned long bit = GPIO_BIT(pin);
+	int ret = -EFAULT;	/* Not registered */
+
+	gpio_lock();
+
+	if (GPIO_ISBID(pin)) {
+		if (~access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] &= ~bit;
+	} else if (GPIO_ISRAM(pin)) {
+		if (~access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] &= ~bit;
+	} else if (GPIO_ISMUX(pin)) {
+		if (~access_map[MUX_INDEX] & bit)
+			goto out;
+		access_map[MUX_INDEX] &= ~bit;
+	} else if (GPIO_ISOUT(pin)) {
+		if (~access_map[OUTP_INDEX] & bit)
+			goto out;
+		access_map[OUTP_INDEX] &= ~bit;
+	} else if (GPIO_ISIN(pin)) {
+		if (~access_map[INP_INDEX] & bit)
+			goto out;
+		access_map[INP_INDEX] &= ~bit;
+	} else
+		goto out;
+	ret = 0;
+
+out:
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
+
+unsigned long pnx4008_gpio_read_pin(unsigned short pin)
+{
+	unsigned long ret = -EFAULT;
+	int gpio = GPIO_BIT_MASK(pin);
+	gpio_lock();
+	if (GPIO_ISOUT(pin)) {
+		ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+	} else if (GPIO_ISRAM(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
+			ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
+		}
+	} else if (GPIO_ISBID(pin)) {
+		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+		if (ret > 0)
+			ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+		else if (ret == 0)
+			ret =
+			    gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
+	} else if (GPIO_ISIN(pin)) {
+		ret = gpio_read_bit(PIO_INP_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin);
+
+/* Write Value to output */
+int pnx4008_gpio_write_pin(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISOUT(pin)) {
+		printk( "writing '%x' to '%x'\n",
+				gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
+		ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
+	} else if (GPIO_ISRAM(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+			ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
+					   PIO_SDOUTP_CLR, gpio);
+	} else if (GPIO_ISBID(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+			ret = gpio_set_bit(output ? PIO_OUTP_SET :
+					   PIO_OUTP_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_write_pin);
+
+/* Value = 1 : Set GPIO pin as output */
+/* Value = 0 : Set GPIO pin as input */
+int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+		ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
+
+/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
+int pnx4008_gpio_read_pin_direction(unsigned short pin)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
+
+/* Value = 1 : Set pin to muxed function  */
+/* Value = 0 : Set pin as GPIO */
+int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin)) {
+		ret =
+		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+				 gpio_to_mux_map[gpio]);
+	} else if (GPIO_ISOUT(pin)) {
+		ret =
+		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+				 outp_to_mux_map[gpio]);
+	} else if (GPIO_ISMUX(pin)) {
+		ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
+
+/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
+int pnx4008_gpio_read_pin_mux(unsigned short pin)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
+	} else if (GPIO_ISOUT(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
+	} else if (GPIO_ISMUX(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
new file mode 100644
index 000000000000..9b0a8e084e99
--- /dev/null
+++ b/arch/arm/mach-pnx4008/irq.c
@@ -0,0 +1,121 @@
+/*
+ * arch/arm/mach-pnx4008/irq.c
+ *
+ * PNX4008 IRQ controller driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (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 <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irq.h>
+
+static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
+
+static void pnx4008_mask_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
+}
+
+static void pnx4008_unmask_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq));	/* unmask interrupt */
+}
+
+static void pnx4008_mask_ack_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
+	__raw_writel(INTC_BIT(irq), INTC_SR(irq));	/* clear interrupt status */
+}
+
+static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
+{
+	switch (type) {
+	case IRQT_RISING:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/*rising edge */
+		set_irq_handler(irq, do_edge_IRQ);
+		break;
+	case IRQT_FALLING:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*falling edge */
+		set_irq_handler(irq, do_edge_IRQ);
+		break;
+	case IRQT_LOW:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*low level */
+		set_irq_handler(irq, do_level_IRQ);
+		break;
+	case IRQT_HIGH:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/* high level */
+		set_irq_handler(irq, do_level_IRQ);
+		break;
+
+	/* IRQT_BOTHEDGE is not supported */
+	default:
+		printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
+		return -1;
+	}
+	return 0;
+}
+
+static struct irqchip pnx4008_irq_chip = {
+	.ack = pnx4008_mask_ack_irq,
+	.mask = pnx4008_mask_irq,
+	.unmask = pnx4008_unmask_irq,
+	.set_type = pnx4008_set_irq_type,
+};
+
+void __init pnx4008_init_irq(void)
+{
+	unsigned int i;
+
+	/* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */
+	pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
+	pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
+	pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
+	pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
+
+	__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
+			(1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
+		INTC_ER(MAIN_BASE_INT));
+	__raw_writel(0, INTC_ER(SIC1_BASE_INT));
+	__raw_writel(0, INTC_ER(SIC2_BASE_INT));
+
+	/* configure all other IRQ's */
+	for (i = 0; i < NR_IRQS; i++) {
+		if (i == SUB2_FIQ_N || i == SUB1_FIQ_N ||
+			i == SUB2_IRQ_N || i == SUB1_IRQ_N)
+			continue;
+		set_irq_flags(i, IRQF_VALID);
+		set_irq_chip(i, &pnx4008_irq_chip);
+		pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
+	}
+}
+
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
new file mode 100644
index 000000000000..3649cd3dfc9a
--- /dev/null
+++ b/arch/arm/mach-pnx4008/pm.c
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/mach-pnx4008/pm.c
+ *
+ * Power Management driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (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 <linux/pm.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/clock.h>
+
+#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
+
+static void *saved_sram;
+
+static struct clk *pll4_clk;
+
+static inline void pnx4008_standby(void)
+{
+	void (*pnx4008_cpu_standby_ptr) (void);
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	clk_disable(pll4_clk);
+
+	/*saving portion of SRAM to be used by suspend function. */
+	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
+
+	/*make sure SRAM copy gets physically written into SDRAM.
+	   SDRAM will be placed into self-refresh during power down */
+	flush_cache_all();
+
+	/*copy suspend function into SRAM */
+	memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
+
+	/*do suspend */
+	pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
+	pnx4008_cpu_standby_ptr();
+
+	/*restoring portion of SRAM that was used by suspend function */
+	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
+
+	clk_enable(pll4_clk);
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static inline void pnx4008_suspend(void)
+{
+	void (*pnx4008_cpu_suspend_ptr) (void);
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	clk_disable(pll4_clk);
+
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+	/*saving portion of SRAM to be used by suspend function. */
+	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
+
+	/*make sure SRAM copy gets physically written into SDRAM.
+	   SDRAM will be placed into self-refresh during power down */
+	flush_cache_all();
+
+	/*copy suspend function into SRAM */
+	memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
+
+	/*do suspend */
+	pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
+	pnx4008_cpu_suspend_ptr();
+
+	/*restoring portion of SRAM that was used by suspend function */
+	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
+
+	clk_enable(pll4_clk);
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int pnx4008_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		pnx4008_standby();
+		break;
+	case PM_SUSPEND_MEM:
+		pnx4008_suspend();
+		break;
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int pnx4008_pm_prepare(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int pnx4008_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops pnx4008_pm_ops = {
+	.prepare = pnx4008_pm_prepare,
+	.enter = pnx4008_pm_enter,
+	.finish = pnx4008_pm_finish,
+};
+
+static int __init pnx4008_pm_init(void)
+{
+	u32 sram_size_to_allocate;
+
+	pll4_clk = clk_get(0, "ck_pll4");
+	if (IS_ERR(pll4_clk)) {
+		printk(KERN_ERR
+		       "PM Suspend cannot acquire ARM(PLL4) clock control\n");
+		return PTR_ERR(pll4_clk);
+	}
+
+	if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
+		sram_size_to_allocate = pnx4008_cpu_standby_sz;
+	else
+		sram_size_to_allocate = pnx4008_cpu_suspend_sz;
+
+	saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
+	if (!saved_sram) {
+		printk(KERN_ERR
+		       "PM Suspend: cannot allocate memory to save portion of SRAM\n");
+		clk_put(pll4_clk);
+		return -ENOMEM;
+	}
+
+	pm_set_ops(&pnx4008_pm_ops);
+	return 0;
+}
+
+late_initcall(pnx4008_pm_init);
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
new file mode 100644
index 000000000000..95a1b3f964a2
--- /dev/null
+++ b/arch/arm/mach-pnx4008/serial.c
@@ -0,0 +1,69 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/serial.c
+ *
+ *  PNX4008 UART initialization
+ *
+ *  Copyright:	MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/platform.h>
+#include <asm/hardware.h>
+
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/arch/clock.h>
+
+#define UART_3		0
+#define UART_4		1
+#define UART_5		2
+#define UART_6		3
+#define UART_UNKNOWN	(-1)
+
+#define UART3_BASE_VA	IO_ADDRESS(PNX4008_UART3_BASE)
+#define UART4_BASE_VA	IO_ADDRESS(PNX4008_UART4_BASE)
+#define UART5_BASE_VA	IO_ADDRESS(PNX4008_UART5_BASE)
+#define UART6_BASE_VA	IO_ADDRESS(PNX4008_UART6_BASE)
+
+#define UART_FCR_OFFSET		8
+#define UART_FIFO_SIZE		64
+
+void pnx4008_uart_init(void)
+{
+	u32 tmp;
+	int i = UART_FIFO_SIZE;
+
+	__raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
+	__raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
+
+	/* Send a NULL to fix the UART HW bug */
+	__raw_writel(0x00, UART5_BASE_VA);
+	__raw_writel(0x00, UART3_BASE_VA);
+
+	while (i--) {
+		tmp = __raw_readl(UART5_BASE_VA);
+		tmp = __raw_readl(UART3_BASE_VA);
+	}
+	__raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
+	__raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
+
+	/* setup wakeup interrupt */
+	start_int_set_rising_edge(SE_U3_RX_INT);
+	start_int_ack(SE_U3_RX_INT);
+	start_int_umask(SE_U3_RX_INT);
+
+	start_int_set_rising_edge(SE_U5_RX_INT);
+	start_int_ack(SE_U5_RX_INT);
+	start_int_umask(SE_U5_RX_INT);
+}
+
diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S
new file mode 100644
index 000000000000..93c802bac269
--- /dev/null
+++ b/arch/arm/mach-pnx4008/sleep.S
@@ -0,0 +1,196 @@
+/*
+ * linux/arch/arm/mach-pnx4008/sleep.S
+ *
+ * PNX4008 support for STOP mode and SDRAM self-refresh
+ *
+ * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
+ *
+ * 2005 (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 <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define PWR_CTRL_REG_OFFS 0x44
+
+#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
+#define MPMC_STATUS_REG_OFFS 0x4
+
+		.text
+
+ENTRY(pnx4008_cpu_suspend)
+	@this function should be entered in Direct run mode.
+
+	@ save registers on stack
+	stmfd	sp!, {r0 - r6, lr}
+
+	@ setup Power Manager base address in r4
+	@ and put it's value in r5
+	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ setup SDRAM controller base address in r2
+	@ and put it's value in r3
+	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do save current bit settings in r1
+	mov	r1, r5
+
+	@ set SDRAM self-refresh bit
+	orr	r5, r5, #(1 << 9)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get into self-refresh mode
+2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #(1 << 2)
+	beq	2b
+
+	@ to prepare SDRAM to get out of self-refresh mode after wakeup
+	orr	r5, r5, #(1 << 7)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do enter stop mode
+	orr	r5, r5, #(1 << 0)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	@ sleeping now...
+
+	@ coming out of STOP mode into Direct Run mode
+	@ clear STOP mode and SDRAM self-refresh bits
+	str	r1, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get out self-refresh mode
+3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #5
+	bne	3b
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_suspend_sz)
+	.word	. - pnx4008_cpu_suspend
+
+ENTRY(pnx4008_cpu_standby)
+	@ save registers on stack
+	stmfd	sp!, {r0 - r6, lr}
+
+	@ setup Power Manager base address in r4
+	@ and put it's value in r5
+	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ setup SDRAM controller base address in r2
+	@ and put it's value in r3
+	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do save current bit settings in r1
+	mov	r1, r5
+
+	@ set SDRAM self-refresh bit
+	orr	r5, r5, #(1 << 9)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get into self-refresh mode
+2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #(1 << 2)
+	beq	2b
+
+	@ set 'get out of self-refresh mode after wakeup' bit
+	orr	r5, r5, #(1 << 7)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	mcr     p15, 0, r0, c7, c0, 4	@ kinda sleeping now...
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get out self-refresh mode
+3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #5
+	bne	3b
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_standby_sz)
+	.word	. - pnx4008_cpu_standby
+
+ENTRY(pnx4008_cache_clean_invalidate)
+	stmfd	sp!, {r0 - r6, lr}
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+1:	mrc	p15, 0, r15, c7, c14, 3		@ test,clean,invalidate
+	bne     1b
+#endif
+	ldmfd   sp!, {r0 - r6, pc}
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
new file mode 100644
index 000000000000..4ce680698529
--- /dev/null
+++ b/arch/arm/mach-pnx4008/time.c
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-pnx4008/time.c
+ *
+ * PNX4008 Timers
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
+ *
+ * 2005 (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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <asm/errno.h>
+
+/*! Note: all timers are UPCOUNTING */
+
+/*!
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long pnx4008_gettimeoffset(void)
+{
+	u32 ticks_to_match =
+	    __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
+	u32 elapsed = LATCH - ticks_to_match;
+	return (elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*!
+ * IRQ handler for the timer
+ */
+static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id,
+					   struct pt_regs *regs)
+{
+	if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
+
+		write_seqlock(&xtime_lock);
+
+		do {
+			timer_tick(regs);
+
+			/*
+			 * this algorithm takes care of possible delay
+			 * for this interrupt handling longer than a normal
+			 * timer period
+			 */
+			__raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
+				     HSTIM_MATCH0);
+			__raw_writel(MATCH0_INT, HSTIM_INT);	/* clear interrupt */
+
+			/*
+			 * The goal is to keep incrementing HSTIM_MATCH0
+			 * register until HSTIM_MATCH0 indicates time after
+			 * what HSTIM_COUNTER indicates.
+			 */
+		} while ((signed)
+			 (__raw_readl(HSTIM_MATCH0) -
+			  __raw_readl(HSTIM_COUNTER)) < 0);
+
+		write_sequnlock(&xtime_lock);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction pnx4008_timer_irq = {
+	.name = "PNX4008 Tick Timer",
+	.flags = SA_INTERRUPT | SA_TIMER,
+	.handler = pnx4008_timer_interrupt
+};
+
+/*!
+ * Set up timer and timer interrupt.
+ */
+static __init void pnx4008_setup_timer(void)
+{
+	__raw_writel(RESET_COUNT, MSTIM_CTRL);
+	while (__raw_readl(MSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
+	__raw_writel(0, MSTIM_CTRL);	/* stop the timer */
+	__raw_writel(0, MSTIM_MCTRL);
+
+	__raw_writel(RESET_COUNT, HSTIM_CTRL);
+	while (__raw_readl(HSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
+	__raw_writel(0, HSTIM_CTRL);
+	__raw_writel(0, HSTIM_MCTRL);
+	__raw_writel(0, HSTIM_CCR);
+	__raw_writel(12, HSTIM_PMATCH);	/* scale down to 1 MHZ */
+	__raw_writel(LATCH, HSTIM_MATCH0);
+	__raw_writel(MR0_INT, HSTIM_MCTRL);
+
+	setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
+
+	__raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL);	/*start timer, stop when JTAG active */
+}
+
+/* Timer Clock Control in PM register */
+#define TIMCLK_CTRL_REG  IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
+#define WATCHDOG_CLK_EN                   1
+#define TIMER_CLK_EN                      2	/* HS and MS timers? */
+
+static u32 timclk_ctrl_reg_save;
+
+void pnx4008_timer_suspend(void)
+{
+	timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
+	__raw_writel(0, TIMCLK_CTRL_REG);	/* disable timers */
+}
+
+void pnx4008_timer_resume(void)
+{
+	__raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG);	/* enable timers */
+}
+
+struct sys_timer pnx4008_timer = {
+	.init = pnx4008_setup_timer,
+	.offset = pnx4008_gettimeoffset,
+	.suspend = pnx4008_timer_suspend,
+	.resume = pnx4008_timer_resume,
+};
+
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 0104fd142e70..ea5137f319c4 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -61,6 +61,7 @@ config MACH_POODLE
 	bool "Enable Sharp SL-5600 (Poodle) Support"
 	depends PXA_SHARPSL_25x
 	select SHARP_LOCOMO
+	select PXA_SSP
 
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 4e8a983e2b83..1610690be419 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
 obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
 obj-$(CONFIG_PXA_SHARP_Cxx00)	+= spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
 obj-$(CONFIG_MACH_AKITA)	+= akita-ioexp.o
-obj-$(CONFIG_MACH_POODLE)	+= poodle.o
+obj-$(CONFIG_MACH_POODLE)	+= poodle.o corgi_ssp.o
 obj-$(CONFIG_MACH_TOSA)         += tosa.o
 
 # Support for blinky lights
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index d6d726036361..bf6648a83901 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -26,6 +27,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -310,8 +312,31 @@ static struct platform_device *devices[] __initdata = {
 	&corgiled_device,
 };
 
+static void corgi_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	if (!machine_is_corgi())
+		/* Green LED off tells the bootloader to halt */
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+	arm_machine_restart('h');
+}
+
+static void corgi_restart(char mode)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	if (!machine_is_corgi())
+		/* Green LED on tells the bootloader to reboot */
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+	arm_machine_restart('h');
+}
+
 static void __init corgi_init(void)
 {
+	pm_power_off = corgi_poweroff;
+	arm_pm_restart = corgi_restart;
+
 	/* setup sleep mode values */
 	PWER  = 0x00000002;
 	PFER  = 0x00000000;
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 7a1ab73e9e10..4c3de4008a43 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -27,6 +27,13 @@
 #include <asm/arch/pxa-regs.h>
 #include "sharpsl.h"
 
+#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
+#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
+#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
+#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
+#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
+
 static void corgi_charger_init(void)
 {
 	pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT);
@@ -195,9 +202,16 @@ static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
 	.read_devdata    = corgipm_read_devdata,
 	.charger_wakeup  = corgi_charger_wakeup,
 	.should_wakeup   = corgi_should_wakeup,
-	.bat_levels      = 40,
-	.bat_levels_noac = spitz_battery_levels_noac,
-	.bat_levels_acin = spitz_battery_levels_acin,
+	.backlight_limit = corgibl_limit_intensity,
+	.charge_on_volt	  = SHARPSL_CHARGE_ON_VOLT,
+	.charge_on_temp	  = SHARPSL_CHARGE_ON_TEMP,
+	.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
+	.charge_acin_low  = SHARPSL_CHARGE_ON_ACIN_LOW,
+	.fatal_acin_volt  = SHARPSL_FATAL_ACIN_VOLT,
+	.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
+	.bat_levels       = 40,
+	.bat_levels_noac  = spitz_battery_levels_noac,
+	.bat_levels_acin  = spitz_battery_levels_acin,
 	.status_high_acin = 188,
 	.status_low_acin  = 178,
 	.status_high_noac = 185,
@@ -214,6 +228,9 @@ static int __devinit corgipm_init(void)
 	if (!corgipm_device)
 		return -ENOMEM;
 
+	if (!machine_is_corgi())
+	    corgi_pm_machinfo.batfull_irq = 1;
+
 	corgipm_device->dev.platform_data = &corgi_pm_machinfo;
 	ret = platform_device_add(corgipm_device);
 
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 8a25a1c8019f..f9421318cb7a 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -50,12 +50,14 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
 	unsigned long ret,flag;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 
 	ssp_write_word(&corgi_ssp_dev,data);
 	ret = ssp_read_word(&corgi_ssp_dev);
 
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	return ret;
@@ -68,12 +70,14 @@ unsigned long corgi_ssp_ads7846_putget(ulong data)
 void corgi_ssp_ads7846_lock(void)
 {
 	spin_lock(&corgi_ssp_lock);
-	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 }
 
 void corgi_ssp_ads7846_unlock(void)
 {
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock(&corgi_ssp_lock);
 }
 
@@ -110,11 +114,13 @@ unsigned long corgi_ssp_dac_put(ulong data)
 	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
 	ssp_enable(&corgi_ssp_dev);
 
-	GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 	ssp_write_word(&corgi_ssp_dev,data);
 	/* Read null data back from device to prevent SSP overflow */
 	ssp_read_word(&corgi_ssp_dev);
-	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
@@ -147,7 +153,8 @@ int corgi_ssp_max1111_get(ulong data)
 	int voltage,voltage1,voltage2;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
 	ssp_enable(&corgi_ssp_dev);
@@ -169,7 +176,8 @@ int corgi_ssp_max1111_get(ulong data)
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
 	ssp_enable(&corgi_ssp_dev);
-	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	if (voltage1 & 0xc0 || voltage2 & 0x3f)
@@ -196,9 +204,12 @@ static int __init corgi_ssp_probe(struct platform_device *dev)
 	int ret;
 
 	/* Chip Select - Disable All */
-	pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
-        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
-        pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_max1111 >= 0)
+	        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+        	pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
 
 	ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
 
@@ -229,9 +240,12 @@ static int corgi_ssp_suspend(struct platform_device *dev, pm_message_t state)
 
 static int corgi_ssp_resume(struct platform_device *dev)
 {
-	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
-	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
 	ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
 	ssp_enable(&corgi_ssp_dev);
 
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 3e26d7ce5bb2..1ab26c6914f2 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -22,6 +22,10 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <asm/arch/pxa2xx_spi.h>
+
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
@@ -196,6 +200,78 @@ static struct resource smc91x_resources[] = {
 	},
 };
 
+/* ADS7846 is connected through SSP ... and if your board has J5 populated,
+ * you can select it to replace the ucb1400 by switching the touchscreen cable
+ * (to J5) and poking board registers (as done below).  Else it's only useful
+ * for the temperature sensors.
+ */
+static struct resource pxa_ssp_resources[] = {
+	[0] = {
+		.start	= __PREG(SSCR0_P(1)),
+		.end	= __PREG(SSCR0_P(1)) + 0x14,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SSP,
+		.end	= IRQ_SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+	.ssp_type	= PXA25x_SSP,
+	.clock_enable	= CKEN3_SSP,
+	.num_chipselect	= 0,
+};
+
+static struct platform_device pxa_ssp = {
+	.name		= "pxa2xx-spi",
+	.id		= 1,
+	.resource	= pxa_ssp_resources,
+	.num_resources	= ARRAY_SIZE(pxa_ssp_resources),
+	.dev = {
+		.platform_data	= &pxa_ssp_master_info,
+	},
+};
+
+static int lubbock_ads7846_pendown_state(void)
+{
+	/* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
+	return 0;
+}
+
+static struct ads7846_platform_data ads_info = {
+	.model			= 7846,
+	.vref_delay_usecs	= 100,		/* internal, no cap */
+	.get_pendown_state	= lubbock_ads7846_pendown_state,
+	// .x_plate_ohms		= 500,	/* GUESS! */
+	// .y_plate_ohms		= 500,	/* GUESS! */
+};
+
+static void ads7846_cs(u32 command)
+{
+	static const unsigned	TS_nCS = 1 << 11;
+	lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS);
+}
+
+static struct pxa2xx_spi_chip ads_hw = {
+	.tx_threshold		= 1,
+	.rx_threshold		= 2,
+	.cs_control		= ads7846_cs,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = { {
+	.modalias	= "ads7846",
+	.platform_data	= &ads_info,
+	.controller_data = &ads_hw,
+	.irq		= LUBBOCK_BB_IRQ,
+	.max_speed_hz	= 120000 /* max sample rate at 3V */
+				* 26 /* command + data + overhead */,
+	.bus_num	= 1,
+	.chip_select	= 0,
+},
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= -1,
@@ -272,6 +348,7 @@ static struct platform_device *devices[] __initdata = {
 	&smc91x_device,
 	&lubbock_flash_device[0],
 	&lubbock_flash_device[1],
+	&pxa_ssp,
 };
 
 static struct pxafb_mach_info sharp_lm8v31 __initdata = {
@@ -400,6 +477,8 @@ static void __init lubbock_init(void)
 	lubbock_flash_data[flashboot^1].name = "application-flash";
 	lubbock_flash_data[flashboot].name = "boot-rom";
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 
 static struct map_desc lubbock_io_desc[] __initdata = {
@@ -416,6 +495,11 @@ static void __init lubbock_map_io(void)
 	pxa_map_io();
 	iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
 
+	/* SSP data pins */
+	pxa_gpio_mode(GPIO23_SCLK_MD);
+	pxa_gpio_mode(GPIO25_STXD_MD);
+	pxa_gpio_mode(GPIO26_SRXD_MD);
+
 	/* This enables the BTUART */
 	pxa_gpio_mode(GPIO42_BTRXD_MD);
 	pxa_gpio_mode(GPIO43_BTTXD_MD);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index a042473deedd..9a9fa87cea9f 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -18,11 +18,14 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -34,12 +37,15 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/poodle.h>
 #include <asm/arch/pxafb.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/arch/ssp.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/locomo.h>
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
 	[0] = {
@@ -117,13 +123,71 @@ static struct resource locomo_resources[] = {
 	},
 };
 
-static struct platform_device locomo_device = {
+struct platform_device poodle_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(locomo_resources),
 	.resource	= locomo_resources,
 };
 
+EXPORT_SYMBOL(poodle_locomo_device);
+
+/*
+ * Poodle SSP Device
+ */
+
+struct platform_device poodle_ssp_device = {
+	.name		= "corgi-ssp",
+	.id		= -1,
+};
+
+struct corgissp_machinfo poodle_ssp_machinfo = {
+	.port		= 1,
+	.cs_lcdcon	= -1,
+	.cs_ads7846	= -1,
+	.cs_max1111	= -1,
+	.clk_lcdcon	= 2,
+	.clk_ads7846	= 36,
+	.clk_max1111	= 2,
+};
+
+
+/*
+ * Poodle Touch Screen Device
+ */
+static struct resource poodlets_resources[] = {
+	[0] = {
+		.start		= POODLE_IRQ_GPIO_TP_INT,
+		.end		= POODLE_IRQ_GPIO_TP_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static unsigned long poodle_get_hsync_len(void)
+{
+	return 0;
+}
+
+static void poodle_null_hsync(void)
+{
+}
+
+static struct corgits_machinfo  poodle_ts_machinfo = {
+	.get_hsync_len   = poodle_get_hsync_len,
+	.put_hsync       = poodle_null_hsync,
+	.wait_hsync      = poodle_null_hsync,
+};
+
+static struct platform_device poodle_ts_device = {
+	.name		= "corgi-ts",
+	.dev		= {
+		.platform_data	= &poodle_ts_machinfo,
+	},
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(poodlets_resources),
+	.resource	= poodlets_resources,
+};
+
 
 /*
  * MMC/SD Device
@@ -141,7 +205,9 @@ static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(
 	pxa_gpio_mode(GPIO6_MMCCLK_MD);
 	pxa_gpio_mode(GPIO8_MMCCS0_MD);
 	pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN);
+	pxa_gpio_mode(POODLE_GPIO_nSD_WP | GPIO_IN);
 	pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT);
+	pxa_gpio_mode(POODLE_GPIO_SD_PWR1 | GPIO_OUT);
 
 	poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
 
@@ -160,12 +226,22 @@ static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
 {
 	struct pxamci_platform_data* p_d = dev->platform_data;
 
-	if (( 1 << vdd) & p_d->ocr_mask)
-		GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
-	else
-		GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+	if (( 1 << vdd) & p_d->ocr_mask) {
+		GPSR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR);
+		mdelay(2);
+		GPSR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1);
+	} else {
+		GPCR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1);
+		GPCR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR);
+	}
+}
+
+static int poodle_mci_get_ro(struct device *dev)
+{
+	return GPLR(POODLE_GPIO_nSD_WP) & GPIO_bit(POODLE_GPIO_nSD_WP);
 }
 
+
 static void poodle_mci_exit(struct device *dev, void *data)
 {
 	free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data);
@@ -174,6 +250,7 @@ static void poodle_mci_exit(struct device *dev, void *data)
 static struct pxamci_platform_data poodle_mci_platform_data = {
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
 	.init 		= poodle_mci_init,
+	.get_ro		= poodle_mci_get_ro,
 	.setpower 	= poodle_mci_setpower,
 	.exit		= poodle_mci_exit,
 };
@@ -243,14 +320,31 @@ static struct pxafb_mach_info poodle_fb_info __initdata = {
 };
 
 static struct platform_device *devices[] __initdata = {
-	&locomo_device,
+	&poodle_locomo_device,
 	&poodle_scoop_device,
+	&poodle_ssp_device,
+	&poodle_ts_device,
 };
 
+static void poodle_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+	arm_machine_restart('h');
+}
+
+static void poodle_restart(char mode)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+	arm_machine_restart('h');
+}
+
 static void __init poodle_init(void)
 {
 	int ret = 0;
 
+	pm_power_off = poodle_poweroff;
+	arm_pm_restart = poodle_restart;
+
 	/* setup sleep mode values */
 	PWER  = 0x00000002;
 	PFER  = 0x00000000;
@@ -288,6 +382,7 @@ static void __init poodle_init(void)
   	GPSR1 = 0x00000000;
         GPSR2 = 0x00000000;
 
+	set_pxa_fb_parent(&poodle_locomo_device.dev);
 	set_pxa_fb_info(&poodle_fb_info);
 	pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
 	pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT);
@@ -301,6 +396,7 @@ static void __init poodle_init(void)
 	if (ret) {
 		printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
 	}
+	corgi_ssp_set_machinfo(&poodle_ssp_machinfo);
 }
 
 static void __init fixup_poodle(struct machine_desc *desc,
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 6d402b262d8a..0f1648780c41 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -128,6 +128,9 @@ struct battery_thresh  spitz_battery_levels_noac[] = {
  */
 int sharpsl_pm_pxa_read_max1111(int channel)
 {
+	if (machine_is_tosa()) // Ugly, better move this function into another module
+	    return 0;
+
 	return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
 			| MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
 }
@@ -156,7 +159,7 @@ void sharpsl_pm_pxa_init(void)
 		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING);
 	}
 
-	if (!machine_is_corgi())
+	if (sharpsl_pm.machinfo->batfull_irq)
 	{
 		/* Register interrupt handler. */
 		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) {
@@ -174,6 +177,6 @@ void sharpsl_pm_pxa_remove(void)
 	if (sharpsl_pm.machinfo->gpio_fatal)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
 
-	if (!machine_is_corgi())
+	if (sharpsl_pm.machinfo->batfull_irq)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
 }
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 44bcb8097c7a..eb9937f6f5cd 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -27,6 +28,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -432,8 +434,31 @@ static struct platform_device *devices[] __initdata = {
 	&spitzled_device,
 };
 
+static void spitz_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
+	GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
+
+	mdelay(1000);
+	arm_machine_restart('h');
+}
+
+static void spitz_restart(char mode)
+{
+	/* Bootloader magic for a reboot */
+	if((MSC0 & 0xffff0000) == 0x7ff00000)
+		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+
+	spitz_poweroff();
+}
+
 static void __init common_init(void)
 {
+	pm_power_off = spitz_poweroff;
+	arm_pm_restart = spitz_restart;
+
 	PMCR = 0x00;
 
 	/* setup sleep mode values */
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 5e5bdc898482..40be833079c7 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -27,6 +27,13 @@
 #include <asm/arch/pxa-regs.h>
 #include "sharpsl.h"
 
+#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
+#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
+#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
+#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
+#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
+
 static int spitz_last_ac_status;
 
 static void spitz_charger_init(void)
@@ -190,6 +197,7 @@ struct sharpsl_charger_machinfo spitz_pm_machinfo = {
 	.gpio_batlock     = SPITZ_GPIO_BAT_COVER,
 	.gpio_acin        = SPITZ_GPIO_AC_IN,
 	.gpio_batfull     = SPITZ_GPIO_CHRG_FULL,
+	.batfull_irq	  = 1,
 	.gpio_fatal       = SPITZ_GPIO_FATAL_BAT,
 	.discharge        = spitz_discharge,
 	.discharge1       = spitz_discharge1,
@@ -200,6 +208,13 @@ struct sharpsl_charger_machinfo spitz_pm_machinfo = {
 	.read_devdata     = spitzpm_read_devdata,
 	.charger_wakeup   = spitz_charger_wakeup,
 	.should_wakeup    = spitz_should_wakeup,
+        .backlight_limit  = corgibl_limit_intensity,
+	.charge_on_volt	  = SHARPSL_CHARGE_ON_VOLT,
+	.charge_on_temp	  = SHARPSL_CHARGE_ON_TEMP,
+	.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
+	.charge_acin_low  = SHARPSL_CHARGE_ON_ACIN_LOW,
+	.fatal_acin_volt  = SHARPSL_FATAL_ACIN_VOLT,
+	.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
 	.bat_levels       = 40,
 	.bat_levels_noac  = spitz_battery_levels_noac,
 	.bat_levels_acin  = spitz_battery_levels_acin,
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 76c0e7f0a219..7152bc13680f 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -19,12 +19,15 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/system.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
@@ -266,8 +269,31 @@ static struct platform_device *devices[] __initdata = {
 	&tosaled_device,
 };
 
+static void tosa_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT);
+	GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET);
+
+	mdelay(1000);
+	arm_machine_restart('h');
+}
+
+static void tosa_restart(char mode)
+{
+	/* Bootloader magic for a reboot */
+	if((MSC0 & 0xffff0000) == 0x7ff00000)
+		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+
+	tosa_poweroff();
+}
+
 static void __init tosa_init(void)
 {
+	pm_power_off = tosa_poweroff;
+	arm_pm_restart = tosa_restart;
+
 	pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN);
 	pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN);
 	pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 970f98dadffc..f5d9cd498a5f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -70,6 +70,24 @@ config ARCH_S3C2440
 	help
 	  Say Y here if you are using the SMDK2440.
 
+config SMDK2440_CPU2440
+	bool "SMDK2440 with S3C2440 cpu module"
+	depends on ARCH_S3C2440
+	default y if ARCH_S3C2440
+	select CPU_S3C2440
+
+config SMDK2440_CPU2442
+	bool "SMDM2440 with S3C2442 cpu module"
+	depends on ARCH_S3C2440
+	select CPU_S3C2442
+
+config MACH_SMDK2413
+	bool "SMDK2413"
+	select CPU_S3C2412
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2413
+
 config MACH_VR1000
 	bool "Thorcom VR1000"
 	select CPU_S3C2410
@@ -102,19 +120,55 @@ config MACH_NEXCODER_2440
 
 endmenu
 
+config S3C2410_CLOCK
+	bool
+	help
+	  Clock code for the S3C2410, and similar processors
+
 config CPU_S3C2410
 	bool
 	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
 	help
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
 
+# internal node to signify if we are only dealing with an S3C2412
+
+config CPU_S3C2412_ONLY
+	bool
+	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
+	default y if CPU_S3C2412
+
+config CPU_S3C2412
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C244X
+	bool
+	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+	help
+	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
 config CPU_S3C2440
 	bool
 	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
+	select CPU_S3C244X
 	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
 
+config CPU_S3C2442
+	bool
+	depends on ARCH_S3C2420
+	select S3C2410_CLOCK
+	select CPU_S3C244X
+	help
+	  Support for S3C2442 Samsung Mobile CPU based systems.
+
 comment "S3C2410 Boot"
 
 config S3C2410_BOOT_WATCHDOG
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 3e5712db6b52..0c7938645df6 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -24,6 +24,20 @@ obj-$(CONFIG_S3C2410_DMA)  += dma.o
 obj-$(CONFIG_PM)	   += pm.o sleep.o
 obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
 
+# S3C2412 support
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412-clock.o
+
+#
+# S3C244X support
+
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x-irq.o
+
+# Clock control
+
+obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
+
 # S3C2440 support
 
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
@@ -31,6 +45,11 @@ obj-$(CONFIG_CPU_S3C2440)  += s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2410-gpio.o
 
+# S3C2442 support
+
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442-clock.o
+
 # bast extras
 
 obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
@@ -43,6 +62,7 @@ obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 6de713ad319a..e13fb6778890 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -3,7 +3,7 @@
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 Clock control support
+ * S3C24XX Core clock control support
  *
  * Based on, and code from linux/arch/arm/mach-versatile/clock.c
  **
@@ -56,25 +56,6 @@ static LIST_HEAD(clocks);
 
 DEFINE_MUTEX(clocks_mutex);
 
-/* old functions */
-
-void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
-{
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	/* ensure none of the special function bits set */
-	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-}
-
 /* enable and disable calls for use with the clk struct */
 
 static int clk_null_enable(struct clk *clk, int enable)
@@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *clk, int enable)
 	return 0;
 }
 
-int s3c24xx_clkcon_enable(struct clk *clk, int enable)
-{
-	s3c24xx_clk_enable(clk->ctrlbit, enable);
-	return 0;
-}
-
 /* Clock API calls */
 
 struct clk *clk_get(struct device *dev, const char *id)
@@ -173,8 +148,11 @@ unsigned long clk_get_rate(struct clk *clk)
 	if (clk->rate != 0)
 		return clk->rate;
 
-	while (clk->parent != NULL && clk->rate == 0)
-		clk = clk->parent;
+	if (clk->get_rate != NULL)
+		return (clk->get_rate)(clk);
+
+	if (clk->parent != NULL)
+		return clk_get_rate(clk->parent);
 
 	return clk->rate;
 }
@@ -233,31 +211,9 @@ EXPORT_SYMBOL(clk_set_rate);
 EXPORT_SYMBOL(clk_get_parent);
 EXPORT_SYMBOL(clk_set_parent);
 
-/* base clock enable */
-
-static int s3c24xx_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long orig = clkslow;
-
-	if (enable)
-		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
-	else
-		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
-	__raw_writel(clkslow, S3C2410_CLKSLOW);
-
-	/* if we started the UPLL, then allow to settle */
-
-	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
-		udelay(200);
-
-	return 0;
-}
-
 /* base clocks */
 
-static struct clk clk_xtal = {
+struct clk clk_xtal = {
 	.name		= "xtal",
 	.id		= -1,
 	.rate		= 0,
@@ -265,23 +221,27 @@ static struct clk clk_xtal = {
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_upll = {
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+};
+
+struct clk clk_upll = {
 	.name		= "upll",
 	.id		= -1,
 	.parent		= NULL,
-	.enable		= s3c24xx_upll_enable,
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_f = {
+struct clk clk_f = {
 	.name		= "fclk",
 	.id		= -1,
 	.rate		= 0,
-	.parent		= NULL,
+	.parent		= &clk_mpll,
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_h = {
+struct clk clk_h = {
 	.name		= "hclk",
 	.id		= -1,
 	.rate		= 0,
@@ -289,7 +249,7 @@ static struct clk clk_h = {
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_p = {
+struct clk clk_p = {
 	.name		= "pclk",
 	.id		= -1,
 	.rate		= 0,
@@ -308,14 +268,14 @@ struct clk clk_usb_bus = {
 
 static int s3c24xx_dclk_enable(struct clk *clk, int enable)
 {
-	unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON);
+	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 	if (enable)
 		dclkcon |= clk->ctrlbit;
 	else
 		dclkcon &= ~clk->ctrlbit;
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 	return 0;
 }
@@ -334,7 +294,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
 
 	clk->parent = parent;
 
-	dclkcon = __raw_readl(S3C2410_DCLKCON);
+	dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
 		if (uclk)
@@ -348,7 +308,7 @@ static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
 			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
 	}
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 	return 0;
 }
@@ -426,108 +386,6 @@ struct clk s3c24xx_uclk = {
 	.id		= -1,
 };
 
-
-/* standard clock definitions */
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_NAND,
-	}, {
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_LCDC,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_PWMT,
-	}, {
-		.name		= "sdi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SDI,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART2,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_GPIO,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_RTC,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SPI,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}
-};
-
 /* initialise the clock system */
 
 int s3c24xx_register_clock(struct clk *clk)
@@ -537,14 +395,6 @@ int s3c24xx_register_clock(struct clk *clk)
 	if (clk->enable == NULL)
 		clk->enable = clk_null_enable;
 
-	/* if this is a standard clock, set the usage state */
-
-	if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) {
-		unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
-
-		clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0;
-	}
-
 	/* add to the list of available clocks */
 
 	mutex_lock(&clocks_mutex);
@@ -561,44 +411,18 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
 				unsigned long hclk,
 				unsigned long pclk)
 {
-	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	struct clk *clkp = init_clocks;
-	int ptr;
-	int ret;
-
-	printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
+	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
 
 	/* initialise the main system clocks */
 
 	clk_xtal.rate = xtal;
-	clk_upll.rate = s3c2410_get_pll(upllcon, xtal);
+	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
 
+	clk_mpll.rate = fclk;
 	clk_h.rate = hclk;
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
 
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsytems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be  careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	mutex_lock(&clocks_mutex);
-
-	s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0);
-
-	mutex_unlock(&clocks_mutex);
-
 	/* assume uart clocks are correctly setup */
 
 	/* register our clocks */
@@ -606,6 +430,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
 	if (s3c24xx_register_clock(&clk_xtal) < 0)
 		printk(KERN_ERR "failed to register master xtal\n");
 
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
 	if (s3c24xx_register_clock(&clk_upll) < 0)
 		printk(KERN_ERR "failed to register upll clock\n");
 
@@ -618,27 +445,5 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
 	if (s3c24xx_register_clock(&clk_p) < 0)
 		printk(KERN_ERR "failed to register cpu pclk\n");
 
-
-	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
-		printk(KERN_ERR "failed to register usb bus clock\n");
-
-	/* register clocks from clock array */
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* show the clock-slow value */
-
-	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
-	       print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
-	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
-	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
-	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
 	return 0;
 }
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 01bb458bf8eb..7f0ea03e1d49 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -22,6 +22,7 @@ struct clk {
 
 	int		    (*enable)(struct clk *, int enable);
 	int		    (*set_rate)(struct clk *c, unsigned long rate);
+	unsigned long	    (*get_rate)(struct clk *c);
 	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
 	int		    (*set_parent)(struct clk *c, struct clk *parent);
 };
@@ -36,6 +37,15 @@ extern struct clk s3c24xx_uclk;
 
 extern struct clk clk_usb_bus;
 
+/* core clock support */
+
+extern struct clk clk_f;
+extern struct clk clk_h;
+extern struct clk clk_p;
+extern struct clk clk_mpll;
+extern struct clk clk_upll;
+extern struct clk clk_xtal;
+
 /* exports for arch/arm/mach-s3c2410
  *
  * Please DO NOT use these outside of arch/arm/mach-s3c2410
@@ -43,7 +53,8 @@ extern struct clk clk_usb_bus;
 
 extern struct mutex clocks_mutex;
 
-extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+
 extern int s3c24xx_register_clock(struct clk *clk);
 
 extern int s3c24xx_setup_clocks(unsigned long xtal,
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
index c940890f621f..a40eaa656177 100644
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -34,6 +34,7 @@
 #include <asm/irq.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
 
 #include <asm/arch/nand.h>
 
@@ -41,6 +42,66 @@
 #include "devs.h"
 #include "pm.h"
 
+/* LED devices */
+
+static struct s3c24xx_led_platdata smdk_pdata_led4 = {
+	.gpio		= S3C2410_GPF4,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led4",
+	.def_trigger	= "timer",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led5 = {
+	.gpio		= S3C2410_GPF5,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led5",
+	.def_trigger	= "nand-disk",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led6 = {
+	.gpio		= S3C2410_GPF6,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led6",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led7 = {
+	.gpio		= S3C2410_GPF7,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led7",
+};
+
+static struct platform_device smdk_led4 = {
+	.name		= "s3c24xx_led",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &smdk_pdata_led4,
+	},
+};
+
+static struct platform_device smdk_led5 = {
+	.name		= "s3c24xx_led",
+	.id		= 1,
+	.dev		= {
+		.platform_data = &smdk_pdata_led5,
+	},
+};
+
+static struct platform_device smdk_led6 = {
+	.name		= "s3c24xx_led",
+	.id		= 2,
+	.dev		= {
+		.platform_data = &smdk_pdata_led6,
+	},
+};
+
+static struct platform_device smdk_led7 = {
+	.name		= "s3c24xx_led",
+	.id		= 3,
+	.dev		= {
+		.platform_data = &smdk_pdata_led7,
+	},
+};
+
 /* NAND parititon from 2.4.18-swl5 */
 
 static struct mtd_partition smdk_default_nand_part[] = {
@@ -111,6 +172,10 @@ static struct s3c2410_platform_nand smdk_nand_info = {
 
 static struct platform_device __initdata *smdk_devs[] = {
 	&s3c_device_nand,
+	&smdk_led4,
+	&smdk_led5,
+	&smdk_led6,
+	&smdk_led7,
 };
 
 void __init smdk_machine_init(void)
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 70c34fcf7858..1c3c6adae6c4 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -37,12 +37,17 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
 
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 #include "s3c2400.h"
 #include "s3c2410.h"
+#include "s3c2412.h"
+#include "s3c244x.h"
 #include "s3c2440.h"
+#include "s3c2442.h"
 
 struct cpu_table {
 	unsigned long	idcode;
@@ -58,7 +63,9 @@ struct cpu_table {
 
 static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2442[]  = "S3C2442";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2440a[] = "S3C2440A";
 
@@ -84,22 +91,40 @@ static struct cpu_table cpu_ids[] __initdata = {
 	{
 		.idcode		= 0x32440000,
 		.idmask		= 0xffffffff,
-		.map_io		= s3c2440_map_io,
-		.init_clocks	= s3c2440_init_clocks,
-		.init_uarts	= s3c2440_init_uarts,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
 		.init		= s3c2440_init,
 		.name		= name_s3c2440
 	},
 	{
 		.idcode		= 0x32440001,
 		.idmask		= 0xffffffff,
-		.map_io		= s3c2440_map_io,
-		.init_clocks	= s3c2440_init_clocks,
-		.init_uarts	= s3c2440_init_uarts,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
 		.init		= s3c2440_init,
 		.name		= name_s3c2440a
 	},
 	{
+		.idcode		= 0x32440aaa,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
+		.init		= s3c2442_init,
+		.name		= name_s3c2442
+	},
+	{
+		.idcode		= 0x32412001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
+	{
 		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2400_map_io,
@@ -157,6 +182,24 @@ void s3c24xx_set_board(struct s3c24xx_board *b)
 
 static struct cpu_table *cpu;
 
+static unsigned long s3c24xx_read_idcode_v5(void)
+{
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+	return __raw_readl(S3C2412_GSTATUS1);
+#else
+	return 1UL;	/* don't look like an 2400 */
+#endif
+}
+
+static unsigned long s3c24xx_read_idcode_v4(void)
+{
+#ifndef CONFIG_CPU_S3C2400
+	return __raw_readl(S3C2410_GSTATUS1);
+#else
+	return 0UL;
+#endif
+}
+
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
 	unsigned long idcode = 0x0;
@@ -164,9 +207,11 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
-#ifndef CONFIG_CPU_S3C2400
-	idcode = __raw_readl(S3C2410_GSTATUS1);
-#endif
+	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
+		idcode = s3c24xx_read_idcode_v5();
+	} else {
+		idcode = s3c24xx_read_idcode_v4();
+	}
 
 	cpu = s3c_lookup_cpu(idcode);
 
@@ -175,13 +220,13 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 		panic("Unknown S3C24XX CPU");
 	}
 
+	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
 	if (cpu->map_io == NULL || cpu->init == NULL) {
 		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
 		panic("Unsupported S3C24XX CPU");
 	}
 
-	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
-
 	(cpu->map_io)(mach_desc, size);
 }
 
@@ -208,6 +253,49 @@ void __init s3c24xx_init_clocks(int xtal)
 		(cpu->init_clocks)(xtal);
 }
 
+/* uart management */
+
+static int nr_uarts __initdata = 0;
+
+static struct s3c2410_uartcfg uart_cfgs[3];
+
+/* s3c24xx_init_uartdevs
+ *
+ * copy the specified platform data and configuration into our central
+ * set of devices, before the data is thrown away after the init process.
+ *
+ * This also fills in the array passed to the serial driver for the
+ * early initialisation of the console.
+*/
+
+void __init s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no)
+{
+	struct platform_device *platdev;
+	struct s3c2410_uartcfg *cfgptr = uart_cfgs;
+	struct s3c24xx_uart_resources *resp;
+	int uart;
+
+	memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
+
+	for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
+		platdev = s3c24xx_uart_src[cfgptr->hwport];
+
+		resp = res + cfgptr->hwport;
+
+		s3c24xx_uart_devs[uart] = platdev;
+
+		platdev->name = name;
+		platdev->resource = resp->resources;
+		platdev->num_resources = resp->nr_resources;
+
+		platdev->dev.platform_data = cfgptr;
+	}
+
+	nr_uarts = no;
+}
+
 void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
 	if (cpu == NULL)
@@ -232,6 +320,10 @@ static int __init s3c_arch_init(void)
 	if (ret != 0)
 		return ret;
 
+	ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
+	if (ret != 0)
+		return ret;
+
 	if (board != NULL) {
 		struct platform_device **ptr = board->devices;
 		int i;
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index fc1067783f6d..b0ed9d2d141b 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -31,6 +31,8 @@
 #define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
 
 /* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
 struct s3c2410_uartcfg;
 struct map_desc;
 
@@ -44,6 +46,10 @@ extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
 
+extern void s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no);
+
 /* the board structure is used at first initialsation time
  * to get info such as the devices to register for this
  * board. This is done because platfrom_add_devices() cannot
@@ -67,4 +73,7 @@ extern struct sys_timer s3c24xx_timer;
 
 /* system device classes */
 
+extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index ca09ba516e4c..ad3845e329ba 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -38,10 +38,86 @@
 #include <asm/arch/regs-serial.h>
 
 #include "devs.h"
+#include "cpu.h"
 
 /* Serial port registrations */
 
-struct platform_device *s3c24xx_uart_devs[3];
+static struct resource s3c2410_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c2410_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c2410_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c2410_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
+	},
+};
+
+/* yart devices */
+
+static struct platform_device s3c24xx_uart_device0 = {
+	.id		= 0,
+};
+
+static struct platform_device s3c24xx_uart_device1 = {
+	.id		= 1,
+};
+
+static struct platform_device s3c24xx_uart_device2 = {
+	.id		= 2,
+};
+
+struct platform_device *s3c24xx_uart_src[3] = {
+	&s3c24xx_uart_device0,
+	&s3c24xx_uart_device1,
+	&s3c24xx_uart_device2,
+};
+
+struct platform_device *s3c24xx_uart_devs[3] = {
+};
 
 /* USB Host Controller */
 
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
index 52c4bab5c761..fa124ed920e0 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/arch/arm/mach-s3c2410/devs.h
@@ -17,7 +17,15 @@
 #include <linux/config.h>
 #include <linux/platform_device.h>
 
+struct s3c24xx_uart_resources {
+	struct resource		*resources;
+	unsigned long		 nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+
 extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
 
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 66d8c068e940..6822dc7f7799 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -191,13 +191,9 @@ static struct irqchip s3c_irq_chip = {
 	.ack	   = s3c_irq_ack,
 	.mask	   = s3c_irq_mask,
 	.unmask	   = s3c_irq_unmask,
-	.set_wake	   = s3c_irq_wake
+	.set_wake  = s3c_irq_wake
 };
 
-/* S3C2410_EINTMASK
- * S3C2410_EINTPEND
- */
-
 static void
 s3c_irqext_mask(unsigned int irqno)
 {
@@ -205,9 +201,9 @@ s3c_irqext_mask(unsigned int irqno)
 
 	irqno -= EXTINT_OFF;
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask |= ( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 	if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
 		/* check to see if all need masking */
@@ -232,11 +228,11 @@ s3c_irqext_ack(unsigned int irqno)
 	bit = 1UL << (irqno - EXTINT_OFF);
 
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 
-	__raw_writel(bit, S3C2410_EINTPEND);
+	__raw_writel(bit, S3C24XX_EINTPEND);
 
-	req = __raw_readl(S3C2410_EINTPEND);
+	req = __raw_readl(S3C24XX_EINTPEND);
 	req &= ~mask;
 
 	/* not sure if we should be acking the parent irq... */
@@ -257,9 +253,9 @@ s3c_irqext_unmask(unsigned int irqno)
 
 	irqno -= EXTINT_OFF;
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask &= ~( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
@@ -275,28 +271,28 @@ s3c_irqext_type(unsigned int irq, unsigned int type)
 	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
 	{
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - IRQ_EINT0) * 2;
 		extint_offset = (irq - IRQ_EINT0) * 4;
 	}
 	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
 	{
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
 		extint_offset = (irq - (EXTINT_OFF)) * 4;
 	}
 	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
 	{
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT1;
+		extint_reg = S3C24XX_EXTINT1;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT8) * 4;
 	}
 	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
 	{
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT2;
+		extint_reg = S3C24XX_EXTINT2;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT16) * 4;
 	} else
@@ -572,6 +568,23 @@ s3c_irq_demux_uart2(unsigned int irq,
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
+static void
+s3c_irq_demux_extint(unsigned int irq,
+		     struct irqdesc *desc,
+		     struct pt_regs *regs)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+
+	if (eintpnd) {
+		irq = fls(eintpnd);
+		irq += (IRQ_EINT4 - (4 + 1));
+
+		desc_handle_irq(irq, irq_desc + irq, regs);
+	}
+}
 
 /* s3c24xx_init_irq
  *
@@ -591,12 +604,12 @@ void __init s3c24xx_init_irq(void)
 
 	last = 0;
 	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_EINTPEND);
+		pend = __raw_readl(S3C24XX_EINTPEND);
 
 		if (pend == 0 || pend == last)
 			break;
 
-		__raw_writel(pend, S3C2410_EINTPEND);
+		__raw_writel(pend, S3C24XX_EINTPEND);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
 		last = pend;
 	}
@@ -630,12 +643,14 @@ void __init s3c24xx_init_irq(void)
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-	for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 
 		switch (irqno) {
 			/* deal with the special IRQs (cascaded) */
 
+		case IRQ_EINT4t7:
+		case IRQ_EINT8t23:
 		case IRQ_UART0:
 		case IRQ_UART1:
 		case IRQ_UART2:
@@ -659,12 +674,14 @@ void __init s3c24xx_init_irq(void)
 
 	/* setup the cascade irq handlers */
 
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
+
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
 	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
-
 	/* external interrupts */
 
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index cc97fbf66291..4a92d6f92d6b 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -131,7 +131,7 @@ static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
 };
 
 
-static struct s3c2410_uartcfg anubis_uartcfgs[] = {
+static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -239,6 +239,54 @@ static struct s3c2410_platform_nand anubis_nand_info = {
 	.select_chip	= anubis_nand_select,
 };
 
+/* IDE channels */
+
+static struct resource anubis_ide0_resource[] = {
+	{
+		.start	= S3C2410_CS3,
+		.end	= S3C2410_CS3 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS3 + (1<<26),
+		.end	= S3C2410_CS3 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device anubis_device_ide0 = {
+	.name		= "simtec-ide",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
+	.resource	= anubis_ide0_resource,
+};
+
+static struct resource anubis_ide1_resource[] = {
+	{
+		.start	= S3C2410_CS4,
+		.end	= S3C2410_CS4 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS4 + (1<<26),
+		.end	= S3C2410_CS4 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device anubis_device_ide1 = {
+	.name		= "simtec-ide",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
+	.resource	= anubis_ide1_resource,
+};
 
 /* Standard Anubis devices */
 
@@ -249,6 +297,8 @@ static struct platform_device *anubis_devices[] __initdata = {
 	&s3c_device_i2c,
  	&s3c_device_rtc,
 	&s3c_device_nand,
+	&anubis_device_ide0,
+	&anubis_device_ide1,
 };
 
 static struct clk *anubis_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 995bb8add331..947234df8160 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -208,7 +208,7 @@ static struct s3c24xx_uart_clksrc bast_serial_clocks[] = {
 };
 
 
-static struct s3c2410_uartcfg bast_uartcfgs[] = {
+static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 646a3a5d33a5..aec431b2830a 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -72,7 +72,7 @@ static struct map_desc h1940_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg h1940_uartcfgs[] = {
+static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
index 07d09509a626..065a1d4e860b 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -51,7 +51,7 @@ static struct map_desc nexcoder_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg nexcoder_uartcfgs[] = {
+static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
index ae0787557751..858fd03c6bc5 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2410/mach-osiris.c
@@ -95,8 +95,7 @@ static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
 	}
 };
 
-
-static struct s3c2410_uartcfg osiris_uartcfgs[] = {
+static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -107,7 +106,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] = {
 		.clocks_size = ARRAY_SIZE(osiris_serial_clocks)
 	},
 	[1] = {
-		.hwport	     = 2,
+		.hwport	     = 1,
 		.flags	     = 0,
 		.ucon	     = UCON,
 		.ulcon	     = ULCON,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index b39daedf93ca..c71673fd9955 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -45,7 +45,7 @@ static struct map_desc otom11_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg otom11_uartcfgs[] = {
+static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 2db932d72c5a..25f7e9f4dcee 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -65,7 +65,7 @@ static struct map_desc smdk2410_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
new file mode 100644
index 000000000000..b7ef7d3c54a9
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-smdk2413.c
@@ -0,0 +1,126 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
+ * loans of SMDK2413 to work with.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#include "common-smdk.h"
+
+static struct map_desc smdk2413_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct platform_device *smdk2413_devices[] __initdata = {
+	&s3c_device_usb,
+	//&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2413_board __initdata = {
+	.devices       = smdk2413_devices,
+	.devices_count = ARRAY_SIZE(smdk2413_devices)
+};
+
+static void __init smdk2413_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init smdk2413_map_io(void)
+{
+	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+	s3c24xx_set_board(&smdk2413_board);
+}
+
+static void __init smdk2413_machine_init(void)
+{
+	smdk_machine_init();
+}
+
+MACHINE_START(S3C2413, "SMDK2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 5fffd1d51047..d661c6b7ff56 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -86,7 +86,7 @@ static struct map_desc smdk2440_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2440_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 785fc9cdcf7c..d18efb279d3d 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -166,7 +166,7 @@ static struct s3c24xx_uart_clksrc vr1000_serial_clocks[] = {
 	}
 };
 
-static struct s3c2410_uartcfg vr1000_uartcfgs[] = {
+static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 4c7ccef6c207..7b244566a436 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -48,7 +48,8 @@ static __init int pm_simtec_init(void)
 
 	/* check which machine we are running on */
 
-	if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
+	if (!machine_is_bast() && !machine_is_vr1000() &&
+	    !machine_is_anubis() && !machine_is_osiris())
 		return 0;
 
 	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index fe57d966a34d..43e9a550a203 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -58,7 +58,11 @@ unsigned long s3c_pm_flags;
 
 /* cache functions from arch/arm/mm/proc-arm920.S */
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 extern void arm920_flush_kern_cache_all(void);
+#else
+static void arm920_flush_kern_cache_all(void) { }
+#endif
 
 #define PFX "s3c24xx-pm: "
 
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
new file mode 100644
index 000000000000..99718663318e
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-clock.c
@@ -0,0 +1,271 @@
+/* linux/arch/arm/mach-s3c2410/clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410,S3C2440,S3C2442 Clock control support
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	/* ensure none of the special function bits set */
+	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2410_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long orig = clkslow;
+
+	if (enable)
+		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
+	else
+		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
+
+	__raw_writel(clkslow, S3C2410_CLKSLOW);
+
+	/* if we started the UPLL, then allow to settle */
+
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+		udelay(200);
+
+	return 0;
+}
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	},
+};
+
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
+
+int __init s3c2410_baseclk_add(void)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	struct clk *xtal;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2410_upll_enable;
+
+	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+		printk(KERN_ERR "failed to register usb bus clock\n");
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2410_clkcon_enable(clkp, 0);
+	}
+
+	/* show the clock-slow value */
+
+	xtal = clk_get(NULL, "xtal");
+
+	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+	       print_mhz(clk_get_rate(xtal) /
+			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
index d5e1caea1d23..471a71490010 100644
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c
@@ -18,9 +18,6 @@
  * 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
- *
- * Changelog
- *	15-Jan-2006  LCVR  Splitted from gpio.c
  */
 
 #include <linux/kernel.h>
@@ -38,7 +35,7 @@
 int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 			   unsigned int config)
 {
-	void __iomem *reg = S3C2410_EINFLT0;
+	void __iomem *reg = S3C24XX_EINFLT0;
 	unsigned long flags;
 	unsigned long val;
 
@@ -47,7 +44,7 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 
 	config &= 0xff;
 
-	pin -= S3C2410_GPG8_EINT16;
+	pin -= S3C2410_GPG8;
 	reg += pin & ~3;
 
 	local_irq_save(flags);
@@ -61,10 +58,10 @@ int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 
 	/* update filter enable */
 
-	val = __raw_readl(S3C2410_EXTINT2);
+	val = __raw_readl(S3C24XX_EXTINT2);
 	val &= ~(1 << ((pin * 4) + 3));
 	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C2410_EXTINT2);
+	__raw_writel(val, S3C24XX_EXTINT2);
 
 	local_irq_restore(flags);
 
@@ -75,7 +72,7 @@ EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
 
 int s3c2410_gpio_getirq(unsigned int pin)
 {
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
 		return -1;	/* not valid interrupts */
 
 	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 0a2013a76549..a110cff9cf6b 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 
 #include <asm/mach/arch.h>
@@ -42,6 +43,7 @@
 
 #include "s3c2410.h"
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 
 /* Initial IO mappings */
@@ -55,93 +57,13 @@ static struct map_desc s3c2410_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
 };
 
-static struct resource s3c_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
 /* our uart devices */
 
-static struct platform_device s3c_uart0 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_uart0_resource),
-	.resource	  = s3c_uart0_resource,
-};
-
-
-static struct platform_device s3c_uart1 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_uart1_resource),
-	.resource	  = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_uart2_resource),
-	.resource	  = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-	&s3c_uart0,
-	&s3c_uart1,
-	&s3c_uart2
-};
-
-static int s3c2410_uart_count = 0;
-
 /* uart registration process */
 
 void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
-	struct platform_device *platdev;
-	int uart;
-
-	for (uart = 0; uart < no; uart++, cfg++) {
-		platdev = uart_devices[cfg->hwport];
-
-		s3c24xx_uart_devs[uart] = platdev;
-		platdev->dev.platform_data = cfg;
-	}
-
-	s3c2410_uart_count = uart;
+	s3c24xx_init_uartdevs("s3c2410-uart", s3c2410_uart_resources, cfg, no);
 }
 
 /* s3c2410_map_io
@@ -187,11 +109,33 @@ void __init s3c2410_init_clocks(int xtal)
 	 */
 
 	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2410_baseclk_add();
 }
 
+struct sysdev_class s3c2410_sysclass = {
+	set_kset_name("s3c2410-core"),
+};
+
+static struct sys_device s3c2410_sysdev = {
+	.cls		= &s3c2410_sysclass,
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2410_core_init(void)
+{
+	return sysdev_class_register(&s3c2410_sysclass);
+}
+
+core_initcall(s3c2410_core_init);
+
 int __init s3c2410_init(void)
 {
 	printk("S3C2410: Initialising architecture\n");
 
-	return platform_add_devices(s3c24xx_uart_devs, s3c2410_uart_count);
+	return sysdev_register(&s3c2410_sysdev);
 }
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
index 4d5312a48209..73f1a2474a61 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/arch/arm/mach-s3c2410/s3c2410.h
@@ -29,6 +29,8 @@ extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c2410_init_clocks(int xtal);
 
+extern  int s3c2410_baseclk_add(void);
+
 #else
 #define s3c2410_init_clocks NULL
 #define s3c2410_init_uarts NULL
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
new file mode 100644
index 000000000000..c95ed3e18580
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-clock.c
@@ -0,0 +1,711 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412,S3C2413 Clock control support
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+int s3c2412_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2412_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+	unsigned long orig = upllcon;
+
+	if (!enable)
+		upllcon |= S3C2412_PLLCON_OFF;
+	else
+		upllcon &= ~S3C2412_PLLCON_OFF;
+
+	__raw_writel(upllcon, S3C2410_UPLLCON);
+
+	/* allow ~150uS for the PLL to settle and lock */
+
+	if (enable && (orig & S3C2412_PLLCON_OFF))
+		udelay(150);
+
+	return 0;
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+	.name		= "extclk",
+	.id		= -1,
+};
+
+static struct clk clk_erefclk = {
+	.name		= "erefclk",
+	.id		= -1,
+};
+
+static struct clk clk_urefclk = {
+	.name		= "urefclk",
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_urefclk)
+		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_usysclk = {
+	.name		= "usysclk",
+	.id		= -1,
+	.parent		= &clk_xtal,
+	.set_parent	= s3c2412_setparent_usysclk,
+};
+
+static struct clk clk_mrefclk = {
+	.name		= "mrefclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static struct clk clk_mdivclk = {
+	.name		= "mdivclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+	if (div > 2)
+		div = 2;
+
+	return parent_rate / div;
+}
+
+static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
+}
+
+static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_usbsrc(clk, rate);
+
+	if ((parent_rate / rate) == 2)
+		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
+	else
+		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_usbsrc = {
+	.name		= "usbsrc",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_usbsrc,
+	.set_rate	= s3c2412_setrate_usbsrc,
+	.round_rate	= s3c2412_roundrate_usbsrc,
+	.set_parent	= s3c2412_setparent_usbsrc,
+};
+
+static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_mdivclk)
+		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_msysclk = {
+	.name		= "msysclk",
+	.id		= -1,
+	.set_parent	= s3c2412_setparent_msysclk,
+};
+
+/* these next clocks have an divider immediately after them,
+ * so we can register them with their divider and leave out the
+ * intermediate clock stage
+*/
+static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations as they cancel out */
+
+	div = (rate / parent_rate);
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / div;
+}
+
+static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_uart(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
+	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_uart = {
+	.name		= "uartclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_uart,
+	.set_rate	= s3c2412_setrate_uart,
+	.set_parent	= s3c2412_setparent_uart,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_i2s(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
+	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_i2s = {
+	.name		= "i2sclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_i2s,
+	.set_rate	= s3c2412_setrate_i2s,
+	.set_parent	= s3c2412_setparent_i2s,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+static unsigned long s3c2412_getrate_cam(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
+	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_cam = {
+	.name		= "camif-upll",	/* same as 2440 name */
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_cam,
+	.set_rate	= s3c2412_setrate_cam,
+	.set_parent	= s3c2412_setparent_cam,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "dma",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA0,
+	}, {
+		.name		= "dma",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA1,
+	}, {
+		.name		= "dma",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA2,
+	}, {
+		.name		= "dma",
+		.id		= 3,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA3,
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
+	}
+};
+
+/* clocks to add where we need to check their parentage */
+
+struct clk_init {
+	struct clk	*clk;
+	unsigned int	 bit;
+	struct clk	*src_0;
+	struct clk	*src_1;
+};
+
+struct clk_init clks_src[] __initdata = {
+	{
+		.clk	= &clk_usysclk,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_urefclk,
+		.src_1	= &clk_upll,
+	}, {
+		.clk	= &clk_i2s,
+		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_cam,
+		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	}, {
+		.clk	= &clk_msysclk,
+		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
+		.src_0	= &clk_mdivclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_uart,
+		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_usbsrc,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	},
+};
+
+/* s3c2412_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static void __init s3c2412_clk_initparents(void)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+	struct clk_init *cip = clks_src;
+	struct clk *src;
+	int ptr;
+	int ret;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
+		ret = s3c24xx_register_clock(cip->clk);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       cip->clk->name, ret);
+		}
+
+		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
+
+		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
+		clk_set_parent(cip->clk, src);
+	}
+}
+
+/* clocks to add straight away */
+
+struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_usb_bus,
+	&clk_erefclk,
+	&clk_urefclk,
+	&clk_mrefclk,
+};
+
+int __init s3c2412_baseclk_add(void)
+{
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2412_upll_enable;
+	clk_usb_bus.parent = &clk_usbsrc;
+	clk_usb_bus.rate = 0x0;
+
+	s3c2412_clk_initparents();
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+		clkp = clks[ptr];
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* ensure usb bus clock is within correct rate of 48MHz */
+
+	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
+		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
+
+		/* for the moment, let's use the UPLL, and see if we can
+		 * get 48MHz */
+
+		clk_set_parent(&clk_usysclk, &clk_upll);
+		clk_set_parent(&clk_usbsrc, &clk_usysclk);
+		clk_set_rate(&clk_usbsrc, 48*1000*1000);
+	}
+
+	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
+	       print_mhz(clk_get_rate(&clk_upll)),
+	       print_mhz(clk_get_rate(&clk_usb_bus)));
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2412_clkcon_enable(clkp, 0);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
new file mode 100644
index 000000000000..e24ffd5e478b
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.c
@@ -0,0 +1,195 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     16-May-2003 BJD  Created initial version
+ *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
+ *     05-Sep-2003 BJD  Moved to kernel v2.6
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
+ *     28-Sep-2004 BJD  Updates for new serial port bits
+ *     04-Nov-2004 BJD  Updated UART configuration process
+ *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
+ *     13-Aug-2005 DA   Removed UART from initial I/O mappings
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2412.h"
+#include "cpu.h"
+#include "devs.h"
+#include "clock.h"
+#include "pm.h"
+
+#ifndef CONFIG_CPU_S3C2412_ONLY
+void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+#endif
+
+/* Initial IO mappings */
+
+static struct map_desc s3c2412_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+	IODESC_ENT(WATCHDOG),
+};
+
+/* uart registration process */
+
+void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
+
+	/* rename devices that are s3c2412/s3c2413 specific */
+	s3c_device_sdi.name  = "s3c2412-sdi";
+	s3c_device_nand.name = "s3c2412-nand";
+}
+
+/* s3c2412_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+*/
+
+void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
+{
+	/* move base of IO */
+
+	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+
+	/* register our io-tables */
+
+	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
+	iotable_init(mach_desc, mach_size);
+}
+
+void __init s3c2412_init_clocks(int xtal)
+{
+	unsigned long tmp;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
+
+	tmp = __raw_readl(S3C2410_CLKDIVN);
+
+	/* work out clock scalings */
+
+	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
+	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brieft summary of clocks, etc */
+
+	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2412_baseclk_add();
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2412 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c2412_sleep[] = {
+	SAVE_ITEM(S3C2412_DSC0),
+	SAVE_ITEM(S3C2412_DSC1),
+	SAVE_ITEM(S3C2413_GPJDAT),
+	SAVE_ITEM(S3C2413_GPJCON),
+	SAVE_ITEM(S3C2413_GPJUP),
+
+	/* save the sleep configuration anyway, just in case these
+	 * get damaged during wakeup */
+
+	SAVE_ITEM(S3C2412_GPBSLPCON),
+	SAVE_ITEM(S3C2412_GPCSLPCON),
+	SAVE_ITEM(S3C2412_GPDSLPCON),
+	SAVE_ITEM(S3C2412_GPESLPCON),
+	SAVE_ITEM(S3C2412_GPFSLPCON),
+	SAVE_ITEM(S3C2412_GPGSLPCON),
+	SAVE_ITEM(S3C2412_GPHSLPCON),
+	SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static int s3c2412_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+#else
+#define s3c2412_suspend NULL
+#define s3c2412_resume  NULL
+#endif
+
+struct sysdev_class s3c2412_sysclass = {
+	set_kset_name("s3c2412-core"),
+	.suspend	= s3c2412_suspend,
+	.resume		= s3c2412_resume
+};
+
+static int __init s3c2412_core_init(void)
+{
+	return sysdev_class_register(&s3c2412_sysclass);
+}
+
+core_initcall(s3c2412_core_init);
+
+static struct sys_device s3c2412_sysdev = {
+	.cls		= &s3c2412_sysclass,
+};
+
+int __init s3c2412_init(void)
+{
+	printk("S3C2412: Initialising architecture\n");
+
+	return sysdev_register(&s3c2412_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
new file mode 100644
index 000000000000..c6e56032a6e7
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.h
@@ -0,0 +1,29 @@
+/* arch/arm/mach-s3c2410/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index d7a30ed6c327..15796864d010 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -91,7 +91,7 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
 static struct clk s3c2440_clk_cam = {
 	.name		= "camif",
 	.id		= -1,
-	.enable		= s3c24xx_clkcon_enable,
+	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
 
@@ -105,7 +105,7 @@ static struct clk s3c2440_clk_cam_upll = {
 static struct clk s3c2440_clk_ac97 = {
 	.name		= "ac97",
 	.id		= -1,
-	.enable		= s3c24xx_clkcon_enable,
+	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
 
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index 278d0044c85d..acfe3870727b 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -100,73 +100,12 @@ static struct irqchip s3c_irq_wdtac97 = {
 	.ack	    = s3c_irq_wdtac97_ack,
 };
 
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-			      struct irqdesc *desc,
-			      struct pt_regs *regs)
-{
-	unsigned int subsrc, submsk;
-	struct irqdesc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 11;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
-			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
-			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
-		}
-	}
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
-}
-
-static void
-s3c_irq_cam_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
-}
-
-static struct irqchip s3c_irq_cam = {
-	.mask	    = s3c_irq_cam_mask,
-	.unmask	    = s3c_irq_cam_unmask,
-	.ack	    = s3c_irq_cam_ack,
-};
-
 static int s3c2440_irq_add(struct sys_device *sysdev)
 {
 	unsigned int irqno;
 
 	printk("S3C2440: IRQ Support\n");
 
-	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_NFCON, do_level_IRQ);
-	set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
 	/* add new chained handler for wdt, ac7 */
 
 	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
@@ -179,18 +118,6 @@ static int s3c2440_irq_add(struct sys_device *sysdev)
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
-	/* add chained handler for camera */
-
-	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_CAM, do_level_IRQ);
-	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
-
-	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_cam);
-		set_irq_handler(irqno, do_level_IRQ);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
 	return 0;
 }
 
@@ -198,10 +125,10 @@ static struct sysdev_driver s3c2440_irq_driver = {
 	.add	= s3c2440_irq_add,
 };
 
-static int s3c24xx_irq_driver(void)
+static int s3c2440_irq_init(void)
 {
 	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
 }
 
-arch_initcall(s3c24xx_irq_driver);
+arch_initcall(s3c2440_irq_init);
 
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index b7fe6d9453fb..0ab50f44f318 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/s3c2440.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * Samsung S3C2440 Mobile CPU support
@@ -8,16 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *	24-Aug-2004 BJD  Start of s3c2440 support
- *	12-Oct-2004 BJD	 Moved clock info out to clock.c
- *	01-Nov-2004 BJD  Fixed clock build code
- *	09-Nov-2004 BJD  Added sysdev for power management
- *	04-Nov-2004 BJD  New serial registration
- *	15-Nov-2004 BJD  Rename the i2c device for the s3c2440
- *	14-Jan-2005 BJD  Moved clock init code into seperate function
- *	14-Jan-2005 BJD  Removed un-used clock bits
 */
 
 #include <linux/kernel.h>
@@ -50,234 +40,20 @@
 #include "cpu.h"
 #include "pm.h"
 
-
-static struct map_desc s3c2440_iodesc[] __initdata = {
-	IODESC_ENT(USBHOST),
-	IODESC_ENT(CLKPWR),
-	IODESC_ENT(LCD),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(ADC),
-	IODESC_ENT(WATCHDOG),
-};
-
-static struct resource s3c_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-/* our uart devices */
-
-static struct platform_device s3c_uart0 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_uart0_resource),
-	.resource	  = s3c_uart0_resource,
-};
-
-static struct platform_device s3c_uart1 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_uart1_resource),
-	.resource	  = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_uart2_resource),
-	.resource	  = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-	&s3c_uart0,
-	&s3c_uart1,
-	&s3c_uart2
-};
-
-/* uart initialisation */
-
-static int __initdata s3c2440_uart_count;
-
-void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	struct platform_device *platdev;
-	int uart;
-
-	for (uart = 0; uart < no; uart++, cfg++) {
-		platdev = uart_devices[cfg->hwport];
-
-		s3c24xx_uart_devs[uart] = platdev;
-		platdev->dev.platform_data = cfg;
-	}
-
-	s3c2440_uart_count = uart;
-}
-
-
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c2440_sleep[] = {
-	SAVE_ITEM(S3C2440_DSC0),
-	SAVE_ITEM(S3C2440_DSC1),
-	SAVE_ITEM(S3C2440_GPJDAT),
-	SAVE_ITEM(S3C2440_GPJCON),
-	SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c2440_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-	return 0;
-}
-
-static int s3c2440_resume(struct sys_device *dev)
-{
-	s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-	return 0;
-}
-
-#else
-#define s3c2440_suspend NULL
-#define s3c2440_resume  NULL
-#endif
-
-struct sysdev_class s3c2440_sysclass = {
-	set_kset_name("s3c2440-core"),
-	.suspend	= s3c2440_suspend,
-	.resume		= s3c2440_resume
-};
-
 static struct sys_device s3c2440_sysdev = {
 	.cls		= &s3c2440_sysclass,
 };
 
-void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
+int __init s3c2440_init(void)
 {
-	/* register our io-tables */
-
-	iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
-	iotable_init(mach_desc, size);
-
-	/* rename any peripherals used differing from the s3c2410 */
-
-	s3c_device_i2c.name  = "s3c2440-i2c";
-	s3c_device_nand.name = "s3c2440-nand";
+	printk("S3C2440: Initialising architecture\n");
 
 	/* change irq for watchdog */
 
 	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
 	s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
-}
-
-void __init s3c2440_init_clocks(int xtal)
-{
-	unsigned long clkdiv;
-	unsigned long camdiv;
-	unsigned long hclk, fclk, pclk;
-	int hdiv = 1;
-
-	/* now we've got our machine bits initialised, work out what
-	 * clocks we've got */
-
-	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
-
-	clkdiv = __raw_readl(S3C2410_CLKDIVN);
-	camdiv = __raw_readl(S3C2440_CAMDIVN);
-
-	/* work out clock scalings */
-
-	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
-	case S3C2440_CLKDIVN_HDIVN_1:
-		hdiv = 1;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_2:
-		hdiv = 2;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_4_8:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_3_6:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
-		break;
-	}
-
-	hclk = fclk / hdiv;
-	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
-
-	/* print brief summary of clocks, etc */
-
-	printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them, and to add new ones after the initialisation
-	 */
-
-	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
-}
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-static int __init s3c2440_core_init(void)
-{
-	return sysdev_class_register(&s3c2440_sysclass);
-}
-
-core_initcall(s3c2440_core_init);
-
-int __init s3c2440_init(void)
-{
-	int ret;
-
-	printk("S3C2440: Initialising architecture\n");
 
-	ret = sysdev_register(&s3c2440_sysdev);
-	if (ret != 0)
-		printk(KERN_ERR "failed to register sysdev for s3c2440\n");
-	else
-		ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count);
+	/* register our system device for everything else */
 
-	return ret;
+	return sysdev_register(&s3c2440_sysdev);
 }
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
new file mode 100644
index 000000000000..d9f54b5cab7f
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442-clock.c
@@ -0,0 +1,171 @@
+/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 Clock support
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+
+	if (div == 3)
+		return parent_rate / 3;
+
+	/* note, we remove the +/- 1 calculations for the divisor */
+
+	div /= 2;
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	rate = s3c2442_camif_upll_round(clk, rate);
+
+	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+	if (rate == parent_rate) {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+	} else if ((parent_rate / rate) == 3) {
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+	} else {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= (((parent_rate / rate) / 2) - 1);
+	}
+
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+	.name		= "camif",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+	.name		= "camif-upll",
+	.id		= -1,
+	.set_rate	= s3c2442_camif_upll_setrate,
+	.round_rate	= s3c2442_camif_upll_round,
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+	unsigned long clkdivn;
+	struct clk *clk_h;
+	struct clk *clk_p;
+	struct clk *clk_upll;
+
+	printk("S3C2442: Clock Support, DVS %s\n",
+	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+	clk_p = clk_get(NULL, "pclk");
+	clk_h = clk_get(NULL, "hclk");
+	clk_upll = clk_get(NULL, "upll");
+
+	if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+		return -EINVAL;
+	}
+
+	/* check rate of UPLL, and if it is near 96MHz, then change
+	 * to using half the UPLL rate for the system */
+
+	if (clk_get_rate(clk_upll) > (94 * MHZ)) {
+		clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+
+		mutex_lock(&clocks_mutex);
+
+		clkdivn = __raw_readl(S3C2410_CLKDIVN);
+		clkdivn |= S3C2440_CLKDIVN_UCLK;
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+		mutex_unlock(&clocks_mutex);
+	}
+
+	s3c2442_clk_cam.parent = clk_h;
+	s3c2442_clk_cam_upll.parent = clk_upll;
+
+	s3c24xx_register_clock(&s3c2442_clk_cam);
+	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+	clk_disable(&s3c2442_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+	.add	= s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
new file mode 100644
index 000000000000..debae2430557
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442.c
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2442.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct sys_device s3c2442_sysdev = {
+	.cls		= &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+	printk("S3C2442: Initialising architecture\n");
+
+	return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
new file mode 100644
index 000000000000..0ae37d24866c
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s3c2410/s3c2442.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
new file mode 100644
index 000000000000..2aadca1ce7eb
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x-irq.c
@@ -0,0 +1,142 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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
+ *
+ * Changelog:
+ *	25-Jul-2005 BJD		Split from irq.c
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+#include "irq.h"
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+			      struct irqdesc *desc,
+			      struct pt_regs *regs)
+{
+	unsigned int subsrc, submsk;
+	struct irqdesc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 11;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
+		}
+	}
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+	.mask	    = s3c_irq_cam_mask,
+	.unmask	    = s3c_irq_cam_unmask,
+	.ack	    = s3c_irq_cam_ack,
+};
+
+static int s3c244x_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_NFCON, do_level_IRQ);
+	set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+	/* add chained handler for camera */
+
+	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_CAM, do_level_IRQ);
+	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_cam);
+		set_irq_handler(irqno, do_level_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c244x_irq_driver = {
+	.add	= s3c244x_irq_add,
+};
+
+static int s3c2440_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
+
+static int s3c2442_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
new file mode 100644
index 000000000000..838bc525e836
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x.c
@@ -0,0 +1,184 @@
+/* linux/arch/arm/mach-s3c2410/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "s3c244x.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(WATCHDOG),
+	IODESC_ENT(LCD),
+	IODESC_ENT(ADC),
+	IODESC_ENT(USBHOST),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+{
+	/* register our io-tables */
+
+	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+	iotable_init(mach_desc, size);
+
+	/* rename any peripherals used differing from the s3c2410 */
+
+	s3c_device_i2c.name  = "s3c2440-i2c";
+	s3c_device_nand.name = "s3c2440-nand";
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+	unsigned long clkdiv;
+	unsigned long camdiv;
+	unsigned long hclk, fclk, pclk;
+	int hdiv = 1;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+	clkdiv = __raw_readl(S3C2410_CLKDIVN);
+	camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+	/* work out clock scalings */
+
+	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+	case S3C2440_CLKDIVN_HDIVN_1:
+		hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_2:
+		hdiv = 2;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_4_8:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_3_6:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+		break;
+	}
+
+	hclk = fclk / hdiv;
+	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+
+	/* print brief summary of clocks, etc */
+
+	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them, and to add new ones after the initialisation
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2410_baseclk_add();
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+	SAVE_ITEM(S3C2440_DSC0),
+	SAVE_ITEM(S3C2440_DSC1),
+	SAVE_ITEM(S3C2440_GPJDAT),
+	SAVE_ITEM(S3C2440_GPJCON),
+	SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+	set_kset_name("s3c2440-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+	set_kset_name("s3c2442-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+	return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+	return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h
new file mode 100644
index 000000000000..3e7f5f75134d
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 73de2eaca22a..5f6761ed96b2 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -66,7 +66,9 @@ ENTRY(s3c2410_cpu_suspend)
 	@@ flush the caches to ensure everything is back out to
 	@@ SDRAM before the core powers down
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	bl	arm920_flush_kern_cache_all
+#endif
 
 	@@ prepare cpu to sleep
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c55b739e10ba..ecf5e232a6fc 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -61,9 +61,9 @@ config CPU_ARM720T
 
 # ARM920T
 config CPU_ARM920T
-	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
-	default y if ARCH_S3C2410 || ARCH_AT91RM9200
+	bool "Support ARM920T processor"
+	depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
+	default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
 	select CPU_32v4
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
@@ -121,8 +121,8 @@ config CPU_ARM925T
 # ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB
-	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
+	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
+	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index 2dfe1ac42ee8..7d977d23f026 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -33,7 +33,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-/* XXX */
+
+#include <asm/thread_notify.h>
 
 #include "softfloat.h"
 #include "fpopcode.h"
@@ -56,16 +57,28 @@ void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
 extern char fpe_type[];
 #endif
 
+static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v)
+{
+	struct thread_info *thread = v;
+
+	if (cmd == THREAD_NOTIFY_FLUSH)
+		nwfpe_init_fpa(&thread->fpstate);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block nwfpe_notifier_block = {
+	.notifier_call = nwfpe_notify,
+};
+
 /* kernel function prototypes required */
 void fp_setup(void);
 
 /* external declarations for saved kernel symbols */
 extern void (*kern_fp_enter)(void);
-extern void (*fp_init)(union fp_state *);
 
 /* Original value of fp_enter from kernel before patched by fpe_init. */
 static void (*orig_fp_enter)(void);
-static void (*orig_fp_init)(union fp_state *);
 
 /* forward declarations */
 extern void nwfpe_enter(void);
@@ -88,20 +101,20 @@ static int __init fpe_init(void)
 	printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
 	       NWFPE_BITS " precision)\n");
 
+	thread_register_notifier(&nwfpe_notifier_block);
+
 	/* Save pointer to the old FP handler and then patch ourselves in */
 	orig_fp_enter = kern_fp_enter;
-	orig_fp_init = fp_init;
 	kern_fp_enter = nwfpe_enter;
-	fp_init = nwfpe_init_fpa;
 
 	return 0;
 }
 
 static void __exit fpe_exit(void)
 {
+	thread_unregister_notifier(&nwfpe_notifier_block);
 	/* Restore the values we saved earlier. */
 	kern_fp_enter = orig_fp_enter;
-	fp_init = orig_fp_init;
 }
 
 /*
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index b2a943bf11ef..3461a6c9665c 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -210,7 +210,8 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
 
 	now = omap_32k_sync_timer_read();
 
-	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+	while ((signed long)(now - omap_32k_last_tick)
+						>= OMAP_32K_TICKS_PER_HZ) {
 		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
 		timer_tick(regs);
 	}
diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
index afabac31dd1d..7e136e77971a 100644
--- a/arch/arm/vfp/Makefile
+++ b/arch/arm/vfp/Makefile
@@ -7,6 +7,9 @@
 # EXTRA_CFLAGS := -DDEBUG
 # EXTRA_AFLAGS := -DDEBUG
 
+AFLAGS		:=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+LDFLAGS		+=--no-warn-mismatch
+
 obj-y			+= vfp.o
 
-vfp-$(CONFIG_VFP)	+= entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o
+vfp-$(CONFIG_VFP)	+= vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index a3f65b47aea9..eb683cd77163 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -192,7 +192,7 @@ vfp_get_double:
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mrrc	p11, 1, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
+	fmrrd	r0, r1, d\dr
 	mov	pc, lr
 	.endr
 
@@ -206,6 +206,6 @@ vfp_put_double:
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mcrr	p11, 1, r1, r2, c\dr	@ fmdrr	r1, r2, d\dr
+	fmdrr	d\dr, r1, r2
 	mov	pc, lr
 	.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 03486be04193..2476f4c2e760 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -15,6 +15,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+
+#include <asm/thread_notify.h>
 #include <asm/vfp.h>
 
 #include "vfpinstr.h"
@@ -36,38 +38,55 @@ union vfp_state *last_VFP_context;
  */
 unsigned int VFP_arch;
 
-/*
- * Per-thread VFP initialisation.
- */
-void vfp_flush_thread(union vfp_state *vfp)
+static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
-	memset(vfp, 0, sizeof(union vfp_state));
+	struct thread_info *thread = v;
+	union vfp_state *vfp = &thread->vfpstate;
 
-	vfp->hard.fpexc = FPEXC_ENABLE;
-	vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		/*
+		 * Per-thread VFP initialisation.
+		 */
+		memset(vfp, 0, sizeof(union vfp_state));
 
-	/*
-	 * Disable VFP to ensure we initialise it first.
-	 */
-	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		vfp->hard.fpexc = FPEXC_ENABLE;
+		vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
 
-	/*
-	 * Ensure we don't try to overwrite our newly initialised
-	 * state information on the first fault.
-	 */
-	if (last_VFP_context == vfp)
-		last_VFP_context = NULL;
-}
+		/*
+		 * Disable VFP to ensure we initialise it first.
+		 */
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
 
-/*
- * Per-thread VFP cleanup.
- */
-void vfp_release_thread(union vfp_state *vfp)
-{
-	if (last_VFP_context == vfp)
-		last_VFP_context = NULL;
+		/*
+		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
+		 * initialised state information on the first fault.
+		 */
+
+	case THREAD_NOTIFY_RELEASE:
+		/*
+		 * Per-thread VFP cleanup.
+		 */
+		if (last_VFP_context == vfp)
+			last_VFP_context = NULL;
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		/*
+		 * Always disable VFP so we can lazily save/restore the
+		 * old state.
+		 */
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		break;
+	}
+
+	return NOTIFY_DONE;
 }
 
+static struct notifier_block vfp_notifier_block = {
+	.notifier_call	= vfp_notifier,
+};
+
 /*
  * Raise a SIGFPE for the current process.
  * sicode describes the signal being raised.
@@ -281,6 +300,8 @@ static int __init vfp_init(void)
 			(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
 			(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
 		vfp_vector = vfp_support_entry;
+
+		thread_register_notifier(&vfp_notifier_block);
 	}
 	return 0;
 }
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index a9b59527a741..81d94e41a189 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1474,7 +1474,7 @@ sys_call_table:
 	.long sys_mknodat
 	.long sys_fchownat
 	.long sys_futimesat
-	.long sys_newfstatat		/* 300 */
+	.long sys_fstatat64		/* 300 */
 	.long sys_unlinkat
 	.long sys_renameat
 	.long sys_linkat
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 0f273a7aca5a..dee637fffda5 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -26,16 +26,6 @@ extern long __memset_user(void *dst, const void *src, size_t count);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
 EXPORT_SYMBOL(ip_fast_csum);
 
 #if 0
@@ -44,8 +34,6 @@ EXPORT_SYMBOL(local_bh_count);
 #endif
 EXPORT_SYMBOL(kernel_thread);
 
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
 EXPORT_SYMBOL(__page_offset);
 EXPORT_SYMBOL(__memcpy_user);
@@ -62,18 +50,12 @@ EXPORT_SYMBOL(memory_end);
 
 EXPORT_SYMBOL(__debug_bug_trap);
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 /* The following are special because they're not called
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(__outsl_ns);
 EXPORT_SYMBOL(__insl_ns);
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
index d4776d1f4e82..b90b70a761d1 100644
--- a/arch/frv/kernel/irq-routing.c
+++ b/arch/frv/kernel/irq-routing.c
@@ -112,7 +112,7 @@ struct irq_source frv_cpuuart[2] = {
 #define __CPUUART(X, A)						\
 	[X] = {							\
 		.muxname	= "uart",			\
-		.muxdata	= (volatile void __iomem *) A,	\
+		.muxdata	= (volatile void __iomem *)(unsigned long)A,\
 		.irqmask	= 1 << IRQ_CPU_UART##X,		\
 		.doirq		= frv_cpuuart_doirq,		\
 	}
@@ -136,7 +136,7 @@ struct irq_source frv_cpudma[8] = {
 #define __CPUDMA(X, A)						\
 	[X] = {							\
 		.muxname	= "dma",			\
-		.muxdata	= (volatile void __iomem *) A,	\
+		.muxdata	= (volatile void __iomem *)(unsigned long)A,\
 		.irqmask	= 1 << IRQ_CPU_DMA##X,		\
 		.doirq		= frv_cpudma_doirq,		\
 	}
@@ -164,7 +164,7 @@ struct irq_source frv_cputimer[3] = {
 #define __CPUTIMER(X)						\
 	[X] = {							\
 		.muxname	= "timer",			\
-		.muxdata	= 0,				\
+		.muxdata	= NULL,				\
 		.irqmask	= 1 << IRQ_CPU_TIMER##X,	\
 		.doirq		= frv_cputimer_doirq,		\
 	}
@@ -187,7 +187,7 @@ struct irq_source frv_cpuexternal[8] = {
 #define __CPUEXTERNAL(X)					\
 	[X] = {							\
 		.muxname	= "ext",			\
-		.muxdata	= 0,				\
+		.muxdata	= NULL,				\
 		.irqmask	= 1 << IRQ_CPU_EXTERNAL##X,	\
 		.doirq		= frv_cpuexternal_doirq,	\
 	}
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 11fa326a8f62..8b112b361914 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -625,7 +625,7 @@ static struct proc_dir_entry * irq_dir [NR_IRQS];
 
 #define HEX_DIGITS 8
 
-static unsigned int parse_hex_value (const char *buffer,
+static unsigned int parse_hex_value (const char __user *buffer,
 				     unsigned long count, unsigned long *ret)
 {
 	unsigned char hexnum [HEX_DIGITS];
@@ -672,7 +672,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
 	return sprintf (page, "%08lx\n", *mask);
 }
 
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
+static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
 					unsigned long count, void *data)
 {
 	unsigned long *mask = (unsigned long *) data, full_count = count, err;
@@ -711,7 +711,7 @@ void init_irq_proc (void)
 	int i;
 
 	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", 0);
+	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
 	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index f0b8fff3e733..43ce28a13a5d 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -137,7 +137,7 @@ unsigned long sleep_phys_sp(void *sp)
 #define CTL_PM_P0 4
 #define CTL_PM_CM 5
 
-static int user_atoi(char *ubuf, size_t len)
+static int user_atoi(char __user *ubuf, size_t len)
 {
 	char buf[16];
 	unsigned long ret;
@@ -159,7 +159,7 @@ static int user_atoi(char *ubuf, size_t len)
  * Send us to sleep.
  */
 static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
-				void *buffer, size_t *lenp, loff_t *fpos)
+				void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int retval, mode;
 
@@ -215,7 +215,7 @@ static int try_set_cmode(int new_cmode)
 
 
 static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
-			 void *buffer, size_t *lenp, loff_t *fpos)
+			 void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_cmode;
 
@@ -227,9 +227,9 @@ static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
 	return try_set_cmode(new_cmode)?:*lenp;
 }
 
-static int cmode_sysctl(ctl_table *table, int *name, int nlen,
-			void *oldval, size_t *oldlenp,
-			void *newval, size_t newlen, void **context)
+static int cmode_sysctl(ctl_table *table, int __user *name, int nlen,
+			void __user *oldval, size_t __user *oldlenp,
+			void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -240,7 +240,7 @@ static int cmode_sysctl(ctl_table *table, int *name, int nlen,
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_cmode_current, (unsigned int *)oldval) ||
+		if (put_user(clock_cmode_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -250,7 +250,7 @@ static int cmode_sysctl(ctl_table *table, int *name, int nlen,
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_cmode, (int *)newval))
+		if (get_user(new_cmode, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_cmode(new_cmode)?:1;
@@ -318,7 +318,7 @@ static int try_set_cm(int new_cm)
 }
 
 static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
-		      void *buffer, size_t *lenp, loff_t *fpos)
+		      void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_p0;
 
@@ -330,9 +330,9 @@ static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
 	return try_set_p0(new_p0)?:*lenp;
 }
 
-static int p0_sysctl(ctl_table *table, int *name, int nlen,
-		     void *oldval, size_t *oldlenp,
-		     void *newval, size_t newlen, void **context)
+static int p0_sysctl(ctl_table *table, int __user *name, int nlen,
+		     void __user *oldval, size_t __user *oldlenp,
+		     void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -343,7 +343,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen,
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_p0_current, (unsigned int *)oldval) ||
+		if (put_user(clock_p0_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -353,7 +353,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen,
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_p0, (int *)newval))
+		if (get_user(new_p0, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_p0(new_p0)?:1;
@@ -362,7 +362,7 @@ static int p0_sysctl(ctl_table *table, int *name, int nlen,
 }
 
 static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
-		      void *buffer, size_t *lenp, loff_t *fpos)
+		      void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_cm;
 
@@ -374,9 +374,9 @@ static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
 	return try_set_cm(new_cm)?:*lenp;
 }
 
-static int cm_sysctl(ctl_table *table, int *name, int nlen,
-		     void *oldval, size_t *oldlenp,
-		     void *newval, size_t newlen, void **context)
+static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
+		     void __user *oldval, size_t __user *oldlenp,
+		     void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -387,7 +387,7 @@ static int cm_sysctl(ctl_table *table, int *name, int nlen,
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_cm_current, (unsigned int *)oldval) ||
+		if (put_user(clock_cm_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -397,7 +397,7 @@ static int cm_sysctl(ctl_table *table, int *name, int nlen,
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_cm, (int *)newval))
+		if (get_user(new_cm, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_cm(new_cm)?:1;
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 0fff8a61ef2a..489e6c489cbe 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -246,7 +246,7 @@ int copy_thread(int nr, unsigned long clone_flags,
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
+asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
 	int error;
 	char * filename;
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 5908deae9607..1f7d65f29e78 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -814,7 +814,7 @@ void __init setup_arch(char **cmdline_p)
 	 * - by now the stack is part of the init task */
 	printk("Memory %08lx-%08lx\n", memory_start, memory_end);
 
-	if (memory_start == memory_end) BUG();
+	BUG_ON(memory_start == memory_end);
 
 	init_mm.start_code = (unsigned long) &_stext;
 	init_mm.end_code = (unsigned long) &_etext;
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 679c1d5cc958..b8a5882b8625 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -98,7 +98,7 @@ int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 
 struct sigframe
 {
-	void (*pretcode)(void);
+	__sigrestore_t pretcode;
 	int sig;
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
@@ -107,10 +107,10 @@ struct sigframe
 
 struct rt_sigframe
 {
-	void (*pretcode)(void);
+	__sigrestore_t pretcode;
 	int sig;
-	struct siginfo *pinfo;
-	void *puc;
+	struct siginfo __user *pinfo;
+	void __user *puc;
 	struct siginfo info;
 	struct ucontext uc;
 	uint32_t retcode[2];
@@ -233,7 +233,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! on_sig_stack(sp))
+		if (! sas_ss_flags(sp))
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
@@ -284,7 +284,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
 		 *	setlos	#__NR_sigreturn,gr7
 		 *	tira	gr0,0
 		 */
-		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
 			goto give_sigsegv;
@@ -300,7 +300,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
 
 	if (get_personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor *) ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 		__get_user(__frame->pc, &funcptr->text);
 		__get_user(__frame->gr15, &funcptr->GOT);
 	} else {
@@ -359,8 +359,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	/* Create the ucontext.  */
 	if (__put_user(0, &frame->uc.uc_flags) ||
-	    __put_user(0, &frame->uc.uc_link) ||
-	    __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
+	    __put_user(NULL, &frame->uc.uc_link) ||
+	    __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
 	    __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
 	    __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
 		goto give_sigsegv;
@@ -382,7 +382,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		 *	setlos	#__NR_sigreturn,gr7
 		 *	tira	gr0,0
 		 */
-		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
 			goto give_sigsegv;
@@ -398,7 +398,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	__frame->gr9 = (unsigned long) &frame->info;
 
 	if (get_personality & FDPIC_FUNCPTRS) {
-		struct fdpic_func_descriptor *funcptr =
+		struct fdpic_func_descriptor __user *funcptr =
 			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 		__get_user(__frame->pc, &funcptr->text);
 		__get_user(__frame->gr15, &funcptr->GOT);
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 931aa6d895e3..c4d4348c9e8e 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -32,7 +32,7 @@
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way unix traditionally does this, though.
  */
-asmlinkage long sys_pipe(unsigned long * fildes)
+asmlinkage long sys_pipe(unsigned long __user * fildes)
 {
 	int fd[2];
 	int error;
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index 408b0f382b42..b908863d6593 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -49,7 +49,7 @@ static void frv_change_dcache_mode(unsigned long newmode)
  * handle requests to dynamically switch the write caching mode delivered by /proc
  */
 static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
-				 void *buffer, size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	unsigned long hsr0;
 	char buff[8];
@@ -123,7 +123,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
  */
 #ifdef CONFIG_MMU
 static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
-				void *buffer, size_t *lenp, loff_t *ppos)
+				void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	pid_t pid;
 	char buff[16], *p;
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c
index 9b751c0f0e84..9fb771a20df3 100644
--- a/arch/frv/kernel/uaccess.c
+++ b/arch/frv/kernel/uaccess.c
@@ -17,7 +17,7 @@
 /*
  * copy a null terminated string from userspace
  */
-long strncpy_from_user(char *dst, const char *src, long count)
+long strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	unsigned long max;
 	char *p, ch;
@@ -70,9 +70,9 @@ EXPORT_SYMBOL(strncpy_from_user);
  *
  * Return 0 on exception, a value greater than N if too long
  */
-long strnlen_user(const char *src, long count)
+long strnlen_user(const char __user *src, long count)
 {
-	const char *p;
+	const char __user *p;
 	long err = 0;
 	char ch;
 
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index c4a1144c98b0..45ae39d84b69 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -32,11 +32,11 @@
  */
 
 static const uint8_t __initdata pci_bus0_irq_routing[32][4] = {
-	[0 ] {	IRQ_FPGA_MB86943_PCI_INTA },
-	[16] {	IRQ_FPGA_RTL8029_INTA },
-	[17] {	IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
-	[18] {	IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA },
-	[19] {	IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD },
+	[0 ] = { IRQ_FPGA_MB86943_PCI_INTA },
+	[16] = { IRQ_FPGA_RTL8029_INTA },
+	[17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
+	[18] = { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA },
+	[19] = { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD },
 };
 
 void __init pcibios_irq_init(void)
diff --git a/arch/frv/mm/kmap.c b/arch/frv/mm/kmap.c
index c54f18e65ea6..40b62c5c2951 100644
--- a/arch/frv/mm/kmap.c
+++ b/arch/frv/mm/kmap.c
@@ -31,15 +31,15 @@
  * Map some physical address range into the kernel address space.
  */
 
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
 {
-	return (void *)physaddr;
+	return (void __iomem *)physaddr;
 }
 
 /*
  * Unmap a ioremap()ed region again
  */
-void iounmap(void *addr)
+void iounmap(void volatile __iomem *addr)
 {
 }
 
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index f13d5e82d4b9..7787f70a05bb 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -307,7 +307,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void *)((usp - frame_size) & -8UL);
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 8dfa3054f10f..1596101cfaf8 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -173,6 +173,12 @@ config ACPI_SRAT
 	bool
 	default y
 	depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+	select ACPI_NUMA
+
+config HAVE_ARCH_PARSE_SRAT
+       bool
+       default y
+       depends on ACPI_SRAT
 
 config X86_SUMMIT_NUMA
 	bool
@@ -224,7 +230,6 @@ config NR_CPUS
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on SMP
-	default off
 	help
 	  SMT scheduler support improves the CPU scheduler's decision making
 	  when dealing with Intel Pentium 4 chips with HyperThreading at a
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 40e5aba3ad3d..97ca17189af5 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -202,6 +202,8 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
 		if (mcfg->config[i].base_reserved) {
 			printk(KERN_ERR PREFIX
 			       "MMCONFIG not in low 4GB of memory\n");
+			kfree(pci_mmcfg_config);
+			pci_mmcfg_config_num = 0;
 			return -ENODEV;
 		}
 	}
@@ -215,7 +217,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
 {
 	struct acpi_table_madt *madt = NULL;
 
-	if (!phys_addr || !size)
+	if (!phys_addr || !size || !cpu_has_apic)
 		return -EINVAL;
 
 	madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -621,9 +623,9 @@ extern u32 pmtmr_ioport;
 
 static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
 {
-	struct fadt_descriptor_rev2 *fadt = NULL;
+	struct fadt_descriptor *fadt = NULL;
 
-	fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size);
+	fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size);
 	if (!fadt) {
 		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
 		return 0;
@@ -754,7 +756,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
 		return -ENODEV;
 	}
 
-	if (!cpu_has_apic)
+	if (!cpu_has_apic) 
 		return -ENODEV;
 
 	/*
diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c
index 9f4cc02717ec..b54fded49834 100644
--- a/arch/i386/kernel/acpi/processor.c
+++ b/arch/i386/kernel/acpi/processor.c
@@ -47,7 +47,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
 	buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
 
 	if (cpu_has(c, X86_FEATURE_EST))
-		buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+		buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
 
 	obj->type = ACPI_TYPE_BUFFER;
 	obj->buffer.length = 12;
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 1cb2b186a3af..4ee83577bf61 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -8,30 +8,17 @@
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/dmi.h>
+#include <linux/cpumask.h>
+
 #include <asm/smp.h>
-#include <asm/tlbflush.h>
 
 /* address in low memory of the wakeup routine. */
 unsigned long acpi_wakeup_address = 0;
 unsigned long acpi_video_flags;
 extern char wakeup_start, wakeup_end;
 
-extern void zap_low_mappings(void);
-
 extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
 
-static void init_low_mapping(pgd_t * pgd, int pgd_limit)
-{
-	int pgd_ofs = 0;
-
-	while ((pgd_ofs < pgd_limit)
-	       && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
-		set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
-		pgd_ofs++, pgd++;
-	}
-	flush_tlb_all();
-}
-
 /**
  * acpi_save_state_mem - save kernel state
  *
@@ -42,7 +29,6 @@ int acpi_save_state_mem(void)
 {
 	if (!acpi_wakeup_address)
 		return 1;
-	init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD);
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
@@ -55,7 +41,6 @@ int acpi_save_state_mem(void)
  */
 void acpi_restore_state_mem(void)
 {
-	zap_low_mappings();
 }
 
 /**
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index 7c74fe0dc93c..9f408eee4e6f 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -56,7 +56,7 @@ wakeup_code:
 1:
 
 	# set up page table
-	movl	$swapper_pg_dir-__PAGE_OFFSET, %eax
+	movl	$swsusp_pg_dir-__PAGE_OFFSET, %eax
 	movl	%eax, %cr3
 
 	testl	$1, real_efer_save_restore - wakeup_code
@@ -265,11 +265,6 @@ ENTRY(acpi_copy_wakeup_routine)
 	movl	$0x12345678, saved_magic
 	ret
 
-.data
-ALIGN
-ENTRY(saved_magic)	.long	0
-ENTRY(saved_eip)	.long	0
-
 save_registers:
 	leal	4(%esp), %eax
 	movl	%eax, saved_context_esp
@@ -304,7 +299,11 @@ ret_point:
 	call	restore_processor_state
 	ret
 
+.data
 ALIGN
+ENTRY(saved_magic)	.long	0
+ENTRY(saved_eip)	.long	0
+
 # saved registers
 saved_gdt:	.long	0,0
 saved_idt:	.long	0,0
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 3d4b2f3d116a..5ab59c12335b 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,7 +62,7 @@ int apic_verbosity;
 
 static void apic_pm_activate(void);
 
-int modern_apic(void)
+static int modern_apic(void)
 {
 	unsigned int lvr, version;
 	/* AMD systems use old APIC versions, so check the CPU */
@@ -113,7 +113,7 @@ void __init apic_intr_init(void)
 }
 
 /* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer = 0;
+int using_apic_timer __read_mostly = 0;
 
 static int enabled_via_apicbase;
 
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index df0e1745f189..9e819eb68229 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -374,14 +374,14 @@ static struct {
 	unsigned short	segment;
 }				apm_bios_entry;
 static int			clock_slowed;
-static int			idle_threshold = DEFAULT_IDLE_THRESHOLD;
-static int			idle_period = DEFAULT_IDLE_PERIOD;
+static int			idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
+static int			idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
 static int			set_pm_idle;
 static int			suspends_pending;
 static int			standbys_pending;
 static int			ignore_sys_suspend;
 static int			ignore_normal_resume;
-static int			bounce_interval = DEFAULT_BOUNCE_INTERVAL;
+static int			bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #	define	clock_cmos_diff	0
@@ -390,8 +390,8 @@ static int			bounce_interval = DEFAULT_BOUNCE_INTERVAL;
 static long			clock_cmos_diff;
 static int			got_clock_diff;
 #endif
-static int			debug;
-static int			smp;
+static int			debug __read_mostly;
+static int			smp __read_mostly;
 static int			apm_disabled = -1;
 #ifdef CONFIG_SMP
 static int			power_off;
@@ -403,8 +403,8 @@ static int			realmode_power_off = 1;
 #else
 static int			realmode_power_off;
 #endif
-static int			exit_kapmd;
-static int			kapmd_running;
+static int			exit_kapmd __read_mostly;
+static int			kapmd_running __read_mostly;
 #ifdef CONFIG_APM_ALLOW_INTS
 static int			allow_ints = 1;
 #else
@@ -416,15 +416,15 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 static DEFINE_SPINLOCK(user_list_lock);
-static struct desc_struct	bad_bios_desc = { 0, 0x00409200 };
+static const struct desc_struct	bad_bios_desc = { 0, 0x00409200 };
 
-static char			driver_version[] = "1.16ac";	/* no spaces */
+static const char		driver_version[] = "1.16ac";	/* no spaces */
 
 /*
  *	APM event names taken from the APM 1.2 specification. These are
  *	the message codes that the BIOS uses to tell us about events
  */
-static char *	apm_event_name[] = {
+static const char *	const apm_event_name[] = {
 	"system standby",
 	"system suspend",
 	"normal resume",
@@ -616,7 +616,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
  *	@ecx_in: ECX register value for BIOS call
  *	@eax: EAX register on return from the BIOS call
  *
- *	Make a BIOS call that does only returns one value, or just status.
+ *	Make a BIOS call that returns one value only, or just status.
  *	If there is an error, then the error code is returned in AH
  *	(bits 8-15 of eax) and this function returns non-zero. This is
  *	used for simpler BIOS operations. This call may hold interrupts
@@ -822,7 +822,7 @@ static void apm_do_busy(void)
 #define IDLE_CALC_LIMIT   (HZ * 100)
 #define IDLE_LEAKY_MAX    16
 
-static void (*original_pm_idle)(void);
+static void (*original_pm_idle)(void) __read_mostly;
 
 /**
  * apm_cpu_idle		-	cpu idling for APM capable Linux
@@ -1063,7 +1063,8 @@ static int apm_engage_power_management(u_short device, int enable)
  
 static int apm_console_blank(int blank)
 {
-	int error, i;
+	int error = APM_NOT_ENGAGED; /* silence gcc */
+	int i;
 	u_short state;
 	static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
 
@@ -1104,7 +1105,8 @@ static int queue_empty(struct apm_user *as)
 
 static apm_event_t get_queued_event(struct apm_user *as)
 {
-	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	if (++as->event_tail >= APM_MAX_EVENTS)
+		as->event_tail = 0;
 	return as->events[as->event_tail];
 }
 
@@ -1118,13 +1120,16 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
 	for (as = user_list; as != NULL; as = as->next) {
 		if ((as == sender) || (!as->reader))
 			continue;
-		as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+		if (++as->event_head >= APM_MAX_EVENTS)
+			as->event_head = 0;
+
 		if (as->event_head == as->event_tail) {
 			static int notified;
 
 			if (notified++ == 0)
 			    printk(KERN_ERR "apm: an event queue overflowed\n");
-			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+			if (++as->event_tail >= APM_MAX_EVENTS)
+				as->event_tail = 0;
 		}
 		as->events[as->event_head] = event;
 		if ((!as->suser) || (!as->writer))
@@ -1282,7 +1287,7 @@ static void standby(void)
 static apm_event_t get_event(void)
 {
 	int		error;
-	apm_event_t	event;
+	apm_event_t	event = APM_NO_EVENTS; /* silence gcc */
 	apm_eventinfo_t	info;
 
 	static int notified;
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index a06a49075f10..44f2c5f2dda1 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -11,6 +11,8 @@
 #include <asm/msr.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
+#include <asm/mtrr.h>
+#include <asm/mce.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
 #include <asm/apic.h>
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 1a7bdcef1926..05668e3598c0 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -48,12 +48,13 @@ MODULE_LICENSE("GPL");
 
 
 struct cpufreq_acpi_io {
-	struct acpi_processor_performance	acpi_data;
+	struct acpi_processor_performance	*acpi_data;
 	struct cpufreq_frequency_table		*freq_table;
 	unsigned int				resume;
 };
 
 static struct cpufreq_acpi_io	*acpi_io_data[NR_CPUS];
+static struct acpi_processor_performance	*acpi_perf_data[NR_CPUS];
 
 static struct cpufreq_driver acpi_cpufreq_driver;
 
@@ -104,64 +105,43 @@ acpi_processor_set_performance (
 {
 	u16			port = 0;
 	u8			bit_width = 0;
-	int			ret;
-	u32			value = 0;
 	int			i = 0;
-	struct cpufreq_freqs    cpufreq_freqs;
-	cpumask_t		saved_mask;
+	int			ret = 0;
+	u32			value = 0;
 	int			retval;
+	struct acpi_processor_performance	*perf;
 
 	dprintk("acpi_processor_set_performance\n");
 
-	/*
-	 * TBD: Use something other than set_cpus_allowed.
-	 * As set_cpus_allowed is a bit racy, 
-	 * with any other set_cpus_allowed for this process.
-	 */
-	saved_mask = current->cpus_allowed;
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
-	if (smp_processor_id() != cpu) {
-		return (-EAGAIN);
-	}
-	
-	if (state == data->acpi_data.state) {
+	retval = 0;
+	perf = data->acpi_data;	
+	if (state == perf->state) {
 		if (unlikely(data->resume)) {
 			dprintk("Called after resume, resetting to P%d\n", state);
 			data->resume = 0;
 		} else {
 			dprintk("Already at target state (P%d)\n", state);
-			retval = 0;
-			goto migrate_end;
+			return (retval);
 		}
 	}
 
-	dprintk("Transitioning from P%d to P%d\n",
-		data->acpi_data.state, state);
-
-	/* cpufreq frequency struct */
-	cpufreq_freqs.cpu = cpu;
-	cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
-	cpufreq_freqs.new = data->freq_table[state].frequency;
-
-	/* notify cpufreq */
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+	dprintk("Transitioning from P%d to P%d\n", perf->state, state);
 
 	/*
 	 * First we write the target state's 'control' value to the
 	 * control_register.
 	 */
 
-	port = data->acpi_data.control_register.address;
-	bit_width = data->acpi_data.control_register.bit_width;
-	value = (u32) data->acpi_data.states[state].control;
+	port = perf->control_register.address;
+	bit_width = perf->control_register.bit_width;
+	value = (u32) perf->states[state].control;
 
 	dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
 
 	ret = acpi_processor_write_port(port, bit_width, value);
 	if (ret) {
 		dprintk("Invalid port width 0x%04x\n", bit_width);
-		retval = ret;
-		goto migrate_end;
+		return (ret);
 	}
 
 	/*
@@ -177,48 +157,35 @@ acpi_processor_set_performance (
 		 * before giving up.
 		 */
 
-		port = data->acpi_data.status_register.address;
-		bit_width = data->acpi_data.status_register.bit_width;
+		port = perf->status_register.address;
+		bit_width = perf->status_register.bit_width;
 
 		dprintk("Looking for 0x%08x from port 0x%04x\n",
-			(u32) data->acpi_data.states[state].status, port);
+			(u32) perf->states[state].status, port);
 
-		for (i=0; i<100; i++) {
+		for (i = 0; i < 100; i++) {
 			ret = acpi_processor_read_port(port, bit_width, &value);
 			if (ret) {	
 				dprintk("Invalid port width 0x%04x\n", bit_width);
-				retval = ret;
-				goto migrate_end;
+				return (ret);
 			}
-			if (value == (u32) data->acpi_data.states[state].status)
+			if (value == (u32) perf->states[state].status)
 				break;
 			udelay(10);
 		}
 	} else {
-		value = (u32) data->acpi_data.states[state].status;
+		value = (u32) perf->states[state].status;
 	}
 
-	/* notify cpufreq */
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
-
-	if (unlikely(value != (u32) data->acpi_data.states[state].status)) {
-		unsigned int tmp = cpufreq_freqs.new;
-		cpufreq_freqs.new = cpufreq_freqs.old;
-		cpufreq_freqs.old = tmp;
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+	if (unlikely(value != (u32) perf->states[state].status)) {
 		printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
 		retval = -ENODEV;
-		goto migrate_end;
+		return (retval);
 	}
 
 	dprintk("Transition successful after %d microseconds\n", i * 10);
 
-	data->acpi_data.state = state;
-
-	retval = 0;
-migrate_end:
-	set_cpus_allowed(current, saved_mask);
+	perf->state = state;
 	return (retval);
 }
 
@@ -230,8 +197,17 @@ acpi_cpufreq_target (
 	unsigned int relation)
 {
 	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+	struct acpi_processor_performance *perf;
+	struct cpufreq_freqs freqs;
+	cpumask_t online_policy_cpus;
+	cpumask_t saved_mask;
+	cpumask_t set_mask;
+	cpumask_t covered_cpus;
+	unsigned int cur_state = 0;
 	unsigned int next_state = 0;
 	unsigned int result = 0;
+	unsigned int j;
+	unsigned int tmp;
 
 	dprintk("acpi_cpufreq_setpolicy\n");
 
@@ -240,11 +216,95 @@ acpi_cpufreq_target (
 			target_freq,
 			relation,
 			&next_state);
-	if (result)
+	if (unlikely(result))
 		return (result);
 
-	result = acpi_processor_set_performance (data, policy->cpu, next_state);
+	perf = data->acpi_data;
+	cur_state = perf->state;
+	freqs.old = data->freq_table[cur_state].frequency;
+	freqs.new = data->freq_table[next_state].frequency;
+
+#ifdef CONFIG_HOTPLUG_CPU
+	/* cpufreq holds the hotplug lock, so we are safe from here on */
+	cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
+#else
+	online_policy_cpus = policy->cpus;
+#endif
+
+	for_each_cpu_mask(j, online_policy_cpus) {
+		freqs.cpu = j;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	/*
+	 * We need to call driver->target() on all or any CPU in
+	 * policy->cpus, depending on policy->shared_type.
+	 */
+	saved_mask = current->cpus_allowed;
+	cpus_clear(covered_cpus);
+	for_each_cpu_mask(j, online_policy_cpus) {
+		/*
+		 * Support for SMP systems.
+		 * Make sure we are running on CPU that wants to change freq
+		 */
+		cpus_clear(set_mask);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			cpus_or(set_mask, set_mask, online_policy_cpus);
+		else
+			cpu_set(j, set_mask);
+
+		set_cpus_allowed(current, set_mask);
+		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+			dprintk("couldn't limit to CPUs in this domain\n");
+			result = -EAGAIN;
+			break;
+		}
+
+		result = acpi_processor_set_performance (data, j, next_state);
+		if (result) {
+			result = -EAGAIN;
+			break;
+		}
+
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			break;
+ 
+		cpu_set(j, covered_cpus);
+	}
+
+	for_each_cpu_mask(j, online_policy_cpus) {
+		freqs.cpu = j;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
 
+	if (unlikely(result)) {
+		/*
+		 * We have failed halfway through the frequency change.
+		 * We have sent callbacks to online_policy_cpus and
+		 * acpi_processor_set_performance() has been called on 
+		 * coverd_cpus. Best effort undo..
+		 */
+
+		if (!cpus_empty(covered_cpus)) {
+			for_each_cpu_mask(j, covered_cpus) {
+				policy->cpu = j;
+				acpi_processor_set_performance (data, 
+						j, 
+						cur_state);
+			}
+		}
+
+		tmp = freqs.new;
+		freqs.new = freqs.old;
+		freqs.old = tmp;
+		for_each_cpu_mask(j, online_policy_cpus) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		}
+	}
+
+	set_cpus_allowed(current, saved_mask);
 	return (result);
 }
 
@@ -270,30 +330,65 @@ acpi_cpufreq_guess_freq (
 	struct cpufreq_acpi_io	*data,
 	unsigned int		cpu)
 {
+	struct acpi_processor_performance	*perf = data->acpi_data;
+
 	if (cpu_khz) {
 		/* search the closest match to cpu_khz */
 		unsigned int i;
 		unsigned long freq;
-		unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
+		unsigned long freqn = perf->states[0].core_frequency * 1000;
 
-		for (i=0; i < (data->acpi_data.state_count - 1); i++) {
+		for (i = 0; i < (perf->state_count - 1); i++) {
 			freq = freqn;
-			freqn = data->acpi_data.states[i+1].core_frequency * 1000;
+			freqn = perf->states[i+1].core_frequency * 1000;
 			if ((2 * cpu_khz) > (freqn + freq)) {
-				data->acpi_data.state = i;
+				perf->state = i;
 				return (freq);
 			}
 		}
-		data->acpi_data.state = data->acpi_data.state_count - 1;
+		perf->state = perf->state_count - 1;
 		return (freqn);
-	} else
+	} else {
 		/* assume CPU is at P0... */
-		data->acpi_data.state = 0;
-		return data->acpi_data.states[0].core_frequency * 1000;
-	
+		perf->state = 0;
+		return perf->states[0].core_frequency * 1000;
+	}
 }
 
 
+/*
+ * acpi_cpufreq_early_init - initialize ACPI P-States library
+ *
+ * Initialize the ACPI P-States library (drivers/acpi/processor_perflib.c)
+ * in order to determine correct frequency and voltage pairings. We can
+ * do _PDC and _PSD and find out the processor dependency for the
+ * actual init that will happen later...
+ */
+static int acpi_cpufreq_early_init_acpi(void)
+{
+	struct acpi_processor_performance	*data;
+	unsigned int				i, j;
+
+	dprintk("acpi_cpufreq_early_init\n");
+
+	for_each_cpu(i) {
+		data = kzalloc(sizeof(struct acpi_processor_performance), 
+			GFP_KERNEL);
+		if (!data) {
+			for_each_cpu(j) {
+				kfree(acpi_perf_data[j]);
+				acpi_perf_data[j] = NULL;
+			}
+			return (-ENOMEM);
+		}
+		acpi_perf_data[i] = data;
+	}
+
+	/* Do initialization in ACPI core */
+	acpi_processor_preregister_performance(acpi_perf_data);
+	return 0;
+}
+
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -303,41 +398,51 @@ acpi_cpufreq_cpu_init (
 	struct cpufreq_acpi_io	*data;
 	unsigned int		result = 0;
 	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+	struct acpi_processor_performance	*perf;
 
 	dprintk("acpi_cpufreq_cpu_init\n");
 
+	if (!acpi_perf_data[cpu])
+		return (-ENODEV);
+
 	data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
 		return (-ENOMEM);
 
+	data->acpi_data = acpi_perf_data[cpu];
 	acpi_io_data[cpu] = data;
 
-	result = acpi_processor_register_performance(&data->acpi_data, cpu);
+	result = acpi_processor_register_performance(data->acpi_data, cpu);
 
 	if (result)
 		goto err_free;
 
+	perf = data->acpi_data;
+	policy->cpus = perf->shared_cpu_map;
+	policy->shared_type = perf->shared_type;
+
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
 		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
 	}
 
 	/* capability check */
-	if (data->acpi_data.state_count <= 1) {
+	if (perf->state_count <= 1) {
 		dprintk("No P-States\n");
 		result = -ENODEV;
 		goto err_unreg;
 	}
-	if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
-	    (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+
+	if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
+	    (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
 		dprintk("Unsupported address space [%d, %d]\n",
-			(u32) (data->acpi_data.control_register.space_id),
-			(u32) (data->acpi_data.status_register.space_id));
+			(u32) (perf->control_register.space_id),
+			(u32) (perf->status_register.space_id));
 		result = -ENODEV;
 		goto err_unreg;
 	}
 
 	/* alloc freq_table */
-	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
+	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL);
 	if (!data->freq_table) {
 		result = -ENOMEM;
 		goto err_unreg;
@@ -345,9 +450,9 @@ acpi_cpufreq_cpu_init (
 
 	/* detect transition latency */
 	policy->cpuinfo.transition_latency = 0;
-	for (i=0; i<data->acpi_data.state_count; i++) {
-		if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
-			policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
+	for (i=0; i<perf->state_count; i++) {
+		if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
+			policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
 	}
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
@@ -355,11 +460,11 @@ acpi_cpufreq_cpu_init (
 	policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
 
 	/* table init */
-	for (i=0; i<=data->acpi_data.state_count; i++)
+	for (i=0; i<=perf->state_count; i++)
 	{
 		data->freq_table[i].index = i;
-		if (i<data->acpi_data.state_count)
-			data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
+		if (i<perf->state_count)
+			data->freq_table[i].frequency = perf->states[i].core_frequency * 1000;
 		else
 			data->freq_table[i].frequency = CPUFREQ_TABLE_END;
 	}
@@ -374,12 +479,12 @@ acpi_cpufreq_cpu_init (
 
 	printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
 	       cpu);
-	for (i = 0; i < data->acpi_data.state_count; i++)
+	for (i = 0; i < perf->state_count; i++)
 		dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
-			(i == data->acpi_data.state?'*':' '), i,
-			(u32) data->acpi_data.states[i].core_frequency,
-			(u32) data->acpi_data.states[i].power,
-			(u32) data->acpi_data.states[i].transition_latency);
+			(i == perf->state?'*':' '), i,
+			(u32) perf->states[i].core_frequency,
+			(u32) perf->states[i].power,
+			(u32) perf->states[i].transition_latency);
 
 	cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
 	
@@ -394,7 +499,7 @@ acpi_cpufreq_cpu_init (
  err_freqfree:
 	kfree(data->freq_table);
  err_unreg:
-	acpi_processor_unregister_performance(&data->acpi_data, cpu);
+	acpi_processor_unregister_performance(perf, cpu);
  err_free:
 	kfree(data);
 	acpi_io_data[cpu] = NULL;
@@ -415,7 +520,7 @@ acpi_cpufreq_cpu_exit (
 	if (data) {
 		cpufreq_frequency_table_put_attr(policy->cpu);
 		acpi_io_data[policy->cpu] = NULL;
-		acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
+		acpi_processor_unregister_performance(data->acpi_data, policy->cpu);
 		kfree(data);
 	}
 
@@ -462,7 +567,10 @@ acpi_cpufreq_init (void)
 
 	dprintk("acpi_cpufreq_init\n");
 
- 	result = cpufreq_register_driver(&acpi_cpufreq_driver);
+	result = acpi_cpufreq_early_init_acpi();
+
+	if (!result)
+ 		result = cpufreq_register_driver(&acpi_cpufreq_driver);
 	
 	return (result);
 }
@@ -471,10 +579,15 @@ acpi_cpufreq_init (void)
 static void __exit
 acpi_cpufreq_exit (void)
 {
+	unsigned int	i;
 	dprintk("acpi_cpufreq_exit\n");
 
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
+	for_each_cpu(i) {
+		kfree(acpi_perf_data[i]);
+		acpi_perf_data[i] = NULL;
+	}
 	return;
 }
 
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index b4277f58f40c..2d6491672559 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -120,7 +120,7 @@ static int pending_bit_stuck(void)
 {
 	u32 lo, hi;
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		return 0;
 
 	rdmsr(MSR_FIDVID_STATUS, lo, hi);
@@ -136,7 +136,7 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
 	u32 lo, hi;
 	u32 i = 0;
 
-	if (cpu_family) {
+	if (cpu_family == CPU_HW_PSTATE) {
 		rdmsr(MSR_PSTATE_STATUS, lo, hi);
 		i = lo & HW_PSTATE_MASK;
 		rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi);
@@ -598,7 +598,7 @@ static void print_basics(struct powernow_k8_data *data)
 	int j;
 	for (j = 0; j < data->numps; j++) {
 		if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
-			if (cpu_family) {
+			if (cpu_family == CPU_HW_PSTATE) {
 			printk(KERN_INFO PFX "   %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
 				(data->powernow_table[j].index & 0xff0000) >> 16,
 				data->powernow_table[j].frequency/1000);
@@ -758,7 +758,7 @@ static int find_psb_table(struct powernow_k8_data *data)
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
 {
-	if (!data->acpi_data.state_count || cpu_family)
+	if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
 		return;
 
 	data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
@@ -801,7 +801,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 		goto err_out;
 	}
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		ret_val = fill_powernow_table_pstate(data, powernow_table);
 	else
 		ret_val = fill_powernow_table_fidvid(data, powernow_table);
@@ -885,8 +885,8 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpuf
 		u32 vid;
 
 		if (data->exttype) {
-			fid = data->acpi_data.states[i].status & FID_MASK;
-			vid = (data->acpi_data.states[i].status >> VID_SHIFT) & VID_MASK;
+			fid = data->acpi_data.states[i].status & EXT_FID_MASK;
+			vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK;
 		} else {
 			fid = data->acpi_data.states[i].control & FID_MASK;
 			vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK;
@@ -1082,7 +1082,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 	if (query_current_values_with_pending_wait(data))
 		goto err_out;
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		dprintk("targ: curr fid 0x%x, did 0x%x\n",
 			data->currfid, data->currvid);
 	else {
@@ -1103,7 +1103,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 
 	powernow_k8_acpi_pst_values(data, newstate);
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		ret = transition_frequency_pstate(data, newstate);
 	else
 		ret = transition_frequency_fidvid(data, newstate);
@@ -1115,7 +1115,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 	}
 	mutex_unlock(&fidvid_mutex);
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
 	else
 		pol->cur = find_khz_freq_from_fid(data->currfid);
@@ -1163,7 +1163,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 		 * Use the PSB BIOS structure. This is only availabe on
 		 * an UP version, and is deprecated by AMD.
 		 */
-		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
+		if (num_online_cpus() != 1) {
 			printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
 			kfree(data);
 			return -ENODEV;
@@ -1197,14 +1197,14 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 	if (query_current_values_with_pending_wait(data))
 		goto err_out;
 
-	if (!cpu_family)
+	if (cpu_family == CPU_OPTERON)
 		fidvid_msr_init();
 
 	/* run on any CPU again */
 	set_cpus_allowed(current, oldmask);
 
 	pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		pol->cpus = cpumask_of_cpu(pol->cpu);
 	else
 		pol->cpus = cpu_core_map[pol->cpu];
@@ -1215,7 +1215,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 	pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
 	    + (3 * (1 << data->irt) * 10)) * 1000;
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
 	else
 		pol->cur = find_khz_freq_from_fid(data->currfid);
@@ -1232,7 +1232,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 
 	cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
-	if (cpu_family)
+	if (cpu_family == CPU_HW_PSTATE)
 		dprintk("cpu_init done, current fid 0x%x, did 0x%x\n",
 			data->currfid, data->currdid);
 	else
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index bf8ad9e43da3..0fb2a3001ba5 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -169,7 +169,9 @@ struct powernow_k8_data {
 #define MVS_MASK        3
 #define VST_MASK     0x7f
 #define VID_MASK     0x1f
-#define FID_MASK     0x3f
+#define FID_MASK     0x1f
+#define EXT_VID_MASK 0x3f
+#define EXT_FID_MASK 0x3f
 
 
 /*
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index ce54ff12c15d..31c3a5baaa7f 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -2,19 +2,15 @@
  * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium
  * M (part of the Centrino chipset).
  *
+ * Since the original Pentium M, most new Intel CPUs support Enhanced
+ * SpeedStep.
+ *
  * Despite the "SpeedStep" in the name, this is almost entirely unlike
  * traditional SpeedStep.
  *
  * Modelled on speedstep.c
  *
  * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
- *
- * WARNING WARNING WARNING
- *
- * This driver manipulates the PERF_CTL MSR, which is only somewhat
- * documented.  While it seems to work on my laptop, it has not been
- * tested anywhere else, and it may not work for you, do strange
- * things or simply crash.
  */
 
 #include <linux/kernel.h>
@@ -36,7 +32,7 @@
 #include <asm/cpufeature.h>
 
 #define PFX		"speedstep-centrino: "
-#define MAINTAINER	"Jeremy Fitzhardinge <jeremy@goop.org>"
+#define MAINTAINER	"cpufreq@lists.linux.org.uk"
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
 
@@ -351,7 +347,36 @@ static unsigned int get_cur_freq(unsigned int cpu)
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 
-static struct acpi_processor_performance p;
+static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
+
+/*
+ * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
+ * library
+ *
+ * Before doing the actual init, we need to do _PSD related setup whenever
+ * supported by the BIOS. These are handled by this early_init routine.
+ */
+static int centrino_cpu_early_init_acpi(void)
+{
+	unsigned int	i, j;
+	struct acpi_processor_performance	*data;
+
+	for_each_cpu(i) {
+		data = kzalloc(sizeof(struct acpi_processor_performance), 
+				GFP_KERNEL);
+		if (!data) {
+			for_each_cpu(j) {
+				kfree(acpi_perf_data[j]);
+				acpi_perf_data[j] = NULL;
+			}
+			return (-ENOMEM);
+		}
+		acpi_perf_data[i] = data;
+	}
+
+	acpi_processor_preregister_performance(acpi_perf_data);
+	return 0;
+}
 
 /*
  * centrino_cpu_init_acpi - register with ACPI P-States library
@@ -365,46 +390,51 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 	unsigned long			cur_freq;
 	int				result = 0, i;
 	unsigned int			cpu = policy->cpu;
+	struct acpi_processor_performance	*p;
+
+	p = acpi_perf_data[cpu];
 
 	/* register with ACPI core */
-	if (acpi_processor_register_performance(&p, cpu)) {
-		dprintk("obtaining ACPI data failed\n");
+	if (acpi_processor_register_performance(p, cpu)) {
+		dprintk(PFX "obtaining ACPI data failed\n");
 		return -EIO;
 	}
+	policy->cpus = p->shared_cpu_map;
+	policy->shared_type = p->shared_type;
 
 	/* verify the acpi_data */
-	if (p.state_count <= 1) {
+	if (p->state_count <= 1) {
 		dprintk("No P-States\n");
 		result = -ENODEV;
 		goto err_unreg;
 	}
 
-	if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-	    (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+	if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+	    (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
 		dprintk("Invalid control/status registers (%x - %x)\n",
-			p.control_register.space_id, p.status_register.space_id);
+			p->control_register.space_id, p->status_register.space_id);
 		result = -EIO;
 		goto err_unreg;
 	}
 
-	for (i=0; i<p.state_count; i++) {
-		if (p.states[i].control != p.states[i].status) {
+	for (i=0; i<p->state_count; i++) {
+		if (p->states[i].control != p->states[i].status) {
 			dprintk("Different control (%llu) and status values (%llu)\n",
-				p.states[i].control, p.states[i].status);
+				p->states[i].control, p->states[i].status);
 			result = -EINVAL;
 			goto err_unreg;
 		}
 
-		if (!p.states[i].core_frequency) {
+		if (!p->states[i].core_frequency) {
 			dprintk("Zero core frequency for state %u\n", i);
 			result = -EINVAL;
 			goto err_unreg;
 		}
 
-		if (p.states[i].core_frequency > p.states[0].core_frequency) {
+		if (p->states[i].core_frequency > p->states[0].core_frequency) {
 			dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
-				p.states[i].core_frequency, p.states[0].core_frequency);
-			p.states[i].core_frequency = 0;
+				p->states[i].core_frequency, p->states[0].core_frequency);
+			p->states[i].core_frequency = 0;
 			continue;
 		}
 	}
@@ -416,26 +446,26 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 	}
 
 	centrino_model[cpu]->model_name=NULL;
-	centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000;
+	centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
 	centrino_model[cpu]->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
-					     (p.state_count + 1), GFP_KERNEL);
+					     (p->state_count + 1), GFP_KERNEL);
         if (!centrino_model[cpu]->op_points) {
                 result = -ENOMEM;
                 goto err_kfree;
         }
 
-        for (i=0; i<p.state_count; i++) {
-		centrino_model[cpu]->op_points[i].index = p.states[i].control;
-		centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000;
+        for (i=0; i<p->state_count; i++) {
+		centrino_model[cpu]->op_points[i].index = p->states[i].control;
+		centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
 		dprintk("adding state %i with frequency %u and control value %04x\n", 
 			i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
 	}
-	centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
+	centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
 
 	cur_freq = get_cur_freq(cpu);
 
-	for (i=0; i<p.state_count; i++) {
-		if (!p.states[i].core_frequency) {
+	for (i=0; i<p->state_count; i++) {
+		if (!p->states[i].core_frequency) {
 			dprintk("skipping state %u\n", i);
 			centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
 			continue;
@@ -451,7 +481,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 		}
 
 		if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
-			p.state = i;
+			p->state = i;
 	}
 
 	/* notify BIOS that we exist */
@@ -464,12 +494,13 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
  err_kfree:
 	kfree(centrino_model[cpu]);
  err_unreg:
-	acpi_processor_unregister_performance(&p, cpu);
-	dprintk("invalid ACPI data\n");
+	acpi_processor_unregister_performance(p, cpu);
+	dprintk(PFX "invalid ACPI data\n");
 	return (result);
 }
 #else
 static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
+static inline int centrino_cpu_early_init_acpi(void) { return 0; }
 #endif
 
 static int centrino_cpu_init(struct cpufreq_policy *policy)
@@ -555,10 +586,15 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 	if (!centrino_model[cpu]->model_name) {
-		dprintk("unregistering and freeing ACPI data\n");
-		acpi_processor_unregister_performance(&p, cpu);
-		kfree(centrino_model[cpu]->op_points);
-		kfree(centrino_model[cpu]);
+		static struct acpi_processor_performance *p;
+
+		if (acpi_perf_data[cpu]) {
+			p = acpi_perf_data[cpu];
+			dprintk("unregistering and freeing ACPI data\n");
+			acpi_processor_unregister_performance(p, cpu);
+			kfree(centrino_model[cpu]->op_points);
+			kfree(centrino_model[cpu]);
+		}
 	}
 #endif
 
@@ -592,63 +628,128 @@ static int centrino_target (struct cpufreq_policy *policy,
 			    unsigned int relation)
 {
 	unsigned int    newstate = 0;
-	unsigned int	msr, oldmsr, h, cpu = policy->cpu;
+	unsigned int	msr, oldmsr = 0, h = 0, cpu = policy->cpu;
 	struct cpufreq_freqs	freqs;
+	cpumask_t		online_policy_cpus;
 	cpumask_t		saved_mask;
-	int			retval;
+	cpumask_t		set_mask;
+	cpumask_t		covered_cpus;
+	int			retval = 0;
+	unsigned int		j, k, first_cpu, tmp;
 
-	if (centrino_model[cpu] == NULL)
+	if (unlikely(centrino_model[cpu] == NULL))
 		return -ENODEV;
 
-	/*
-	 * Support for SMP systems.
-	 * Make sure we are running on the CPU that wants to change frequency
-	 */
-	saved_mask = current->cpus_allowed;
-	set_cpus_allowed(current, policy->cpus);
-	if (!cpu_isset(smp_processor_id(), policy->cpus)) {
-		dprintk("couldn't limit to CPUs in this domain\n");
-		return(-EAGAIN);
+	if (unlikely(cpufreq_frequency_table_target(policy,
+			centrino_model[cpu]->op_points,
+			target_freq,
+			relation,
+			&newstate))) {
+		return -EINVAL;
 	}
 
-	if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq,
-					   relation, &newstate)) {
-		retval = -EINVAL;
-		goto migrate_end;
-	}
+#ifdef CONFIG_HOTPLUG_CPU
+	/* cpufreq holds the hotplug lock, so we are safe from here on */
+	cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
+#else
+	online_policy_cpus = policy->cpus;
+#endif
 
-	msr = centrino_model[cpu]->op_points[newstate].index;
-	rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+	saved_mask = current->cpus_allowed;
+	first_cpu = 1;
+	cpus_clear(covered_cpus);
+	for_each_cpu_mask(j, online_policy_cpus) {
+		/*
+		 * Support for SMP systems.
+		 * Make sure we are running on CPU that wants to change freq
+		 */
+		cpus_clear(set_mask);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			cpus_or(set_mask, set_mask, online_policy_cpus);
+		else
+			cpu_set(j, set_mask);
+
+		set_cpus_allowed(current, set_mask);
+		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+			dprintk("couldn't limit to CPUs in this domain\n");
+			retval = -EAGAIN;
+			if (first_cpu) {
+				/* We haven't started the transition yet. */
+				goto migrate_end;
+			}
+			break;
+		}
 
-	if (msr == (oldmsr & 0xffff)) {
-		retval = 0;
-		dprintk("no change needed - msr was and needs to be %x\n", oldmsr);
-		goto migrate_end;
-	}
+		msr = centrino_model[cpu]->op_points[newstate].index;
+
+		if (first_cpu) {
+			rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+			if (msr == (oldmsr & 0xffff)) {
+				dprintk("no change needed - msr was and needs "
+					"to be %x\n", oldmsr);
+				retval = 0;
+				goto migrate_end;
+			}
+
+			freqs.old = extract_clock(oldmsr, cpu, 0);
+			freqs.new = extract_clock(msr, cpu, 0);
+
+			dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
+				target_freq, freqs.old, freqs.new, msr);
+
+			for_each_cpu_mask(k, online_policy_cpus) {
+				freqs.cpu = k;
+				cpufreq_notify_transition(&freqs,
+					CPUFREQ_PRECHANGE);
+			}
+
+			first_cpu = 0;
+			/* all but 16 LSB are reserved, treat them with care */
+			oldmsr &= ~0xffff;
+			msr &= 0xffff;
+			oldmsr |= msr;
+		}
 
-	freqs.cpu = cpu;
-	freqs.old = extract_clock(oldmsr, cpu, 0);
-	freqs.new = extract_clock(msr, cpu, 0);
+		wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			break;
 
-	dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
-		target_freq, freqs.old, freqs.new, msr);
+		cpu_set(j, covered_cpus);
+	}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	for_each_cpu_mask(k, online_policy_cpus) {
+		freqs.cpu = k;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
 
-	/* all but 16 LSB are "reserved", so treat them with
-	   care */
-	oldmsr &= ~0xffff;
-	msr &= 0xffff;
-	oldmsr |= msr;
+	if (unlikely(retval)) {
+		/*
+		 * We have failed halfway through the frequency change.
+		 * We have sent callbacks to policy->cpus and
+		 * MSRs have already been written on coverd_cpus.
+		 * Best effort undo..
+		 */
 
-	wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+		if (!cpus_empty(covered_cpus)) {
+			for_each_cpu_mask(j, covered_cpus) {
+				set_cpus_allowed(current, cpumask_of_cpu(j));
+				wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+			}
+		}
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		tmp = freqs.new;
+		freqs.new = freqs.old;
+		freqs.old = tmp;
+		for_each_cpu_mask(j, online_policy_cpus) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		}
+	}
 
-	retval = 0;
 migrate_end:
 	set_cpus_allowed(current, saved_mask);
-	return (retval);
+	return 0;
 }
 
 static struct freq_attr* centrino_attr[] = {
@@ -690,12 +791,25 @@ static int __init centrino_init(void)
 	if (!cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
 
+	centrino_cpu_early_init_acpi();
+
 	return cpufreq_register_driver(&centrino_driver);
 }
 
 static void __exit centrino_exit(void)
 {
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+	unsigned int j;
+#endif
+	
 	cpufreq_unregister_driver(&centrino_driver);
+
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+	for_each_cpu(j) {
+		kfree(acpi_perf_data[j]);
+		acpi_perf_data[j] = NULL;
+	}
+#endif
 }
 
 MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 00f2e058797c..fc32c8028e24 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -184,7 +184,7 @@ static void __init geode_configure(void)
 
 
 #ifdef CONFIG_PCI
-static struct pci_device_id cyrix_55x0[] = {
+static struct pci_device_id __initdata cyrix_55x0[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
 	{ },
@@ -272,14 +272,15 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
 
 		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
 		isa_dma_bridge_buggy = 2;
-#endif		
-		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
- 
+
+
 		/*
 		 *  The 5510/5520 companion chips have a funky PIT.
 		 */  
 		if (pci_dev_present(cyrix_55x0))
 			pit_latch_buggy = 1;
+#endif
+		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
 
 		/* GXm supports extended cpuid levels 'ala' AMD */
 		if (c->cpuid_level == 2) {
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index f94cdb7aca50..a19fcb262dbb 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -52,7 +52,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
 		/* VIA/Cyrix/Centaur-defined */
 		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
index d75524758daf..c4351972d9af 100644
--- a/arch/i386/kernel/i387.c
+++ b/arch/i386/kernel/i387.c
@@ -25,7 +25,7 @@
 #define HAVE_HWFP 1
 #endif
 
-static unsigned long mxcsr_feature_mask = 0xffffffff;
+static unsigned long mxcsr_feature_mask __read_mostly = 0xffffffff;
 
 void mxcsr_feature_mask_init(void)
 {
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 323ef8ab3244..b7636b96e104 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -271,8 +271,8 @@ static int i8259A_shutdown(struct sys_device *dev)
 	 * the kernel initialization code can get it
 	 * out of.
 	 */
-	outb(0xff, 0x21);	/* mask all of 8259A-1 */
-	outb(0xff, 0xA1);	/* mask all of 8259A-1 */
+	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
+	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
 	return 0;
 }
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index d70f2ade5cde..a62df3e764c5 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -267,7 +267,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 # include <linux/slab.h>		/* kmalloc() */
 # include <linux/timer.h>	/* time_after() */
  
-# ifdef CONFIG_BALANCED_IRQ_DEBUG
+#ifdef CONFIG_BALANCED_IRQ_DEBUG
 #  define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
 #  define Dprintk(x...) do { TDprintk(x); } while (0)
 # else
@@ -275,10 +275,15 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
 #  define Dprintk(x...) 
 # endif
 
-
 #define IRQBALANCE_CHECK_ARCH -999
-static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
-static int physical_balance = 0;
+#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
+#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
+#define BALANCED_IRQ_LESS_DELTA		(HZ)
+
+static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
+static int physical_balance __read_mostly;
+static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
 
 static struct irq_cpu_info {
 	unsigned long * last_irq;
@@ -297,12 +302,14 @@ static struct irq_cpu_info {
 
 #define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
 
-#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
-#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
-#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
-#define BALANCED_IRQ_LESS_DELTA		(HZ)
+static cpumask_t balance_irq_affinity[NR_IRQS] = {
+	[0 ... NR_IRQS-1] = CPU_MASK_ALL
+};
 
-static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
+{
+	balance_irq_affinity[irq] = mask;
+}
 
 static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
 			unsigned long now, int direction)
@@ -340,7 +347,7 @@ static inline void balance_irq(int cpu, int irq)
 	if (irqbalance_disabled)
 		return; 
 
-	cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
+	cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
 	new_cpu = move(cpu, allowed_mask, now, 1);
 	if (cpu != new_cpu) {
 		set_pending_irq(irq, cpumask_of_cpu(new_cpu));
@@ -529,7 +536,9 @@ tryanotherirq:
 		}
 	}
 
-	cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
+	cpus_and(allowed_mask,
+		cpu_online_map,
+		balance_irq_affinity[selected_irq]);
 	target_cpu_mask = cpumask_of_cpu(min_loaded);
 	cpus_and(tmp, target_cpu_mask, allowed_mask);
 
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index f3a9c78c4a24..248e922ee13a 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -42,8 +42,8 @@ union irq_ctx {
 	u32                     stack[THREAD_SIZE/sizeof(u32)];
 };
 
-static union irq_ctx *hardirq_ctx[NR_CPUS];
-static union irq_ctx *softirq_ctx[NR_CPUS];
+static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 #endif
 
 /*
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 38806f427849..395a9a6dff88 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -607,7 +607,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	if (args->regs && user_mode(args->regs))
+	if (args->regs && user_mode_vm(args->regs))
 		return ret;
 
 	switch (val) {
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index e7c138f66c5a..0a865889b2a9 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -91,7 +91,10 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION 	"1.14"
+static int verbose;
+module_param(verbose, int, 0644);
+
+#define MICROCODE_VERSION 	"1.14a"
 
 #define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
 #define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
@@ -122,14 +125,15 @@ static unsigned int user_buffer_size;	/* it's size */
 
 typedef enum mc_error_code {
 	MC_SUCCESS 	= 0,
-	MC_NOTFOUND 	= 1,
-	MC_MARKED 	= 2,
-	MC_ALLOCATED 	= 3,
+	MC_IGNORED 	= 1,
+	MC_NOTFOUND 	= 2,
+	MC_MARKED 	= 3,
+	MC_ALLOCATED 	= 4,
 } mc_error_code_t;
 
 static struct ucode_cpu_info {
 	unsigned int sig;
-	unsigned int pf;
+	unsigned int pf, orig_pf;
 	unsigned int rev;
 	unsigned int cksum;
 	mc_error_code_t err;
@@ -164,6 +168,7 @@ static void collect_cpu_info (void *unused)
 			rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
 			uci->pf = 1 << ((val[1] >> 18) & 7);
 		}
+		uci->orig_pf = uci->pf;
 	}
 
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -197,21 +202,34 @@ static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_he
 	pr_debug("   Checksum 0x%x\n", cksum);
 
 	if (mc_header->rev < uci->rev) {
-		printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision"
-		       " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-		goto out;
+		if (uci->err == MC_NOTFOUND) {
+			uci->err = MC_IGNORED;
+			uci->cksum = mc_header->rev;
+		} else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
+			uci->cksum = mc_header->rev;
 	} else if (mc_header->rev == uci->rev) {
-		/* notify the caller of success on this cpu */
-		uci->err = MC_SUCCESS;
-		goto out;
+		if (uci->err < MC_MARKED) {
+			/* notify the caller of success on this cpu */
+			uci->err = MC_SUCCESS;
+		}
+	} else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
+		pr_debug("microcode: CPU%d found a matching microcode update with "
+			" revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
+		uci->cksum = cksum;
+		uci->pf = pf; /* keep the original mc pf for cksum calculation */
+		uci->err = MC_MARKED; /* found the match */
+		for_each_online_cpu(cpu_num) {
+			if (ucode_cpu_info + cpu_num != uci
+			    && ucode_cpu_info[cpu_num].mc == uci->mc) {
+				uci->mc = NULL;
+				break;
+			}
+		}
+		if (uci->mc != NULL) {
+			vfree(uci->mc);
+			uci->mc = NULL;
+		}
 	}
-
-	pr_debug("microcode: CPU%d found a matching microcode update with "
-		" revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-	uci->cksum = cksum;
-	uci->pf = pf; /* keep the original mc pf for cksum calculation */
-	uci->err = MC_MARKED; /* found the match */
-out:
 	return;
 }
 
@@ -253,10 +271,8 @@ static int find_matching_ucodes (void)
 
 		for_each_online_cpu(cpu_num) {
 			struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-			if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
-				continue;
 
-			if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf))
+			if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
 				mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
 		}
 
@@ -295,9 +311,8 @@ static int find_matching_ucodes (void)
 				}
 				for_each_online_cpu(cpu_num) {
 					struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-					if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
-						continue;
-					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) {
+
+					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
 						mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
 					}
 				}
@@ -368,6 +383,13 @@ static void do_update_one (void * unused)
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
 	if (uci->mc == NULL) {
+		if (verbose) {
+			if (uci->err == MC_SUCCESS)
+				printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
+					cpu_num, uci->rev);
+			else
+				printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
+		}
 		return;
 	}
 
@@ -426,6 +448,9 @@ out_free:
 					ucode_cpu_info[j].mc = NULL;
 			}
 		}
+		if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
+			printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
+			       " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
 	}
 out:
 	return error;
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index dd6b0e3386ce..e6023970aa40 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -48,6 +48,7 @@
 #include <linux/crash_dump.h>
 #include <linux/dmi.h>
 #include <linux/pfn.h>
+#include <linux/suspend.h>
 
 #include <video/edid.h>
 
@@ -1434,6 +1435,111 @@ static void set_mca_bus(int x)
 static void set_mca_bus(int x) { }
 #endif
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+static void __init mark_nosave_page_range(unsigned long start, unsigned long end)
+{
+	struct page *page;
+	while (start <= end) {
+		page = pfn_to_page(start);
+		SetPageNosave(page);
+		start++;
+	}
+}
+
+static void __init e820_nosave_reserved_pages(void)
+{
+	int i;
+	unsigned long r_start = 0, r_end = 0;
+
+	/* Assume e820 map is sorted */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long start, end;
+
+		start = PFN_DOWN(ei->addr);
+		end = PFN_UP(ei->addr + ei->size);
+		if (start >= end)
+			continue;
+		if (ei->type == E820_RESERVED)
+			continue;
+		r_end = start;
+		/*
+		 * Highmem 'Reserved' pages are marked as reserved, swsusp
+		 * will not save/restore them, so we ignore these pages here.
+		 */
+		if (r_end > max_low_pfn)
+			r_end = max_low_pfn;
+		if (r_end > r_start)
+			mark_nosave_page_range(r_start, r_end-1);
+		if (r_end >= max_low_pfn)
+			break;
+		r_start = end;
+	}
+}
+
+static void __init e820_save_acpi_pages(void)
+{
+	int i;
+
+	/* Assume e820 map is sorted */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long start, end;
+
+		start = ei->addr;
+		end = ei->addr + ei->size;
+		if (start >= end)
+			continue;
+		if (ei->type != E820_ACPI && ei->type != E820_NVS)
+			continue;
+		/*
+		 * If the region is below max_low_pfn, it will be
+		 * saved/restored by swsusp follow 'RAM' type.
+		 */
+		if (start < (max_low_pfn << PAGE_SHIFT))
+			start = max_low_pfn << PAGE_SHIFT;
+		/*
+		 * Highmem pages (ACPI NVS/Data) are reserved, but swsusp
+		 * highmem save/restore will not save/restore them. We marked
+		 * them as arch saveable pages here
+		 */
+		if (end > start)
+			swsusp_add_arch_pages(start, end);
+	}
+}
+
+extern char __start_rodata, __end_rodata;
+/*
+ * BIOS reserved region/hole - no save/restore
+ * ACPI NVS - save/restore
+ * ACPI Data - this is a little tricky, the mem could be used by OS after OS
+ * reads tables from the region, but anyway save/restore the memory hasn't any
+ * side effect and Linux runtime module load/unload might use it.
+ * kernel rodata - no save/restore (kernel rodata isn't changed)
+ */
+static int __init mark_nosave_pages(void)
+{
+	unsigned long pfn_start, pfn_end;
+
+	/* FIXME: provide a version for efi BIOS */
+	if (efi_enabled)
+		return 0;
+	/* BIOS reserved regions & holes */
+	e820_nosave_reserved_pages();
+
+	/* kernel rodata */
+	pfn_start = PFN_UP(virt_to_phys(&__start_rodata));
+	pfn_end = PFN_DOWN(virt_to_phys(&__end_rodata));
+	mark_nosave_page_range(pfn_start, pfn_end-1);
+
+	/* record ACPI Data/NVS as saveable */
+	e820_save_acpi_pages();
+
+	return 0;
+}
+core_initcall(mark_nosave_pages);
+#endif
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 52b3ed5d2cb5..989c85255dbe 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -39,7 +39,6 @@
 #define NODE_ARRAY_OFFSET(x)	((x) % 8)	/* 8 bits/char */
 #define BMAP_SET(bmap, bit)	((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit))
 #define BMAP_TEST(bmap, bit)	((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit)))
-#define MAX_PXM_DOMAINS		256	/* 1 byte and no promises about values */
 /* bitmap length; _PXM is at most 255 */
 #define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) 
 static u8 pxm_bitmap[PXM_BITMAP_LEN];	/* bitmap of proximity domains */
@@ -213,19 +212,11 @@ static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_c
 		node_end_pfn[nid] = memory_chunk->end_pfn;
 }
 
-static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
-
-int pxm_to_node(int pxm)
-{
-	return pxm_to_nid_map[pxm];
-}
-
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
 	u8 *start, *end, *p;
 	int i, j, nid;
-	u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
 	start = (u8 *)(&(sratp->reserved) + 1);	/* skip header */
 	p = start;
@@ -235,10 +226,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 	memset(node_memory_chunk, 0, sizeof(node_memory_chunk));
 	memset(zholes_size, 0, sizeof(zholes_size));
 
-	/* -1 in these maps means not available */
-	memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
-	memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
-
 	num_memory_chunks = 0;
 	while (p < end) {
 		switch (*p) {
@@ -278,9 +265,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 	nodes_clear(node_online_map);
 	for (i = 0; i < MAX_PXM_DOMAINS; i++) {
 		if (BMAP_TEST(pxm_bitmap, i)) {
-			nid = num_online_nodes();
-			pxm_to_nid_map[i] = nid;
-			nid_to_pxm_map[nid] = i;
+			int nid = acpi_map_pxm_to_node(i);
 			node_set_online(nid);
 		}
 	}
@@ -288,7 +273,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 
 	/* set cnode id in memory chunk structure */
 	for (i = 0; i < num_memory_chunks; i++)
-		node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
+		node_memory_chunk[i].nid = pxm_to_node(node_memory_chunk[i].pxm);
 
 	printk("pxm bitmap: ");
 	for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index af56987f69b0..dd63d4775398 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -316,3 +316,4 @@ ENTRY(sys_call_table)
 	.long sys_sync_file_range
 	.long sys_tee			/* 315 */
 	.long sys_vmsplice
+	.long sys_move_pages
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0e498369f35e..dcc14477af1f 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -149,6 +149,12 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
 	while (valid_stack_ptr(tinfo, (void *)ebp)) {
 		addr = *(unsigned long *)(ebp + 4);
 		printed = print_addr_and_symbol(addr, log_lvl, printed);
+		/*
+		 * break out of recursive entries (such as
+		 * end_of_stack_stop_unwind_function):
+	 	 */
+		if (ebp == *(unsigned long *)ebp)
+			break;
 		ebp = *(unsigned long *)ebp;
 	}
 #else
@@ -268,8 +274,9 @@ void show_registers(struct pt_regs *regs)
 		regs->esi, regs->edi, regs->ebp, esp);
 	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
 		regs->xds & 0xffff, regs->xes & 0xffff, ss);
-	printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)",
-		current->comm, current->pid, current_thread_info(), current);
+	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+		TASK_COMM_LEN, current->comm, current->pid,
+		current_thread_info(), current, current->thread_info);
 	/*
 	 * When in-kernel, we also print out the stack and code at the
 	 * time of the fault..
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 8831303a473f..7512f39c9f25 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -37,6 +37,13 @@ SECTIONS
 
   RODATA
 
+  . = ALIGN(4);
+  __tracedata_start = .;
+  .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
+	*(.tracedata)
+  }
+  __tracedata_end = .;
+
   /* writeable */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
 	*(.data)
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 4cf981d70f45..6979297ce278 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -425,15 +425,121 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
 		       : "eax", "edx", "memory");
 	return size;
 }
+
+/*
+ * Non Temporal Hint version of __copy_user_zeroing_intel.  It is cache aware.
+ * hyoshiok@miraclelinux.com
+ */
+
+static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+				const void __user *from, unsigned long size)
+{
+        int d0, d1;
+
+	__asm__ __volatile__(
+	       "        .align 2,0x90\n"
+	       "0:      movl 32(%4), %%eax\n"
+	       "        cmpl $67, %0\n"
+	       "        jbe 2f\n"
+	       "1:      movl 64(%4), %%eax\n"
+	       "        .align 2,0x90\n"
+	       "2:      movl 0(%4), %%eax\n"
+	       "21:     movl 4(%4), %%edx\n"
+	       "        movnti %%eax, 0(%3)\n"
+	       "        movnti %%edx, 4(%3)\n"
+	       "3:      movl 8(%4), %%eax\n"
+	       "31:     movl 12(%4),%%edx\n"
+	       "        movnti %%eax, 8(%3)\n"
+	       "        movnti %%edx, 12(%3)\n"
+	       "4:      movl 16(%4), %%eax\n"
+	       "41:     movl 20(%4), %%edx\n"
+	       "        movnti %%eax, 16(%3)\n"
+	       "        movnti %%edx, 20(%3)\n"
+	       "10:     movl 24(%4), %%eax\n"
+	       "51:     movl 28(%4), %%edx\n"
+	       "        movnti %%eax, 24(%3)\n"
+	       "        movnti %%edx, 28(%3)\n"
+	       "11:     movl 32(%4), %%eax\n"
+	       "61:     movl 36(%4), %%edx\n"
+	       "        movnti %%eax, 32(%3)\n"
+	       "        movnti %%edx, 36(%3)\n"
+	       "12:     movl 40(%4), %%eax\n"
+	       "71:     movl 44(%4), %%edx\n"
+	       "        movnti %%eax, 40(%3)\n"
+	       "        movnti %%edx, 44(%3)\n"
+	       "13:     movl 48(%4), %%eax\n"
+	       "81:     movl 52(%4), %%edx\n"
+	       "        movnti %%eax, 48(%3)\n"
+	       "        movnti %%edx, 52(%3)\n"
+	       "14:     movl 56(%4), %%eax\n"
+	       "91:     movl 60(%4), %%edx\n"
+	       "        movnti %%eax, 56(%3)\n"
+	       "        movnti %%edx, 60(%3)\n"
+	       "        addl $-64, %0\n"
+	       "        addl $64, %4\n"
+	       "        addl $64, %3\n"
+	       "        cmpl $63, %0\n"
+	       "        ja  0b\n"
+	       "        sfence \n"
+	       "5:      movl  %0, %%eax\n"
+	       "        shrl  $2, %0\n"
+	       "        andl $3, %%eax\n"
+	       "        cld\n"
+	       "6:      rep; movsl\n"
+	       "        movl %%eax,%0\n"
+	       "7:      rep; movsb\n"
+	       "8:\n"
+	       ".section .fixup,\"ax\"\n"
+	       "9:      lea 0(%%eax,%0,4),%0\n"
+	       "16:     pushl %0\n"
+	       "        pushl %%eax\n"
+	       "        xorl %%eax,%%eax\n"
+	       "        rep; stosb\n"
+	       "        popl %%eax\n"
+	       "        popl %0\n"
+	       "        jmp 8b\n"
+	       ".previous\n"
+	       ".section __ex_table,\"a\"\n"
+	       "	.align 4\n"
+	       "	.long 0b,16b\n"
+	       "	.long 1b,16b\n"
+	       "	.long 2b,16b\n"
+	       "	.long 21b,16b\n"
+	       "	.long 3b,16b\n"
+	       "	.long 31b,16b\n"
+	       "	.long 4b,16b\n"
+	       "	.long 41b,16b\n"
+	       "	.long 10b,16b\n"
+	       "	.long 51b,16b\n"
+	       "	.long 11b,16b\n"
+	       "	.long 61b,16b\n"
+	       "	.long 12b,16b\n"
+	       "	.long 71b,16b\n"
+	       "	.long 13b,16b\n"
+	       "	.long 81b,16b\n"
+	       "	.long 14b,16b\n"
+	       "	.long 91b,16b\n"
+	       "	.long 6b,9b\n"
+	       "        .long 7b,16b\n"
+	       ".previous"
+	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
+	       :  "1"(to), "2"(from), "0"(size)
+	       : "eax", "edx", "memory");
+	return size;
+}
+
 #else
+
 /*
  * Leave these declared but undefined.  They should not be any references to
  * them
  */
-unsigned long
-__copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size);
-unsigned long
-__copy_user_intel(void __user *to, const void *from, unsigned long size);
+unsigned long __copy_user_zeroing_intel(void *to, const void __user *from,
+					unsigned long size);
+unsigned long __copy_user_intel(void __user *to, const void *from,
+					unsigned long size);
+unsigned long __copy_user_zeroing_intel_nocache(void *to,
+				const void __user *from, unsigned long size);
 #endif /* CONFIG_X86_INTEL_USERCOPY */
 
 /* Generic arbitrary sized copy.  */
@@ -515,8 +621,8 @@ do {									\
 		: "memory");						\
 } while (0)
 
-
-unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n)
+unsigned long __copy_to_user_ll(void __user *to, const void *from,
+				unsigned long n)
 {
 	BUG_ON((long) n < 0);
 #ifndef CONFIG_X86_WP_WORKS_OK
@@ -576,8 +682,8 @@ survive:
 }
 EXPORT_SYMBOL(__copy_to_user_ll);
 
-unsigned long
-__copy_from_user_ll(void *to, const void __user *from, unsigned long n)
+unsigned long __copy_from_user_ll(void *to, const void __user *from,
+					unsigned long n)
 {
 	BUG_ON((long)n < 0);
 	if (movsl_is_ok(to, from, n))
@@ -588,6 +694,21 @@ __copy_from_user_ll(void *to, const void __user *from, unsigned long n)
 }
 EXPORT_SYMBOL(__copy_from_user_ll);
 
+unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
+					unsigned long n)
+{
+	BUG_ON((long)n < 0);
+#ifdef CONFIG_X86_INTEL_USERCOPY
+	if ( n > 64 && cpu_has_xmm2)
+                n = __copy_user_zeroing_intel_nocache(to, from, n);
+	else
+		__copy_user_zeroing(to, from, n);
+#else
+        __copy_user_zeroing(to, from, n);
+#endif
+	return n;
+}
+
 /**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 7f0fcf219a26..bd6fe96cc16d 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -77,12 +77,15 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
 	unsigned seg = regs->xcs & 0xffff;
 	u32 seg_ar, seg_limit, base, *desc;
 
+	/* Unlikely, but must come before segment checks. */
+	if (unlikely(regs->eflags & VM_MASK)) {
+		base = seg << 4;
+		*eip_limit = base + 0xffff;
+		return base + (eip & 0xffff);
+	}
+
 	/* The standard kernel/user address space limit. */
 	*eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
-
-	/* Unlikely, but must come before segment checks. */
-	if (unlikely((regs->eflags & VM_MASK) != 0))
-		return eip + (seg << 4);
 	
 	/* By far the most common cases. */
 	if (likely(seg == __USER_CS || seg == __KERNEL_CS))
@@ -380,12 +383,12 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
 		goto bad_area;
 	if (error_code & 4) {
 		/*
-		 * accessing the stack below %esp is always a bug.
-		 * The "+ 32" is there due to some instructions (like
-		 * pusha) doing post-decrement on the stack and that
-		 * doesn't show up until later..
+		 * Accessing the stack below %esp is always a bug.
+		 * The large cushion allows instructions like enter
+		 * and pusha to work.  ("enter $65535,$31" pushes
+		 * 32 pointers and then decrements %esp by 65535.)
 		 */
-		if (address + 32 < regs->esp)
+		if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp)
 			goto bad_area;
 	}
 	if (expand_stack(vma, address))
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 3df1371d4520..bf19513f0cea 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -29,6 +29,7 @@
 #include <linux/efi.h>
 #include <linux/memory_hotplug.h>
 #include <linux/initrd.h>
+#include <linux/cpumask.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -384,7 +385,7 @@ static void __init pagetable_init (void)
 #endif
 }
 
-#ifdef CONFIG_SOFTWARE_SUSPEND
+#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
 /*
  * Swap suspend & friends need this for resume because things like the intel-agp
  * driver might have split up a kernel 4MB mapping.
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 92c3d9f0e731..0887b34bc59b 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -209,19 +209,19 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot)
 }
 
 void global_flush_tlb(void)
-{ 
-	LIST_HEAD(l);
+{
+	struct list_head l;
 	struct page *pg, *next;
 
 	BUG_ON(irqs_disabled());
 
 	spin_lock_irq(&cpa_lock);
-	list_splice_init(&df_list, &l);
+	list_replace_init(&df_list, &l);
 	spin_unlock_irq(&cpa_lock);
 	flush_map();
 	list_for_each_entry_safe(pg, next, &l, lru)
 		__free_page(pg);
-} 
+}
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 void kernel_map_pages(struct page *page, int numpages, int enable)
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index dbece776c5b2..c624b61e1104 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -288,6 +288,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
 void pcibios_disable_device (struct pci_dev *dev)
 {
+	pcibios_disable_resources(dev);
 	if (pcibios_disable_irq)
 		pcibios_disable_irq(dev);
 }
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index ed2c8c899bd3..7852827a599b 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -242,6 +242,15 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
 	return 0;
 }
 
+void pcibios_disable_resources(struct pci_dev *dev)
+{
+	u16 cmd;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
+
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain crappy BIOSes forget to set it properly.
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 06dab00aaadc..8ce69508f3c7 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -198,14 +198,14 @@ static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigne
  */
 static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
 
 	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
 }
 
 static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
 	unsigned int val = irqmap[irq];
 		
 	if (val) {
@@ -256,13 +256,13 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
  */
 static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+	static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 	return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
 }
 
 static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+	static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
 	return 1;
 }
@@ -274,13 +274,13 @@ static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq
  */
 static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
 	return read_config_nybble(router,0x43, pirqmap[pirq-1]);
 }
 
 static int pirq_ite_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
 	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
 	return 1;
 }
@@ -505,7 +505,7 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
 
 static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
 {
-	static struct pci_device_id pirq_440gx[] = {
+	static struct pci_device_id __initdata pirq_440gx[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
 		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
 		{ },
@@ -880,6 +880,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
 		DBG(" -> got IRQ %d\n", irq);
 		msg = "Found";
+		eisa_set_level_irq(irq);
 	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
 		DBG(" -> assigning IRQ %d", newirq);
 		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 6b1ea0c9a570..e545b0992c48 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -15,7 +15,9 @@
 #include <asm/e820.h>
 #include "pci.h"
 
-#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
 
 /* Assume systems with more busses have correct MCFG */
 #define MAX_CHECK_BUS 16
@@ -197,9 +199,10 @@ void __init pci_mmcfg_init(void)
 		return;
 
 	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
 			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
+				pci_mmcfg_config[0].base_address);
 		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
 		return;
 	}
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 12035e29108b..12bf3d8dda29 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -35,6 +35,7 @@ extern unsigned int pcibios_max_latency;
 
 void pcibios_resource_survey(void);
 int pcibios_enable_resources(struct pci_dev *, int);
+void pcibios_disable_resources(struct pci_dev *);
 
 /* pci-pc.c */
 
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 79b2370c7fac..e6517915fe3e 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -10,6 +10,8 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/suspend.h>
+#include <asm/mtrr.h>
+#include <asm/mce.h>
 
 static struct saved_context saved_context;
 
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 0f3076a820c3..18318749884b 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -77,6 +77,7 @@ choice
 config IA64_GENERIC
 	bool "generic"
 	select ACPI
+	select PCI
 	select NUMA
 	select ACPI_NUMA
 	help
@@ -273,7 +274,6 @@ config HOTPLUG_CPU
 config SCHED_SMT
 	bool "SMT scheduler support"
 	depends on SMP
-	default off
 	help
 	  Improves the CPU scheduler's decision making when dealing with
 	  Intel IA64 chips with MultiThreading at a cost of slightly increased
@@ -449,6 +449,8 @@ config PCI_DOMAINS
 	bool
 	default PCI
 
+source "drivers/pci/pcie/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 80ea7506fa1a..21033ed83307 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -71,6 +71,8 @@ all: compressed unwcheck
 
 compressed: vmlinux.gz
 
+vmlinuz: vmlinux.gz
+
 vmlinux.gz: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
 
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index bdccd0b1eb60..5825ddee58d6 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1958,7 +1958,7 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 	if (pxm < 0)
 		return;
 
-	node = pxm_to_nid_map[pxm];
+	node = pxm_to_node(pxm);
 
 	if (node >= MAX_NUMNODES || !node_online(node))
 		return;
@@ -1999,7 +1999,7 @@ acpi_sba_ioc_add(struct acpi_device *device)
 		if (!iovp_shift)
 			iovp_shift = min(PAGE_SHIFT, 16);
 	}
-	ACPI_MEM_FREE(dev_info);
+	kfree(dev_info);
 
 	/*
 	 * default anything not caught above or specified on cmdline to 4k
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 58c93a30348c..ca16d9556bde 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -68,8 +68,6 @@ EXPORT_SYMBOL(pm_power_off);
 unsigned char acpi_kbd_controller_present = 1;
 unsigned char acpi_legacy_devices;
 
-static unsigned int __initdata acpi_madt_rev;
-
 unsigned int acpi_cpei_override;
 unsigned int acpi_cpei_phys_cpuid;
 
@@ -243,6 +241,8 @@ acpi_parse_iosapic(acpi_table_entry_header * header, const unsigned long end)
 	return iosapic_init(iosapic->address, iosapic->global_irq_base);
 }
 
+static unsigned int __initdata acpi_madt_rev;
+
 static int __init
 acpi_parse_plat_int_src(acpi_table_entry_header * header,
 			const unsigned long end)
@@ -415,9 +415,6 @@ static int __initdata srat_num_cpus;	/* number of cpus */
 static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
 #define pxm_bit_set(bit)	(set_bit(bit,(void *)pxm_flag))
 #define pxm_bit_test(bit)	(test_bit(bit,(void *)pxm_flag))
-/* maps to convert between proximity domain and logical node ID */
-int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
-int __initdata nid_to_pxm_map[MAX_NUMNODES];
 static struct acpi_table_slit __initdata *slit_table;
 
 static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa)
@@ -533,22 +530,17 @@ void __init acpi_numa_arch_fixup(void)
 	 * MCD - This can probably be dropped now.  No need for pxm ID to node ID
 	 * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES.
 	 */
-	/* calculate total number of nodes in system from PXM bitmap */
-	memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
-	memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
 	nodes_clear(node_online_map);
 	for (i = 0; i < MAX_PXM_DOMAINS; i++) {
 		if (pxm_bit_test(i)) {
-			int nid = num_online_nodes();
-			pxm_to_nid_map[i] = nid;
-			nid_to_pxm_map[nid] = i;
+			int nid = acpi_map_pxm_to_node(i);
 			node_set_online(nid);
 		}
 	}
 
 	/* set logical node id in memory chunk structure */
 	for (i = 0; i < num_node_memblks; i++)
-		node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
+		node_memblk[i].nid = pxm_to_node(node_memblk[i].nid);
 
 	/* assign memory bank numbers for each chunk on each node */
 	for_each_online_node(i) {
@@ -562,7 +554,7 @@ void __init acpi_numa_arch_fixup(void)
 
 	/* set logical node id in cpu structure */
 	for (i = 0; i < srat_num_cpus; i++)
-		node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
+		node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
 
 	printk(KERN_INFO "Number of logical nodes in system = %d\n",
 	       num_online_nodes());
@@ -575,11 +567,11 @@ void __init acpi_numa_arch_fixup(void)
 	for (i = 0; i < slit_table->localities; i++) {
 		if (!pxm_bit_test(i))
 			continue;
-		node_from = pxm_to_nid_map[i];
+		node_from = pxm_to_node(i);
 		for (j = 0; j < slit_table->localities; j++) {
 			if (!pxm_bit_test(j))
 				continue;
-			node_to = pxm_to_nid_map[j];
+			node_to = pxm_to_node(j);
 			node_distance(node_from, node_to) =
 			    slit_table->entry[i * slit_table->localities + j];
 		}
@@ -626,7 +618,7 @@ EXPORT_SYMBOL(acpi_unregister_gsi);
 static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size)
 {
 	struct acpi_table_header *fadt_header;
-	struct fadt_descriptor_rev2 *fadt;
+	struct fadt_descriptor *fadt;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
@@ -635,7 +627,7 @@ static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size)
 	if (fadt_header->revision != 3)
 		return -ENODEV;	/* Only deal with ACPI 2.0 FADT */
 
-	fadt = (struct fadt_descriptor_rev2 *)fadt_header;
+	fadt = (struct fadt_descriptor *)fadt_header;
 
 	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
 		acpi_kbd_controller_present = 0;
@@ -785,9 +777,9 @@ int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
 
 	/*
 	 * Assuming that the container driver would have set the proximity
-	 * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag
+	 * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag
 	 */
-	node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id];
+	node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id);
 
 	node_cpuid[cpu].phys_id = physid;
 #endif
@@ -966,7 +958,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
 	if (pxm < 0)
 		return AE_OK;
 
-	node = pxm_to_nid_map[pxm];
+	node = pxm_to_node(pxm);
 
 	if (node >= MAX_NUMNODES || !node_online(node) ||
 	    cpus_empty(node_to_cpumask(node)))
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 77225659e968..16e7b6600ae6 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -217,16 +217,24 @@ void foo(void)
 	DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
 	       offsetof (struct ia64_mca_cpu, init_stack));
 	BLANK();
-	DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET,
-	       offsetof (struct ia64_sal_os_state, sal_ra));
 	DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET,
 	       offsetof (struct ia64_sal_os_state, os_gp));
-	DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
-	       offsetof (struct ia64_sal_os_state, pal_min_state));
 	DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET,
 	       offsetof (struct ia64_sal_os_state, proc_state_param));
+	DEFINE(IA64_SAL_OS_STATE_SAL_RA_OFFSET,
+	       offsetof (struct ia64_sal_os_state, sal_ra));
+	DEFINE(IA64_SAL_OS_STATE_SAL_GP_OFFSET,
+	       offsetof (struct ia64_sal_os_state, sal_gp));
+	DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
+	       offsetof (struct ia64_sal_os_state, pal_min_state));
+	DEFINE(IA64_SAL_OS_STATE_OS_STATUS_OFFSET,
+	       offsetof (struct ia64_sal_os_state, os_status));
+	DEFINE(IA64_SAL_OS_STATE_CONTEXT_OFFSET,
+	       offsetof (struct ia64_sal_os_state, context));
 	DEFINE(IA64_SAL_OS_STATE_SIZE,
 	       sizeof (struct ia64_sal_os_state));
+	BLANK();
+
 	DEFINE(IA64_PMSA_GR_OFFSET,
 	       offsetof (struct pal_min_state_area_s, pmsa_gr));
 	DEFINE(IA64_PMSA_BANK1_GR_OFFSET,
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 12cfedce73b1..c33d0ba7e300 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -8,6 +8,8 @@
  * Copyright (C) 1999-2003 Hewlett-Packard Co.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
+ * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  * All EFI Runtime Services are not implemented yet as EFI only
  * supports physical mode addressing on SoftSDV. This is to be fixed
@@ -622,28 +624,20 @@ efi_get_iobase (void)
 	return 0;
 }
 
-static efi_memory_desc_t *
-efi_memory_descriptor (unsigned long phys_addr)
+static struct kern_memdesc *
+kern_memory_descriptor (unsigned long phys_addr)
 {
-	void *efi_map_start, *efi_map_end, *p;
-	efi_memory_desc_t *md;
-	u64 efi_desc_size;
-
-	efi_map_start = __va(ia64_boot_param->efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
-	efi_desc_size = ia64_boot_param->efi_memdesc_size;
+	struct kern_memdesc *md;
 
-	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
-		md = p;
-
-		if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
+	for (md = kern_memmap; md->start != ~0UL; md++) {
+		if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT))
 			 return md;
 	}
 	return 0;
 }
 
-static int
-efi_memmap_has_mmio (void)
+static efi_memory_desc_t *
+efi_memory_descriptor (unsigned long phys_addr)
 {
 	void *efi_map_start, *efi_map_end, *p;
 	efi_memory_desc_t *md;
@@ -656,8 +650,8 @@ efi_memmap_has_mmio (void)
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
 
-		if (md->type == EFI_MEMORY_MAPPED_IO)
-			return 1;
+		if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
+			 return md;
 	}
 	return 0;
 }
@@ -683,71 +677,125 @@ efi_mem_attributes (unsigned long phys_addr)
 }
 EXPORT_SYMBOL(efi_mem_attributes);
 
-/*
- * Determines whether the memory at phys_addr supports the desired
- * attribute (WB, UC, etc).  If this returns 1, the caller can safely
- * access size bytes at phys_addr with the specified attribute.
- */
-int
-efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr)
+u64
+efi_mem_attribute (unsigned long phys_addr, unsigned long size)
 {
 	unsigned long end = phys_addr + size;
 	efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
+	u64 attr;
+
+	if (!md)
+		return 0;
+
+	/*
+	 * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells
+	 * the kernel that firmware needs this region mapped.
+	 */
+	attr = md->attribute & ~EFI_MEMORY_RUNTIME;
+	do {
+		unsigned long md_end = efi_md_end(md);
+
+		if (end <= md_end)
+			return attr;
+
+		md = efi_memory_descriptor(md_end);
+		if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
+			return 0;
+	} while (md);
+	return 0;
+}
+
+u64
+kern_mem_attribute (unsigned long phys_addr, unsigned long size)
+{
+	unsigned long end = phys_addr + size;
+	struct kern_memdesc *md;
+	u64 attr;
 
 	/*
-	 * Some firmware doesn't report MMIO regions in the EFI memory
-	 * map.  The Intel BigSur (a.k.a. HP i2000) has this problem.
-	 * On those platforms, we have to assume UC is valid everywhere.
+	 * This is a hack for ioremap calls before we set up kern_memmap.
+	 * Maybe we should do efi_memmap_init() earlier instead.
 	 */
-	if (!md || (md->attribute & attr) != attr) {
-		if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio())
-			return 1;
+	if (!kern_memmap) {
+		attr = efi_mem_attribute(phys_addr, size);
+		if (attr & EFI_MEMORY_WB)
+			return EFI_MEMORY_WB;
 		return 0;
 	}
 
+	md = kern_memory_descriptor(phys_addr);
+	if (!md)
+		return 0;
+
+	attr = md->attribute;
 	do {
-		unsigned long md_end = efi_md_end(md);
+		unsigned long md_end = kmd_end(md);
 
 		if (end <= md_end)
-			return 1;
+			return attr;
 
-		md = efi_memory_descriptor(md_end);
-		if (!md || (md->attribute & attr) != attr)
+		md = kern_memory_descriptor(md_end);
+		if (!md || md->attribute != attr)
 			return 0;
 	} while (md);
 	return 0;
 }
+EXPORT_SYMBOL(kern_mem_attribute);
 
-/*
- * For /dev/mem, we only allow read & write system calls to access
- * write-back memory, because read & write don't allow the user to
- * control access size.
- */
 int
 valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
-	return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
+	u64 attr;
+
+	/*
+	 * /dev/mem reads and writes use copy_to_user(), which implicitly
+	 * uses a granule-sized kernel identity mapping.  It's really
+	 * only safe to do this for regions in kern_memmap.  For more
+	 * details, see Documentation/ia64/aliasing.txt.
+	 */
+	attr = kern_mem_attribute(phys_addr, size);
+	if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
+		return 1;
+	return 0;
 }
 
-/*
- * We allow mmap of anything in the EFI memory map that supports
- * either write-back or uncacheable access.  For uncacheable regions,
- * the supported access sizes are system-dependent, and the user is
- * responsible for using the correct size.
- *
- * Note that this doesn't currently allow access to hot-added memory,
- * because that doesn't appear in the boot-time EFI memory map.
- */
 int
 valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
-	if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
-		return 1;
+	/*
+	 * MMIO regions are often missing from the EFI memory map.
+	 * We must allow mmap of them for programs like X, so we
+	 * currently can't do any useful validation.
+	 */
+	return 1;
+}
 
-	if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
-		return 1;
+pgprot_t
+phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size,
+		     pgprot_t vma_prot)
+{
+	unsigned long phys_addr = pfn << PAGE_SHIFT;
+	u64 attr;
 
-	return 0;
+	/*
+	 * For /dev/mem mmap, we use user mappings, but if the region is
+	 * in kern_memmap (and hence may be covered by a kernel mapping),
+	 * we must use the same attribute as the kernel mapping.
+	 */
+	attr = kern_mem_attribute(phys_addr, size);
+	if (attr & EFI_MEMORY_WB)
+		return pgprot_cacheable(vma_prot);
+	else if (attr & EFI_MEMORY_UC)
+		return pgprot_noncached(vma_prot);
+
+	/*
+	 * Some chipsets don't support UC access to memory.  If
+	 * WB is supported, we prefer that.
+	 */
+	if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
+		return pgprot_cacheable(vma_prot);
+
+	return pgprot_noncached(vma_prot);
 }
 
 int __init
diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S
index 5a7fe70212a9..a56e161d7515 100644
--- a/arch/ia64/kernel/efi_stub.S
+++ b/arch/ia64/kernel/efi_stub.S
@@ -61,7 +61,7 @@ GLOBAL_ENTRY(efi_call_phys)
 	or loc3=loc3,r17
 	mov b6=r2
 	;;
-	andcm r16=loc3,r16		// get psr with IT, DT, and RT bits cleared
+	andcm r16=loc3,r16	// get psr with IT, DT, and RT bits cleared
 	br.call.sptk.many rp=ia64_switch_mode_phys
 .ret0:	mov out4=in5
 	mov out0=in1
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index bcb80ca5cf40..32c999f58d12 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1584,7 +1584,7 @@ sys_call_table:
 	data8 sys_keyctl
 	data8 sys_ioprio_set
 	data8 sys_ioprio_get			// 1275
-	data8 sys_ni_syscall
+	data8 sys_move_pages
 	data8 sys_inotify_init
 	data8 sys_inotify_add_watch
 	data8 sys_inotify_rm_watch
diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h
index 78eeb0793419..ebc3dfb88826 100644
--- a/arch/ia64/kernel/entry.h
+++ b/arch/ia64/kernel/entry.h
@@ -23,6 +23,7 @@
 
 #define PT(f)		(IA64_PT_REGS_##f##_OFFSET)
 #define SW(f)		(IA64_SWITCH_STACK_##f##_OFFSET)
+#define SOS(f)		(IA64_SAL_OS_STATE_##f##_OFFSET)
 
 #define PT_REGS_SAVES(off)			\
 	.unwabi 3, 'i';				\
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 6c4d59fd0364..ef9a2b49307a 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -46,6 +46,10 @@
 
 #define IRQ_DEBUG	0
 
+/* These can be overridden in platform_irq_init */
+int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
+int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
+
 /* default base addr of IPI table */
 void __iomem *ipi_base_addr = ((void __iomem *)
 			       (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
@@ -60,7 +64,7 @@ __u8 isa_irq_to_vector_map[16] = {
 };
 EXPORT_SYMBOL(isa_irq_to_vector_map);
 
-static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)];
 
 int
 assign_irq_vector (int irq)
@@ -89,6 +93,19 @@ free_irq_vector (int vector)
 		printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
 }
 
+int
+reserve_irq_vector (int vector)
+{
+	int pos;
+
+	if (vector < IA64_FIRST_DEVICE_VECTOR ||
+	    vector > IA64_LAST_DEVICE_VECTOR)
+		return -EINVAL;
+
+	pos = vector - IA64_FIRST_DEVICE_VECTOR;
+	return test_and_set_bit(pos, ia64_vector_mask);
+}
+
 #ifdef CONFIG_SMP
 #	define IS_RESCHEDULE(vec)	(vec == IA64_IPI_RESCHEDULE)
 #else
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 6dff024cd62b..c1bd1feffab0 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -159,7 +159,7 @@ ia64_os_mca_spin:
 	GET_IA64_MCA_DATA(r2)
 	// Using MCA stack, struct ia64_sal_os_state, variable proc_state_param
 	;;
-	add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2
+	add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2
 	;;
 	ld8 r18=[r3]				// Get processor state parameter on existing PALE_CHECK.
 	;;
@@ -479,9 +479,11 @@ ia64_state_save:
 	st8 [temp2]=r11,16	// rv_rc
 	mov r11=cr.iipa
 	;;
-	st8 [temp1]=r18,16	// proc_state_param
-	st8 [temp2]=r19,16	// monarch
+	st8 [temp1]=r18		// proc_state_param
+	st8 [temp2]=r19		// monarch
 	mov r6=IA64_KR(CURRENT)
+	add temp1=SOS(SAL_RA), regs
+	add temp2=SOS(SAL_GP), regs
 	;;
 	st8 [temp1]=r12,16	// sal_ra
 	st8 [temp2]=r10,16	// sal_gp
@@ -503,12 +505,14 @@ ia64_state_save:
 	st8 [temp2]=r11,16	// cr.iipa
 	mov r12=cr.iim
 	;;
-	st8 [temp1]=r12,16	// cr.iim
+	st8 [temp1]=r12		// cr.iim
 (p1)	mov r12=IA64_MCA_COLD_BOOT
 (p2)	mov r12=IA64_INIT_WARM_BOOT
 	mov r6=cr.iha
+	add temp1=SOS(OS_STATUS), regs
 	;;
-	st8 [temp2]=r6,16	// cr.iha
+	st8 [temp2]=r6		// cr.iha
+	add temp2=SOS(CONTEXT), regs
 	st8 [temp1]=r12		// os_status, default is cold boot
 	mov r6=IA64_MCA_SAME_CONTEXT
 	;;
@@ -820,8 +824,8 @@ ia64_state_restore:
 	// Restore the SAL to OS state. The previous code left regs at pt_regs.
 	add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs
 	;;
-	add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs
-	add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs
+	add temp1=SOS(SAL_RA), regs
+	add temp2=SOS(SAL_GP), regs
 	;;
 	ld8 r12=[temp1],16	// sal_ra
 	ld8 r9=[temp2],16	// sal_gp
@@ -842,8 +846,10 @@ ia64_state_restore:
 	;;
 	mov cr.itir=temp3
 	mov cr.iipa=temp4
-	ld8 temp3=[temp1],16	// cr.iim
-	ld8 temp4=[temp2],16	// cr.iha
+	ld8 temp3=[temp1]	// cr.iim
+	ld8 temp4=[temp2]		// cr.iha
+	add temp1=SOS(OS_STATUS), regs
+	add temp2=SOS(CONTEXT), regs
 	;;
 	mov cr.iim=temp3
 	mov cr.iha=temp4
@@ -916,7 +922,7 @@ ia64_state_restore:
 
 ia64_new_stack:
 	add regs=MCA_PT_REGS_OFFSET, r3
-	add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3
+	add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3
 	mov b0=r2			// save return address
 	GET_IA64_MCA_DATA(temp1)
 	invala
@@ -1020,7 +1026,7 @@ ia64_old_stack:
 
 ia64_set_kernel_registers:
 	add temp3=MCA_SP_OFFSET, r3
-	add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3
+	add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
 	mov b0=r2		// save return address
 	GET_IA64_MCA_DATA(temp1)
 	;;
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 077f21216b65..6d7bc8ff7b3a 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -532,7 +532,6 @@ static ctl_table pfm_sysctl_root[] = {
 static struct ctl_table_header *pfm_sysctl_header;
 
 static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
-static int pfm_flush(struct file *filp);
 
 #define pfm_get_cpu_var(v)		__ia64_per_cpu_var(v)
 #define pfm_get_cpu_data(a,b)		per_cpu(a, b)
@@ -595,10 +594,11 @@ pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 }
 
 
-static struct super_block *
-pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
+static int
+pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
+	     struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC);
+	return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt);
 }
 
 static struct file_system_type pfm_fs_type = {
@@ -1773,7 +1773,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)
  * When caller is self-monitoring, the context is unloaded.
  */
 static int
-pfm_flush(struct file *filp)
+pfm_flush(struct file *filp, fl_owner_t id)
 {
 	pfm_context_t *ctx;
 	struct task_struct *task;
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 056f7a6eedc7..77fa65903d94 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -227,7 +227,7 @@ static int sal_cache_flush_drops_interrupts;
 static void __init
 check_sal_cache_flush (void)
 {
-	unsigned long flags, itv;
+	unsigned long flags;
 	int cpu;
 	u64 vector;
 
@@ -238,9 +238,6 @@ check_sal_cache_flush (void)
 	 * Schedule a timer interrupt, wait until it's reported, and see if
 	 * SAL_CACHE_FLUSH drops it.
 	 */
-	itv = ia64_get_itv();
-	BUG_ON((itv & (1 << 16)) == 0);
-
 	ia64_set_itv(IA64_TIMER_VECTOR);
 	ia64_set_itm(ia64_get_itc() + 1000);
 
@@ -260,7 +257,6 @@ check_sal_cache_flush (void)
 		ia64_eoi();
 	}
 
-	ia64_set_itv(itv);
 	local_irq_restore(flags);
 	put_cpu();
 }
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index e4dfda1eb7dd..6dba2d63f24d 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -260,6 +260,7 @@ reserve_memory (void)
 	n++;
 
 	num_rsvd_regions = n;
+	BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n);
 
 	sort_regions(rsvd_region, num_rsvd_regions);
 }
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index fcd2bad0286f..5f03b9e524dd 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (C) 2001-2006 Silicon Graphics, Inc.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -29,15 +29,8 @@
 #include <asm/tlbflush.h>
 #include <asm/sn/arch.h>
 
-#define DEBUG	0
 
-#if DEBUG
-#define dprintk			printk
-#else
-#define dprintk(x...)		do { } while (0)
-#endif
-
-void __init efi_memmap_walk_uc (efi_freemem_callback_t callback);
+extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
 
 #define MAX_UNCACHED_GRANULES	5
 static int allocated_granules;
@@ -60,6 +53,7 @@ static void uncached_ipi_visibility(void *data)
 static void uncached_ipi_mc_drain(void *data)
 {
 	int status;
+
 	status = ia64_pal_mc_drain();
 	if (status)
 		printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
@@ -67,30 +61,35 @@ static void uncached_ipi_mc_drain(void *data)
 }
 
 
-static unsigned long
-uncached_get_new_chunk(struct gen_pool *poolp)
+/*
+ * Add a new chunk of uncached memory pages to the specified pool.
+ *
+ * @pool: pool to add new chunk of uncached memory to
+ * @nid: node id of node to allocate memory from, or -1
+ *
+ * This is accomplished by first allocating a granule of cached memory pages
+ * and then converting them to uncached memory pages.
+ */
+static int uncached_add_chunk(struct gen_pool *pool, int nid)
 {
 	struct page *page;
-	void *tmp;
 	int status, i;
-	unsigned long addr, node;
+	unsigned long c_addr, uc_addr;
 
 	if (allocated_granules >= MAX_UNCACHED_GRANULES)
-		return 0;
+		return -1;
+
+	/* attempt to allocate a granule's worth of cached memory pages */
 
-	node = poolp->private;
-	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO,
+	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
 				IA64_GRANULE_SHIFT-PAGE_SHIFT);
+	if (!page)
+		return -1;
 
-	dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n",
-		page, (unsigned long)(page-vmem_map) << PAGE_SHIFT);
+	/* convert the memory pages from cached to uncached */
 
-	/*
-	 * Do magic if no mem on local node! XXX
-	 */
-	if (!page)
-		return 0;
-	tmp = page_address(page);
+	c_addr = (unsigned long)page_address(page);
+	uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
 
 	/*
 	 * There's a small race here where it's possible for someone to
@@ -100,76 +99,90 @@ uncached_get_new_chunk(struct gen_pool *poolp)
 	for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
 		SetPageUncached(&page[i]);
 
-	flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE);
+	flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE);
 
 	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
-
-	dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
-		status, raw_smp_processor_id());
-
 	if (!status) {
 		status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
 		if (status)
-			printk(KERN_WARNING "smp_call_function failed for "
-			       "uncached_ipi_visibility! (%i)\n", status);
+			goto failed;
 	}
 
+	preempt_disable();
+
 	if (ia64_platform_is("sn2"))
-		sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE);
+		sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE);
 	else
-		flush_icache_range((unsigned long)tmp,
-				   (unsigned long)tmp+IA64_GRANULE_SIZE);
+		flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
+
+	/* flush the just introduced uncached translation from the TLB */
+	local_flush_tlb_all();
+
+	preempt_enable();
 
 	ia64_pal_mc_drain();
 	status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
 	if (status)
-		printk(KERN_WARNING "smp_call_function failed for "
-		       "uncached_ipi_mc_drain! (%i)\n", status);
+		goto failed;
 
-	addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
+	/*
+	 * The chunk of memory pages has been converted to uncached so now we
+	 * can add it to the pool.
+	 */
+	status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid);
+	if (status)
+		goto failed;
 
 	allocated_granules++;
-	return addr;
+	return 0;
+
+	/* failed to convert or add the chunk so give it back to the kernel */
+failed:
+	for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
+		ClearPageUncached(&page[i]);
+
+	free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
+	return -1;
 }
 
 
 /*
  * uncached_alloc_page
  *
+ * @starting_nid: node id of node to start with, or -1
+ *
  * Allocate 1 uncached page. Allocates on the requested node. If no
  * uncached pages are available on the requested node, roundrobin starting
- * with higher nodes.
+ * with the next higher node.
  */
-unsigned long
-uncached_alloc_page(int nid)
+unsigned long uncached_alloc_page(int starting_nid)
 {
-	unsigned long maddr;
+	unsigned long uc_addr;
+	struct gen_pool *pool;
+	int nid;
 
-	maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE);
+	if (unlikely(starting_nid >= MAX_NUMNODES))
+		return 0;
 
-	dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n",
-		maddr, nid);
+	if (starting_nid < 0)
+		starting_nid = numa_node_id();
+	nid = starting_nid;
 
-	/*
-	 * If no memory is availble on our local node, try the
-	 * remaining nodes in the system.
-	 */
-	if (!maddr) {
-		int i;
-
-		for (i = MAX_NUMNODES - 1; i >= 0; i--) {
-			if (i == nid || !node_online(i))
-				continue;
-			maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE);
-			dprintk(KERN_DEBUG "uncached_alloc_page alternate search "
-				"returns %lx on node %i\n", maddr, i);
-			if (maddr) {
-				break;
-			}
-		}
-	}
+	do {
+		if (!node_online(nid))
+			continue;
+		pool = uncached_pool[nid];
+		if (pool == NULL)
+			continue;
+		do {
+			uc_addr = gen_pool_alloc(pool, PAGE_SIZE);
+			if (uc_addr != 0)
+				return uc_addr;
+		} while (uncached_add_chunk(pool, nid) == 0);
+
+	} while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
 
-	return maddr;
+	return 0;
 }
 EXPORT_SYMBOL(uncached_alloc_page);
 
@@ -177,21 +190,22 @@ EXPORT_SYMBOL(uncached_alloc_page);
 /*
  * uncached_free_page
  *
+ * @uc_addr: uncached address of page to free
+ *
  * Free a single uncached page.
  */
-void
-uncached_free_page(unsigned long maddr)
+void uncached_free_page(unsigned long uc_addr)
 {
-	int node;
-
-	node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET);
+	int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
+	struct gen_pool *pool = uncached_pool[nid];
 
-	dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
+	if (unlikely(pool == NULL))
+		return;
 
-	if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
-		panic("uncached_free_page invalid address %lx\n", maddr);
+	if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
+		panic("uncached_free_page invalid address %lx\n", uc_addr);
 
-	gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE);
+	gen_pool_free(pool, uc_addr, PAGE_SIZE);
 }
 EXPORT_SYMBOL(uncached_free_page);
 
@@ -199,43 +213,39 @@ EXPORT_SYMBOL(uncached_free_page);
 /*
  * uncached_build_memmap,
  *
+ * @uc_start: uncached starting address of a chunk of uncached memory
+ * @uc_end: uncached ending address of a chunk of uncached memory
+ * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc())
+ *
  * Called at boot time to build a map of pages that can be used for
  * memory special operations.
  */
-static int __init
-uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
+static int __init uncached_build_memmap(unsigned long uc_start,
+					unsigned long uc_end, void *arg)
 {
-	long length = end - start;
-	int node;
-
-	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
+	int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
+	struct gen_pool *pool = uncached_pool[nid];
+	size_t size = uc_end - uc_start;
 
 	touch_softlockup_watchdog();
-	memset((char *)start, 0, length);
 
-	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
-
-	for (; start < end ; start += PAGE_SIZE) {
-		dprintk(KERN_INFO "sticking %lx into the pool!\n", start);
-		gen_pool_free(uncached_pool[node], start, PAGE_SIZE);
+	if (pool != NULL) {
+		memset((char *)uc_start, 0, size);
+		(void) gen_pool_add(pool, uc_start, size, nid);
 	}
-
 	return 0;
 }
 
 
-static int __init uncached_init(void) {
-	int i;
+static int __init uncached_init(void)
+{
+	int nid;
 
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (!node_online(i))
-			continue;
-		uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT,
-						   &uncached_get_new_chunk, i);
+	for_each_online_node(nid) {
+		uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid);
 	}
 
-	efi_memmap_walk_uc(uncached_build_memmap);
-
+	efi_memmap_walk_uc(uncached_build_memmap, NULL);
 	return 0;
 }
 
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index cafa8776a53d..11f08001f8c2 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -671,9 +671,11 @@ int add_memory(u64 start, u64 size)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(add_memory);
 
 int remove_memory(u64 start, u64 size)
 {
 	return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(remove_memory);
 #endif
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 643ccc6960ce..07bd02b6c372 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/efi.h>
 #include <asm/io.h>
+#include <asm/meminit.h>
 
 static inline void __iomem *
 __ioremap (unsigned long offset, unsigned long size)
@@ -21,16 +22,29 @@ __ioremap (unsigned long offset, unsigned long size)
 void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
-		return phys_to_virt(offset);
+	u64 attr;
+	unsigned long gran_base, gran_size;
 
-	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+	/*
+	 * For things in kern_memmap, we must use the same attribute
+	 * as the rest of the kernel.  For more details, see
+	 * Documentation/ia64/aliasing.txt.
+	 */
+	attr = kern_mem_attribute(offset, size);
+	if (attr & EFI_MEMORY_WB)
+		return phys_to_virt(offset);
+	else if (attr & EFI_MEMORY_UC)
 		return __ioremap(offset, size);
 
 	/*
-	 * Someday this should check ACPI resources so we
-	 * can do the right thing for hot-plugged regions.
+	 * Some chipsets don't support UC access to memory.  If
+	 * WB is supported for the whole granule, we prefer that.
 	 */
+	gran_base = GRANULEROUNDDOWN(offset);
+	gran_size = GRANULEROUNDUP(offset + size) - gran_base;
+	if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
+		return phys_to_virt(offset);
+
 	return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap);
@@ -38,6 +52,9 @@ EXPORT_SYMBOL(ioremap);
 void __iomem *
 ioremap_nocache (unsigned long offset, unsigned long size)
 {
+	if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
+		return 0;
+
 	return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap_nocache);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index ab829a22f8a4..61dd8608da4f 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -352,7 +352,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
 	pxm = acpi_get_pxm(controller->acpi_handle);
 #ifdef CONFIG_NUMA
 	if (pxm >= 0)
-		controller->node = pxm_to_nid_map[pxm];
+		controller->node = pxm_to_node(pxm);
 #endif
 
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
@@ -645,18 +645,31 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
 int
 pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma)
 {
+	unsigned long size = vma->vm_end - vma->vm_start;
+	pgprot_t prot;
 	char *addr;
 
+	/*
+	 * Avoid attribute aliasing.  See Documentation/ia64/aliasing.txt
+	 * for more details.
+	 */
+	if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
+		return -EINVAL;
+	prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
+				    vma->vm_page_prot);
+	if (pgprot_val(prot) != pgprot_val(pgprot_noncached(vma->vm_page_prot)))
+		return -EINVAL;
+
 	addr = pci_get_legacy_mem(bus);
 	if (IS_ERR(addr))
 		return PTR_ERR(addr);
 
 	vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_page_prot = prot;
 	vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
 
 	if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			    vma->vm_end - vma->vm_start, vma->vm_page_prot))
+			    size, vma->vm_page_prot))
 		return -EAGAIN;
 
 	return 0;
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 5101ac462643..dc09a6a28a37 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -58,7 +58,7 @@ static int max_pcibus_number = 255;	/* Default highest pci bus number */
  */
 
 static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
 {
 	return 0;
 }
@@ -457,13 +457,6 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
 		pcidev_info->pdi_sn_irq_info = NULL;
 		kfree(sn_irq_info);
 	}
-
-	/*
-	 * MSI currently not supported on altix.  Remove this when
-	 * the MSI abstraction patches are integrated into the kernel
-	 * (sometime after 2.6.16 releases)
-	 */
-	dev->no_msi = 1;
 }
 
 /*
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index c265e02f5036..dc8e2b696713 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -26,11 +26,11 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
 
 int sn_force_interrupt_flag = 1;
 extern int sn_ioif_inited;
-static struct list_head **sn_irq_lh;
+struct list_head **sn_irq_lh;
 static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
 
-static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
-				     u64 sn_irq_info,
+u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
+				     struct sn_irq_info *sn_irq_info,
 				     int req_irq, nasid_t req_nasid,
 				     int req_slice)
 {
@@ -40,12 +40,13 @@ static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
 
 	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
 			(u64) SAL_INTR_ALLOC, (u64) local_nasid,
-			(u64) local_widget, (u64) sn_irq_info, (u64) req_irq,
+			(u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
 			(u64) req_nasid, (u64) req_slice);
+
 	return ret_stuff.status;
 }
 
-static inline void sn_intr_free(nasid_t local_nasid, int local_widget,
+void sn_intr_free(nasid_t local_nasid, int local_widget,
 				struct sn_irq_info *sn_irq_info)
 {
 	struct ia64_sal_retval ret_stuff;
@@ -112,73 +113,91 @@ static void sn_end_irq(unsigned int irq)
 
 static void sn_irq_info_free(struct rcu_head *head);
 
-static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
+				       nasid_t nasid, int slice)
 {
-	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
-	int cpuid, cpuphys;
+	int vector;
+	int cpuphys;
+	int64_t bridge;
+	int local_widget, status;
+	nasid_t local_nasid;
+	struct sn_irq_info *new_irq_info;
+	struct sn_pcibus_provider *pci_provider;
 
-	cpuid = first_cpu(mask);
-	cpuphys = cpu_physical_id(cpuid);
+	new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+	if (new_irq_info == NULL)
+		return NULL;
 
-	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
-				 sn_irq_lh[irq], list) {
-		u64 bridge;
-		int local_widget, status;
-		nasid_t local_nasid;
-		struct sn_irq_info *new_irq_info;
-		struct sn_pcibus_provider *pci_provider;
-
-		new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
-		if (new_irq_info == NULL)
-			break;
-		memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
-
-		bridge = (u64) new_irq_info->irq_bridge;
-		if (!bridge) {
-			kfree(new_irq_info);
-			break; /* irq is not a device interrupt */
-		}
+	memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
+
+	bridge = (u64) new_irq_info->irq_bridge;
+	if (!bridge) {
+		kfree(new_irq_info);
+		return NULL; /* irq is not a device interrupt */
+	}
 
-		local_nasid = NASID_GET(bridge);
+	local_nasid = NASID_GET(bridge);
 
-		if (local_nasid & 1)
-			local_widget = TIO_SWIN_WIDGETNUM(bridge);
-		else
-			local_widget = SWIN_WIDGETNUM(bridge);
+	if (local_nasid & 1)
+		local_widget = TIO_SWIN_WIDGETNUM(bridge);
+	else
+		local_widget = SWIN_WIDGETNUM(bridge);
 
-		/* Free the old PROM new_irq_info structure */
-		sn_intr_free(local_nasid, local_widget, new_irq_info);
-		/* Update kernels new_irq_info with new target info */
-		unregister_intr_pda(new_irq_info);
+	vector = sn_irq_info->irq_irq;
+	/* Free the old PROM new_irq_info structure */
+	sn_intr_free(local_nasid, local_widget, new_irq_info);
+	/* Update kernels new_irq_info with new target info */
+	unregister_intr_pda(new_irq_info);
 
-		/* allocate a new PROM new_irq_info struct */
-		status = sn_intr_alloc(local_nasid, local_widget,
-				       __pa(new_irq_info), irq,
-				       cpuid_to_nasid(cpuid),
-				       cpuid_to_slice(cpuid));
+	/* allocate a new PROM new_irq_info struct */
+	status = sn_intr_alloc(local_nasid, local_widget,
+			       new_irq_info, vector,
+			       nasid, slice);
 
-		/* SAL call failed */
-		if (status) {
-			kfree(new_irq_info);
-			break;
-		}
+	/* SAL call failed */
+	if (status) {
+		kfree(new_irq_info);
+		return NULL;
+	}
 
-		new_irq_info->irq_cpuid = cpuid;
-		register_intr_pda(new_irq_info);
+	cpuphys = nasid_slice_to_cpuid(nasid, slice);
+	new_irq_info->irq_cpuid = cpuphys;
+	register_intr_pda(new_irq_info);
 
-		pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
-		if (pci_provider && pci_provider->target_interrupt)
-			(pci_provider->target_interrupt)(new_irq_info);
+	pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
 
-		spin_lock(&sn_irq_info_lock);
-		list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
-		spin_unlock(&sn_irq_info_lock);
-		call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+	/*
+	 * If this represents a line interrupt, target it.  If it's
+	 * an msi (irq_int_bit < 0), it's already targeted.
+	 */
+	if (new_irq_info->irq_int_bit >= 0 &&
+	    pci_provider && pci_provider->target_interrupt)
+		(pci_provider->target_interrupt)(new_irq_info);
+
+	spin_lock(&sn_irq_info_lock);
+	list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+	spin_unlock(&sn_irq_info_lock);
+	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
 
 #ifdef CONFIG_SMP
-		set_irq_affinity_info((irq & 0xff), cpuphys, 0);
+	set_irq_affinity_info((vector & 0xff), cpuphys, 0);
 #endif
-	}
+
+	return new_irq_info;
+}
+
+static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+{
+	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
+	nasid_t nasid;
+	int slice;
+
+	nasid = cpuid_to_nasid(first_cpu(mask));
+	slice = cpuid_to_slice(first_cpu(mask));
+
+	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
+				 sn_irq_lh[irq], list)
+		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
 }
 
 struct hw_interrupt_type irq_type_sn = {
@@ -202,6 +221,9 @@ void sn_irq_init(void)
 	int i;
 	irq_desc_t *base_desc = irq_desc;
 
+	ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
+	ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
+
 	for (i = 0; i < NR_IRQS; i++) {
 		if (base_desc[i].handler == &no_irq_type) {
 			base_desc[i].handler = &irq_type_sn;
@@ -285,6 +307,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
 	/* link it into the sn_irq[irq] list */
 	spin_lock(&sn_irq_info_lock);
 	list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
+	reserve_irq_vector(sn_irq_info->irq_irq);
 	spin_unlock(&sn_irq_info_lock);
 
 	register_intr_pda(sn_irq_info);
@@ -310,8 +333,11 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
 	spin_lock(&sn_irq_info_lock);
 	list_del_rcu(&sn_irq_info->list);
 	spin_unlock(&sn_irq_info_lock);
+	if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
+		free_irq_vector(sn_irq_info->irq_irq);
 	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
 	pci_dev_put(pci_dev);
+
 }
 
 static inline void
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 30988dfbddff..93577abae36d 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -139,7 +139,7 @@ static int __init pxm_to_nasid(int pxm)
 	int i;
 	int nid;
 
-	nid = pxm_to_nid_map[pxm];
+	nid = pxm_to_node(pxm);
 	for (i = 0; i < num_node_memblks; i++) {
 		if (node_memblk[i].nid == nid) {
 			return NASID_GET(node_memblk[i].start_paddr);
@@ -704,7 +704,7 @@ void __init build_cnode_tables(void)
 	 * cnode == node for all C & M bricks.
 	 */
 	for_each_online_node(node) {
-		nasid = pxm_to_nasid(nid_to_pxm_map[node]);
+		nasid = pxm_to_nasid(node_to_pxm(node));
 		sn_cnodeid_to_nasid[node] = nasid;
 		physical_node_map[nasid] = node;
 	}
diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c
index bc3cfa17cd0f..2862cb33026d 100644
--- a/arch/ia64/sn/kernel/sn2/cache.c
+++ b/arch/ia64/sn/kernel/sn2/cache.c
@@ -3,11 +3,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * 
- * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2003, 2006 Silicon Graphics, Inc. All rights reserved.
  *
  */
 #include <linux/module.h>
 #include <asm/pgalloc.h>
+#include <asm/sn/arch.h>
 
 /**
  * sn_flush_all_caches - flush a range of address from all caches (incl. L4)
@@ -17,18 +18,24 @@
  * Flush a range of addresses from all caches including L4. 
  * All addresses fully or partially contained within 
  * @flush_addr to @flush_addr + @bytes are flushed
- * from the all caches.
+ * from all caches.
  */
 void
 sn_flush_all_caches(long flush_addr, long bytes)
 {
-	flush_icache_range(flush_addr, flush_addr+bytes);
+	unsigned long addr = flush_addr;
+
+	/* SHub1 requires a cached address */
+	if (is_shub1() && (addr & RGN_BITS) == RGN_BASE(RGN_UNCACHED))
+		addr = (addr - RGN_BASE(RGN_UNCACHED)) + RGN_BASE(RGN_KERNEL);
+
+	flush_icache_range(addr, addr + bytes);
 	/*
 	 * The last call may have returned before the caches
 	 * were actually flushed, so we call it again to make
 	 * sure.
 	 */
-	flush_icache_range(flush_addr, flush_addr+bytes);
+	flush_icache_range(addr, addr + bytes);
 	mb();
 }
 EXPORT_SYMBOL(sn_flush_all_caches);
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 739c948dc504..9a8a29339d2d 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -51,6 +51,8 @@ static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
 static int sn_hwperf_init(void);
 static DECLARE_MUTEX(sn_hwperf_init_mutex);
 
+#define cnode_possible(n)	((n) < num_cnodes)
+
 static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
 {
 	int e;
@@ -127,14 +129,14 @@ static int sn_hwperf_geoid_to_cnode(char *location)
 		}
 	}
 
-	return node_possible(cnode) ? cnode : -1;
+	return cnode_possible(cnode) ? cnode : -1;
 }
 
 static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
 {
 	if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
 		BUG();
-	if (!obj->sn_hwp_this_part)
+	if (SN_HWPERF_FOREIGN(obj))
 		return -1;
 	return sn_hwperf_geoid_to_cnode(obj->location);
 }
@@ -199,12 +201,12 @@ static void print_pci_topology(struct seq_file *s)
 
 static inline int sn_hwperf_has_cpus(cnodeid_t node)
 {
-	return node_online(node) && nr_cpus_node(node);
+	return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node);
 }
 
 static inline int sn_hwperf_has_mem(cnodeid_t node)
 {
-	return node_online(node) && NODE_DATA(node)->node_present_pages;
+	return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages;
 }
 
 static struct sn_hwperf_object_info *
@@ -237,7 +239,7 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb
 	int found_mem = 0;
 	int found_cpu = 0;
 
-	if (!node_possible(node))
+	if (!cnode_possible(node))
 		return -EINVAL;
 
 	if (sn_hwperf_has_cpus(node)) {
@@ -442,7 +444,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
 	seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location,
 		obj->sn_hwp_this_part ? "local" : "shared", obj->name);
 
-	if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
+	if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)))
 		seq_putc(s, '\n');
 	else {
 		cnodeid_t near_mem = -1;
@@ -468,22 +470,24 @@ static int sn_topology_show(struct seq_file *s, void *d)
 		/*
 		 * CPUs on this node, if any
 		 */
-		cpumask = node_to_cpumask(ordinal);
-		for_each_online_cpu(i) {
-			if (cpu_isset(i, cpumask)) {
-				slice = 'a' + cpuid_to_slice(i);
-				c = cpu_data(i);
-				seq_printf(s, "cpu %d %s%c local"
-					" freq %luMHz, arch ia64",
-					i, obj->location, slice,
-					c->proc_freq / 1000000);
-				for_each_online_cpu(j) {
-					seq_printf(s, j ? ":%d" : ", dist %d",
-						node_distance(
-						    cpu_to_node(i),
-						    cpu_to_node(j)));
+		if (!SN_HWPERF_IS_IONODE(obj)) {
+			cpumask = node_to_cpumask(ordinal);
+			for_each_online_cpu(i) {
+				if (cpu_isset(i, cpumask)) {
+					slice = 'a' + cpuid_to_slice(i);
+					c = cpu_data(i);
+					seq_printf(s, "cpu %d %s%c local"
+						" freq %luMHz, arch ia64",
+						i, obj->location, slice,
+						c->proc_freq / 1000000);
+					for_each_online_cpu(j) {
+						seq_printf(s, j ? ":%d" : ", dist %d",
+							node_distance(
+						    	cpu_to_node(i),
+						    	cpu_to_node(j)));
+					}
+					seq_putc(s, '\n');
 				}
-				seq_putc(s, '\n');
 			}
 		}
 	}
@@ -523,7 +527,7 @@ static int sn_topology_show(struct seq_file *s, void *d)
 			if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
 				/* both ends local to this partition */
 				seq_puts(s, " local");
-			else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part)
+			else if (SN_HWPERF_FOREIGN(p))
 				/* both ends of the link in foreign partiton */
 				seq_puts(s, " foreign");
 			else
@@ -776,7 +780,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
 
 	case SN_HWPERF_GET_NODE_NASID:
 		if (a.sz != sizeof(u64) ||
-		   (node = a.arg) < 0 || !node_possible(node)) {
+		   (node = a.arg) < 0 || !cnode_possible(node)) {
 			r = -EINVAL;
 			goto error;
 		}
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index b4b84c269210..7a291a271511 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -11,7 +11,7 @@
 
 #include <linux/module.h>
 #include <asm/dma.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/sn_sal.h>
@@ -113,7 +113,8 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size,
 	 * resources.
 	 */
 
-	*dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
+	*dma_handle = provider->dma_map_consistent(pdev, phys_addr, size,
+						   SN_DMA_ADDR_PHYS);
 	if (!*dma_handle) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		free_pages((unsigned long)cpuaddr, get_order(size));
@@ -176,7 +177,7 @@ dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 	BUG_ON(dev->bus != &pci_bus_type);
 
 	phys_addr = __pa(cpu_addr);
-	dma_addr = provider->dma_map(pdev, phys_addr, size);
+	dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
 	if (!dma_addr) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		return 0;
@@ -260,7 +261,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	for (i = 0; i < nhwentries; i++, sg++) {
 		phys_addr = SG_ENT_PHYS_ADDRESS(sg);
 		sg->dma_address = provider->dma_map(pdev,
-						    phys_addr, sg->length);
+						    phys_addr, sg->length,
+						    SN_DMA_ADDR_PHYS);
 
 		if (!sg->dma_address) {
 			printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index 9f86bb6519aa..a86c7b945962 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -41,7 +41,7 @@ extern int sn_ioif_inited;
 
 static dma_addr_t
 pcibr_dmamap_ate32(struct pcidev_info *info,
-		   u64 paddr, size_t req_size, u64 flags)
+		   u64 paddr, size_t req_size, u64 flags, int dma_flags)
 {
 
 	struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
@@ -81,9 +81,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info,
 	if (IS_PCIX(pcibus_info))
 		ate_flags &= ~(PCI32_ATE_PREF);
 
-	xio_addr =
-	    IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-	    PHYS_TO_TIODMA(paddr);
+	if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS))
+		xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+	    					      PHYS_TO_TIODMA(paddr);
+	else
+		xio_addr = paddr;
+
 	offset = IOPGOFF(xio_addr);
 	ate = ate_flags | (xio_addr - offset);
 
@@ -91,6 +94,13 @@ pcibr_dmamap_ate32(struct pcidev_info *info,
 	if (IS_PIC_SOFT(pcibus_info)) {
 		ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT);
 	}
+
+	/*
+	 * If we're mapping for MSI, set the MSI bit in the ATE
+	 */
+	if (dma_flags & SN_DMA_MSI)
+		ate |= PCI32_ATE_MSI;
+
 	ate_write(pcibus_info, ate_index, ate_count, ate);
 
 	/*
@@ -105,20 +115,27 @@ pcibr_dmamap_ate32(struct pcidev_info *info,
 	if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR)
 		ATE_SWAP_ON(pci_addr);
 
+
 	return pci_addr;
 }
 
 static dma_addr_t
 pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
-			u64 dma_attributes)
+			u64 dma_attributes, int dma_flags)
 {
 	struct pcibus_info *pcibus_info = (struct pcibus_info *)
 	    ((info->pdi_host_pcidev_info)->pdi_pcibus_info);
 	u64 pci_addr;
 
 	/* Translate to Crosstalk View of Physical Address */
-	pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-		    PHYS_TO_TIODMA(paddr)) | dma_attributes;
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		pci_addr = IS_PIC_SOFT(pcibus_info) ?
+				PHYS_TO_DMA(paddr) :
+		    		PHYS_TO_TIODMA(paddr) | dma_attributes;
+	else
+		pci_addr = IS_PIC_SOFT(pcibus_info) ?
+				paddr :
+				paddr | dma_attributes;
 
 	/* Handle Bus mode */
 	if (IS_PCIX(pcibus_info))
@@ -130,7 +147,9 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
 		    ((u64) pcibus_info->
 		     pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
 	} else
-		pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
+		pci_addr |= (dma_flags & SN_DMA_MSI) ?
+				TIOCP_PCI64_CMDTYPE_MSI :
+				TIOCP_PCI64_CMDTYPE_MEM;
 
 	/* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */
 	if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn))
@@ -141,7 +160,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
 
 static dma_addr_t
 pcibr_dmatrans_direct32(struct pcidev_info * info,
-			u64 paddr, size_t req_size, u64 flags)
+			u64 paddr, size_t req_size, u64 flags, int dma_flags)
 {
 	struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
 	struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
@@ -156,8 +175,14 @@ pcibr_dmatrans_direct32(struct pcidev_info * info,
 		return 0;
 	}
 
-	xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-	    PHYS_TO_TIODMA(paddr);
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+	    					      PHYS_TO_TIODMA(paddr);
+	else
+		xio_addr = paddr;
 
 	xio_base = pcibus_info->pbi_dir_xbase;
 	offset = xio_addr - xio_base;
@@ -327,7 +352,7 @@ void sn_dma_flush(u64 addr)
  */
 
 dma_addr_t
-pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags)
 {
 	dma_addr_t dma_handle;
 	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
@@ -344,11 +369,11 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
 		 */
 
 		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-						     PCI64_ATTR_PREF);
+						     PCI64_ATTR_PREF, dma_flags);
 	} else {
 		/* Handle 32-63 bit cards via direct mapping */
 		dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
-						     size, 0);
+						     size, 0, dma_flags);
 		if (!dma_handle) {
 			/*
 			 * It is a 32 bit card and we cannot do direct mapping,
@@ -356,7 +381,8 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
 			 */
 
 			dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
-							size, PCI32_ATE_PREF);
+							size, PCI32_ATE_PREF,
+							dma_flags);
 		}
 	}
 
@@ -365,18 +391,18 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
 
 dma_addr_t
 pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
-			 size_t size)
+			 size_t size, int dma_flags)
 {
 	dma_addr_t dma_handle;
 	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
 
 	if (hwdev->dev.coherent_dma_mask == ~0UL) {
 		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-					    PCI64_ATTR_BAR);
+					    PCI64_ATTR_BAR, dma_flags);
 	} else {
 		dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
 						    phys_addr, size,
-						    PCI32_ATE_BAR);
+						    PCI32_ATE_BAR, dma_flags);
 	}
 
 	return dma_handle;
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index be0176912968..20de72791b97 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -515,11 +515,17 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
 	/*
+	 * Not supported for now ...
+	 */
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
+	/*
 	 * If card is 64 or 48 bit addresable, use a direct mapping.  32
 	 * bit direct is so restrictive w.r.t. where the memory resides that
 	 * we don't use it even though CA has some support.
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 833295624e5d..2d7948567ebc 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
@@ -170,7 +170,8 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
 	(ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
 
 #define ATE_VALID(ate)	((ate) & (1UL << 63))
-#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
+#define ATE_MAKE(addr, ps, msi) \
+	(((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0))
 
 /*
  * Flavors of ate-based mapping supported by tioce_alloc_map()
@@ -196,15 +197,17 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr)
  *
  * 63    - must be 1 to indicate d64 mode to CE hardware
  * 62    - barrier bit ... controlled with tioce_dma_barrier()
- * 61    - 0 since this is not an MSI transaction
+ * 61    - msi bit ... specified through dma_flags
  * 60:54 - reserved, MBZ
  */
 static u64
-tioce_dma_d64(unsigned long ct_addr)
+tioce_dma_d64(unsigned long ct_addr, int dma_flags)
 {
 	u64 bus_addr;
 
 	bus_addr = ct_addr | (1UL << 63);
+	if (dma_flags & SN_DMA_MSI)
+		bus_addr |= (1UL << 61);
 
 	return bus_addr;
 }
@@ -261,7 +264,7 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
  */
 static u64
 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
-		u64 ct_addr, int len)
+		u64 ct_addr, int len, int dma_flags)
 {
 	int i;
 	int j;
@@ -270,6 +273,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 	int entries;
 	int nates;
 	u64 pagesize;
+	int msi_capable, msi_wanted;
 	u64 *ate_shadow;
 	u64 *ate_reg;
 	u64 addr;
@@ -291,6 +295,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 		ate_reg = ce_mmr->ce_ure_ate3240;
 		pagesize = ce_kern->ce_ate3240_pagesize;
 		bus_base = TIOCE_M32_MIN;
+		msi_capable = 1;
 		break;
 	case TIOCE_ATE_M40:
 		first = 0;
@@ -299,6 +304,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 		ate_reg = ce_mmr->ce_ure_ate40;
 		pagesize = MB(64);
 		bus_base = TIOCE_M40_MIN;
+		msi_capable = 0;
 		break;
 	case TIOCE_ATE_M40S:
 		/*
@@ -311,11 +317,16 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 		ate_reg = ce_mmr->ce_ure_ate3240;
 		pagesize = GB(16);
 		bus_base = TIOCE_M40S_MIN;
+		msi_capable = 0;
 		break;
 	default:
 		return 0;
 	}
 
+	msi_wanted = dma_flags & SN_DMA_MSI;
+	if (msi_wanted && !msi_capable)
+		return 0;
+
 	nates = ATE_NPAGES(ct_addr, len, pagesize);
 	if (nates > entries)
 		return 0;
@@ -344,7 +355,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
 	for (j = 0; j < nates; j++) {
 		u64 ate;
 
-		ate = ATE_MAKE(addr, pagesize);
+		ate = ATE_MAKE(addr, pagesize, msi_wanted);
 		ate_shadow[i + j] = ate;
 		tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
 		addr += pagesize;
@@ -371,7 +382,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
  * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
  */
 static u64
-tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
+tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags)
 {
 	int dma_ok;
 	int port;
@@ -381,6 +392,9 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
 	u64 ct_lower;
 	dma_addr_t bus_addr;
 
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
 	ct_upper = ct_addr & ~0x3fffffffUL;
 	ct_lower = ct_addr & 0x3fffffffUL;
 
@@ -507,7 +521,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
  */
 static u64
 tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
-		 int barrier)
+		 int barrier, int dma_flags)
 {
 	unsigned long flags;
 	u64 ct_addr;
@@ -523,15 +537,18 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
 	if (dma_mask < 0x7fffffffUL)
 		return 0;
 
-	ct_addr = PHYS_TO_TIODMA(paddr);
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		ct_addr = PHYS_TO_TIODMA(paddr);
+	else
+		ct_addr = paddr;
 
 	/*
 	 * If the device can generate 64 bit addresses, create a D64 map.
-	 * Since this should never fail, bypass the rest of the checks.
 	 */
 	if (dma_mask == ~0UL) {
-		mapaddr = tioce_dma_d64(ct_addr);
-		goto dma_map_done;
+		mapaddr = tioce_dma_d64(ct_addr, dma_flags);
+		if (mapaddr)
+			goto dma_map_done;
 	}
 
 	pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
@@ -574,18 +591,22 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
 
 		if (byte_count > MB(64)) {
 			mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
-						  port, ct_addr, byte_count);
+						  port, ct_addr, byte_count,
+						  dma_flags);
 			if (!mapaddr)
 				mapaddr =
 				    tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
-						    ct_addr, byte_count);
+						    ct_addr, byte_count,
+						    dma_flags);
 		} else {
 			mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
-						  ct_addr, byte_count);
+						  ct_addr, byte_count,
+						  dma_flags);
 			if (!mapaddr)
 				mapaddr =
 				    tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
-						    port, ct_addr, byte_count);
+						    port, ct_addr, byte_count,
+						    dma_flags);
 		}
 	}
 
@@ -593,7 +614,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
 	 * 32-bit direct is the next mode to try
 	 */
 	if (!mapaddr && dma_mask >= 0xffffffffUL)
-		mapaddr = tioce_dma_d32(pdev, ct_addr);
+		mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags);
 
 	/*
 	 * Last resort, try 32-bit ATE-based map.
@@ -601,7 +622,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
 	if (!mapaddr)
 		mapaddr =
 		    tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
-				    byte_count);
+				    byte_count, dma_flags);
 
 	spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
 
@@ -622,9 +643,9 @@ dma_map_done:
  * in the address.
  */
 static u64
-tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
-	return tioce_do_dma_map(pdev, paddr, byte_count, 0);
+	return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
 }
 
 /**
@@ -636,9 +657,9 @@ tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
  * Simply call tioce_do_dma_map() to create a map with the barrier bit set
  * in the address.
  */ static u64
-tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
-	return tioce_do_dma_map(pdev, paddr, byte_count, 1);
+	return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
 }
 
 /**
@@ -696,7 +717,7 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit)
 	while (ate_index <= last_ate) {
 		u64 ate;
 
-		ate = ATE_MAKE(0xdeadbeef, ps);
+		ate = ATE_MAKE(0xdeadbeef, ps, 0);
 		ce_kern->ce_ate3240_shadow[ate_index] = ate;
 		tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
 				 ate);
@@ -1002,7 +1023,7 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
 		       ~0ULL);
-	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL);
+	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, 0ULL);
 
 	if (request_irq(SGI_PCIASIC_ERROR,
 			tioce_error_intr_handler,
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 320fde05dc63..522079f8c2ba 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -226,7 +226,7 @@ ENTRY(nmi_handler)
 inthandler:
 	SAVE_ALL_INT
 	GET_CURRENT(%d0)
-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
 					|  put exception # in d0
 	bfextu %sp@(PT_VECTOR){#4,#10},%d0
 
@@ -245,7 +245,7 @@ inthandler:
 3:	addql	#8,%sp			|  pop parameters off stack
 
 ret_from_interrupt:
-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
 	jeq	1f
 2:
 	RESTORE_ALL
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 514d323ad536..4b85514792e7 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -95,6 +95,12 @@ void __init init_IRQ(void)
 {
 	int i;
 
+	/* assembly irq entry code relies on this... */
+	if (HARDIRQ_MASK != 0x00ff0000) {
+		extern void hardirq_mask_is_broken(void);
+		hardirq_mask_is_broken();
+	}
+
 	for (i = 0; i < SYS_IRQS; i++) {
 		if (mach_default_handler)
 			irq_list[i].handler = (*mach_default_handler)[i];
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 866917bfa028..f9af893cd289 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -763,7 +763,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void __user *)((usp - frame_size) & -8UL);
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index cdf58fbb3e73..837a88709902 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -114,7 +114,7 @@ void __init base_trap_init(void)
 	if(MACH_IS_SUN3X) {
 		extern e_vector *sun3x_prom_vbr;
 
-		__asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
+		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
 	}
 
 	/* setup the exception vector table */
@@ -992,6 +992,7 @@ void show_registers(struct pt_regs *regs)
 
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
+	unsigned long *p;
 	unsigned long *endstack;
 	int i;
 
@@ -1004,12 +1005,13 @@ void show_stack(struct task_struct *task, unsigned long *stack)
 	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
 
 	printk("Stack from %08lx:", (unsigned long)stack);
+	p = stack;
 	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (stack + 1 > endstack)
+		if (p + 1 > endstack)
 			break;
 		if (i % 8 == 0)
 			printk("\n       ");
-		printk(" %08lx", *stack++);
+		printk(" %08lx", *p++);
 	}
 	printk("\n");
 	show_trace(stack);
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index ebe51a513817..6bbf19f96007 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -4,5 +4,5 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y		:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
-			checksum.o string.o semaphore.o
+lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+	   checksum.o string.o semaphore.o uaccess.o
diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c
new file mode 100644
index 000000000000..1bc188c0d983
--- /dev/null
+++ b/arch/m68k/lib/uaccess.c
@@ -0,0 +1,222 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+unsigned long __generic_copy_from_user(void *to, const void __user *from,
+				       unsigned long n)
+{
+	unsigned long tmp, res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	2f\n"
+		"1:	moves.l	(%1)+,%3\n"
+		"	move.l	%3,(%2)+\n"
+		"	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"2:	btst	#1,%5\n"
+		"	jeq	4f\n"
+		"3:	moves.w	(%1)+,%3\n"
+		"	move.w	%3,(%2)+\n"
+		"4:	btst	#0,%5\n"
+		"	jeq	6f\n"
+		"5:	moves.b	(%1)+,%3\n"
+		"	move.b  %3,(%2)+\n"
+		"6:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	move.l	%0,%3\n"
+		"7:	clr.l	(%2)+\n"
+		"	subq.l	#1,%3\n"
+		"	jne	7b\n"
+		"	lsl.l	#2,%0\n"
+		"	btst	#1,%5\n"
+		"	jeq	8f\n"
+		"30:	clr.w	(%2)+\n"
+		"	addq.l	#2,%0\n"
+		"8:	btst	#0,%5\n"
+		"	jeq	6b\n"
+		"50:	clr.b	(%2)+\n"
+		"	addq.l	#1,%0\n"
+		"	jra	6b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.long	3b,30b\n"
+		"	.long	5b,50b\n"
+		"	.previous"
+		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+		: "0" (n / 4), "d" (n & 3));
+
+	return res;
+}
+EXPORT_SYMBOL(__generic_copy_from_user);
+
+unsigned long __generic_copy_to_user(void __user *to, const void *from,
+				     unsigned long n)
+{
+	unsigned long tmp, res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	4f\n"
+		"1:	move.l	(%1)+,%3\n"
+		"2:	moves.l	%3,(%2)+\n"
+		"3:	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"4:	btst	#1,%5\n"
+		"	jeq	6f\n"
+		"	move.w	(%1)+,%3\n"
+		"5:	moves.w	%3,(%2)+\n"
+		"6:	btst	#0,%5\n"
+		"	jeq	8f\n"
+		"	move.b	(%1)+,%3\n"
+		"7:	moves.b  %3,(%2)+\n"
+		"8:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"20:	lsl.l	#2,%0\n"
+		"50:	add.l	%5,%0\n"
+		"	jra	7b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	2b,20b\n"
+		"	.long	3b,20b\n"
+		"	.long	5b,50b\n"
+		"	.long	6b,50b\n"
+		"	.long	7b,50b\n"
+		"	.long	8b,50b\n"
+		"	.previous"
+		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+		: "0" (n / 4), "d" (n & 3));
+
+	return res;
+}
+EXPORT_SYMBOL(__generic_copy_to_user);
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+long strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	long res;
+	char c;
+
+	if (count <= 0)
+		return count;
+
+	asm volatile ("\n"
+		"1:	moves.b	(%2)+,%4\n"
+		"	move.b	%4,(%1)+\n"
+		"	jeq	2f\n"
+		"	subq.l	#1,%3\n"
+		"	jne	1b\n"
+		"2:	sub.l	%3,%0\n"
+		"3:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	move.l	%5,%0\n"
+		"	jra	3b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.previous"
+		: "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c)
+		: "i" (-EFAULT), "0" (count));
+
+	return res;
+}
+EXPORT_SYMBOL(strncpy_from_user);
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char __user *src, long n)
+{
+	char c;
+	long res;
+
+	asm volatile ("\n"
+		"1:	subq.l	#1,%1\n"
+		"	jmi	3f\n"
+		"2:	moves.b	(%0)+,%2\n"
+		"	tst.b	%2\n"
+		"	jne	1b\n"
+		"	jra	4f\n"
+		"\n"
+		"3:	addq.l	#1,%0\n"
+		"4:	sub.l	%4,%0\n"
+		"5:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"20:	sub.l	%0,%0\n"
+		"	jra	5b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	2b,20b\n"
+		"	.previous\n"
+		: "=&a" (res), "+d" (n), "=&d" (c)
+		: "0" (src), "r" (src));
+
+	return res;
+}
+EXPORT_SYMBOL(strnlen_user);
+
+/*
+ * Zero Userspace
+ */
+
+unsigned long clear_user(void __user *to, unsigned long n)
+{
+	unsigned long res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	3f\n"
+		"1:	moves.l	%2,(%1)+\n"
+		"2:	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"3:	btst	#1,%4\n"
+		"	jeq	5f\n"
+		"4:	moves.w	%2,(%1)+\n"
+		"5:	btst	#0,%4\n"
+		"	jeq	7f\n"
+		"6:	moves.b	%2,(%1)\n"
+		"7:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	lsl.l	#2,%0\n"
+		"40:	add.l	%4,%0\n"
+		"	jra	7b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.long	2b,10b\n"
+		"	.long	4b,40b\n"
+		"	.long	5b,40b\n"
+		"	.long	6b,40b\n"
+		"	.long	7b,40b\n"
+		"	.previous"
+		: "=d" (res), "+a" (to)
+		: "r" (0), "0" (n / 4), "d" (n & 3));
+
+    return res;
+}
+EXPORT_SYMBOL(clear_user);
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 14f8d3f4e195..19dce75711b1 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -89,24 +89,11 @@ extern void mac_debugging_long(int, long);
 
 static void mac_get_model(char *str);
 
-void mac_bang(int irq, void *vector, struct pt_regs *p)
-{
-	printk(KERN_INFO "Resetting ...\n");
-	mac_reset();
-}
-
 static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
 {
 	via_init_clock(vector);
 }
 
-#if 0
-void mac_waitbut (void)
-{
-	;
-}
-#endif
-
 extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *);
 
 irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)=
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 1809601ad903..7a1600bd195d 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -216,7 +216,6 @@ static void scc_irq_disable(int);
  * console_loglevel determines NMI handler function
  */
 
-extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
 irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *);
 irqreturn_t mac_debug_handler(int, void *, struct pt_regs *);
 
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index cd528bf7b43f..a6e3814c8666 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/ide.h>
 
-#include <asm/traps.h>
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
@@ -71,7 +70,6 @@ void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
-extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
 extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
 extern int oss_present;
 
@@ -212,11 +210,6 @@ void __init via_init(void)
 			break;
 	}
 #else
-	/* The alernate IRQ mapping seems to just not work. Anyone with a   */
-	/* supported machine is welcome to take a stab at fixing it. It     */
-	/* _should_ work on the following Quadras: 610,650,700,800,900,950  */
-	/*                                               - 1999-06-12 (jmt) */
-
 	via_alt_mapping = 0;
 #endif
 
@@ -270,12 +263,6 @@ void __init via_register_interrupts(void)
 		cpu_request_irq(IRQ_AUTO_1, via1_irq,
 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
 				(void *) via1);
-#if 0 /* interferes with serial on some machines */
-		if (!psc_present) {
-			cpu_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
-					"Off Switch", mac_bang);
-		}
-#endif
 	}
 	cpu_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
 			"via2", (void *) via2);
@@ -471,8 +458,8 @@ irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs)
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
 			via2[gIER] = irq_bit;
-			mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
 			via2[gIFR] = irq_bit | rbv_clear;
+			mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
 			via2[gIER] = irq_bit | 0x80;
 		}
 	return IRQ_HANDLED;
@@ -529,6 +516,7 @@ void via_irq_enable(int irq) {
 		}
 		via2[gIER] = irq_bit | 0x80;
 	} else if (irq_src == 7) {
+		nubus_active |= irq_bit;
 		if (rbv_present) {
 			/* enable the slot interrupt. SIER works like IER. */
 			via2[rSIER] = IER_SET_BIT(irq_idx);
@@ -550,7 +538,6 @@ void via_irq_enable(int irq) {
 				}
 			}
 		}
-		nubus_active |= irq_bit;
 	}
 }
 
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index afb57eeafdcb..bdb11103694b 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -203,7 +203,7 @@ void __init paging_init(void)
 {
 	int chunk;
 	unsigned long mem_avail = 0;
-	unsigned long zones_size[3] = { 0, };
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 
 #ifdef DEBUG
 	{
@@ -257,12 +257,12 @@ void __init paging_init(void)
 #ifdef DEBUG
 	printk ("before free_area_init\n");
 #endif
-	zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ?
-			 (mach_max_dma_address+1) : (unsigned long)high_memory);
-	zones_size[1] = (unsigned long)high_memory - zones_size[0];
+	zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
+				(mach_max_dma_address+1) : (unsigned long)high_memory);
+	zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
 
-	zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT;
-	zones_size[1] >>= PAGE_SHIFT;
+	zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
+	zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
 
 	free_area_init(zones_size);
 }
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index a47be196a47c..ac6640ade0b1 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -46,7 +46,7 @@ void __init paging_init(void)
 	unsigned long address;
 	unsigned long next_pgtable;
 	unsigned long bootmem_end;
-	unsigned long zones_size[3] = {0, 0, 0};
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 	unsigned long size;
 
 
@@ -92,8 +92,7 @@ void __init paging_init(void)
 	current->mm = NULL;
 
 	/* memory sizing is a hack stolen from motorola.c..  hope it works for us */
-	zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
-	zones_size[1] = 0;
+	zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
 
 	free_area_init(zones_size);
 
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index e1b3aa39e270..8e2c5a88efa7 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -553,7 +553,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void *)((usp - frame_size) & -8UL);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a0ac0e5f61ad..2d2fdf77e308 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -497,7 +497,7 @@ einval:	li	v0, -EINVAL
 	sys	sys_sched_get_priority_min 1
 	sys	sys_sched_rr_get_interval 2	/* 4165 */
 	sys	sys_nanosleep,		2
-	sys	sys_mremap,		4
+	sys	sys_mremap,		5
 	sys	sys_accept		3
 	sys	sys_bind		3
 	sys	sys_connect		3	/* 4170 */
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 5407b784cd01..19e1ef43eb4b 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __user *path,
 	if (error)
 		goto out;
 
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf)
 		goto out;
 	}
 
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf)
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf)
 		error = -EBADF;
 		goto out;
 	}
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user *
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf)
 		error = -EBADF;
 		goto out;
 	}
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 05273ccced0e..cb69727027ae 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -145,7 +145,7 @@ static int hpux_ustat(dev_t dev, struct hpux_ustat __user *ubuf)
 	s = user_get_super(dev);
 	if (s == NULL)
 		goto out;
-	err = vfs_statfs(s, &sbuf);
+	err = vfs_statfs(s->s_root, &sbuf);
 	drop_super(s);
 	if (err)
 		goto out;
@@ -186,12 +186,12 @@ struct hpux_statfs {
      int16_t f_pad;
 };
 
-static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf)
+static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
 {
 	struct kstatfs st;
 	int retval;
 	
-	retval = vfs_statfs(sb, &st);
+	retval = vfs_statfs(dentry, &st);
 	if (retval)
 		return retval;
 
@@ -219,7 +219,7 @@ asmlinkage long hpux_statfs(const char __user *path,
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct hpux_statfs tmp;
-		error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs_hpux(nd.dentry, &tmp);
 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 			error = -EFAULT;
 		path_release(&nd);
@@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs_hpux(file->f_dentry, &tmp);
 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 		error = -EFAULT;
 	fput(file);
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 05767e83cf2d..cc38edfd90c5 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -248,7 +248,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
 			(unsigned long)ka, sp, frame_size);
 	
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp; /* Stacks grow up! */
 
 	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6729c98b66f9..e922a88b2bad 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -45,6 +45,10 @@ config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
 
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
 config PPC
 	bool
 	default y
@@ -137,6 +141,15 @@ config PPC_85xx
 	select FSL_SOC
 	select 85xx
 
+config PPC_86xx
+	bool "Freescale 86xx"
+	select 6xx
+	select FSL_SOC
+	select PPC_FPU
+	select ALTIVEC
+	help
+	  The Freescale E600 SoCs have 74xx cores.
+
 config 40x
 	bool "AMCC 40x"
 
@@ -336,7 +349,7 @@ endchoice
 
 config PPC_PSERIES
 	depends on PPC_MULTIPLATFORM && PPC64
-	bool "  IBM pSeries & new (POWER5-based) iSeries"
+	bool "IBM pSeries & new (POWER5-based) iSeries"
 	select PPC_I8259
 	select PPC_RTAS
 	select RTAS_ERROR_LOGGING
@@ -344,7 +357,7 @@ config PPC_PSERIES
 	default y
 
 config PPC_CHRP
-	bool "  Common Hardware Reference Platform (CHRP) based machines"
+	bool "Common Hardware Reference Platform (CHRP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
@@ -354,7 +367,7 @@ config PPC_CHRP
 	default y
 
 config PPC_PMAC
-	bool "  Apple PowerMac based machines"
+	bool "Apple PowerMac based machines"
 	depends on PPC_MULTIPLATFORM
 	select PPC_INDIRECT_PCI if PPC32
 	select PPC_MPC106 if PPC32
@@ -370,7 +383,7 @@ config PPC_PMAC64
 	default y
 
 config PPC_PREP
-	bool "  PowerPC Reference Platform (PReP) based machines"
+	bool "PowerPC Reference Platform (PReP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
@@ -379,7 +392,7 @@ config PPC_PREP
 
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM && PPC64
-	bool "  Maple 970FX Evaluation Board"
+	bool "Maple 970FX Evaluation Board"
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
@@ -391,8 +404,18 @@ config PPC_MAPLE
 	  For more informations, refer to <http://www.970eval.com>
 
 config PPC_CELL
-	bool "  Cell Broadband Processor Architecture"
+	bool
+	default n
+
+config PPC_CELL_NATIVE
+	bool
+	select PPC_CELL
+	default n
+
+config PPC_IBM_CELL_BLADE
+	bool "  IBM Cell Blade"
 	depends on PPC_MULTIPLATFORM && PPC64
+	select PPC_CELL_NATIVE
 	select PPC_RTAS
 	select MMIO_NVRAM
 	select PPC_UDBG_16550
@@ -439,11 +462,6 @@ config MPIC_BROKEN_U3
 	depends on PPC_MAPLE
 	default y
 
-config CELL_IIC
-	depends on PPC_CELL
-	bool
-	default y
-
 config IBMVIO
 	depends on PPC_PSERIES || PPC_ISERIES
 	bool
@@ -545,6 +563,7 @@ source arch/powerpc/platforms/embedded6xx/Kconfig
 source arch/powerpc/platforms/4xx/Kconfig
 source arch/powerpc/platforms/83xx/Kconfig
 source arch/powerpc/platforms/85xx/Kconfig
+source arch/powerpc/platforms/86xx/Kconfig
 source arch/powerpc/platforms/8xx/Kconfig
 source arch/powerpc/platforms/cell/Kconfig
 
@@ -699,7 +718,6 @@ config PPC_64K_PAGES
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on PPC64 && SMP
-	default off
 	help
 	  SMT scheduler support improves the CPU scheduler's decision making
 	  when dealing with POWER5 cpus at a cost of slightly increased
@@ -776,6 +794,7 @@ config GENERIC_ISA_DMA
 
 config PPC_I8259
 	bool
+	default y if MPC8641_HPCN
 	default n
 
 config PPC_INDIRECT_PCI
@@ -798,8 +817,8 @@ config MCA
 	bool
 
 config PCI
-	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
-	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx
+	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
+	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	help
@@ -827,12 +846,12 @@ config PCI_8260
 	default y
 
 config 8260_PCI9
-	bool "  Enable workaround for MPC826x erratum PCI 9"
+	bool "Enable workaround for MPC826x erratum PCI 9"
 	depends on PCI_8260 && !ADS8272
 	default y
 
 choice
-	prompt "  IDMA channel for PCI 9 workaround"
+	prompt "IDMA channel for PCI 9 workaround"
 	depends on 8260_PCI9
 
 config 8260_PCI9_IDMA1
@@ -849,6 +868,8 @@ config 8260_PCI9_IDMA4
 
 endchoice
 
+source "drivers/pci/pcie/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 8d48e9e7162a..c69006ae8246 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -110,13 +110,16 @@ config SERIAL_TEXT_DEBUG
 	depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
 		PPC_GEN550 || PPC_MPC52xx
 
+config PPC_EARLY_DEBUG
+	bool "Early debugging (dangerous)"
+
 choice
-	prompt "Early debugging (dangerous)"
-	bool
-	optional
+	prompt "Early debugging console"
+	depends on PPC_EARLY_DEBUG
 	help
-	  Enable early debugging. Careful, if you enable debugging for the
-	  wrong type of machine your kernel _will not boot_.
+	  Use the selected console for early debugging. Careful, if you
+	  enable debugging for the wrong type of machine your kernel
+	  _will not boot_.
 
 config PPC_EARLY_DEBUG_LPAR
 	bool "LPAR HV Console"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index ed5b26aa8be3..01667d1d571d 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -108,7 +108,6 @@ ifeq ($(CONFIG_6xx),y)
 CFLAGS		+= -mcpu=powerpc
 endif
 
-cpu-as-$(CONFIG_PPC64BRIDGE)	+= -Wa,-mppc64bridge
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
 cpu-as-$(CONFIG_POWER4)		+= -Wa,-maltivec
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 840ae595a617..d961bfeed05f 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -29,8 +29,8 @@ OBJCOPYFLAGS    := contents,alloc,load,readonly,data
 OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
 OBJCOPY_MIB_ARGS  := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
 
-zlib       := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
-zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
+zlib       := inffast.c inflate.c inftrees.c
+zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
 zliblinuxheader := zlib.h zconf.h zutil.h
 
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 816446f0e497..b66634c9ea34 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -33,6 +33,14 @@ extern char _vmlinux_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
 
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char builtin_cmdline[512]
+	__attribute__((section("__builtin_cmdline")));
+
+
 struct addr_range {
 	unsigned long addr;
 	unsigned long size;
@@ -204,6 +212,23 @@ static int is_elf32(void *hdr)
 	return 1;
 }
 
+void export_cmdline(void* chosen_handle)
+{
+        int len;
+        char cmdline[2] = { 0, 0 };
+
+	if (builtin_cmdline[0] == 0)
+		return;
+
+        len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
+        if (len > 0 && cmdline[0] != 0)
+		return;
+
+	setprop(chosen_handle, "bootargs", builtin_cmdline,
+		strlen(builtin_cmdline) + 1);
+}
+
+
 void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 {
 	int len;
@@ -289,6 +314,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
 	}
 
+	export_cmdline(chosen_handle);
+
 	/* Skip over the ELF header */
 #ifdef DEBUG
 	printf("... skipping 0x%lx bytes of ELF header\n\r",
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 3e2ddd4a5a81..a57b184c564f 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -31,4 +31,11 @@ static inline int getprop(void *phandle, const char *name,
 	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
 }
 
+
+static inline int setprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
+
 #endif				/* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index dbe421dc3c11..b8b8d4675dc0 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Thu Mar 23 20:48:09 2006
+# Linux kernel version: 2.6.17
+# Mon Jun 19 17:23:03 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -55,7 +56,7 @@ CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-# CONFIG_CPUSETS is not set
+CONFIG_CPUSETS=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -116,13 +117,15 @@ CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 CONFIG_PPC_CELL=y
+CONFIG_PPC_CELL_NATIVE=y
+CONFIG_PPC_IBM_CELL_BLADE=y
+CONFIG_PPC_SYSTEMSIM=y
 # CONFIG_U3_DART is not set
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=y
 CONFIG_MMIO_NVRAM=y
-CONFIG_CELL_IIC=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
@@ -132,7 +135,9 @@ CONFIG_CELL_IIC=y
 # Cell Broadband Engine options
 #
 CONFIG_SPU_FS=m
+CONFIG_SPU_BASE=y
 CONFIG_SPUFS_MMAP=y
+CONFIG_CBE_RAS=y
 
 #
 # Kernel options
@@ -152,20 +157,24 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
-# CONFIG_NUMA is not set
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 CONFIG_SPARSEMEM_MANUAL=y
 CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
 CONFIG_HAVE_MEMORY_PRESENT=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPARSEMEM_EXTREME=y
-# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_MEMORY_HOTPLUG=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_ARCH_MEMORY_PROBE=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
@@ -182,6 +191,7 @@ CONFIG_GENERIC_ISA_DMA=y
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -476,7 +486,7 @@ CONFIG_DM_MULTIPATH=m
 #
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_BONDING=y
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 
@@ -624,6 +634,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
+# CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
 
 #
@@ -766,6 +777,7 @@ CONFIG_I2C_ALGOBIT=y
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1054,11 +1066,7 @@ CONFIG_DEBUGGER=y
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
new file mode 100644
index 000000000000..9bb022a523fe
--- /dev/null
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -0,0 +1,846 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Sun Apr  2 11:23:42 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+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_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_85xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_85xx=y
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# 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_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF 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"
+CONFIG_MPIC=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC85xx_CDS=y
+CONFIG_MPC8540=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# 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=y
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_FLATMEM_ENABLE=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_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI 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_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM 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_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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_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_PCI=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_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+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
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS 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_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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_SYSFS=y
+CONFIG_TMPFS=y
+# 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 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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
+# CONFIG_9P_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 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
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
new file mode 100644
index 000000000000..d7a30f9bc535
--- /dev/null
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -0,0 +1,921 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Fri Jun 16 10:47:09 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+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_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+# CONFIG_SLAB is not set
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_SLOB=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_MPIC=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Platform Support
+#
+CONFIG_MPC8641_HPCN=y
+CONFIG_MPC8641=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=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_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI 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_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# 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=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# 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_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# 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_NET_DIVERT 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_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM 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_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# 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=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# 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_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# 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_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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+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
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS 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_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# 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 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# 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
+# CONFIG_9P_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=y
+# CONFIG_LDM_DEBUG 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
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index 57a027971d67..addc79381c3b 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:21:32 2006
+# Linux kernel version: 2.6.17-rc5
+# Mon May 29 14:47:49 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -27,11 +28,11 @@ CONFIG_CLASSIC32=y
 # CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_8xx is not set
 # CONFIG_E200 is not set
-# CONFIG_E500 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
@@ -59,6 +60,7 @@ CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_EMBEDDED is not set
@@ -73,10 +75,6 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -88,7 +86,6 @@ CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -97,6 +94,8 @@ CONFIG_KMOD=y
 # Block layer
 #
 CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
 
 #
 # IO Schedulers
@@ -124,6 +123,7 @@ CONFIG_MPIC=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -182,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -239,7 +238,9 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -250,9 +251,10 @@ CONFIG_IP_FIB_HASH=y
 # 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_AH=y
+CONFIG_INET_ESP=y
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -264,6 +266,8 @@ CONFIG_TCP_CONG_BIC=y
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -278,12 +282,15 @@ CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -305,15 +312,15 @@ CONFIG_IP_NF_NETBIOS_NS=m
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
@@ -335,6 +342,7 @@ CONFIG_IP_NF_NAT_FTP=m
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -350,10 +358,12 @@ CONFIG_IP_NF_ARP_MANGLE=m
 #
 CONFIG_IP_DCCP=m
 CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
 
 #
 # DCCP CCIDs Configuration (EXPERIMENTAL)
 #
+CONFIG_IP_DCCP_CCID2=m
 CONFIG_IP_DCCP_CCID3=m
 CONFIG_IP_DCCP_TFRC_LIB=m
 
@@ -361,7 +371,6 @@ CONFIG_IP_DCCP_TFRC_LIB=m
 # DCCP Kernel Hacking
 #
 # CONFIG_IP_DCCP_DEBUG is not set
-# CONFIG_IP_DCCP_UNLOAD_HACK is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -477,6 +486,8 @@ CONFIG_IEEE80211=m
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -662,9 +673,8 @@ CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -694,16 +704,17 @@ CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
 
 #
@@ -740,7 +751,7 @@ CONFIG_IEEE1394_OHCI1394=m
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
 # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
+# CONFIG_IEEE1394_ETH1394 is not set
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
 
@@ -769,10 +780,10 @@ CONFIG_THERM_ADT746X=m
 # Network device support
 #
 CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
@@ -857,6 +868,7 @@ CONFIG_PCNET32=y
 # Wireless LAN (non-hamradio)
 #
 CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
 
 #
 # Obsolete Wireless cards support (pre-802.11)
@@ -992,6 +1004,7 @@ CONFIG_HW_CONSOLE=y
 # Serial drivers
 #
 CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -1027,6 +1040,7 @@ CONFIG_GEN_RTC=y
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 CONFIG_DRM=m
 # CONFIG_DRM_TDFX is not set
@@ -1081,7 +1095,6 @@ CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -1100,10 +1113,8 @@ CONFIG_I2C_POWERMAC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_M41T00 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -1131,18 +1142,16 @@ CONFIG_I2C_POWERMAC=y
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -1152,6 +1161,7 @@ CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -1175,7 +1185,6 @@ CONFIG_FB_MATROX_MYSTIQUE=y
 # CONFIG_FB_MATROX_G is not set
 # CONFIG_FB_MATROX_I2C is not set
 # CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -1234,9 +1243,11 @@ CONFIG_SND_SEQ_DUMMY=m
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -1253,6 +1264,7 @@ CONFIG_SND_DUMMY=m
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALS4000 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
@@ -1285,6 +1297,7 @@ CONFIG_SND_DUMMY=m
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -1310,6 +1323,8 @@ CONFIG_SND_USB_AUDIO=m
 #
 # PCMCIA devices
 #
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
 
 #
 # Open Sound System
@@ -1321,6 +1336,7 @@ CONFIG_SND_USB_AUDIO=m
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1336,7 +1352,9 @@ CONFIG_USB_DYNAMIC_MINORS=y
 #
 # USB Host Controller Drivers
 #
-# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1347,7 +1365,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
 
@@ -1358,7 +1375,17 @@ CONFIG_USB_PRINTER=m
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1374,9 +1401,7 @@ CONFIG_USB_HIDINPUT_POWERBOOK=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1391,15 +1416,6 @@ CONFIG_USB_APPLETOUCH=y
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1429,6 +1445,7 @@ CONFIG_USB_SERIAL=m
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
@@ -1436,6 +1453,7 @@ CONFIG_USB_SERIAL=m
 # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 CONFIG_USB_SERIAL_VISOR=m
 CONFIG_USB_SERIAL_IPAQ=m
 # CONFIG_USB_SERIAL_IR is not set
@@ -1460,6 +1478,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
@@ -1484,6 +1503,7 @@ CONFIG_USB_EZUSB=y
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
@@ -1502,6 +1522,19 @@ CONFIG_USB_EZUSB=y
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -1511,6 +1544,11 @@ CONFIG_USB_EZUSB=y
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1518,14 +1556,14 @@ CONFIG_EXT2_FS=y
 # 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_POSIX_ACL=y
 # CONFIG_EXT3_FS_SECURITY 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_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1534,7 +1572,7 @@ CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
 
 #
@@ -1566,7 +1604,6 @@ CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1590,17 +1627,24 @@ CONFIG_HFSPLUS_FS=m
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
@@ -1681,7 +1725,7 @@ CONFIG_NLS_UTF8=m
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_TEXTSEARCH=y
@@ -1735,29 +1779,29 @@ CONFIG_BOOTX_TEXT=y
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# 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_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 58e68ce09b0f..31708ad4574e 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 11:48:00 2006
+# Linux kernel version: 2.6.17-rc4
+# Sun May 28 07:26:56 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@ CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -126,8 +127,9 @@ CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=m
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
-# CONFIG_IBMEBUS is not set
+CONFIG_IBMEBUS=y
 # CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -143,7 +145,7 @@ CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT is not set
 # CONFIG_PREEMPT_BKL is not set
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_HOTPLUG_CPU=y
@@ -155,6 +157,7 @@ CONFIG_EEH=y
 CONFIG_SCANLOG=m
 CONFIG_LPARCFG=y
 CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
@@ -467,7 +470,7 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
-# CONFIG_SCSI_SAS_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -499,13 +502,18 @@ CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 CONFIG_SCSI_IPR=y
 CONFIG_SCSI_IPR_TRACE=y
 CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -521,7 +529,7 @@ CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -764,7 +772,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_ICOM=m
-# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_JSM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -773,7 +781,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TIPAR is not set
 CONFIG_HVC_DRIVER=y
 CONFIG_HVC_CONSOLE=y
-# CONFIG_HVC_RTAS is not set
+CONFIG_HVC_RTAS=y
 CONFIG_HVCS=m
 
 #
@@ -1031,9 +1039,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1105,16 +1111,25 @@ CONFIG_USB_MON=y
 # CONFIG_NEW_LEDS is not set
 
 #
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
-# CONFIG_INFINIBAND_USER_MAD is not set
-# CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
-# CONFIG_INFINIBAND_SRP is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SRP=m
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1159,15 +1174,15 @@ CONFIG_XFS_EXPORT=y
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
-# CONFIG_OCFS2_FS is not set
+CONFIG_OCFS2_FS=m
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -1199,7 +1214,7 @@ CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1317,7 +1332,7 @@ CONFIG_ZLIB_DEFLATE=m
 #
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
-# CONFIG_KPROBES is not set
+CONFIG_KPROBES=y
 
 #
 # Kernel hacking
@@ -1329,7 +1344,7 @@ CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1339,17 +1354,13 @@ CONFIG_DEBUG_FS=y
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index faaec9c6f78f..4734b5de599d 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -35,17 +35,19 @@ struct aligninfo {
 
 #define INVALID	{ 0, 0 }
 
-#define LD	1	/* load */
-#define ST	2	/* store */
-#define	SE	4	/* sign-extend value */
-#define F	8	/* to/from fp regs */
-#define U	0x10	/* update index register */
-#define M	0x20	/* multiple load/store */
-#define SW	0x40	/* byte swap int or ... */
-#define S	0x40	/* ... single-precision fp */
-#define SX	0x40	/* byte count in XER */
+/* Bits in the flags field */
+#define LD	0	/* load */
+#define ST	1	/* store */
+#define	SE	2	/* sign-extend value */
+#define F	4	/* to/from fp regs */
+#define U	8	/* update index register */
+#define M	0x10	/* multiple load/store */
+#define SW	0x20	/* byte swap */
+#define S	0x40	/* single-precision fp or... */
+#define SX	0x40	/* ... byte count in XER */
 #define HARD	0x80	/* string, stwcx. */
 
+/* DSISR bits reported for a DCBZ instruction: */
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
 
 #define SWAP(a, b)	(t = (a), (a) = (b), (b) = t)
@@ -256,12 +258,16 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
 #define REG_BYTE(rp, i)		*((u8 *)(rp) + (i))
 #endif
 
+#define SWIZ_PTR(p)		((unsigned char __user *)((p) ^ swiz))
+
 static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 			    unsigned int reg, unsigned int nb,
-			    unsigned int flags, unsigned int instr)
+			    unsigned int flags, unsigned int instr,
+			    unsigned long swiz)
 {
 	unsigned long *rptr;
-	unsigned int nb0, i;
+	unsigned int nb0, i, bswiz;
+	unsigned long p;
 
 	/*
 	 * We do not try to emulate 8 bytes multiple as they aren't really
@@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 			if (nb == 0)
 				return 1;
 		} else {
-			if (__get_user(instr,
-				       (unsigned int __user *)regs->nip))
+			unsigned long pc = regs->nip ^ (swiz & 4);
+
+			if (__get_user(instr, (unsigned int __user *)pc))
 				return -EFAULT;
+			if (swiz == 0 && (flags & SW))
+				instr = cpu_to_le32(instr);
 			nb = (instr >> 11) & 0x1f;
 			if (nb == 0)
 				nb = 32;
@@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 		return -EFAULT;	/* bad address */
 
 	rptr = &regs->gpr[reg];
-	if (flags & LD) {
+	p = (unsigned long) addr;
+	bswiz = (flags & SW)? 3: 0;
+
+	if (!(flags & ST)) {
 		/*
 		 * This zeroes the top 4 bytes of the affected registers
 		 * in 64-bit mode, and also zeroes out any remaining
@@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 			memset(&regs->gpr[0], 0,
 			       ((nb0 + 3) / 4) * sizeof(unsigned long));
 
-		for (i = 0; i < nb; ++i)
-			if (__get_user(REG_BYTE(rptr, i), addr + i))
+		for (i = 0; i < nb; ++i, ++p)
+			if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
 				return -EFAULT;
 		if (nb0 > 0) {
 			rptr = &regs->gpr[0];
 			addr += nb;
-			for (i = 0; i < nb0; ++i)
-				if (__get_user(REG_BYTE(rptr, i), addr + i))
+			for (i = 0; i < nb0; ++i, ++p)
+				if (__get_user(REG_BYTE(rptr, i ^ bswiz),
+					       SWIZ_PTR(p)))
 					return -EFAULT;
 		}
 
 	} else {
-		for (i = 0; i < nb; ++i)
-			if (__put_user(REG_BYTE(rptr, i), addr + i))
+		for (i = 0; i < nb; ++i, ++p)
+			if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
 				return -EFAULT;
 		if (nb0 > 0) {
 			rptr = &regs->gpr[0];
 			addr += nb;
-			for (i = 0; i < nb0; ++i)
-				if (__put_user(REG_BYTE(rptr, i), addr + i))
+			for (i = 0; i < nb0; ++i, ++p)
+				if (__put_user(REG_BYTE(rptr, i ^ bswiz),
+					       SWIZ_PTR(p)))
 					return -EFAULT;
 		}
 	}
@@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs)
 	unsigned int reg, areg;
 	unsigned int dsisr;
 	unsigned char __user *addr;
-	unsigned char __user *p;
+	unsigned long p, swiz;
 	int ret, t;
 	union {
 		u64 ll;
@@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs)
 	 * let's make one up from the instruction
 	 */
 	if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
-		unsigned int real_instr;
-		if (unlikely(__get_user(real_instr,
-					(unsigned int __user *)regs->nip)))
+		unsigned long pc = regs->nip;
+
+		if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
+			pc ^= 4;
+		if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
 			return -EFAULT;
-		dsisr = make_dsisr(real_instr);
+		if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
+			instr = cpu_to_le32(instr);
+		dsisr = make_dsisr(instr);
 	}
 
 	/* extract the operation and registers from the dsisr */
@@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs)
 	nb = aligninfo[instr].len;
 	flags = aligninfo[instr].flags;
 
+	/* Byteswap little endian loads and stores */
+	swiz = 0;
+	if (regs->msr & MSR_LE) {
+		flags ^= SW;
+		/*
+		 * So-called "PowerPC little endian" mode works by
+		 * swizzling addresses rather than by actually doing
+		 * any byte-swapping.  To emulate this, we XOR each
+		 * byte address with 7.  We also byte-swap, because
+		 * the processor's address swizzling depends on the
+		 * operand size (it xors the address with 7 for bytes,
+		 * 6 for halfwords, 4 for words, 0 for doublewords) but
+		 * we will xor with 7 and load/store each byte separately.
+		 */
+		if (cpu_has_feature(CPU_FTR_PPC_LE))
+			swiz = 7;
+	}
+
 	/* DAR has the operand effective address */
 	addr = (unsigned char __user *)regs->dar;
 
@@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs)
 	 * function
 	 */
 	if (flags & M)
-		return emulate_multiple(regs, addr, reg, nb, flags, instr);
+		return emulate_multiple(regs, addr, reg, nb,
+					flags, instr, swiz);
 
 	/* Verify the address of the operand */
 	if (unlikely(user_mode(regs) &&
@@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs)
 	/* If we are loading, get the data from user space, else
 	 * get it from register values
 	 */
-	if (flags & LD) {
+	if (!(flags & ST)) {
 		data.ll = 0;
 		ret = 0;
-		p = addr;
+		p = (unsigned long) addr;
 		switch (nb) {
 		case 8:
-			ret |= __get_user(data.v[0], p++);
-			ret |= __get_user(data.v[1], p++);
-			ret |= __get_user(data.v[2], p++);
-			ret |= __get_user(data.v[3], p++);
+			ret |= __get_user(data.v[0], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[1], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[2], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[3], SWIZ_PTR(p++));
 		case 4:
-			ret |= __get_user(data.v[4], p++);
-			ret |= __get_user(data.v[5], p++);
+			ret |= __get_user(data.v[4], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[5], SWIZ_PTR(p++));
 		case 2:
-			ret |= __get_user(data.v[6], p++);
-			ret |= __get_user(data.v[7], p++);
+			ret |= __get_user(data.v[6], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[7], SWIZ_PTR(p++));
 			if (unlikely(ret))
 				return -EFAULT;
 		}
-	} else if (flags & F)
+	} else if (flags & F) {
 		data.dd = current->thread.fpr[reg];
-	else
+		if (flags & S) {
+			/* Single-precision FP store requires conversion... */
+#ifdef CONFIG_PPC_FPU
+			preempt_disable();
+			enable_kernel_fp();
+			cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+			preempt_enable();
+#else
+			return 0;
+#endif
+		}
+	} else
 		data.ll = regs->gpr[reg];
 
-	/* Perform other misc operations like sign extension, byteswap,
+	if (flags & SW) {
+		switch (nb) {
+		case 8:
+			SWAP(data.v[0], data.v[7]);
+			SWAP(data.v[1], data.v[6]);
+			SWAP(data.v[2], data.v[5]);
+			SWAP(data.v[3], data.v[4]);
+			break;
+		case 4:
+			SWAP(data.v[4], data.v[7]);
+			SWAP(data.v[5], data.v[6]);
+			break;
+		case 2:
+			SWAP(data.v[6], data.v[7]);
+			break;
+		}
+	}
+
+	/* Perform other misc operations like sign extension
 	 * or floating point single precision conversion
 	 */
-	switch (flags & ~U) {
+	switch (flags & ~(U|SW)) {
 	case LD+SE:	/* sign extend */
 		if ( nb == 2 )
 			data.ll = data.x16.low16;
 		else	/* nb must be 4 */
 			data.ll = data.x32.low32;
 		break;
-	case LD+S:	/* byte-swap */
-	case ST+S:
-		if (nb == 2) {
-			SWAP(data.v[6], data.v[7]);
-		} else {
-			SWAP(data.v[4], data.v[7]);
-			SWAP(data.v[5], data.v[6]);
-		}
-		break;
 
-	/* Single-precision FP load and store require conversions... */
+	/* Single-precision FP load requires conversion... */
 	case LD+F+S:
 #ifdef CONFIG_PPC_FPU
 		preempt_disable();
@@ -486,34 +543,24 @@ int fix_alignment(struct pt_regs *regs)
 		return 0;
 #endif
 		break;
-	case ST+F+S:
-#ifdef CONFIG_PPC_FPU
-		preempt_disable();
-		enable_kernel_fp();
-		cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
-		preempt_enable();
-#else
-		return 0;
-#endif
-		break;
 	}
 
 	/* Store result to memory or update registers */
 	if (flags & ST) {
 		ret = 0;
-		p = addr;
+		p = (unsigned long) addr;
 		switch (nb) {
 		case 8:
-			ret |= __put_user(data.v[0], p++);
-			ret |= __put_user(data.v[1], p++);
-			ret |= __put_user(data.v[2], p++);
-			ret |= __put_user(data.v[3], p++);
+			ret |= __put_user(data.v[0], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[1], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[2], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[3], SWIZ_PTR(p++));
 		case 4:
-			ret |= __put_user(data.v[4], p++);
-			ret |= __put_user(data.v[5], p++);
+			ret |= __put_user(data.v[4], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[5], SWIZ_PTR(p++));
 		case 2:
-			ret |= __put_user(data.v[6], p++);
-			ret |= __put_user(data.v[7], p++);
+			ret |= __put_user(data.v[6], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[7], SWIZ_PTR(p++));
 		}
 		if (unlikely(ret))
 			return -EFAULT;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8f85c5e8a55a..ff2940548929 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -122,9 +122,8 @@ int main(void)
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
 	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-#ifdef CONFIG_PPC_64K_PAGES
-	DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir));
-#endif
+	DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
+	DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
 #ifdef CONFIG_HUGETLB_PAGE
 	DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
 	DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 55ed7716636f..365381fcb27c 100644
--- a/arch/powerpc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -210,9 +210,11 @@ setup_745x_specifics:
 	 * the firmware. If any, we disable NAP capability as
 	 * it's known to be bogus on rev 2.1 and earlier
 	 */
+BEGIN_FTR_SECTION
 	mfspr	r11,SPRN_L3CR
 	andis.	r11,r11,L3CR_L3E@h
 	beq	1f
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
 	lwz	r6,CPU_SPEC_FEATURES(r5)
 	andi.	r0,r6,CPU_FTR_L3_DISABLE_NAP
 	beq	1f
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index b61d86e7ceb6..271418308d53 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -73,23 +73,6 @@ _GLOBAL(__970_cpu_preinit)
 	isync
 	blr
 
-_GLOBAL(__setup_cpu_power4)
-	blr
-
-_GLOBAL(__setup_cpu_be)
-        /* Set large page sizes LP=0: 16MB, LP=1: 64KB */
-        addi    r3, 0,  0
-        ori     r3, r3, HID6_LB
-        sldi    r3, r3, 32
-        nor     r3, r3, r3
-        mfspr   r4, SPRN_HID6
-        and     r4, r4, r3
-        addi    r3, 0, 0x02000
-        sldi    r3, r3, 32
-        or      r4, r4, r3
-        mtspr   SPRN_HID6, r4
-	blr
-
 _GLOBAL(__setup_cpu_ppc970)
 	mfspr	r0,SPRN_HID0
 	li	r11,5			/* clear DOZE and SLEEP */
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 3f7182db9ed5..1c114880dc05 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -30,11 +30,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
  * part of the cputable though. That has to be fixed for both ppc32
  * and ppc64
  */
-#ifdef CONFIG_PPC64
-extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
-#else
+#ifdef CONFIG_PPC32
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -58,7 +54,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
 #define COMMON_USER_POWER5_PLUS	(COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
 				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
 #define COMMON_USER_POWER6	(COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
-				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
+				 PPC_FEATURE_TRUE_LE)
 #define COMMON_USER_BOOKE	(PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
 				 PPC_FEATURE_BOOKE)
 
@@ -78,11 +75,10 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00400000,
 		.cpu_name		= "POWER3 (630)",
 		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64,
+		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "power3",
@@ -92,11 +88,10 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00410000,
 		.cpu_name		= "POWER3 (630+)",
 		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64,
+		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "power3",
@@ -110,7 +105,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -124,7 +118,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -138,7 +131,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -152,7 +144,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -166,7 +157,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power4",
@@ -180,7 +170,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power4",
@@ -200,17 +189,11 @@ struct cpu_spec	cpu_specs[] = {
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
 	},
-#endif /* CONFIG_PPC64 */
-#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
 	{	/* PPC970FX */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x003c0000,
 		.cpu_name		= "PPC970FX",
-#ifdef CONFIG_PPC32
-		.cpu_features		= CPU_FTRS_970_32,
-#else
 		.cpu_features		= CPU_FTRS_PPC970,
-#endif
 		.cpu_user_features	= COMMON_USER_POWER4 |
 			PPC_FEATURE_HAS_ALTIVEC_COMP,
 		.icache_bsize		= 128,
@@ -221,8 +204,6 @@ struct cpu_spec	cpu_specs[] = {
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
 	},
-#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
-#ifdef CONFIG_PPC64
 	{	/* PPC970MP */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00440000,
@@ -232,6 +213,7 @@ struct cpu_spec	cpu_specs[] = {
 			PPC_FEATURE_HAS_ALTIVEC_COMP,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
+		.num_pmcs		= 8,
 		.cpu_setup		= __setup_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
@@ -246,9 +228,13 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power5",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+		/* SIHV / SIPR bits are implemented on POWER4+ (GQ)
+		 * and above but only works on POWER5 and above
+		 */
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5",
 	},
 	{	/* Power5 GS */
@@ -260,9 +246,10 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power5+",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5+",
 	},
 	{	/* Power6 */
@@ -273,10 +260,13 @@ struct cpu_spec	cpu_specs[] = {
 		.cpu_user_features	= COMMON_USER_POWER6,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
+		.num_pmcs		= 8,
 		.oprofile_cpu_type	= "ppc64/power6",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+ 		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
+ 		.oprofile_mmcra_sipr	= POWER6_MMCRA_SIPR,
+ 		.oprofile_mmcra_clear	= POWER6_MMCRA_THRM |
+ 			POWER6_MMCRA_OTHER,
 		.platform		= "power6",
 	},
 	{	/* Cell Broadband Engine */
@@ -289,7 +279,6 @@ struct cpu_spec	cpu_specs[] = {
 			PPC_FEATURE_SMT,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.cpu_setup		= __setup_cpu_be,
 		.platform		= "ppc-cell-be",
 	},
 	{	/* default match */
@@ -301,7 +290,6 @@ struct cpu_spec	cpu_specs[] = {
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.platform		= "power4",
 	}
 #endif	/* CONFIG_PPC64 */
@@ -323,7 +311,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00030000,
 		.cpu_name		= "603",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -334,7 +322,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00060000,
 		.cpu_name		= "603e",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -345,7 +333,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00070000,
 		.cpu_name		= "603ev",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -356,7 +344,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00040000,
 		.cpu_name		= "604",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 2,
@@ -368,7 +356,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00090000,
 		.cpu_name		= "604e",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -380,7 +368,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00090000,
 		.cpu_name		= "604r",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -392,7 +380,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x000a0000,
 		.cpu_name		= "604ev",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -404,7 +392,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00084202,
 		.cpu_name		= "740/750",
 		.cpu_features		= CPU_FTRS_740_NOTAU,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -416,7 +404,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00080100,
 		.cpu_name		= "750CX",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -428,7 +416,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00082200,
 		.cpu_name		= "750CX",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -440,7 +428,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00082210,
 		.cpu_name		= "750CXe",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -452,7 +440,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00083214,
 		.cpu_name		= "750CXe",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -464,7 +452,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00083000,
 		.cpu_name		= "745/755",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -476,7 +464,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x70000100,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX1,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -488,7 +476,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x70000200,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX2,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -500,7 +488,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x70000000,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -512,7 +500,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x70020000,
 		.cpu_name		= "750GX",
 		.cpu_features		= CPU_FTRS_750GX,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -524,7 +512,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x00080000,
 		.cpu_name		= "740/750",
 		.cpu_features		= CPU_FTRS_740,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -536,7 +524,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x000c1101,
 		.cpu_name		= "7400 (1.1)",
 		.cpu_features		= CPU_FTRS_7400_NOTAU,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -548,7 +537,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x000c0000,
 		.cpu_name		= "7400",
 		.cpu_features		= CPU_FTRS_7400,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -560,7 +550,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x800c0000,
 		.cpu_name		= "7410",
 		.cpu_features		= CPU_FTRS_7400,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -572,7 +563,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80000200,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_20,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -586,7 +578,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80000201,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_21,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -600,7 +593,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80000000,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_23,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -614,7 +608,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80010100,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455_1,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -628,7 +623,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80010200,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455_20,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -642,7 +638,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80010000,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -656,7 +653,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80020100,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447_10,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -670,7 +668,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80020101,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447_10,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -684,7 +683,7 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80020000,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -698,7 +697,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80030000,
 		.cpu_name		= "7447A",
 		.cpu_features		= CPU_FTRS_7447A,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -712,7 +712,8 @@ struct cpu_spec	cpu_specs[] = {
 		.pvr_value		= 0x80040000,
 		.cpu_name		= "7448",
 		.cpu_features		= CPU_FTRS_7447A,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -721,6 +722,18 @@ struct cpu_spec	cpu_specs[] = {
 		.oprofile_type		= PPC_OPROFILE_G4,
 		.platform		= "ppc7450",
 	},
+        {       /* 8641 */
+               .pvr_mask               = 0xffffffff,
+               .pvr_value              = 0x80040010,
+               .cpu_name               = "8641",
+               .cpu_features           = CPU_FTRS_7447A,
+               .cpu_user_features      = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .num_pmcs               = 6,
+               .cpu_setup              = __setup_cpu_745x
+        },
+
 	{	/* 82xx (8240, 8245, 8260 are all 603e cores) */
 		.pvr_mask		= 0x7fff0000,
 		.pvr_value		= 0x00810000,
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 778f22fd85d2..dbcb85994f46 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -22,6 +22,7 @@
 #include <linux/elf.h>
 #include <linux/elfcore.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/types.h>
 
 #include <asm/processor.h>
@@ -174,6 +175,8 @@ static void crash_kexec_prepare_cpus(void)
 
 void default_machine_crash_shutdown(struct pt_regs *regs)
 {
+	unsigned int irq;
+
 	/*
 	 * This function is only called after the system
 	 * has paniced or is otherwise in a critical state.
@@ -186,6 +189,16 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
 	 */
 	local_irq_disable();
 
+	for_each_irq(irq) {
+		struct irq_desc *desc = irq_descp(irq);
+
+		if (desc->status & IRQ_INPROGRESS)
+			desc->handler->end(irq);
+
+		if (!(desc->status & IRQ_DISABLED))
+			desc->handler->disable(irq);
+	}
+
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 0);
 
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 764d07329716..371973be8d71 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -25,6 +25,11 @@
 #define DBG(fmt...)
 #endif
 
+void reserve_kdump_trampoline(void)
+{
+	lmb_reserve(0, KDUMP_RESERVE_LIMIT);
+}
+
 static void __init create_trampoline(unsigned long addr)
 {
 	/* The maximum range of a single instruction branch, is the current
@@ -39,11 +44,11 @@ static void __init create_trampoline(unsigned long addr)
 	create_branch(addr + 4, addr + PHYSICAL_START, 0);
 }
 
-void __init kdump_setup(void)
+void __init setup_kdump_trampoline(void)
 {
 	unsigned long i;
 
-	DBG(" -> kdump_setup()\n");
+	DBG(" -> setup_kdump_trampoline()\n");
 
 	for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
 		create_trampoline(i);
@@ -52,7 +57,7 @@ void __init kdump_setup(void)
 	create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
 	create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
 
-	DBG(" <- kdump_setup()\n");
+	DBG(" <- setup_kdump_trampoline()\n");
 }
 
 #ifdef CONFIG_PROC_VMCORE
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 19ad5c6b1818..221062c960c9 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -57,6 +57,7 @@ system_call_common:
 	beq-	1f
 	ld	r1,PACAKSAVE(r13)
 1:	std	r10,0(r1)
+	crclr	so
 	std	r11,_NIP(r1)
 	std	r12,_MSR(r1)
 	std	r0,GPR0(r1)
@@ -75,7 +76,6 @@ system_call_common:
 	std	r11,GPR11(r1)
 	std	r11,GPR12(r1)
 	std	r9,GPR13(r1)
-	crclr	so
 	mfcr	r9
 	mflr	r10
 	li	r11,0xc01
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 340730fb8c91..01f71200c603 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -72,7 +72,7 @@ _GLOBAL(load_up_fpu)
 	std	r12,_MSR(r1)
 #endif
 	lfd	fr0,THREAD_FPSCR(r5)
-	mtfsf	0xff,fr0
+	MTFSF_L(fr0)
 	REST_32FPRS(0, r5)
 #ifndef CONFIG_SMP
 	subi	r4,r5,THREAD
@@ -127,7 +127,7 @@ _GLOBAL(giveup_fpu)
 
 _GLOBAL(cvt_fd)
 	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	mtfsf	0xff,0
+	MTFSF_L(0)
 	lfs	0,0(r3)
 	stfd	0,0(r4)
 	mffs	0
@@ -136,7 +136,7 @@ _GLOBAL(cvt_fd)
 
 _GLOBAL(cvt_df)
 	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	mtfsf	0xff,0
+	MTFSF_L(0)
 	lfd	0,0(r3)
 	stfs	0,0(r4)
 	mffs	0
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index a0579e859b21..b25b25902d15 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -973,6 +973,13 @@ __secondary_start_gemini:
         b       __secondary_start
 #endif /* CONFIG_GEMINI */
 
+	.globl __secondary_start_mpc86xx
+__secondary_start_mpc86xx:
+	mfspr	r3, SPRN_PIR
+	stw	r3, __secondary_hold_acknowledge@l(0)
+	mr	r24, r3			/* cpu # */
+	b	__secondary_start
+
 	.globl	__secondary_start_pmac_0
 __secondary_start_pmac_0:
 	/* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
@@ -1088,7 +1095,12 @@ load_up_mmu:
 	LOAD_BAT(1,r3,r4,r5)
 	LOAD_BAT(2,r3,r4,r5)
 	LOAD_BAT(3,r3,r4,r5)
-
+BEGIN_FTR_SECTION
+	LOAD_BAT(4,r3,r4,r5)
+	LOAD_BAT(5,r3,r4,r5)
+	LOAD_BAT(6,r3,r4,r5)
+	LOAD_BAT(7,r3,r4,r5)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
 	blr
 
 /*
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index b7d140430a41..831acbdf2592 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -316,6 +316,21 @@ label##_pSeries:					\
 	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
 
+#define HSTD_EXCEPTION_PSERIES(n, label)		\
+	. = n;						\
+	.globl label##_pSeries;				\
+label##_pSeries:					\
+	HMT_MEDIUM;					\
+	mtspr	SPRN_SPRG1,r20;		/* save r20 */	\
+	mfspr	r20,SPRN_HSRR0;		/* copy HSRR0 to SRR0 */ \
+	mtspr	SPRN_SRR0,r20;				\
+	mfspr	r20,SPRN_HSRR1;		/* copy HSRR0 to SRR0 */ \
+	mtspr	SPRN_SRR1,r20;				\
+	mfspr	r20,SPRN_SPRG1;		/* restore r20 */ \
+	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+
+
 #define STD_EXCEPTION_ISERIES(n, label, area)		\
 	.globl label##_iSeries;				\
 label##_iSeries:					\
@@ -544,8 +559,17 @@ system_call_pSeries:
 
 	STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)
 
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
+#endif /* CONFIG_CBE_RAS */
 	STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
+#endif /* CONFIG_CBE_RAS */
 	STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
+#endif /* CONFIG_CBE_RAS */
 
 	. = 0x3000
 
@@ -827,6 +851,11 @@ machine_check_common:
 #else
 	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
 #endif
+#ifdef CONFIG_CBE_RAS
+	STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
+	STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
+	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
+#endif /* CONFIG_CBE_RAS */
 
 /*
  * Here we have detected that the kernel stack pointer is bad.
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c
index fd8214caedee..a13a93dfc655 100644
--- a/arch/powerpc/kernel/iomap.c
+++ b/arch/powerpc/kernel/iomap.c
@@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep);
 
 void __iomem *ioport_map(unsigned long port, unsigned int len)
 {
-	if (!_IO_IS_VALID(port))
-		return NULL;
 	return (void __iomem *) (port+pci_io_base);
 }
 
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 4eba60a32890..7cb77c20fc5d 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -418,10 +418,11 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
  * Build a iommu_table structure.  This contains a bit map which
  * is used to manage allocation of the tce space.
  */
-struct iommu_table *iommu_init_table(struct iommu_table *tbl)
+struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 {
 	unsigned long sz;
 	static int welcomed = 0;
+	struct page *page;
 
 	/* Set aside 1/4 of the table for large allocations. */
 	tbl->it_halfpoint = tbl->it_size * 3 / 4;
@@ -429,10 +430,10 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
 	/* number of bytes needed for the bitmap */
 	sz = (tbl->it_size + 7) >> 3;
 
-	tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz));
-	if (!tbl->it_map)
+	page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz));
+	if (!page)
 		panic("iommu_init_table: Can't allocate %ld bytes\n", sz);
-
+	tbl->it_map = page_address(page);
 	memset(tbl->it_map, 0, sz);
 
 	tbl->it_hint = 0;
@@ -536,11 +537,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
  * to the dma address (mapping) of the first page.
  */
 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
 {
 	void *ret = NULL;
 	dma_addr_t mapping;
 	unsigned int npages, order;
+	struct page *page;
 
 	size = PAGE_ALIGN(size);
 	npages = size >> PAGE_SHIFT;
@@ -560,9 +562,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
 		return NULL;
 
 	/* Alloc enough pages (and possibly more) */
-	ret = (void *)__get_free_pages(flag, order);
-	if (!ret)
+	page = alloc_pages_node(node, flag, order);
+	if (!page)
 		return NULL;
+	ret = page_address(page);
 	memset(ret, 0, size);
 
 	/* Set up tces to cover the allocated range */
@@ -570,9 +573,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
 			      mask >> PAGE_SHIFT, order);
 	if (mapping == DMA_ERROR_CODE) {
 		free_pages((unsigned long)ret, order);
-		ret = NULL;
-	} else
-		*dma_handle = mapping;
+		return NULL;
+	}
+	*dma_handle = mapping;
 	return ret;
 }
 
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 57d560c68897..40d4c14fde8f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -47,6 +47,7 @@
 #include <linux/cpumask.h>
 #include <linux/profile.h>
 #include <linux/bitops.h>
+#include <linux/pci.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -379,8 +380,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
 #endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_IRQSTACKS
-struct thread_info *softirq_ctx[NR_CPUS];
-struct thread_info *hardirq_ctx[NR_CPUS];
+struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
+struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
 
 void irq_ctx_init(void)
 {
@@ -436,6 +437,30 @@ void do_softirq(void)
 }
 EXPORT_SYMBOL(do_softirq);
 
+#ifdef CONFIG_PCI_MSI
+int pci_enable_msi(struct pci_dev * pdev)
+{
+	if (ppc_md.enable_msi)
+		return ppc_md.enable_msi(pdev);
+	else
+		return -1;
+}
+
+void pci_disable_msi(struct pci_dev * pdev)
+{
+	if (ppc_md.disable_msi)
+		ppc_md.disable_msi(pdev);
+}
+
+void pci_scan_msi_device(struct pci_dev *dev) {}
+int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
+void pci_disable_msix(struct pci_dev *dev) {}
+void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
+void pci_no_msi(void) {}
+
+#endif
+
 #ifdef CONFIG_PPC64
 static int __init setup_noirqdistrib(char *str)
 {
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 2cbde865d4f5..c02deaab26c7 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
 
 	current_weight = (resource >> 5 * 8) & 0xFF;
 
-	pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
+	pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
 		 __FUNCTION__, current_entitled, current_weight);
 
-	pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
+	pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
 		 __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
 
 	retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index ee166c586642..a8fa04ef27cd 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -21,6 +21,7 @@
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
 #include <asm/paca.h>
+#include <asm/lmb.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>	/* _end */
 #include <asm/prom.h>
@@ -335,7 +336,105 @@ static void __init export_htab_values(void)
 	of_node_put(node);
 }
 
+static struct property crashk_base_prop = {
+	.name = "linux,crashkernel-base",
+	.length = sizeof(unsigned long),
+	.value = (unsigned char *)&crashk_res.start,
+};
+
+static unsigned long crashk_size;
+
+static struct property crashk_size_prop = {
+	.name = "linux,crashkernel-size",
+	.length = sizeof(unsigned long),
+	.value = (unsigned char *)&crashk_size,
+};
+
+static void __init export_crashk_values(void)
+{
+	struct device_node *node;
+	struct property *prop;
+
+	node = of_find_node_by_path("/chosen");
+	if (!node)
+		return;
+
+	/* There might be existing crash kernel properties, but we can't
+	 * be sure what's in them, so remove them. */
+	prop = of_find_property(node, "linux,crashkernel-base", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	prop = of_find_property(node, "linux,crashkernel-size", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	if (crashk_res.start != 0) {
+		prom_add_property(node, &crashk_base_prop);
+		crashk_size = crashk_res.end - crashk_res.start + 1;
+		prom_add_property(node, &crashk_size_prop);
+	}
+
+	of_node_put(node);
+}
+
 void __init kexec_setup(void)
 {
 	export_htab_values();
+	export_crashk_values();
+}
+
+static int __init early_parse_crashk(char *p)
+{
+	unsigned long size;
+
+	if (!p)
+		return 1;
+
+	size = memparse(p, &p);
+
+	if (*p == '@')
+		crashk_res.start = memparse(p + 1, &p);
+	else
+		crashk_res.start = KDUMP_KERNELBASE;
+
+	crashk_res.end = crashk_res.start + size - 1;
+
+	return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+	unsigned long size;
+
+	if (crashk_res.start == 0)
+		return;
+
+	/* We might have got these values via the command line or the
+	 * device tree, either way sanitise them now. */
+
+	size = crashk_res.end - crashk_res.start + 1;
+
+	if (crashk_res.start != KDUMP_KERNELBASE)
+		printk("Crash kernel location must be 0x%x\n",
+				KDUMP_KERNELBASE);
+
+	crashk_res.start = KDUMP_KERNELBASE;
+	size = PAGE_ALIGN(size);
+	crashk_res.end = crashk_res.start + size - 1;
+
+	/* Crash kernel trumps memory limit */
+	if (memory_limit && memory_limit <= crashk_res.end) {
+		memory_limit = crashk_res.end + 1;
+		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+				memory_limit);
+	}
+
+	lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+	return (start + size) > crashk_res.start && start <= crashk_res.end;
 }
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index be982023409e..01d3916c4cb1 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -216,7 +216,7 @@ _GLOBAL(call_setup_cpu)
 	lwz	r4,0(r4)
 	add	r4,r4,r3
 	lwz	r5,CPU_SPEC_SETUP(r4)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	add	r5,r5,r3
 	beqlr
 	mtctr	r5
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 2778cce058e2..e8883d42c43c 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -482,7 +482,9 @@ _GLOBAL(identify_cpu)
 	sub	r0,r3,r5
 	std	r0,0(r4)
 	ld	r4,CPU_SPEC_SETUP(r3)
+	cmpdi	0,r4,0
 	add	r4,r4,r5
+	beqlr
 	ld	r4,0(r4)
 	add	r4,r4,r5
 	mtctr	r4
@@ -768,9 +770,6 @@ _GLOBAL(giveup_altivec)
 
 #endif /* CONFIG_ALTIVEC */
 
-_GLOBAL(__setup_cpu_power3)
-	blr
-
 _GLOBAL(execve)
 	li	r0,__NR_execve
 	sc
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index ada50aa5b600..6960f090991e 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -204,7 +204,7 @@ static void nvram_print_partitions(char * label)
 	printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
 	list_for_each(p, &nvram_part->partition) {
 		tmp_part = list_entry(p, struct nvram_partition, partition);
-		printk(KERN_WARNING "%d    \t%02x\t%02x\t%d\t%s\n",
+		printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%s\n",
 		       tmp_part->index, tmp_part->header.signature,
 		       tmp_part->header.checksum, tmp_part->header.length,
 		       tmp_part->header.name);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index b129d2e4b759..c858eb4bef17 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -1113,9 +1113,10 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
 	int	i;
 	int	rc = 0;
 
-#define push_end(res, size) do { unsigned long __sz = (size) ; \
-	res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
-    } while (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;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4c4449be81ce..5ad87c426bed 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -42,14 +42,6 @@
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
 
-/*
- * legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
- * devices we don't have access to.
- */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
 #ifdef CONFIG_PPC_MULTIPLATFORM
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
@@ -235,8 +227,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
 	pci_setup_pci_controller(phb);
 	phb->arch_data = dev;
 	phb->is_dynamic = mem_init_done;
-	if (dev)
+	if (dev) {
+		PHB_SET_NODE(phb, of_node_to_nid(dev));
 		add_linux_pci_domain(dev, phb);
+	}
 	return phb;
 }
 
@@ -396,7 +390,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 
 	dev->current_state = 4;		/* unknown power state */
 
-	if (!strcmp(type, "pci")) {
+	if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
 		/* a PCI-PCI bridge */
 		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
 		dev->rom_base_reg = PCI_ROM_ADDRESS1;
@@ -605,7 +599,7 @@ static int __init pcibios_init(void)
 	iSeries_pcibios_init(); 
 #endif
 
-	printk("PCI: Probing PCI hardware\n");
+	printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -630,14 +624,14 @@ static int __init pcibios_init(void)
 	/* Cache the location of the ISA bridge (if we have one) */
 	ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
 	if (ppc64_isabridge_dev != NULL)
-		printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
+		printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
 	/* map in PCI I/O space */
 	phbs_remap_io();
 #endif
 
-	printk("PCI: Probing PCI hardware done\n");
+	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
 	return 0;
 }
@@ -804,7 +798,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
 	else
 		prot |= _PAGE_GUARDED;
 
-	printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+	printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
 	       prot);
 
 	return __pgprot(prot);
@@ -894,8 +888,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 	return ret;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pdev;
 	struct device_node *np;
@@ -907,13 +901,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att
 	return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_MULTIPLATFORM
 	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -1104,8 +1095,6 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
 			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
 						hose->io_base_virt);
 			of_node_put(isa_dn);
-			/* Allow all IO */
-			io_page_mask = -1;
 		}
 	}
 
@@ -1212,7 +1201,7 @@ int remap_bus_range(struct pci_bus *bus)
 		return 1;
 	if (start_phys == 0)
 		return 1;
-	printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
+	printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
 	if (__ioremap_explicit(start_phys, start_virt, size,
 			       _PAGE_NO_CACHE | _PAGE_GUARDED))
 		return 1;
@@ -1232,27 +1221,13 @@ static void phbs_remap_io(void)
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long start, end, mask, offset;
+	unsigned long offset;
 
 	if (res->flags & IORESOURCE_IO) {
 		offset = (unsigned long)hose->io_base_virt - pci_io_base;
 
-		start = res->start += offset;
-		end = res->end += offset;
-
-		/* Need to allow IO access to pages that are in the
-		   ISA range */
-		if (start < MAX_ISA_PORT) {
-			if (end > MAX_ISA_PORT)
-				end = MAX_ISA_PORT;
-
-			start >>= PAGE_SHIFT;
-			end >>= PAGE_SHIFT;
-
-			/* get the range of pages for the map */
-			mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
-			io_page_mask |= mask;
-		}
+		res->start += offset;
+		res->end += offset;
 	} else if (res->flags & IORESOURCE_MEM) {
 		res->start += hose->pci_mem_offset;
 		res->end += hose->pci_mem_offset;
@@ -1442,3 +1417,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 
 	return -EOPNOTSUPP;
 }
+
+#ifdef CONFIG_NUMA
+int pcibus_to_node(struct pci_bus *bus)
+{
+	struct pci_controller *phb = pci_bus_to_host(bus);
+	return phb->node;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+#endif
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c
index e1a32f802c0b..72ce082ce738 100644
--- a/arch/powerpc/kernel/pci_direct_iommu.c
+++ b/arch/powerpc/kernel/pci_direct_iommu.c
@@ -82,13 +82,17 @@ static int pci_direct_dma_supported(struct device *dev, u64 mask)
 	return mask < 0x100000000ull;
 }
 
+static struct dma_mapping_ops pci_direct_ops = {
+	.alloc_coherent = pci_direct_alloc_coherent,
+	.free_coherent = pci_direct_free_coherent,
+	.map_single = pci_direct_map_single,
+	.unmap_single = pci_direct_unmap_single,
+	.map_sg = pci_direct_map_sg,
+	.unmap_sg = pci_direct_unmap_sg,
+	.dma_supported = pci_direct_dma_supported,
+};
+
 void __init pci_direct_iommu_init(void)
 {
-	pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
-	pci_dma_ops.free_coherent = pci_direct_free_coherent;
-	pci_dma_ops.map_single = pci_direct_map_single;
-	pci_dma_ops.unmap_single = pci_direct_unmap_single;
-	pci_dma_ops.map_sg = pci_direct_map_sg;
-	pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
-	pci_dma_ops.dma_supported = pci_direct_dma_supported;
+	pci_dma_ops = pci_direct_ops;
 }
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 12c4c9e9bbc7..1c18953514c3 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -31,6 +31,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/ppc-pci.h>
+#include <asm/firmware.h>
 
 /*
  * Traverse_func that inits the PCI fields of the device node.
@@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
 		pdn->busno = (regs[0] >> 16) & 0xff;
 		pdn->devfn = (regs[0] >> 8) & 0xff;
 	}
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+		if (busp)
+			pdn->bussubno = *busp;
+	}
 
 	pdn->pci_ext_config_space = (type && *type == 1);
 	return NULL;
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c1d95e14bbed..0688b2534acb 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -44,16 +44,16 @@
  */
 #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
 
-static inline struct iommu_table *devnode_table(struct device *dev)
+static inline struct iommu_table *device_to_table(struct device *hwdev)
 {
 	struct pci_dev *pdev;
 
-	if (!dev) {
+	if (!hwdev) {
 		pdev = ppc64_isabridge_dev;
 		if (!pdev)
 			return NULL;
 	} else
-		pdev = to_pci_dev(dev);
+		pdev = to_pci_dev(hwdev);
 
 	return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
 }
@@ -85,14 +85,15 @@ static inline unsigned long device_to_mask(struct device *hwdev)
 static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
-	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
-			device_to_mask(hwdev), flag);
+	return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
+			device_to_mask(hwdev), flag,
+			pcibus_to_node(to_pci_dev(hwdev)->bus));
 }
 
 static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
+	iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be 
@@ -104,7 +105,7 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(devnode_table(hwdev), vaddr, size,
+	return iommu_map_single(device_to_table(hwdev), vaddr, size,
 			        device_to_mask(hwdev), direction);
 }
 
@@ -112,27 +113,27 @@ static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction)
 {
-	iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
+	iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
 }
 
 
 static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
+	return iommu_map_sg(pdev, device_to_table(pdev), sglist,
 			nelems, device_to_mask(pdev), direction);
 }
 
 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
+	iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
 }
 
 /* We support DMA to/from any memory page via the iommu */
 static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	struct iommu_table *tbl = devnode_table(dev);
+	struct iommu_table *tbl = device_to_table(dev);
 
 	if (!tbl || tbl->it_offset > mask) {
 		printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
@@ -147,13 +148,17 @@ static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 		return 1;
 }
 
+struct dma_mapping_ops pci_iommu_ops = {
+	.alloc_coherent = pci_iommu_alloc_coherent,
+	.free_coherent = pci_iommu_free_coherent,
+	.map_single = pci_iommu_map_single,
+	.unmap_single = pci_iommu_unmap_single,
+	.map_sg = pci_iommu_map_sg,
+	.unmap_sg = pci_iommu_unmap_sg,
+	.dma_supported = pci_iommu_dma_supported,
+};
+
 void pci_iommu_init(void)
 {
-	pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
-	pci_dma_ops.free_coherent = pci_iommu_free_coherent;
-	pci_dma_ops.map_single = pci_iommu_map_single;
-	pci_dma_ops.unmap_single = pci_iommu_unmap_single;
-	pci_dma_ops.map_sg = pci_iommu_map_sg;
-	pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
-	pci_dma_ops.dma_supported = pci_iommu_dma_supported;
+	pci_dma_ops = pci_iommu_ops;
 }
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 3c2cf661f6d9..2b87f82df135 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -52,7 +52,7 @@ static int __init proc_ppc64_create(void)
 	if (!root)
 		return 1;
 
-	if (!machine_is(pseries) && !machine_is(cell))
+	if (!of_find_node_by_path("/rtas"))
 		return 0;
 
 	if (!proc_mkdir("rtas", root))
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2dd47d2dd998..e4732459c485 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -708,6 +708,61 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
 	return put_user(val, (unsigned int __user *) adr);
 }
 
+int set_endian(struct task_struct *tsk, unsigned int val)
+{
+	struct pt_regs *regs = tsk->thread.regs;
+
+	if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) ||
+	    (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE)))
+		return -EINVAL;
+
+	if (regs == NULL)
+		return -EINVAL;
+
+	if (val == PR_ENDIAN_BIG)
+		regs->msr &= ~MSR_LE;
+	else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE)
+		regs->msr |= MSR_LE;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int get_endian(struct task_struct *tsk, unsigned long adr)
+{
+	struct pt_regs *regs = tsk->thread.regs;
+	unsigned int val;
+
+	if (!cpu_has_feature(CPU_FTR_PPC_LE) &&
+	    !cpu_has_feature(CPU_FTR_REAL_LE))
+		return -EINVAL;
+
+	if (regs == NULL)
+		return -EINVAL;
+
+	if (regs->msr & MSR_LE) {
+		if (cpu_has_feature(CPU_FTR_REAL_LE))
+			val = PR_ENDIAN_LITTLE;
+		else
+			val = PR_ENDIAN_PPC_LITTLE;
+	} else
+		val = PR_ENDIAN_BIG;
+
+	return put_user(val, (unsigned int __user *)adr);
+}
+
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+	tsk->thread.align_ctl = val;
+	return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+	return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
+}
+
 #define TRUNC_PTR(x)	((typeof(x))(((unsigned long)(x)) & 0xffffffff))
 
 int sys_clone(unsigned long clone_flags, unsigned long usp,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9a07f97f0712..483455c5bb02 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -50,6 +50,7 @@
 #include <asm/machdep.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
+#include <asm/kexec.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
 	return mem;
 }
 
+static int __init early_parse_mem(char *p)
+{
+	if (!p)
+		return 1;
+
+	memory_limit = PAGE_ALIGN(memparse(p, &p));
+	DBG("memory limit = 0x%lx\n", memory_limit);
+
+	return 0;
+}
+early_param("mem", early_parse_mem);
+
+/*
+ * The device tree may be allocated below our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out now.
+ */
+static void move_device_tree(void)
+{
+	unsigned long start, size;
+	void *p;
+
+	DBG("-> move_device_tree\n");
+
+	start = __pa(initial_boot_params);
+	size = initial_boot_params->totalsize;
+
+	if ((memory_limit && (start + size) > memory_limit) ||
+			overlaps_crashkernel(start, size)) {
+		p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
+		memcpy(p, initial_boot_params, size);
+		initial_boot_params = (struct boot_param_header *)p;
+		DBG("Moved device tree to 0x%p\n", p);
+	}
+
+	DBG("<- move_device_tree\n");
+}
 
 /**
  * unflattens the device-tree passed by the firmware, creating the
@@ -911,7 +948,10 @@ static struct ibm_pa_feature {
 	{CPU_FTR_CTRL, 0,		0, 3, 0},
 	{CPU_FTR_NOEXECUTE, 0,		0, 6, 0},
 	{CPU_FTR_NODSISRALIGN, 0,	1, 1, 1},
+#if 0
+	/* put this back once we know how to test if firmware does 64k IO */
 	{CPU_FTR_CI_LARGE_PAGE, 0,	1, 2, 0},
+#endif
 };
 
 static void __init check_cpu_pa_features(unsigned long node)
@@ -1070,6 +1110,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 		iommu_force_on = 1;
 #endif
 
+	/* mem=x on the command line is the preferred mechanism */
  	lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
  	if (lprop)
  		memory_limit = *lprop;
@@ -1123,17 +1164,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 
 	DBG("Command line is: %s\n", cmd_line);
 
-	if (strstr(cmd_line, "mem=")) {
-		char *p, *q;
-
-		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
-			q = p + 4;
-			if (p > cmd_line && p[-1] != ' ')
-				continue;
-			memory_limit = memparse(q, &q);
-		}
-	}
-
 	/* break now */
 	return 1;
 }
@@ -1237,9 +1267,17 @@ static void __init early_reserve_mem(void)
 {
 	u64 base, size;
 	u64 *reserve_map;
+	unsigned long self_base;
+	unsigned long self_size;
 
 	reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
 					initial_boot_params->off_mem_rsvmap);
+
+	/* before we do anything, lets reserve the dt blob */
+	self_base = __pa((unsigned long)initial_boot_params);
+	self_size = initial_boot_params->totalsize;
+	lmb_reserve(self_base, self_size);
+
 #ifdef CONFIG_PPC32
 	/* 
 	 * Handle the case where we might be booting from an old kexec
@@ -1254,6 +1292,9 @@ static void __init early_reserve_mem(void)
 			size_32 = *(reserve_map_32++);
 			if (size_32 == 0)
 				break;
+			/* skip if the reservation is for the blob */
+			if (base_32 == self_base && size_32 == self_size)
+				continue;
 			DBG("reserving: %x -> %x\n", base_32, size_32);
 			lmb_reserve(base_32, size_32);
 		}
@@ -1265,6 +1306,9 @@ static void __init early_reserve_mem(void)
 		size = *(reserve_map++);
 		if (size == 0)
 			break;
+		/* skip if the reservation is for the blob */
+		if (base == self_base && size == self_size)
+			continue;
 		DBG("reserving: %llx -> %llx\n", base, size);
 		lmb_reserve(base, size);
 	}
@@ -1292,18 +1336,26 @@ void __init early_init_devtree(void *params)
 	lmb_init();
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-	lmb_enforce_memory_limit(memory_limit);
-	lmb_analyze();
 
-	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
+	/* Save command line for /proc/cmdline and then parse parameters */
+	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	parse_early_param();
 
 	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
 	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
-#ifdef CONFIG_CRASH_DUMP
-	lmb_reserve(0, KDUMP_RESERVE_LIMIT);
-#endif
+	reserve_kdump_trampoline();
+	reserve_crashkernel();
 	early_reserve_mem();
 
+	lmb_enforce_memory_limit(memory_limit);
+	lmb_analyze();
+
+	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
+
+	/* We may need to relocate the flat tree, do it now.
+	 * FIXME .. and the initrd too? */
+	move_device_tree();
+
 	DBG("Scanning CPUs ...\n");
 
 	/* Retreive CPU related informations from the flat tree
@@ -2053,29 +2105,46 @@ int prom_update_property(struct device_node *np,
 	return 0;
 }
 
-#ifdef CONFIG_KEXEC
-/* We may have allocated the flat device tree inside the crash kernel region
- * in prom_init. If so we need to move it out into regular memory. */
-void kdump_move_device_tree(void)
-{
-	unsigned long start, end;
-	struct boot_param_header *new;
-
-	start = __pa((unsigned long)initial_boot_params);
-	end = start + initial_boot_params->totalsize;
-
-	if (end < crashk_res.start || start > crashk_res.end)
-		return;
 
-	new = (struct boot_param_header*)
-		__va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
-
-	memcpy(new, initial_boot_params, initial_boot_params->totalsize);
+/* Find the device node for a given logical cpu number, also returns the cpu
+ * local thread number (index in ibm,interrupt-server#s) if relevant and
+ * asked for (non NULL)
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
+{
+	int hardid;
+	struct device_node *np;
 
-	initial_boot_params = new;
+	hardid = get_hard_smp_processor_id(cpu);
 
-	DBG("Flat device tree blob moved to %p\n", initial_boot_params);
+	for_each_node_by_type(np, "cpu") {
+		u32 *intserv;
+		unsigned int plen, t;
 
-	/* XXX should we unreserve the old DT? */
+		/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
+		 * fallback to "reg" property and assume no threads
+		 */
+		intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
+					      &plen);
+		if (intserv == NULL) {
+			u32 *reg = (u32 *)get_property(np, "reg", NULL);
+			if (reg == NULL)
+				continue;
+			if (*reg == hardid) {
+				if (thread)
+					*thread = 0;
+				return np;
+			}
+		} else {
+			plen /= sizeof(u32);
+			for (t = 0; t < plen; t++) {
+				if (hardid == intserv[t]) {
+					if (thread)
+						*thread = t;
+					return np;
+				}
+			}
+		}
+	}
+	return NULL;
 }
-#endif /* CONFIG_KEXEC */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f70bd090dacd..8c28eb0cbdac 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -194,19 +194,12 @@ static int __initdata of_platform;
 
 static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
 
-static unsigned long __initdata prom_memory_limit;
-
 static unsigned long __initdata alloc_top;
 static unsigned long __initdata alloc_top_high;
 static unsigned long __initdata alloc_bottom;
 static unsigned long __initdata rmo_top;
 static unsigned long __initdata ram_top;
 
-#ifdef CONFIG_KEXEC
-static unsigned long __initdata prom_crashk_base;
-static unsigned long __initdata prom_crashk_size;
-#endif
-
 static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
 static int __initdata mem_reserve_cnt;
 
@@ -574,7 +567,7 @@ static void __init early_cmdline_parse(void)
 	if ((long)_prom->chosen > 0)
 		l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
 #ifdef CONFIG_CMDLINE
-	if (l == 0) /* dbl check */
+	if (l <= 0 || p[0] == '\0') /* dbl check */
 		strlcpy(RELOC(prom_cmd_line),
 			RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
 #endif /* CONFIG_CMDLINE */
@@ -593,45 +586,6 @@ static void __init early_cmdline_parse(void)
 			RELOC(iommu_force_on) = 1;
 	}
 #endif
-
-	opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
-	if (opt) {
-		opt += 4;
-		RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
-#ifdef CONFIG_PPC64
-		/* Align to 16 MB == size of ppc64 large page */
-		RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
-#endif
-	}
-
-#ifdef CONFIG_KEXEC
-	/*
-	 * crashkernel=size@addr specifies the location to reserve for
-	 * crash kernel.
-	 */
-	opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
-	if (opt) {
-		opt += 12;
-		RELOC(prom_crashk_size) = 
-			prom_memparse(opt, (const char **)&opt);
-
-		if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
-			RELOC(prom_crashk_size)) {
-			prom_printf("Warning: crashkernel size is not "
-					"aligned to 16MB\n");
-		}
-
-		/*
-		 * At present, the crash kernel always run at 32MB.
-		 * Just ignore whatever user passed.
-		 */
-		RELOC(prom_crashk_base) = 0x2000000;
-		if (*opt == '@') {
-			prom_printf("Warning: PPC64 kdump kernel always runs "
-					"at 32 MB\n");
-		}
-	}
-#endif
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -1116,29 +1070,6 @@ static void __init prom_init_mem(void)
 	}
 
 	/*
-	 * If prom_memory_limit is set we reduce the upper limits *except* for
-	 * alloc_top_high. This must be the real top of RAM so we can put
-	 * TCE's up there.
-	 */
-
-	RELOC(alloc_top_high) = RELOC(ram_top);
-
-	if (RELOC(prom_memory_limit)) {
-		if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
-			prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
-				RELOC(prom_memory_limit));
-			RELOC(prom_memory_limit) = 0;
-		} else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
-			prom_printf("Ignoring mem=%x >= ram_top.\n",
-				RELOC(prom_memory_limit));
-			RELOC(prom_memory_limit) = 0;
-		} else {
-			RELOC(ram_top) = RELOC(prom_memory_limit);
-			RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
-		}
-	}
-
-	/*
 	 * Setup our top alloc point, that is top of RMO or top of
 	 * segment 0 when running non-LPAR.
 	 * Some RS64 machines have buggy firmware where claims up at
@@ -1150,20 +1081,14 @@ static void __init prom_init_mem(void)
 		RELOC(rmo_top) = RELOC(ram_top);
 	RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
 	RELOC(alloc_top) = RELOC(rmo_top);
+	RELOC(alloc_top_high) = RELOC(ram_top);
 
 	prom_printf("memory layout at init:\n");
-	prom_printf("  memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
 	prom_printf("  alloc_bottom : %x\n", RELOC(alloc_bottom));
 	prom_printf("  alloc_top    : %x\n", RELOC(alloc_top));
 	prom_printf("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
 	prom_printf("  rmo_top      : %x\n", RELOC(rmo_top));
 	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base)) {
-		prom_printf("  crashk_base  : %x\n",  RELOC(prom_crashk_base));
-		prom_printf("  crashk_size  : %x\n", RELOC(prom_crashk_size));
-	}
-#endif
 }
 
 
@@ -1349,16 +1274,10 @@ static void __init prom_initialize_tce_table(void)
 
 	reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
 
-	if (RELOC(prom_memory_limit)) {
-		/*
-		 * We align the start to a 16MB boundary so we can map
-		 * the TCE area using large pages if possible.
-		 * The end should be the top of RAM so no need to align it.
-		 */
-		RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
-							  0x1000000);
-		RELOC(prom_tce_alloc_end) = local_alloc_top;
-	}
+	/* These are only really needed if there is a memory limit in
+	 * effect, but we don't know so export them always. */
+	RELOC(prom_tce_alloc_start) = local_alloc_bottom;
+	RELOC(prom_tce_alloc_end) = local_alloc_top;
 
 	/* Flag the first invalid entry */
 	prom_debug("ending prom_initialize_tce_table\n");
@@ -2041,11 +1960,7 @@ static void __init flatten_device_tree(void)
 	/* Version 16 is not backward compatible */
 	hdr->last_comp_version = 0x10;
 
-	/* Reserve the whole thing and copy the reserve map in, we
-	 * also bump mem_reserve_cnt to cause further reservations to
-	 * fail since it's too late.
-	 */
-	reserve_mem(RELOC(dt_header_start), hdr->totalsize);
+	/* Copy the reserve map in */
 	memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
 
 #ifdef DEBUG_PROM
@@ -2058,6 +1973,9 @@ static void __init flatten_device_tree(void)
 				    RELOC(mem_reserve_map)[i].size);
 	}
 #endif
+	/* Bump mem_reserve_cnt to cause further reservations to fail
+	 * since it's too late.
+	 */
 	RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
 
 	prom_printf("Device tree strings 0x%x -> 0x%x\n",
@@ -2280,10 +2198,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 	 */
 	prom_init_mem();
 
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base))
-		reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
-#endif
 	/*
 	 * Determine which cpu is actually running right _now_
 	 */
@@ -2317,10 +2231,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 	/*
 	 * Fill in some infos for use by the kernel later on
 	 */
-	if (RELOC(prom_memory_limit))
-		prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
-			     &RELOC(prom_memory_limit),
-			     sizeof(prom_memory_limit));
 #ifdef CONFIG_PPC64
 	if (RELOC(ppc64_iommu_off))
 		prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
@@ -2340,16 +2250,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 	}
 #endif
 
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base)) {
-		prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
-			PTRRELOC(&prom_crashk_base),
-			sizeof(RELOC(prom_crashk_base)));
-		prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
-			PTRRELOC(&prom_crashk_size),
-			sizeof(RELOC(prom_crashk_size)));
-	}
-#endif
 	/*
 	 * Fixup any known bugs in the device-tree
 	 */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 3934c227549b..45df420383cc 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -548,3 +548,28 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
 	return __of_address_to_resource(dev, addrp, size, flags, r);
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
+		unsigned long *busno, unsigned long *phys, unsigned long *size)
+{
+	u32 *dma_window, cells;
+	unsigned char *prop;
+
+	dma_window = (u32 *)dma_window_prop;
+
+	/* busno is always one cell */
+	*busno = *(dma_window++);
+
+	prop = get_property(dn, "ibm,#dma-address-cells", NULL);
+	if (!prop)
+		prop = get_property(dn, "#address-cells", NULL);
+
+	cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn);
+	*phys = of_read_addr(dma_window, cells);
+
+	dma_window += cells;
+
+	prop = get_property(dn, "ibm,#dma-size-cells", NULL);
+	cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
+	*size = of_read_addr(dma_window, cells);
+}
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 4a677d1bd4ef..5563e2e7d89c 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -404,7 +404,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		ret = ptrace_detach(child, data);
 		break;
 
-#ifdef CONFIG_PPC64
 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
 		int i;
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
@@ -468,7 +467,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		}
 		break;
 	}
-#endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_ALTIVEC
 	case PTRACE_GETVRREGS:
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 34d073fb6091..77578c093dda 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -14,19 +14,20 @@
 unsigned long __init rtas_get_boot_time(void)
 {
 	int ret[8];
-	int error, wait_time;
+	int error;
+	unsigned int wait_time;
 	u64 max_wait_tb;
 
 	max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
 	do {
 		error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
-			wait_time = rtas_extended_busy_delay_time(error);
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			/* This is boot time so we spin. */
 			udelay(wait_time*1000);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
 	if (error != 0 && printk_ratelimit()) {
 		printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time(void)
 void rtas_get_rtc_time(struct rtc_time *rtc_tm)
 {
         int ret[8];
-	int error, wait_time;
+	int error;
+	unsigned int wait_time;
 	u64 max_wait_tb;
 
 	max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
 	do {
 		error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			if (in_interrupt() && printk_ratelimit()) {
 				memset(rtc_tm, 0, sizeof(struct rtc_time));
 				printk(KERN_WARNING "error: reading clock"
 				       " would delay interrupt\n");
 				return;	/* delay not allowed */
 			}
-			wait_time = rtas_extended_busy_delay_time(error);
 			msleep(wait_time);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
         if (error != 0 && printk_ratelimit()) {
                 printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *tm)
 				  tm->tm_year + 1900, tm->tm_mon + 1,
 				  tm->tm_mday, tm->tm_hour, tm->tm_min,
 				  tm->tm_sec, 0);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			if (in_interrupt())
 				return 1;	/* probably decrementer */
-			wait_time = rtas_extended_busy_delay_time(error);
 			msleep(wait_time);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
         if (error != 0 && printk_ratelimit())
                 printk(KERN_WARNING "error: setting the clock failed (%d)\n",
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 0112318213ab..17dc79198515 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -370,24 +370,36 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
 	return ret;
 }
 
-/* Given an RTAS status code of 990n compute the hinted delay of 10^n
- * (last digit) milliseconds.  For now we bound at n=5 (100 sec).
+/* For RTAS_BUSY (-2), delay for 1 millisecond.  For an extended busy status
+ * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
  */
-unsigned int rtas_extended_busy_delay_time(int status)
+unsigned int rtas_busy_delay_time(int status)
 {
-	int order = status - 9900;
-	unsigned long ms;
+	int order;
+	unsigned int ms = 0;
+
+	if (status == RTAS_BUSY) {
+		ms = 1;
+	} else if (status >= 9900 && status <= 9905) {
+		order = status - 9900;
+		for (ms = 1; order > 0; order--)
+			ms *= 10;
+	}
 
-	if (order < 0)
-		order = 0;	/* RTC depends on this for -2 clock busy */
-	else if (order > 5)
-		order = 5;	/* bound */
+	return ms;
+}
 
-	/* Use microseconds for reasonable accuracy */
-	for (ms = 1; order > 0; order--)
-		ms *= 10;
+/* For an RTAS busy status code, perform the hinted delay. */
+unsigned int rtas_busy_delay(int status)
+{
+	unsigned int ms;
 
-	return ms; 
+	might_sleep();
+	ms = rtas_busy_delay_time(status);
+	if (ms)
+		msleep(ms);
+
+	return ms;
 }
 
 int rtas_error_rc(int rtas_rc)
@@ -438,22 +450,14 @@ int rtas_get_power_level(int powerdomain, int *level)
 int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
 	int token = rtas_token("set-power-level");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -463,22 +467,14 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 int rtas_get_sensor(int sensor, int index, int *state)
 {
 	int token = rtas_token("get-sensor-state");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 2, 2, state, sensor, index);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -488,23 +484,14 @@ int rtas_get_sensor(int sensor, int index, int *state)
 int rtas_set_indicator(int indicator, int index, int new_value)
 {
 	int token = rtas_token("set-indicator");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		}
-		else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -555,13 +542,11 @@ void rtas_os_term(char *str)
 	do {
 		status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
 				   __pa(rtas_os_term_buf));
+	} while (rtas_busy_delay(status));
 
-		if (status == RTAS_BUSY)
-			udelay(1);
-		else if (status != 0)
-			printk(KERN_EMERG "ibm,os-term call failed %d\n",
+	if (status != 0)
+		printk(KERN_EMERG "ibm,os-term call failed %d\n",
 			       status);
-	} while (status == RTAS_BUSY);
 }
 
 static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
@@ -608,9 +593,31 @@ out:
 static int rtas_ibm_suspend_me(struct rtas_args *args)
 {
 	int i;
+	long state;
+	long rc;
+	unsigned long dummy;
 
 	struct rtas_suspend_me_data data;
 
+	/* Make sure the state is valid */
+	rc = plpar_hcall(H_VASI_STATE,
+			 ((u64)args->args[0] << 32) | args->args[1],
+			 0, 0, 0,
+			 &state, &dummy, &dummy);
+
+	if (rc) {
+		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
+		return rc;
+	} else if (state == H_VASI_ENABLED) {
+		args->args[args->nargs] = RTAS_NOT_SUSPENDABLE;
+		return 0;
+	} else if (state != H_VASI_SUSPENDING) {
+		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
+		       state);
+		args->args[args->nargs] = -1;
+		return 0;
+	}
+
 	data.waiting = 1;
 	data.args = args;
 
@@ -789,7 +796,8 @@ EXPORT_SYMBOL(rtas_token);
 EXPORT_SYMBOL(rtas_call);
 EXPORT_SYMBOL(rtas_data_buf);
 EXPORT_SYMBOL(rtas_data_buf_lock);
-EXPORT_SYMBOL(rtas_extended_busy_delay_time);
+EXPORT_SYMBOL(rtas_busy_delay_time);
+EXPORT_SYMBOL(rtas_busy_delay);
 EXPORT_SYMBOL(rtas_get_sensor);
 EXPORT_SYMBOL(rtas_get_power_level);
 EXPORT_SYMBOL(rtas_set_power_level);
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index aaf384c3f04a..1442b63a75da 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -365,20 +365,12 @@ static int rtas_excl_release(struct inode *inode, struct file *file)
 
 static void manage_flash(struct rtas_manage_flash_t *args_buf)
 {
-	unsigned int wait_time;
 	s32 rc;
 
-	while (1) {
+	do {
 		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 
 			       1, NULL, args_buf->op);
-		if (rc == RTAS_RC_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	args_buf->status = rc;
 }
@@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
 static void validate_flash(struct rtas_validate_flash_t *args_buf)
 {
 	int token = rtas_token("ibm,validate-flash-image");
-	unsigned int wait_time;
 	int update_results;
 	s32 rc;	
 
 	rc = 0;
-	while(1) {
+	do {
 		spin_lock(&rtas_data_buf_lock);
 		memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE);
 		rc = rtas_call(token, 2, 2, &update_results, 
 			       (u32) __pa(rtas_data_buf), args_buf->buf_size);
 		memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE);
 		spin_unlock(&rtas_data_buf_lock);
-			
-		if (rc == RTAS_RC_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	args_buf->status = rc;
 	args_buf->update_results = update_results;
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 57b539a03fa9..6eb7e49b394a 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -313,7 +313,9 @@ unsigned long __init find_and_init_phbs(void)
 	for (node = of_get_next_child(root, NULL);
 	     node != NULL;
 	     node = of_get_next_child(root, node)) {
-		if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+		if (node->type == NULL || (strcmp(node->type, "pci") != 0 &&
+					   strcmp(node->type, "pciex") != 0))
 			continue;
 
 		phb = pcibios_alloc_controller(node);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 684ab1d49c65..bd328123af75 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -443,6 +443,7 @@ void __init smp_setup_cpu_maps(void)
 }
 #endif /* CONFIG_SMP */
 
+int __initdata do_early_xmon;
 #ifdef CONFIG_XMON
 static int __init early_xmon(char *p)
 {
@@ -456,7 +457,7 @@ static int __init early_xmon(char *p)
 			return 0;
 	}
 	xmon_init(1);
-	debugger(NULL);
+	do_early_xmon = 1;
 
 	return 0;
 }
@@ -524,3 +525,20 @@ int check_legacy_ioport(unsigned long base_port)
 	return ppc_md.check_legacy_ioport(base_port);
 }
 EXPORT_SYMBOL(check_legacy_ioport);
+
+static int ppc_panic_event(struct notifier_block *this,
+                             unsigned long event, void *ptr)
+{
+	ppc_md.panic(ptr);  /* May not return */
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_panic_block = {
+	.notifier_call = ppc_panic_event,
+	.priority = INT_MIN /* may not return; must be done last */
+};
+
+void __init setup_panic(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
+}
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
index 2ebba755272e..4c67ad7fae08 100644
--- a/arch/powerpc/kernel/setup.h
+++ b/arch/powerpc/kernel/setup.h
@@ -2,5 +2,8 @@
 #define _POWERPC_KERNEL_SETUP_H
 
 void check_for_initrd(void);
+void do_init_bootmem(void);
+void setup_panic(void);
+extern int do_early_xmon;
 
 #endif /* _POWERPC_KERNEL_SETUP_H */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 69ac25701344..e5a44812441a 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -131,12 +131,6 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys)
 	/* Do some early initialization based on the flat device tree */
 	early_init_devtree(__va(dt_ptr));
 
-	/* Check default command line */
-#ifdef CONFIG_CMDLINE
-	if (cmd_line[0] == 0)
-		strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
 	probe_machine();
 
 #ifdef CONFIG_6xx
@@ -235,7 +229,7 @@ arch_initcall(ppc_init);
 /* Warning, IO base is not yet inited */
 void __init setup_arch(char **cmdline_p)
 {
-	extern void do_init_bootmem(void);
+	*cmdline_p = cmd_line;
 
 	/* so udelay does something sensible, assume <= 1000 bogomips */
 	loops_per_jiffy = 500000000 / HZ;
@@ -285,16 +279,16 @@ void __init setup_arch(char **cmdline_p)
 	/* reboot on panic */
 	panic_timeout = 180;
 
+	if (ppc_md.panic)
+		setup_panic();
+
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = klimit;
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-	*cmdline_p = cmd_line;
-
-	parse_early_param();
+	if (do_early_xmon)
+		debugger(NULL);
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4467c49903b6..78f3a5fd43f6 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -100,12 +100,6 @@ unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
 
 
-static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-static struct notifier_block ppc64_panic_block = {
-	.notifier_call = ppc64_panic_event,
-	.priority = INT_MIN /* may not return; must be done last */
-};
-
 #ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
@@ -199,9 +193,7 @@ void __init early_setup(unsigned long dt_ptr)
 	/* Probe the machine type */
 	probe_machine();
 
-#ifdef CONFIG_CRASH_DUMP
-	kdump_setup();
-#endif
+	setup_kdump_trampoline();
 
 	DBG("Found, Initializing memory management...\n");
 
@@ -353,9 +345,6 @@ void __init setup_system(void)
 {
 	DBG(" -> setup_system()\n");
 
-#ifdef CONFIG_KEXEC
-	kdump_move_device_tree();
-#endif
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
@@ -420,10 +409,8 @@ void __init setup_system(void)
 	 */
 	register_early_udbg_console();
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-	parse_early_param();
+	if (do_early_xmon)
+		debugger(NULL);
 
 	check_smt_enabled();
 	smp_setup_cpu_maps();
@@ -456,13 +443,6 @@ void __init setup_system(void)
 	DBG(" <- setup_system()\n");
 }
 
-static int ppc64_panic_event(struct notifier_block *this,
-                             unsigned long event, void *ptr)
-{
-	ppc_md.panic((char *)ptr);  /* May not return */
-	return NOTIFY_DONE;
-}
-
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
@@ -517,8 +497,6 @@ static void __init emergency_stack_init(void)
  */
 void __init setup_arch(char **cmdline_p)
 {
-	extern void do_init_bootmem(void);
-
 	ppc64_boot_msg(0x12, "Setup Arch");
 
 	*cmdline_p = cmd_line;
@@ -535,8 +513,7 @@ void __init setup_arch(char **cmdline_p)
 	panic_timeout = 180;
 
 	if (ppc_md.panic)
-		atomic_notifier_chain_register(&panic_notifier_list,
-				&ppc64_panic_block);
+		setup_panic();
 
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 8fdeca2d4597..d73b25e22fca 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_regs *regs,
 {
 	long err;
 	unsigned int save_r2 = 0;
-#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
 	unsigned long msr;
-#endif
 
 	/*
 	 * restore general registers but not including MSR or SOFTE. Also
@@ -430,11 +428,16 @@ static long restore_user_regs(struct pt_regs *regs,
 	if (!sig)
 		save_r2 = (unsigned int)regs->gpr[2];
 	err = restore_general_regs(regs, sr);
+	err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
 	if (!sig)
 		regs->gpr[2] = (unsigned long) save_r2;
 	if (err)
 		return 1;
 
+	/* if doing signal return, restore the previous little-endian mode */
+	if (sig)
+		regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
 	/*
 	 * Do this before updating the thread state in
 	 * current->thread.fpr/vr/evr.  That way, if we get preempted
@@ -455,7 +458,7 @@ static long restore_user_regs(struct pt_regs *regs,
 	/* force the process to reload the altivec registers from
 	   current->thread when it next does altivec instructions */
 	regs->msr &= ~MSR_VEC;
-	if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+	if (msr & MSR_VEC) {
 		/* restore altivec registers from the stack */
 		if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
 				     sizeof(sr->mc_vregs)))
@@ -472,7 +475,7 @@ static long restore_user_regs(struct pt_regs *regs,
 	/* force the process to reload the spe registers from
 	   current->thread when it next does spe instructions */
 	regs->msr &= ~MSR_SPE;
-	if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+	if (msr & MSR_SPE) {
 		/* restore spe registers from the stack */
 		if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
 				     ELF_NEVRREG * sizeof(u32)))
@@ -757,10 +760,10 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
 
 	/* Save user registers on the stack */
 	frame = &rt_sf->uc.uc_mcontext;
-	if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+	if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
 		if (save_user_regs(regs, frame, 0))
 			goto badframe;
-		regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+		regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
 	} else {
 		if (save_user_regs(regs, frame, __NR_rt_sigreturn))
 			goto badframe;
@@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
 	regs->gpr[5] = (unsigned long) &rt_sf->uc;
 	regs->gpr[6] = (unsigned long) rt_sf;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->trap = 0;
 	return 1;
 
@@ -1038,10 +1043,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
-	if (vdso32_sigtramp && current->thread.vdso_base) {
+	if (vdso32_sigtramp && current->mm->context.vdso_base) {
 		if (save_user_regs(regs, &frame->mctx, 0))
 			goto badframe;
-		regs->link = current->thread.vdso_base + vdso32_sigtramp;
+		regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
 	} else {
 		if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
 			goto badframe;
@@ -1056,6 +1061,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) sc;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->trap = 0;
 
 	return 1;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index c2db642f4cdd..6e75d7ab6d4d 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -141,9 +141,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 	unsigned long err = 0;
 	unsigned long save_r13 = 0;
 	elf_greg_t *gregs = (elf_greg_t *)regs;
-#ifdef CONFIG_ALTIVEC
 	unsigned long msr;
-#endif
 	int i;
 
 	/* If this is not a signal return, we preserve the TLS in r13 */
@@ -154,7 +152,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 	err |= __copy_from_user(regs, &sc->gp_regs,
 				PT_MSR*sizeof(unsigned long));
 
-	/* skip MSR and SOFTE */
+	/* get MSR separately, transfer the LE bit if doing signal return */
+	err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+	if (sig)
+		regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
+	/* skip SOFTE */
 	for (i = PT_MSR+1; i <= PT_RESULT; i++) {
 		if (i == PT_SOFTE)
 			continue;
@@ -179,7 +182,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 
 #ifdef CONFIG_ALTIVEC
 	err |= __get_user(v_regs, &sc->v_regs);
-	err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
 	if (err)
 		return err;
 	if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
@@ -396,8 +398,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
 	current->thread.fpscr.val = 0;
 
 	/* Set up to return from userspace. */
-	if (vdso64_rt_sigtramp && current->thread.vdso_base) {
-		regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+	if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
+		regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
 	} else {
 		err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
 		if (err)
@@ -412,6 +414,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
 
 	/* Set up "regs" so we "return" to the signal handler. */
 	err |= get_user(regs->nip, &funct_desc_ptr->entry);
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->gpr[1] = newsp;
 	err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
 	regs->gpr[3] = signr;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 530f7dba0bd2..c5d179d4f818 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -492,7 +492,7 @@ int __devinit __cpu_up(unsigned int cpu)
 	 * -- Cort
 	 */
 	if (system_state < SYSTEM_RUNNING)
-		for (c = 5000; c && !cpu_callin_map[cpu]; c--)
+		for (c = 50000; c && !cpu_callin_map[cpu]; c--)
 			udelay(100);
 #ifdef CONFIG_HOTPLUG_CPU
 	else
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 26ed1f5ef16e..ee75ccf1a802 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -32,6 +32,10 @@
 #define SYS32ONLY(func)		.long	sys_##func
 #define SYSX(f, f3264, f32)	.long	f32
 #endif
+#define SYSCALL_SPU(func)	SYSCALL(func)
+#define COMPAT_SYS_SPU(func)	COMPAT_SYS(func)
+#define PPC_SYS_SPU(func)	PPC_SYS(func)
+#define SYSX_SPU(f, f3264, f32)	SYSX(f, f3264, f32)
 
 #ifdef CONFIG_PPC64
 #define sys_sigpending	sys_ni_syscall
@@ -39,309 +43,4 @@
 #endif
 
 _GLOBAL(sys_call_table)
-SYSCALL(restart_syscall)
-SYSCALL(exit)
-PPC_SYS(fork)
-SYSCALL(read)
-SYSCALL(write)
-COMPAT_SYS(open)
-SYSCALL(close)
-COMPAT_SYS(waitpid)
-COMPAT_SYS(creat)
-SYSCALL(link)
-SYSCALL(unlink)
-COMPAT_SYS(execve)
-SYSCALL(chdir)
-COMPAT_SYS(time)
-SYSCALL(mknod)
-SYSCALL(chmod)
-SYSCALL(lchown)
-SYSCALL(ni_syscall)
-OLDSYS(stat)
-SYSX(sys_lseek,ppc32_lseek,sys_lseek)
-SYSCALL(getpid)
-COMPAT_SYS(mount)
-SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
-SYSCALL(setuid)
-SYSCALL(getuid)
-COMPAT_SYS(stime)
-COMPAT_SYS(ptrace)
-SYSCALL(alarm)
-OLDSYS(fstat)
-COMPAT_SYS(pause)
-COMPAT_SYS(utime)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(access)
-COMPAT_SYS(nice)
-SYSCALL(ni_syscall)
-SYSCALL(sync)
-COMPAT_SYS(kill)
-SYSCALL(rename)
-COMPAT_SYS(mkdir)
-SYSCALL(rmdir)
-SYSCALL(dup)
-SYSCALL(pipe)
-COMPAT_SYS(times)
-SYSCALL(ni_syscall)
-SYSCALL(brk)
-SYSCALL(setgid)
-SYSCALL(getgid)
-SYSCALL(signal)
-SYSCALL(geteuid)
-SYSCALL(getegid)
-SYSCALL(acct)
-SYSCALL(umount)
-SYSCALL(ni_syscall)
-COMPAT_SYS(ioctl)
-COMPAT_SYS(fcntl)
-SYSCALL(ni_syscall)
-COMPAT_SYS(setpgid)
-SYSCALL(ni_syscall)
-SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
-COMPAT_SYS(umask)
-SYSCALL(chroot)
-SYSCALL(ustat)
-SYSCALL(dup2)
-SYSCALL(getppid)
-SYSCALL(getpgrp)
-SYSCALL(setsid)
-SYS32ONLY(sigaction)
-SYSCALL(sgetmask)
-COMPAT_SYS(ssetmask)
-SYSCALL(setreuid)
-SYSCALL(setregid)
-SYS32ONLY(sigsuspend)
-COMPAT_SYS(sigpending)
-COMPAT_SYS(sethostname)
-COMPAT_SYS(setrlimit)
-COMPAT_SYS(old_getrlimit)
-COMPAT_SYS(getrusage)
-COMPAT_SYS(gettimeofday)
-COMPAT_SYS(settimeofday)
-COMPAT_SYS(getgroups)
-COMPAT_SYS(setgroups)
-SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
-SYSCALL(symlink)
-OLDSYS(lstat)
-COMPAT_SYS(readlink)
-SYSCALL(uselib)
-SYSCALL(swapon)
-SYSCALL(reboot)
-SYSX(sys_ni_syscall,old32_readdir,old_readdir)
-SYSCALL(mmap)
-SYSCALL(munmap)
-SYSCALL(truncate)
-SYSCALL(ftruncate)
-SYSCALL(fchmod)
-SYSCALL(fchown)
-COMPAT_SYS(getpriority)
-COMPAT_SYS(setpriority)
-SYSCALL(ni_syscall)
-COMPAT_SYS(statfs)
-COMPAT_SYS(fstatfs)
-SYSCALL(ni_syscall)
-COMPAT_SYS(socketcall)
-COMPAT_SYS(syslog)
-COMPAT_SYS(setitimer)
-COMPAT_SYS(getitimer)
-COMPAT_SYS(newstat)
-COMPAT_SYS(newlstat)
-COMPAT_SYS(newfstat)
-SYSX(sys_ni_syscall,sys_uname,sys_uname)
-SYSCALL(ni_syscall)
-SYSCALL(vhangup)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(wait4)
-SYSCALL(swapoff)
-COMPAT_SYS(sysinfo)
-COMPAT_SYS(ipc)
-SYSCALL(fsync)
-SYS32ONLY(sigreturn)
-PPC_SYS(clone)
-COMPAT_SYS(setdomainname)
-PPC_SYS(newuname)
-SYSCALL(ni_syscall)
-COMPAT_SYS(adjtimex)
-SYSCALL(mprotect)
-SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
-SYSCALL(ni_syscall)
-SYSCALL(init_module)
-SYSCALL(delete_module)
-SYSCALL(ni_syscall)
-SYSCALL(quotactl)
-COMPAT_SYS(getpgid)
-SYSCALL(fchdir)
-SYSCALL(bdflush)
-COMPAT_SYS(sysfs)
-SYSX(ppc64_personality,ppc64_personality,sys_personality)
-SYSCALL(ni_syscall)
-SYSCALL(setfsuid)
-SYSCALL(setfsgid)
-SYSCALL(llseek)
-COMPAT_SYS(getdents)
-SYSX(sys_select,ppc32_select,ppc_select)
-SYSCALL(flock)
-SYSCALL(msync)
-COMPAT_SYS(readv)
-COMPAT_SYS(writev)
-COMPAT_SYS(getsid)
-SYSCALL(fdatasync)
-COMPAT_SYS(sysctl)
-SYSCALL(mlock)
-SYSCALL(munlock)
-SYSCALL(mlockall)
-SYSCALL(munlockall)
-COMPAT_SYS(sched_setparam)
-COMPAT_SYS(sched_getparam)
-COMPAT_SYS(sched_setscheduler)
-COMPAT_SYS(sched_getscheduler)
-SYSCALL(sched_yield)
-COMPAT_SYS(sched_get_priority_max)
-COMPAT_SYS(sched_get_priority_min)
-COMPAT_SYS(sched_rr_get_interval)
-COMPAT_SYS(nanosleep)
-SYSCALL(mremap)
-SYSCALL(setresuid)
-SYSCALL(getresuid)
-SYSCALL(ni_syscall)
-SYSCALL(poll)
-COMPAT_SYS(nfsservctl)
-SYSCALL(setresgid)
-SYSCALL(getresgid)
-COMPAT_SYS(prctl)
-COMPAT_SYS(rt_sigreturn)
-COMPAT_SYS(rt_sigaction)
-COMPAT_SYS(rt_sigprocmask)
-COMPAT_SYS(rt_sigpending)
-COMPAT_SYS(rt_sigtimedwait)
-COMPAT_SYS(rt_sigqueueinfo)
-COMPAT_SYS(rt_sigsuspend)
-COMPAT_SYS(pread64)
-COMPAT_SYS(pwrite64)
-SYSCALL(chown)
-SYSCALL(getcwd)
-SYSCALL(capget)
-SYSCALL(capset)
-COMPAT_SYS(sigaltstack)
-SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-PPC_SYS(vfork)
-COMPAT_SYS(getrlimit)
-COMPAT_SYS(readahead)
-SYS32ONLY(mmap2)
-SYS32ONLY(truncate64)
-SYS32ONLY(ftruncate64)
-SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
-SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
-SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
-SYSCALL(pciconfig_read)
-SYSCALL(pciconfig_write)
-SYSCALL(pciconfig_iobase)
-SYSCALL(ni_syscall)
-SYSCALL(getdents64)
-SYSCALL(pivot_root)
-SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
-SYSCALL(madvise)
-SYSCALL(mincore)
-SYSCALL(gettid)
-SYSCALL(tkill)
-SYSCALL(setxattr)
-SYSCALL(lsetxattr)
-SYSCALL(fsetxattr)
-SYSCALL(getxattr)
-SYSCALL(lgetxattr)
-SYSCALL(fgetxattr)
-SYSCALL(listxattr)
-SYSCALL(llistxattr)
-SYSCALL(flistxattr)
-SYSCALL(removexattr)
-SYSCALL(lremovexattr)
-SYSCALL(fremovexattr)
-COMPAT_SYS(futex)
-COMPAT_SYS(sched_setaffinity)
-COMPAT_SYS(sched_getaffinity)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-SYS32ONLY(sendfile64)
-COMPAT_SYS(io_setup)
-SYSCALL(io_destroy)
-COMPAT_SYS(io_getevents)
-COMPAT_SYS(io_submit)
-SYSCALL(io_cancel)
-SYSCALL(set_tid_address)
-SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
-SYSCALL(exit_group)
-SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
-SYSCALL(epoll_create)
-SYSCALL(epoll_ctl)
-SYSCALL(epoll_wait)
-SYSCALL(remap_file_pages)
-SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create)
-COMPAT_SYS(timer_settime)
-COMPAT_SYS(timer_gettime)
-SYSCALL(timer_getoverrun)
-SYSCALL(timer_delete)
-COMPAT_SYS(clock_settime)
-COMPAT_SYS(clock_gettime)
-COMPAT_SYS(clock_getres)
-COMPAT_SYS(clock_nanosleep)
-SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
-COMPAT_SYS(tgkill)
-COMPAT_SYS(utimes)
-COMPAT_SYS(statfs64)
-COMPAT_SYS(fstatfs64)
-SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
-PPC_SYS(rtas)
-OLDSYS(debug_setcontext)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(mbind)
-COMPAT_SYS(get_mempolicy)
-COMPAT_SYS(set_mempolicy)
-COMPAT_SYS(mq_open)
-SYSCALL(mq_unlink)
-COMPAT_SYS(mq_timedsend)
-COMPAT_SYS(mq_timedreceive)
-COMPAT_SYS(mq_notify)
-COMPAT_SYS(mq_getsetattr)
-COMPAT_SYS(kexec_load)
-COMPAT_SYS(add_key)
-COMPAT_SYS(request_key)
-COMPAT_SYS(keyctl)
-COMPAT_SYS(waitid)
-COMPAT_SYS(ioprio_set)
-COMPAT_SYS(ioprio_get)
-SYSCALL(inotify_init)
-SYSCALL(inotify_add_watch)
-SYSCALL(inotify_rm_watch)
-SYSCALL(spu_run)
-SYSCALL(spu_create)
-COMPAT_SYS(pselect6)
-COMPAT_SYS(ppoll)
-SYSCALL(unshare)
-SYSCALL(splice)
-SYSCALL(tee)
-SYSCALL(vmsplice)
-COMPAT_SYS(openat)
-SYSCALL(mkdirat)
-SYSCALL(mknodat)
-SYSCALL(fchownat)
-COMPAT_SYS(futimesat)
-SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
-SYSCALL(unlinkat)
-SYSCALL(renameat)
-SYSCALL(linkat)
-SYSCALL(symlinkat)
-SYSCALL(readlinkat)
-SYSCALL(fchmodat)
-SYSCALL(faccessat)
-COMPAT_SYS(get_robust_list)
-COMPAT_SYS(set_robust_list)
-
-/*
- * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
- * as well when appropriate.
- */
+#include <asm/systbl.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 24e3ad756de0..d20907561f46 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -76,7 +76,6 @@
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
-extern int piranha_simulator;
 #ifdef CONFIG_PPC_ISERIES
 unsigned long iSeries_recal_titan = 0;
 unsigned long iSeries_recal_tb = 0; 
@@ -858,42 +857,50 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
-void __init generic_calibrate_decr(void)
+static int __init get_freq(char *name, int cells, unsigned long *val)
 {
 	struct device_node *cpu;
 	unsigned int *fp;
-	int node_found;
+	int found = 0;
 
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
+	/* The cpu node should have timebase and clock frequency properties */
 	cpu = of_find_node_by_type(NULL, "cpu");
 
-	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
-	node_found = 0;
 	if (cpu) {
-		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
-						  NULL);
+		fp = (unsigned int *)get_property(cpu, name, NULL);
 		if (fp) {
-			node_found = 1;
-			ppc_tb_freq = *fp;
+			found = 1;
+			*val = 0;
+			while (cells--)
+				*val = (*val << 32) | *fp++;
 		}
+
+		of_node_put(cpu);
 	}
-	if (!node_found)
+
+	return found;
+}
+
+void __init generic_calibrate_decr(void)
+{
+	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
+
+	if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) &&
+	    !get_freq("timebase-frequency", 1, &ppc_tb_freq)) {
+
 		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
 				"(not found)\n");
+	}
 
-	ppc_proc_freq = DEFAULT_PROC_FREQ;
-	node_found = 0;
-	if (cpu) {
-		fp = (unsigned int *)get_property(cpu, "clock-frequency",
-						  NULL);
-		if (fp) {
-			node_found = 1;
-			ppc_proc_freq = *fp;
-		}
+	ppc_proc_freq = DEFAULT_PROC_FREQ;	/* hardcoded default */
+
+	if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) &&
+	    !get_freq("clock-frequency", 1, &ppc_proc_freq)) {
+
+		printk(KERN_ERR "WARNING: Estimating processor frequency "
+				"(not found)\n");
 	}
+
 #ifdef CONFIG_BOOKE
 	/* Set the time base to zero */
 	mtspr(SPRN_TBWL, 0);
@@ -905,11 +912,6 @@ void __init generic_calibrate_decr(void)
 	/* Enable decrementer interrupt */
 	mtspr(SPRN_TCR, TCR_DIE);
 #endif
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating processor frequency "
-				"(not found)\n");
-
-	of_node_put(cpu);
 }
 
 unsigned long get_boot_time(void)
@@ -945,9 +947,9 @@ void __init time_init(void)
 	} else {
 		/* Normal PowerPC with timebase register */
 		ppc_md.calibrate_decr();
-		printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n",
 		       ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
-		printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
+		printk(KERN_DEBUG "time_init: processor frequency   = %lu.%.6lu MHz\n",
 		       ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
 		tb_last_stamp = tb_last_jiffy = get_tb();
 	}
@@ -1010,10 +1012,7 @@ void __init time_init(void)
 	tb_to_ns_scale = scale;
 	tb_to_ns_shift = shift;
 
-#ifdef CONFIG_PPC_ISERIES
-	if (!piranha_simulator)
-#endif
-		tm = get_boot_time();
+	tm = get_boot_time();
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 064a52564692..91a6e04d9741 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -658,7 +658,7 @@ static int emulate_instruction(struct pt_regs *regs)
 	u32 instword;
 	u32 rd;
 
-	if (!user_mode(regs))
+	if (!user_mode(regs) || (regs->msr & MSR_LE))
 		return -EINVAL;
 	CHECK_FULL_REGS(regs);
 
@@ -805,9 +805,11 @@ void __kprobes program_check_exception(struct pt_regs *regs)
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed;
+	int fixed = 0;
 
-	fixed = fix_alignment(regs);
+	/* we don't implement logging of alignment exceptions */
+	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+		fixed = fix_alignment(regs);
 
 	if (fixed == 1) {
 		regs->nip += 4;	/* skip over emulated instruction */
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 3774e80094f5..67d9fd9ae2b5 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/console.h>
+#include <linux/init.h>
 #include <asm/processor.h>
 #include <asm/udbg.h>
 
@@ -141,12 +142,14 @@ static int early_console_initialized;
 
 void __init disable_early_printk(void)
 {
-#if 1
 	if (!early_console_initialized)
 		return;
+	if (strstr(saved_command_line, "udbg-immortal")) {
+		printk(KERN_INFO "early console immortal !\n");
+		return;
+	}
 	unregister_console(&udbg_console);
 	early_console_initialized = 0;
-#endif
 }
 
 /* called by setup_system */
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 573afb68d69e..bc3e15be3087 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	struct vm_area_struct *vma;
 	unsigned long vdso_pages;
 	unsigned long vdso_base;
+	int rc;
 
 #ifdef CONFIG_PPC64
 	if (test_thread_flag(TIF_32BIT)) {
@@ -237,20 +238,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	vdso_base = VDSO32_MBASE;
 #endif
 
-	current->thread.vdso_base = 0;
+	current->mm->context.vdso_base = 0;
 
 	/* vDSO has a problem and was disabled, just don't "enable" it for the
 	 * process
 	 */
 	if (vdso_pages == 0)
 		return 0;
-
-	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	if (vma == NULL)
-		return -ENOMEM;
-
-	memset(vma, 0, sizeof(*vma));
-
 	/* Add a page to the vdso size for the data page */
 	vdso_pages ++;
 
@@ -259,17 +253,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	 * at vdso_base which is the "natural" base for it, but we might fail
 	 * and end up putting it elsewhere.
 	 */
+	down_write(&mm->mmap_sem);
 	vdso_base = get_unmapped_area(NULL, vdso_base,
 				      vdso_pages << PAGE_SHIFT, 0, 0);
-	if (vdso_base & ~PAGE_MASK) {
-		kmem_cache_free(vm_area_cachep, vma);
-		return (int)vdso_base;
+	if (IS_ERR_VALUE(vdso_base)) {
+		rc = vdso_base;
+		goto fail_mmapsem;
 	}
 
-	current->thread.vdso_base = vdso_base;
 
+	/* Allocate a VMA structure and fill it up */
+	vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma == NULL) {
+		rc = -ENOMEM;
+		goto fail_mmapsem;
+	}
 	vma->vm_mm = mm;
-	vma->vm_start = current->thread.vdso_base;
+	vma->vm_start = vdso_base;
 	vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
 
 	/*
@@ -282,23 +282,38 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	 * It's fine to use that for setting breakpoints in the vDSO code
 	 * pages though
 	 */
-	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
 	vma->vm_ops = &vdso_vmops;
 
-	down_write(&mm->mmap_sem);
-	if (insert_vm_struct(mm, vma)) {
-		up_write(&mm->mmap_sem);
-		kmem_cache_free(vm_area_cachep, vma);
-		return -ENOMEM;
-	}
+	/* Insert new VMA */
+	rc = insert_vm_struct(mm, vma);
+	if (rc)
+		goto fail_vma;
+
+	/* Put vDSO base into mm struct and account for memory usage */
+	current->mm->context.vdso_base = vdso_base;
 	mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	up_write(&mm->mmap_sem);
-
 	return 0;
+
+ fail_vma:
+	kmem_cache_free(vm_area_cachep, vma);
+ fail_mmapsem:
+	up_write(&mm->mmap_sem);
+	return rc;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
+		return "[vdso]";
+	return NULL;
 }
 
+
+
 static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
 				  unsigned long *size)
 {
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 66b3d03c5fa5..9416b4ab92ec 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -53,12 +53,12 @@ fpenable:
 	stfd	fr31,8(r1)
 	LDCONST(fr1, fpzero)
 	mffs	fr31
-	mtfsf	0xff,fr1
+	MTFSF_L(fr1)
 	blr
 
 fpdisable:
 	mtlr	r12
-	mtfsf	0xff,fr31
+	MTFSF_L(fr31)
 	lfd	fr31,8(r1)
 	lfd	fr1,16(r1)
 	lfd	fr0,24(r1)
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 971020cf3f7d..cdf5867838a6 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -13,27 +13,116 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#include <linux/types.h>
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/kobject.h>
+
 #include <asm/iommu.h>
 #include <asm/dma.h>
 #include <asm/vio.h>
 #include <asm/prom.h>
-
-static const struct vio_device_id *vio_match_device(
-		const struct vio_device_id *, const struct vio_dev *);
-
-struct vio_dev vio_bus_device  = { /* fake "parent" device */
+#include <asm/firmware.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/hvcall.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/iommu.h>
+
+extern struct subsystem devices_subsys; /* needed for vio_find_name() */
+
+static struct vio_dev vio_bus_device  = { /* fake "parent" device */
 	.name = vio_bus_device.dev.bus_id,
 	.type = "",
 	.dev.bus_id = "vio",
 	.dev.bus = &vio_bus_type,
 };
 
-static struct vio_bus_ops vio_bus_ops;
+#ifdef CONFIG_PPC_ISERIES
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
+EXPORT_SYMBOL(iSeries_vio_dev);
+
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+static void __init iommu_vio_init(void)
+{
+	iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+	veth_iommu_table.it_size /= 2;
+	vio_iommu_table = veth_iommu_table;
+	vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+	if (!iommu_init_table(&veth_iommu_table, -1))
+		printk("Virtual Bus VETH TCE table failed.\n");
+	if (!iommu_init_table(&vio_iommu_table, -1))
+		printk("Virtual Bus VIO TCE table failed.\n");
+}
+#endif
+
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		if (strcmp(dev->type, "network") == 0)
+			return &veth_iommu_table;
+		return &vio_iommu_table;
+	} else
+#endif
+	{
+		unsigned char *dma_window;
+		struct iommu_table *tbl;
+		unsigned long offset, size;
+
+		dma_window = get_property(dev->dev.platform_data,
+				"ibm,my-dma-window", NULL);
+		if (!dma_window)
+			return NULL;
+
+		tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+		of_parse_dma_window(dev->dev.platform_data, dma_window,
+				&tbl->it_index, &offset, &size);
+
+		/* TCE table size - measured in tce entries */
+		tbl->it_size = size >> PAGE_SHIFT;
+		/* offset for VIO should always be 0 */
+		tbl->it_offset = offset >> PAGE_SHIFT;
+		tbl->it_busno = 0;
+		tbl->it_type = TCE_VB;
+
+		return iommu_init_table(tbl, -1);
+	}
+}
+
+/**
+ * vio_match_device: - Tell if a VIO device has a matching
+ *			VIO device id structure.
+ * @ids:	array of VIO device id structures to search in
+ * @dev:	the VIO device structure to match against
+ *
+ * Used by a driver to check whether a VIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * vio_device_id structure or NULL if there is no match.
+ */
+static const struct vio_device_id *vio_match_device(
+		const struct vio_device_id *ids, const struct vio_dev *dev)
+{
+	while (ids->type[0] != '\0') {
+		if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
+		    device_is_compatible(dev->dev.platform_data, ids->compat))
+			return ids;
+		ids++;
+	}
+	return NULL;
+}
 
 /*
  * Convert from struct device to struct vio_dev and pass to driver.
@@ -106,35 +195,110 @@ void vio_unregister_driver(struct vio_driver *viodrv)
 }
 EXPORT_SYMBOL(vio_unregister_driver);
 
+/* vio_dev refcount hit 0 */
+static void __devinit vio_dev_release(struct device *dev)
+{
+	if (dev->platform_data) {
+		/* XXX free TCE table */
+		of_node_put(dev->platform_data);
+	}
+	kfree(to_vio_dev(dev));
+}
+
 /**
- * vio_match_device: - Tell if a VIO device has a matching
- *			VIO device id structure.
- * @ids:	array of VIO device id structures to search in
- * @dev:	the VIO device structure to match against
+ * vio_register_device_node: - Register a new vio device.
+ * @of_node:	The OF node for this device.
  *
- * Used by a driver to check whether a VIO device present in the
- * system is in its list of supported devices. Returns the matching
- * vio_device_id structure or NULL if there is no match.
+ * Creates and initializes a vio_dev structure from the data in
+ * of_node (dev.platform_data) and adds it to the list of virtual devices.
+ * Returns a pointer to the created vio_dev or NULL if node has
+ * NULL device_type or compatible fields.
  */
-static const struct vio_device_id *vio_match_device(
-		const struct vio_device_id *ids, const struct vio_dev *dev)
+struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
 {
-	while (ids->type[0] != '\0') {
-		if (vio_bus_ops.match(ids, dev))
-			return ids;
-		ids++;
+	struct vio_dev *viodev;
+	unsigned int *unit_address;
+	unsigned int *irq_p;
+
+	/* we need the 'device_type' property, in order to match with drivers */
+	if (of_node->type == NULL) {
+		printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
+				__FUNCTION__,
+				of_node->name ? of_node->name : "<unknown>");
+		return NULL;
 	}
-	return NULL;
+
+	unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
+	if (unit_address == NULL) {
+		printk(KERN_WARNING "%s: node %s missing 'reg'\n",
+				__FUNCTION__,
+				of_node->name ? of_node->name : "<unknown>");
+		return NULL;
+	}
+
+	/* allocate a vio_dev for this node */
+	viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
+	if (viodev == NULL)
+		return NULL;
+
+	viodev->dev.platform_data = of_node_get(of_node);
+
+	viodev->irq = NO_IRQ;
+	irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
+	if (irq_p) {
+		int virq = virt_irq_create_mapping(*irq_p);
+		if (virq == NO_IRQ) {
+			printk(KERN_ERR "Unable to allocate interrupt "
+			       "number for %s\n", of_node->full_name);
+		} else
+			viodev->irq = irq_offset_up(virq);
+	}
+
+	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+	viodev->name = of_node->name;
+	viodev->type = of_node->type;
+	viodev->unit_address = *unit_address;
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		unit_address = (unsigned int *)get_property(of_node,
+				"linux,unit_address", NULL);
+		if (unit_address != NULL)
+			viodev->unit_address = *unit_address;
+	}
+	viodev->iommu_table = vio_build_iommu_table(viodev);
+
+	/* init generic 'struct device' fields: */
+	viodev->dev.parent = &vio_bus_device.dev;
+	viodev->dev.bus = &vio_bus_type;
+	viodev->dev.release = vio_dev_release;
+
+	/* register with generic device framework */
+	if (device_register(&viodev->dev)) {
+		printk(KERN_ERR "%s: failed to register device %s\n",
+				__FUNCTION__, viodev->dev.bus_id);
+		/* XXX free TCE table */
+		kfree(viodev);
+		return NULL;
+	}
+
+	return viodev;
 }
+EXPORT_SYMBOL(vio_register_device_node);
 
 /**
  * vio_bus_init: - Initialize the virtual IO bus
  */
-int __init vio_bus_init(struct vio_bus_ops *ops)
+static int __init vio_bus_init(void)
 {
 	int err;
+	struct device_node *node_vroot;
 
-	vio_bus_ops = *ops;
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		iommu_vio_init();
+		vio_bus_device.iommu_table = &vio_iommu_table;
+		iSeries_vio_dev = &vio_bus_device.dev;
+	}
+#endif
 
 	err = bus_register(&vio_bus_type);
 	if (err) {
@@ -153,47 +317,48 @@ int __init vio_bus_init(struct vio_bus_ops *ops)
 		return err;
 	}
 
-	return 0;
-}
+	node_vroot = find_devices("vdevice");
+	if (node_vroot) {
+		struct device_node *of_node;
+
+		/*
+		 * Create struct vio_devices for each virtual device in
+		 * the device tree. Drivers will associate with them later.
+		 */
+		for (of_node = node_vroot->child; of_node != NULL;
+				of_node = of_node->sibling) {
+			printk(KERN_DEBUG "%s: processing %p\n",
+					__FUNCTION__, of_node);
+			vio_register_device_node(of_node);
+		}
+	}
 
-/* vio_dev refcount hit 0 */
-static void __devinit vio_dev_release(struct device *dev)
-{
-	if (vio_bus_ops.release_device)
-		vio_bus_ops.release_device(dev);
-	kfree(to_vio_dev(dev));
+	return 0;
 }
+__initcall(vio_bus_init);
 
-static ssize_t viodev_show_name(struct device *dev,
+static ssize_t name_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
 }
-DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
 
-struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
+static ssize_t devspec_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
-	/* init generic 'struct device' fields: */
-	viodev->dev.parent = &vio_bus_device.dev;
-	viodev->dev.bus = &vio_bus_type;
-	viodev->dev.release = vio_dev_release;
-
-	/* register with generic device framework */
-	if (device_register(&viodev->dev)) {
-		printk(KERN_ERR "%s: failed to register device %s\n",
-				__FUNCTION__, viodev->dev.bus_id);
-		return NULL;
-	}
-	device_create_file(&viodev->dev, &dev_attr_name);
+	struct device_node *of_node = dev->platform_data;
 
-	return viodev;
+	return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
 }
 
+static struct device_attribute vio_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(devspec),
+	__ATTR_NULL
+};
+
 void __devinit vio_unregister_device(struct vio_dev *viodev)
 {
-	if (vio_bus_ops.unregister_device)
-		vio_bus_ops.unregister_device(viodev);
-	device_remove_file(&viodev->dev, &dev_attr_name);
 	device_unregister(&viodev->dev);
 }
 EXPORT_SYMBOL(vio_unregister_device);
@@ -229,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
-			dma_handle, ~0ul, flag);
+			dma_handle, ~0ul, flag, -1);
 }
 
 static void vio_free_coherent(struct device *dev, size_t size,
@@ -267,22 +432,23 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
 			char *buffer, int buffer_size)
 {
 	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct device_node *dn = dev->platform_data;
 	char *cp;
 	int length;
 
 	if (!num_envp)
 		return -ENOMEM;
 
-	if (!vio_dev->dev.platform_data)
+	if (!dn)
 		return -ENODEV;
-	cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length);
+	cp = (char *)get_property(dn, "compatible", &length);
 	if (!cp)
 		return -ENODEV;
 
 	envp[0] = buffer;
 	length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
 				vio_dev->type, cp);
-	if (buffer_size - length <= 0)
+	if ((buffer_size - length) <= 0)
 		return -ENOMEM;
 	envp[1] = NULL;
 	return 0;
@@ -290,9 +456,81 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
 
 struct bus_type vio_bus_type = {
 	.name = "vio",
+	.dev_attrs = vio_dev_attrs,
 	.uevent = vio_hotplug,
 	.match = vio_bus_match,
 	.probe = vio_bus_probe,
 	.remove = vio_bus_remove,
 	.shutdown = vio_bus_shutdown,
 };
+
+/**
+ * vio_get_attribute: - get attribute for virtual device
+ * @vdev:	The vio device to get property.
+ * @which:	The property/attribute to be extracted.
+ * @length:	Pointer to length of returned data size (unused if NULL).
+ *
+ * Calls prom.c's get_property() to return the value of the
+ * attribute specified by @which
+*/
+const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
+{
+	return get_property(vdev->dev.platform_data, which, length);
+}
+EXPORT_SYMBOL(vio_get_attribute);
+
+#ifdef CONFIG_PPC_PSERIES
+/* vio_find_name() - internal because only vio.c knows how we formatted the
+ * kobject name
+ * XXX once vio_bus_type.devices is actually used as a kset in
+ * drivers/base/bus.c, this function should be removed in favor of
+ * "device_find(kobj_name, &vio_bus_type)"
+ */
+static struct vio_dev *vio_find_name(const char *kobj_name)
+{
+	struct kobject *found;
+
+	found = kset_find_obj(&devices_subsys.kset, kobj_name);
+	if (!found)
+		return NULL;
+
+	return to_vio_dev(container_of(found, struct device, kobj));
+}
+
+/**
+ * vio_find_node - find an already-registered vio_dev
+ * @vnode: device_node of the virtual device we're looking for
+ */
+struct vio_dev *vio_find_node(struct device_node *vnode)
+{
+	uint32_t *unit_address;
+	char kobj_name[BUS_ID_SIZE];
+
+	/* construct the kobject name from the device node */
+	unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
+	if (!unit_address)
+		return NULL;
+	snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+
+	return vio_find_name(kobj_name);
+}
+EXPORT_SYMBOL(vio_find_node);
+
+int vio_enable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_enable_interrupts);
+
+int vio_disable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_disable_interrupts);
+#endif /* CONFIG_PPC_PSERIES */
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fe79c2584cb0..8b25953dc4f0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -93,6 +93,11 @@ SECTIONS
 		__ptov_table_begin = .;
 		*(.ptov_fixup);
 		__ptov_table_end = .;
+#ifdef CONFIG_PPC_ISERIES
+		__dt_strings_start = .;
+		*(.dt_strings);
+		__dt_strings_end = .;
+#endif
 	}
 
 	. = ALIGN(16);
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 34f5c2e074c9..ff7096458249 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -2,12 +2,15 @@
 # Makefile for ppc-specific library files..
 #
 
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS		+= -mno-minimal-toc
+endif
+
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-y			:= string.o strcase.o
 obj-$(CONFIG_PPC32)	+= div64.o copy_32.o checksum_32.o
 endif
 
-obj-y			+= bitops.o
 obj-$(CONFIG_PPC64)	+= checksum_64.o copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o \
 			   strcase.o
diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c
deleted file mode 100644
index f68ad71a0187..000000000000
--- a/arch/powerpc/lib/bitops.c
+++ /dev/null
@@ -1,150 +0,0 @@
-#include <linux/types.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/bitops.h>
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
-			    unsigned long offset)
-{
-	const unsigned long *p = addr + BITOP_WORD(offset);
-	unsigned long result = offset & ~(BITS_PER_LONG-1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset %= BITS_PER_LONG;
-	if (offset) {
-		tmp = *(p++);
-		tmp &= (~0UL << offset);
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG-1)) {
-		if ((tmp = *(p++)))
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	tmp &= (~0UL >> (BITS_PER_LONG - size));
-	if (tmp == 0UL)		/* Are any bits set? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + __ffs(tmp);
-}
-EXPORT_SYMBOL(find_next_bit);
-
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-				 unsigned long offset)
-{
-	const unsigned long *p = addr + BITOP_WORD(offset);
-	unsigned long result = offset & ~(BITS_PER_LONG-1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset %= BITS_PER_LONG;
-	if (offset) {
-		tmp = *(p++);
-		tmp |= ~0UL >> (BITS_PER_LONG - offset);
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (~tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG-1)) {
-		if (~(tmp = *(p++)))
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	tmp |= ~0UL << size;
-	if (tmp == ~0UL)	/* Are any bits zero? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + ffz(tmp);
-}
-EXPORT_SYMBOL(find_next_zero_bit);
-
-static inline unsigned int ext2_ilog2(unsigned int x)
-{
-	int lz;
-
-	asm("cntlzw %0,%1": "=r"(lz):"r"(x));
-	return 31 - lz;
-}
-
-static inline unsigned int ext2_ffz(unsigned int x)
-{
-	u32 rc;
-	if ((x = ~x) == 0)
-		return 32;
-	rc = ext2_ilog2(x & -x);
-	return rc;
-}
-
-unsigned long find_next_zero_le_bit(const unsigned long *addr,
-				    unsigned long size, unsigned long offset)
-{
-	const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5);
-	unsigned int result = offset & ~31;
-	unsigned int tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset &= 31;
-	if (offset) {
-		tmp = cpu_to_le32p(p++);
-		tmp |= ~0U >> (32 - offset);	/* bug or feature ? */
-		if (size < 32)
-			goto found_first;
-		if (tmp != ~0)
-			goto found_middle;
-		size -= 32;
-		result += 32;
-	}
-	while (size >= 32) {
-		if ((tmp = cpu_to_le32p(p++)) != ~0)
-			goto found_middle;
-		result += 32;
-		size -= 32;
-	}
-	if (!size)
-		return result;
-	tmp = cpu_to_le32p(p);
-found_first:
-	tmp |= ~0 << size;
-	if (tmp == ~0)		/* Are any bits zero? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + ext2_ffz(tmp);
-}
-EXPORT_SYMBOL(find_next_zero_le_bit);
diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
index ea469eefa146..94255beeecd3 100644
--- a/arch/powerpc/mm/hash_low_32.S
+++ b/arch/powerpc/mm/hash_low_32.S
@@ -74,12 +74,6 @@ _GLOBAL(hash_page_sync)
  */
 	.text
 _GLOBAL(hash_page)
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	MTMSRD(r0)
-	isync
-#endif
 	tophys(r7,0)			/* gets -KERNELBASE into r7 */
 #ifdef CONFIG_SMP
 	addis	r8,r7,mmu_hash_lock@h
@@ -285,7 +279,6 @@ Hash_base = 0xc0180000
 Hash_bits = 12				/* e.g. 256kB hash table */
 Hash_msk = (((1 << Hash_bits) - 1) * 64)
 
-#ifndef CONFIG_PPC64BRIDGE
 /* defines for the PTE format for 32-bit PPCs */
 #define PTE_SIZE	8
 #define PTEG_SIZE	64
@@ -299,21 +292,6 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
 #define SET_V(r)	oris r,r,PTE_V@h
 #define CLR_V(r,t)	rlwinm r,r,0,1,31
 
-#else
-/* defines for the PTE format for 64-bit PPCs */
-#define PTE_SIZE	16
-#define PTEG_SIZE	128
-#define LG_PTEG_SIZE	7
-#define LDPTEu		ldu
-#define STPTE		std
-#define CMPPTE		cmpd
-#define PTE_H		2
-#define PTE_V		1
-#define TST_V(r)	andi. r,r,PTE_V
-#define SET_V(r)	ori r,r,PTE_V
-#define CLR_V(r,t)	li t,PTE_V; andc r,r,t
-#endif /* CONFIG_PPC64BRIDGE */
-
 #define HASH_LEFT	31-(LG_PTEG_SIZE+Hash_bits-1)
 #define HASH_RIGHT	31-LG_PTEG_SIZE
 
@@ -331,14 +309,8 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
 
 	/* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r5,r3,12		/* shift vsid into position */
-	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r5)			/* set V (valid) bit */
 
 	/* Get the address of the primary PTE group in the hash table (r3) */
@@ -516,14 +488,8 @@ _GLOBAL(flush_hash_pages)
 	add	r3,r3,r0		/* note code below trims to 24 bits */
 
 	/* Construct the high word of the PPC-style PTE (r11) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r11,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r11,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r11,r3,12		/* shift vsid into position */
-	rlwimi	r11,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r11)			/* set V (valid) bit */
 
 #ifdef CONFIG_SMP
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index e0d02c4a2615..52e914238959 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -136,6 +136,7 @@ _GLOBAL(__hash_page_4K)
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...) 
@@ -368,6 +369,7 @@ _GLOBAL(__hash_page_4K)
 	rlwinm	r30,r4,32-9+7,31-7,31-7	/* _PAGE_RW -> _PAGE_DIRTY */
 	or	r30,r30,r31
 	ori	r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
+	oris	r30,r30,_PAGE_COMBO@h
 	/* Write the linux PTE atomically (setting busy) */
 	stdcx.	r30,0,r6
 	bne-	1b
@@ -400,6 +402,7 @@ _GLOBAL(__hash_page_4K)
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...)
@@ -426,6 +429,14 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
 	andi.	r0,r31,_PAGE_HASHPTE
 	li	r26,0			/* Default hidx */
 	beq	htab_insert_pte
+
+	/*
+	 * Check if the pte was already inserted into the hash table
+	 * as a 64k HW page, and invalidate the 64k HPTE if so.
+	 */
+	andis.	r0,r31,_PAGE_COMBO@h
+	beq	htab_inval_old_hpte
+
 	ld	r6,STK_PARM(r6)(r1)
 	ori	r26,r6,0x8000		/* Load the hidx mask */
 	ld	r26,0(r26)
@@ -496,6 +507,19 @@ _GLOBAL(htab_call_hpte_remove)
 	/* Try all again */
 	b	htab_insert_pte
 
+	/*
+	 * Call out to C code to invalidate an 64k HW HPTE that is
+	 * useless now that the segment has been switched to 4k pages.
+	 */
+htab_inval_old_hpte:
+	mr	r3,r29			/* virtual addr */
+	mr	r4,r31			/* PTE.pte */
+	li	r5,0			/* PTE.hidx */
+	li	r6,MMU_PAGE_64K		/* psize */
+	ld	r7,STK_PARM(r8)(r1)	/* local */
+	bl	.flush_hash_page
+	b	htab_insert_pte
+	
 htab_bail_ok:
 	li	r3,0
 	b	htab_bail
@@ -636,6 +660,12 @@ _GLOBAL(__hash_page_64K)
 	 * is changing this PTE anyway and might hash it.
 	 */
 	bne-	ht64_bail_ok
+BEGIN_FTR_SECTION
+	/* Check if PTE has the cache-inhibit bit set */
+	andi.	r0,r31,_PAGE_NO_CACHE
+	/* If so, bail out and refault as a 4k page */
+	bne-	ht64_bail_ok
+END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
 	/* Prepare new PTE value (turn access RW into DIRTY, then
 	 * add BUSY,HASHPTE and ACCESSED)
 	 */
@@ -671,6 +701,7 @@ _GLOBAL(__hash_page_64K)
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...)
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 994856e55b7c..a0f3cbd00d39 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -238,7 +238,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 		DBG_LOW(" -> hit\n");
 		/* Update the HPTE */
 		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
-			(newpp & (HPTE_R_PP | HPTE_R_N));
+			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
 		native_unlock_hpte(hptep);
 	}
 
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index c006d9039633..d03fd2b4445e 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -92,10 +92,15 @@ unsigned long htab_size_bytes;
 unsigned long htab_hash_mask;
 int mmu_linear_psize = MMU_PAGE_4K;
 int mmu_virtual_psize = MMU_PAGE_4K;
+int mmu_vmalloc_psize = MMU_PAGE_4K;
+int mmu_io_psize = MMU_PAGE_4K;
 #ifdef CONFIG_HUGETLB_PAGE
 int mmu_huge_psize = MMU_PAGE_16M;
 unsigned int HPAGE_SHIFT;
 #endif
+#ifdef CONFIG_PPC_64K_PAGES
+int mmu_ci_restrictions;
+#endif
 
 /* There are definitions of page sizes arrays to be used when none
  * is provided by the firmware.
@@ -308,20 +313,31 @@ static void __init htab_init_page_sizes(void)
 	else if (mmu_psize_defs[MMU_PAGE_1M].shift)
 		mmu_linear_psize = MMU_PAGE_1M;
 
+#ifdef CONFIG_PPC_64K_PAGES
 	/*
 	 * Pick a size for the ordinary pages. Default is 4K, we support
-	 * 64K if cache inhibited large pages are supported by the
-	 * processor
+	 * 64K for user mappings and vmalloc if supported by the processor.
+	 * We only use 64k for ioremap if the processor
+	 * (and firmware) support cache-inhibited large pages.
+	 * If not, we use 4k and set mmu_ci_restrictions so that
+	 * hash_page knows to switch processes that use cache-inhibited
+	 * mappings to 4k pages.
 	 */
-#ifdef CONFIG_PPC_64K_PAGES
-	if (mmu_psize_defs[MMU_PAGE_64K].shift &&
-	    cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
+	if (mmu_psize_defs[MMU_PAGE_64K].shift) {
 		mmu_virtual_psize = MMU_PAGE_64K;
+		mmu_vmalloc_psize = MMU_PAGE_64K;
+		if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
+			mmu_io_psize = MMU_PAGE_64K;
+		else
+			mmu_ci_restrictions = 1;
+	}
 #endif
 
-	printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n",
+	printk(KERN_DEBUG "Page orders: linear mapping = %d, "
+	       "virtual = %d, io = %d\n",
 	       mmu_psize_defs[mmu_linear_psize].shift,
-	       mmu_psize_defs[mmu_virtual_psize].shift);
+	       mmu_psize_defs[mmu_virtual_psize].shift,
+	       mmu_psize_defs[mmu_io_psize].shift);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/* Init large page size. Currently, we pick 16M or 1M depending
@@ -556,6 +572,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 	pte_t *ptep;
 	cpumask_t tmp;
 	int rc, user_region = 0, local = 0;
+	int psize;
 
 	DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
 		ea, access, trap);
@@ -575,10 +592,15 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 			return 1;
 		}
 		vsid = get_vsid(mm->context.id, ea);
+		psize = mm->context.user_psize;
 		break;
 	case VMALLOC_REGION_ID:
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
+		if (ea < VMALLOC_END)
+			psize = mmu_vmalloc_psize;
+		else
+			psize = mmu_io_psize;
 		break;
 	default:
 		/* Not a valid range
@@ -629,7 +651,40 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 #ifndef CONFIG_PPC_64K_PAGES
 	rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
 #else
-	if (mmu_virtual_psize == MMU_PAGE_64K)
+	if (mmu_ci_restrictions) {
+		/* If this PTE is non-cacheable, switch to 4k */
+		if (psize == MMU_PAGE_64K &&
+		    (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+			if (user_region) {
+				psize = MMU_PAGE_4K;
+				mm->context.user_psize = MMU_PAGE_4K;
+				mm->context.sllp = SLB_VSID_USER |
+					mmu_psize_defs[MMU_PAGE_4K].sllp;
+			} else if (ea < VMALLOC_END) {
+				/*
+				 * some driver did a non-cacheable mapping
+				 * in vmalloc space, so switch vmalloc
+				 * to 4k pages
+				 */
+				printk(KERN_ALERT "Reducing vmalloc segment "
+				       "to 4kB pages because of "
+				       "non-cacheable mapping\n");
+				psize = mmu_vmalloc_psize = MMU_PAGE_4K;
+			}
+		}
+		if (user_region) {
+			if (psize != get_paca()->context.user_psize) {
+				get_paca()->context = mm->context;
+				slb_flush_and_rebolt();
+			}
+		} else if (get_paca()->vmalloc_sllp !=
+			   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
+			get_paca()->vmalloc_sllp =
+				mmu_psize_defs[mmu_vmalloc_psize].sllp;
+			slb_flush_and_rebolt();
+		}
+	}
+	if (psize == MMU_PAGE_64K)
 		rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
 	else
 		rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
@@ -681,7 +736,18 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 #ifndef CONFIG_PPC_64K_PAGES
 	__hash_page_4K(ea, access, vsid, ptep, trap, local);
 #else
-	if (mmu_virtual_psize == MMU_PAGE_64K)
+	if (mmu_ci_restrictions) {
+		/* If this PTE is non-cacheable, switch to 4k */
+		if (mm->context.user_psize == MMU_PAGE_64K &&
+		    (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+			mm->context.user_psize = MMU_PAGE_4K;
+			mm->context.sllp = SLB_VSID_USER |
+				mmu_psize_defs[MMU_PAGE_4K].sllp;
+			get_paca()->context = mm->context;
+			slb_flush_and_rebolt();
+		}
+	}
+	if (mm->context.user_psize == MMU_PAGE_64K)
 		__hash_page_64K(ea, access, vsid, ptep, trap, local);
 	else
 		__hash_page_4K(ea, access, vsid, ptep, trap, local);
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 417d58518558..8b6f522655a6 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -89,20 +89,25 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn,
 	return lmb_addrs_adjacent(base1, size1, base2, size2);
 }
 
-/* Assumption: base addr of region 1 < base addr of region 2 */
-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
-		unsigned long r1, unsigned long r2)
+static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
 {
 	unsigned long i;
 
-	rgn->region[r1].size += rgn->region[r2].size;
-	for (i=r2; i < rgn->cnt-1; i++) {
-		rgn->region[i].base = rgn->region[i+1].base;
-		rgn->region[i].size = rgn->region[i+1].size;
+	for (i = r; i < rgn->cnt - 1; i++) {
+		rgn->region[i].base = rgn->region[i + 1].base;
+		rgn->region[i].size = rgn->region[i + 1].size;
 	}
 	rgn->cnt--;
 }
 
+/* Assumption: base addr of region 1 < base addr of region 2 */
+static void __init lmb_coalesce_regions(struct lmb_region *rgn,
+		unsigned long r1, unsigned long r2)
+{
+	rgn->region[r1].size += rgn->region[r2].size;
+	lmb_remove_region(rgn, r2);
+}
+
 /* This routine called with relocation disabled. */
 void __init lmb_init(void)
 {
@@ -294,17 +299,16 @@ unsigned long __init lmb_end_of_DRAM(void)
 	return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
 }
 
-/*
- * Truncate the lmb list to memory_limit if it's set
- * You must call lmb_analyze() after this.
- */
+/* You must call lmb_analyze() after this. */
 void __init lmb_enforce_memory_limit(unsigned long memory_limit)
 {
 	unsigned long i, limit;
+	struct lmb_property *p;
 
 	if (! memory_limit)
 		return;
 
+	/* Truncate the lmb regions to satisfy the memory limit. */
 	limit = memory_limit;
 	for (i = 0; i < lmb.memory.cnt; i++) {
 		if (limit > lmb.memory.region[i].size) {
@@ -316,4 +320,21 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
 		lmb.memory.cnt = i + 1;
 		break;
 	}
+
+	lmb.rmo_size = lmb.memory.region[0].size;
+
+	/* And truncate any reserves above the limit also. */
+	for (i = 0; i < lmb.reserved.cnt; i++) {
+		p = &lmb.reserved.region[i];
+
+		if (p->base > memory_limit)
+			p->size = 0;
+		else if ((p->base + p->size) > memory_limit)
+			p->size = memory_limit - p->base;
+
+		if (p->size == 0) {
+			lmb_remove_region(&lmb.reserved, i);
+			i--;
+		}
+	}
 }
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 741dd8802d49..69f3b9a20beb 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -299,9 +299,9 @@ void __init paging_init(void)
 	kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
-	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
-	printk(KERN_INFO "Memory hole size: %ldMB\n",
+	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
 	/*
 	 * All pages are DMA-able so we put them all in the DMA zone.
@@ -380,7 +380,7 @@ void __init mem_init(void)
 			totalhigh_pages++;
 		}
 		totalram_pages += totalhigh_pages;
-		printk(KERN_INFO "High memory: %luk\n",
+		printk(KERN_DEBUG "High memory: %luk\n",
 		       totalhigh_pages << (PAGE_SHIFT-10));
 	}
 #endif /* CONFIG_HIGHMEM */
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
index a8816e0f6a86..e326e4249e1a 100644
--- a/arch/powerpc/mm/mmu_context_32.c
+++ b/arch/powerpc/mm/mmu_context_32.c
@@ -30,7 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-mm_context_t next_mmu_context;
+unsigned long next_mmu_context;
 unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
 #ifdef FEW_CONTEXTS
 atomic_t nr_free_contexts;
diff --git a/arch/powerpc/mm/mmu_context_64.c b/arch/powerpc/mm/mmu_context_64.c
index 714a84dd8d5d..65d18dca266f 100644
--- a/arch/powerpc/mm/mmu_context_64.c
+++ b/arch/powerpc/mm/mmu_context_64.c
@@ -49,6 +49,9 @@ again:
 	}
 
 	mm->context.id = index;
+	mm->context.user_psize = mmu_virtual_psize;
+	mm->context.sllp = SLB_VSID_USER |
+		mmu_psize_defs[mmu_virtual_psize].sllp;
 
 	return 0;
 }
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 092355f37399..aa98cb3b59d8 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -487,9 +487,9 @@ static void __init setup_nonnuma(void)
 	unsigned long total_ram = lmb_phys_mem_size();
 	unsigned int i;
 
-	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
-	printk(KERN_INFO "Memory hole size: %ldMB\n",
+	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
 
 	for (i = 0; i < lmb.memory.cnt; ++i)
@@ -507,7 +507,7 @@ void __init dump_numa_cpu_topology(void)
 		return;
 
 	for_each_online_node(node) {
-		printk(KERN_INFO "Node %d CPUs:", node);
+		printk(KERN_DEBUG "Node %d CPUs:", node);
 
 		count = 0;
 		/*
@@ -543,7 +543,7 @@ static void __init dump_numa_memory_topology(void)
 	for_each_online_node(node) {
 		unsigned long i;
 
-		printk(KERN_INFO "Node %d Memory:", node);
+		printk(KERN_DEBUG "Node %d Memory:", node);
 
 		count = 0;
 
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ed7fcfe5fd37..2ed43a493b31 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -42,18 +42,14 @@ unsigned long _SDR1;
 
 union ubat {			/* BAT register values to be loaded */
 	BAT	bat;
-#ifdef CONFIG_PPC64BRIDGE
-	u64	word[2];
-#else
 	u32	word[2];
-#endif
-} BATS[4][2];			/* 4 pairs of IBAT, DBAT */
+} BATS[8][2];			/* 8 pairs of IBAT, DBAT */
 
 struct batrange {		/* stores address ranges mapped by BATs */
 	unsigned long start;
 	unsigned long limit;
 	unsigned long phys;
-} bat_addrs[4];
+} bat_addrs[8];
 
 /*
  * Return PA for this VA if it is mapped by a BAT, or 0
@@ -190,7 +186,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 		return;
 	pmd = pmd_offset(pgd_offset(mm, ea), ea);
 	if (!pmd_none(*pmd))
-		add_hash_page(mm->context, ea, pmd_val(*pmd));
+		add_hash_page(mm->context.id, ea, pmd_val(*pmd));
 }
 
 /*
@@ -220,15 +216,9 @@ void __init MMU_init_hw(void)
 
 	if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
 
-#ifdef CONFIG_PPC64BRIDGE
-#define LG_HPTEG_SIZE	7		/* 128 bytes per HPTEG */
-#define SDR1_LOW_BITS	(lg_n_hpteg - 11)
-#define MIN_N_HPTEG	2048		/* min 256kB hash table */
-#else
 #define LG_HPTEG_SIZE	6		/* 64 bytes per HPTEG */
 #define SDR1_LOW_BITS	((n_hpteg - 1) >> 10)
 #define MIN_N_HPTEG	1024		/* min 64kB hash table */
-#endif
 
 	/*
 	 * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index ffc8ed4de62d..6a8bf6c6000e 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -60,19 +60,19 @@ static inline void create_slbe(unsigned long ea, unsigned long flags,
 		     : "memory" );
 }
 
-static void slb_flush_and_rebolt(void)
+void slb_flush_and_rebolt(void)
 {
 	/* If you change this make sure you change SLB_NUM_BOLTED
 	 * appropriately too. */
-	unsigned long linear_llp, virtual_llp, lflags, vflags;
+	unsigned long linear_llp, vmalloc_llp, lflags, vflags;
 	unsigned long ksp_esid_data;
 
 	WARN_ON(!irqs_disabled());
 
 	linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp;
 	lflags = SLB_VSID_KERNEL | linear_llp;
-	vflags = SLB_VSID_KERNEL | virtual_llp;
+	vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
 	ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
 	if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET)
@@ -122,9 +122,6 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
 
 	get_paca()->slb_cache_ptr = 0;
 	get_paca()->context = mm->context;
-#ifdef CONFIG_PPC_64K_PAGES
-	get_paca()->pgdir = mm->pgd;
-#endif /* CONFIG_PPC_64K_PAGES */
 
 	/*
 	 * preload some userspace segments into the SLB.
@@ -167,11 +164,10 @@ static inline void patch_slb_encoding(unsigned int *insn_addr,
 
 void slb_initialize(void)
 {
-	unsigned long linear_llp, virtual_llp;
+	unsigned long linear_llp, vmalloc_llp, io_llp;
 	static int slb_encoding_inited;
 	extern unsigned int *slb_miss_kernel_load_linear;
-	extern unsigned int *slb_miss_kernel_load_virtual;
-	extern unsigned int *slb_miss_user_load_normal;
+	extern unsigned int *slb_miss_kernel_load_io;
 #ifdef CONFIG_HUGETLB_PAGE
 	extern unsigned int *slb_miss_user_load_huge;
 	unsigned long huge_llp;
@@ -181,18 +177,19 @@ void slb_initialize(void)
 
 	/* Prepare our SLB miss handler based on our page size */
 	linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	io_llp = mmu_psize_defs[mmu_io_psize].sllp;
+	vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp;
+	get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp;
+
 	if (!slb_encoding_inited) {
 		slb_encoding_inited = 1;
 		patch_slb_encoding(slb_miss_kernel_load_linear,
 				   SLB_VSID_KERNEL | linear_llp);
-		patch_slb_encoding(slb_miss_kernel_load_virtual,
-				   SLB_VSID_KERNEL | virtual_llp);
-		patch_slb_encoding(slb_miss_user_load_normal,
-				   SLB_VSID_USER | virtual_llp);
+		patch_slb_encoding(slb_miss_kernel_load_io,
+				   SLB_VSID_KERNEL | io_llp);
 
 		DBG("SLB: linear  LLP = %04x\n", linear_llp);
-		DBG("SLB: virtual LLP = %04x\n", virtual_llp);
+		DBG("SLB: io      LLP = %04x\n", io_llp);
 #ifdef CONFIG_HUGETLB_PAGE
 		patch_slb_encoding(slb_miss_user_load_huge,
 				   SLB_VSID_USER | huge_llp);
@@ -207,7 +204,7 @@ void slb_initialize(void)
 	unsigned long lflags, vflags;
 
 	lflags = SLB_VSID_KERNEL | linear_llp;
-	vflags = SLB_VSID_KERNEL | virtual_llp;
+	vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
 	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
 	asm volatile("isync":::"memory");
@@ -215,7 +212,6 @@ void slb_initialize(void)
 	asm volatile("isync; slbia; isync":::"memory");
 	create_slbe(PAGE_OFFSET, lflags, 0);
 
-	/* VMALLOC space has 4K pages always for now */
 	create_slbe(VMALLOC_START, vflags, 1);
 
 	/* We don't bolt the stack for the time being - we're in boot,
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index abfaabf667bf..8548dcf8ef8b 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -59,10 +59,19 @@ _GLOBAL(slb_miss_kernel_load_linear)
 	li	r11,0
 	b	slb_finish_load
 
-1:	/* vmalloc/ioremap mapping encoding bits, the "li" instruction below
+1:	/* vmalloc/ioremap mapping encoding bits, the "li" instructions below
 	 * will be patched by the kernel at boot
 	 */
-_GLOBAL(slb_miss_kernel_load_virtual)
+BEGIN_FTR_SECTION
+	/* check whether this is in vmalloc or ioremap space */
+	clrldi	r11,r10,48
+	cmpldi	r11,(VMALLOC_SIZE >> 28) - 1
+	bgt	5f
+	lhz	r11,PACAVMALLOCSLLP(r13)
+	b	slb_finish_load
+5:
+END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
+_GLOBAL(slb_miss_kernel_load_io)
 	li	r11,0
 	b	slb_finish_load
 
@@ -96,9 +105,7 @@ _GLOBAL(slb_miss_user_load_huge)
 1:
 #endif /* CONFIG_HUGETLB_PAGE */
 
-_GLOBAL(slb_miss_user_load_normal)
-	li	r11,0
-
+	lhz	r11,PACACONTEXTSLLP(r13)
 2:
 	ld	r9,PACACONTEXTID(r13)
 	rldimi	r10,r9,USER_ESID_BITS,0
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 4a9291d9fef8..691320c90b78 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -200,10 +200,6 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
 
 	__get_cpu_var(stab_cache_ptr) = 0;
 
-#ifdef CONFIG_PPC_64K_PAGES
-	get_paca()->pgdir = mm->pgd;
-#endif /* CONFIG_PPC_64K_PAGES */
-
 	/* Now preload some entries for the new task */
 	if (test_tsk_thread_flag(tsk, TIF_32BIT))
 		unmapped_base = TASK_UNMAPPED_BASE_USER32;
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
index ad580f3742e5..02eb23e036d5 100644
--- a/arch/powerpc/mm/tlb_32.c
+++ b/arch/powerpc/mm/tlb_32.c
@@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
 
 	if (Hash != 0) {
 		ptephys = __pa(ptep) & PAGE_MASK;
-		flush_hash_pages(mm->context, addr, ptephys, 1);
+		flush_hash_pages(mm->context.id, addr, ptephys, 1);
 	}
 }
 
@@ -102,7 +102,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start,
 	pmd_t *pmd;
 	unsigned long pmd_end;
 	int count;
-	unsigned int ctx = mm->context;
+	unsigned int ctx = mm->context.id;
 
 	if (Hash == 0) {
 		_tlbia();
@@ -172,7 +172,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
 	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
 	if (!pmd_none(*pmd))
-		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
+		flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
 	FINISH_FLUSH;
 }
 
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index f734b11566c2..e7449b068c82 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -131,7 +131,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
 {
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
 	unsigned long vsid;
-	unsigned int psize = mmu_virtual_psize;
+	unsigned int psize;
 	int i;
 
 	i = batch->index;
@@ -148,7 +148,8 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
 #else
 		BUG();
 #endif
-	}
+	} else
+		psize = pte_pagesize_index(pte);
 
 	/*
 	 * This can happen when we are in the middle of a TLB batch and
diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
index d03c0e5ca870..eb2dece76a54 100644
--- a/arch/powerpc/oprofile/Kconfig
+++ b/arch/powerpc/oprofile/Kconfig
@@ -1,5 +1,4 @@
 config PROFILING
-	depends on !PPC_ISERIES
 	bool "Profiling support (EXPERIMENTAL)"
 	help
 	  Say Y here to enable the extended profiling support mechanisms used
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index f5f9859a8338..3145d610b5b0 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -1,3 +1,7 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS	+= -mno-minimal-toc
+endif
+
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
 DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index 5b1de7e8041e..27ad56bd227e 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -22,6 +22,7 @@
 #include <asm/pmc.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
+#include <asm/firmware.h>
 
 static struct op_powerpc_model *model;
 
@@ -130,6 +131,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	if (!cur_cpu_spec->oprofile_cpu_type)
 		return -ENODEV;
 
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return -ENODEV;
+
 	switch (cur_cpu_spec->oprofile_type) {
 #ifdef CONFIG_PPC64
 		case PPC_OPROFILE_RS64:
@@ -162,7 +166,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 	ops->stop = op_powerpc_stop;
 	ops->backtrace = op_powerpc_backtrace;
 
-	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+	printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n",
 	       ops->cpu_type);
 
 	return 0;
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4c2beab1fdc1..506f6b79f893 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -24,10 +24,6 @@
 static unsigned long reset_value[OP_MAX_COUNTER];
 
 static int oprofile_running;
-static int mmcra_has_sihv;
-/* Unfortunately these bits vary between CPUs */
-static unsigned long mmcra_sihv = MMCRA_SIHV;
-static unsigned long mmcra_sipr = MMCRA_SIPR;
 
 /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
 static u32 mmcr0_val;
@@ -41,16 +37,6 @@ static void power4_reg_setup(struct op_counter_config *ctr,
 	int i;
 
 	/*
-	 * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
-	 * However we disable it on all POWER4 until we verify it works
-	 * (I was seeing some strange behaviour last time I tried).
-	 *
-	 * It has been verified to work on POWER5 so we enable it there.
-	 */
-	if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
-		mmcra_has_sihv = 1;
-
-	/*
 	 * The performance counter event settings are given in the mmcr0,
 	 * mmcr1 and mmcra values passed from the user in the
 	 * op_system_config structure (sys variable).
@@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_regs *regs)
 	unsigned long mmcra;
 
 	/* Cant do much about it */
-	if (!mmcra_has_sihv)
+	if (!cur_cpu_spec->oprofile_mmcra_sihv)
 		return pc;
 
 	mmcra = mfspr(SPRN_MMCRA);
 
 	/* Were we in the hypervisor? */
-	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
+	if (firmware_has_feature(FW_FEATURE_LPAR) &&
+	    (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
 		/* function descriptor madness */
 		return *((unsigned long *)hypervisor_bucket);
 
 	/* We were in userspace, nothing to do */
-	if (mmcra & mmcra_sipr)
+	if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr)
 		return pc;
 
 #ifdef CONFIG_PPC_RTAS
@@ -235,15 +222,14 @@ static unsigned long get_pc(struct pt_regs *regs)
 	return pc;
 }
 
-static int get_kernel(unsigned long pc)
+static int get_kernel(unsigned long pc, unsigned long mmcra)
 {
 	int is_kernel;
 
-	if (!mmcra_has_sihv) {
+	if (!cur_cpu_spec->oprofile_mmcra_sihv) {
 		is_kernel = is_kernel_addr(pc);
 	} else {
-		unsigned long mmcra = mfspr(SPRN_MMCRA);
-		is_kernel = ((mmcra & mmcra_sipr) == 0);
+		is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0);
 	}
 
 	return is_kernel;
@@ -257,9 +243,12 @@ static void power4_handle_interrupt(struct pt_regs *regs,
 	int val;
 	int i;
 	unsigned int mmcr0;
+	unsigned long mmcra;
+
+	mmcra = mfspr(SPRN_MMCRA);
 
 	pc = get_pc(regs);
-	is_kernel = get_kernel(pc);
+	is_kernel = get_kernel(pc, mmcra);
 
 	/* set the PMM bit (see comment below) */
 	mtmsrd(mfmsr() | MSR_PMM);
@@ -287,6 +276,10 @@ static void power4_handle_interrupt(struct pt_regs *regs,
 	 */
 	mmcr0 &= ~MMCR0_PMAO;
 
+	/* Clear the appropriate bits in the MMCRA */
+	mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear;
+	mtspr(SPRN_MMCRA, mmcra);
+
 	/*
 	 * now clear the freeze bit, counting will not start until we
 	 * rfid from this exception, because only at that point will
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 06e371282f57..454fc53289ab 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,13 +11,20 @@ config MPC8540_ADS
 	help
 	  This option enables support for the MPC 8540 ADS board
 
+config MPC85xx_CDS
+	bool "Freescale MPC85xx CDS"
+	select DEFAULT_UIMAGE
+	select PPC_I8259 if PCI
+	help
+	  This option enables support for the MPC85xx CDS board
+
 endchoice
 
 config MPC8540
 	bool
 	select PPC_UDBG_16550
 	select PPC_INDIRECT_PCI
-	default y if MPC8540_ADS
+	default y if MPC8540_ADS || MPC85xx_CDS
 
 config PPC_INDIRECT_PCI_BE
 	bool
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index ffc4139cb214..7615aa59c78b 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_PPC_85xx)	+= misc.o pci.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
+obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
new file mode 100644
index 000000000000..18e6e11f7020
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -0,0 +1,359 @@
+/*
+ * MPC85xx setup and early boot code plus other random bits.
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2005 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/i8259.h>
+
+#include <sysdev/fsl_soc.h>
+#include "mpc85xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static int cds_pci_slot = 2;
+static volatile u8 *cadmus;
+
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ *
+ * Note:  Likely, this table and the following function should be
+ *        obtained and derived from the OF Device Tree.
+ */
+static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
+	MPC85XX_INTERNAL_IRQ_SENSES,
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Ext 0: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 1: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 2: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 3: PCI slot 3 */
+#else
+	0x0,				/* External  0: */
+	0x0,				/* External  1: */
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+#endif
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
+	0x0,				/* External  6: */
+	0x0,				/* External  7: */
+	0x0,				/* External  8: */
+	0x0,				/* External  9: */
+	0x0,				/* External 10: */
+#ifdef CONFIG_PCI
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),    /* Ext 11: PCI2 slot 0 */
+#else
+	0x0,				/* External 11: */
+#endif
+};
+
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	if (!hose->index)
+	{
+		/* Handle PCI1 interrupts */
+		char pci_irq_table[][4] =
+			/*
+			 *      PCI IDSEL/INTPIN->INTLINE
+			 *        A      B      C      D
+			 */
+
+			/* Note IRQ assignment for slots is based on which slot the elysium is
+			 * in -- in this setup elysium is in slot #2 (this PIRQA as first
+			 * interrupt on slot */
+		{
+			{ 0, 1, 2, 3 }, /* 16 - PMC */
+			{ 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
+			{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
+			{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
+			{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
+			{ 3, 0, 1, 2 }, /* 21 - Slot 4 */
+		};
+
+		const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
+		int i, j;
+
+		for (i = 0; i < 6; i++)
+			for (j = 0; j < 4; j++)
+				pci_irq_table[i][j] =
+					((pci_irq_table[i][j] + 5 -
+					  cds_pci_slot) & 0x3) + PIRQ0A;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		/* Handle PCI2 interrupts (if we have one) */
+		char pci_irq_table[][4] =
+		{
+			/*
+			 * We only have one slot and one interrupt
+			 * going to PIRQA - PIRQD */
+			{ PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
+		};
+
+		const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+#define ARCADIA_HOST_BRIDGE_IDSEL	17
+#define ARCADIA_2ND_BRIDGE_IDSEL	3
+
+extern int mpc85xx_pci2_busno;
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (mpc85xx_pci2_busno)
+		if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	/* We explicitly do not go past the Tundra 320 Bridge */
+	if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+mpc85xx_cds_pcibios_fixup(void)
+{
+	struct pci_dev *dev;
+	u_char		c;
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+		/*
+		 * U-Boot does not set the enable bits
+		 * for the IDE device. Force them on here.
+		 */
+		pci_read_config_byte(dev, 0x40, &c);
+		c |= 0x03; /* IDE: Chip Enable Bits */
+		pci_write_config_byte(dev, 0x40, c);
+
+		/*
+		 * Since only primary interface works, force the
+		 * IDE function to standard primary IDE interrupt
+		 * w/ 8259 offset
+		 */
+		dev->irq = 14;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		pci_dev_put(dev);
+	}
+
+	/*
+	 * Force legacy USB interrupt routing
+	 */
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
+		dev->irq = 10;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+		pci_dev_put(dev);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_2, dev))) {
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		pci_dev_put(dev);
+	}
+}
+#endif /* CONFIG_PCI */
+
+void __init mpc85xx_cds_pic_init(void)
+{
+	struct mpic *mpic1;
+	phys_addr_t OpenPIC_PAddr;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
+
+	mpic1 = mpic_alloc(OpenPIC_PAddr,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
+			mpc85xx_cds_openpic_initsenses,
+			sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC  ");
+	BUG_ON(mpic1 == NULL);
+	mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
+	mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
+	mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
+	mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
+	mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
+	mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
+	mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
+	mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
+
+	/* dummy mappings to get to 48 */
+	mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
+	mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
+	mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
+	mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
+
+	/* External ints */
+	mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
+	mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
+	mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
+
+	mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+	mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL);
+
+	i8259_init(0,0);
+#endif
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init
+mpc85xx_cds_setup_arch(void)
+{
+	struct device_node *cpu;
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc85xx_cds_setup_arch()", 0);
+
+	cpu = of_find_node_by_type(NULL, "cpu");
+	if (cpu != 0) {
+		unsigned int *fp;
+
+		fp = (int *)get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 500000000 / HZ;
+		of_node_put(cpu);
+	}
+
+	cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
+	cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
+
+	if (ppc_md.progress) {
+		char buf[40];
+		snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",
+				cadmus[CM_VER], cds_pci_slot);
+		ppc_md.progress(buf, 0);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc85xx_map_irq;
+	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+#endif
+
+#ifdef  CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+}
+
+
+void
+mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_cds_probe(void)
+{
+	/* We always match for now, eventually we should look at
+	 * the flat dev tree to ensure this is the board we are
+	 * supposed to run on
+	 */
+	return 1;
+}
+
+define_machine(mpc85xx_cds) {
+	.name		= "MPC85xx CDS",
+	.probe		= mpc85xx_cds_probe,
+	.setup_arch	= mpc85xx_cds_setup_arch,
+	.init_IRQ	= mpc85xx_cds_pic_init,
+	.show_cpuinfo	= mpc85xx_cds_show_cpuinfo,
+	.get_irq	= mpic_get_irq,
+	.restart	= mpc85xx_restart,
+	.calibrate_decr = generic_calibrate_decr,
+	.progress	= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
new file mode 100644
index 000000000000..671f54ff185a
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
@@ -0,0 +1,43 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ *
+ * MPC85xx CDS board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2004 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.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_CDS_H__
+#define __MACH_MPC85XX_CDS_H__
+
+/* CADMUS info */
+#define CADMUS_BASE (0xf8004000)
+#define CADMUS_SIZE (256)
+#define CM_VER	(0)
+#define CM_CSR	(1)
+#define CM_RST	(2)
+
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR	(0xf8000000)
+#define CDS_RTC_SIZE	(8 * 1024)
+
+/* PCI interrupt controller */
+#define PIRQ0A			MPC85xx_IRQ_EXT0
+#define PIRQ0B			MPC85xx_IRQ_EXT1
+#define PIRQ0C			MPC85xx_IRQ_EXT2
+#define PIRQ0D			MPC85xx_IRQ_EXT3
+#define PIRQ1A			MPC85xx_IRQ_EXT11
+
+#define NR_8259_INTS		16
+#define CPM_IRQ_OFFSET		NR_8259_INTS
+
+#define MPC85xx_OPENPIC_IRQ_OFFSET	80
+
+#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
new file mode 100644
index 000000000000..3a87863d2876
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -0,0 +1,36 @@
+menu "Platform Support"
+	depends on PPC_86xx
+
+choice
+	prompt "Machine Type"
+	default MPC8641_HPCN
+
+config MPC8641_HPCN
+	bool "Freescale MPC8641 HPCN"
+	help
+	  This option enables support for the MPC8641 HPCN board.
+
+endchoice
+
+
+config MPC8641
+	bool
+	select PPC_INDIRECT_PCI
+	select PPC_UDBG_16550
+	default y if MPC8641_HPCN
+
+config MPIC
+	bool
+	default y
+
+config PPC_INDIRECT_PCI_BE
+	bool
+	depends on PPC_86xx
+	default y
+
+config PPC_STD_MMU
+	bool
+	depends on PPC_86xx
+	default y
+
+endmenu
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
new file mode 100644
index 000000000000..7be796c5d5c9
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the PowerPC 86xx linux kernel.
+#
+
+
+ifeq ($(CONFIG_PPC_86xx),y)
+obj-$(CONFIG_SMP)		+= mpc86xx_smp.o
+endif
+obj-$(CONFIG_MPC8641_HPCN)	+= mpc86xx_hpcn.o
+obj-$(CONFIG_PCI)		+= pci.o mpc86xx_pcie.o
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
new file mode 100644
index 000000000000..5042253758b7
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -0,0 +1,54 @@
+/*
+ * MPC8641 HPCN board definitions
+ *
+ * Copyright 2006 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.
+ *
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ */
+
+#ifndef __MPC8641_HPCN_H__
+#define __MPC8641_HPCN_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+/* PCI interrupt controller */
+#define PIRQA		3
+#define PIRQB		4
+#define PIRQC		5
+#define PIRQD		6
+#define PIRQ7		7
+#define PIRQE		9
+#define PIRQF		10
+#define PIRQG		11
+#define PIRQH		12
+
+/* PCI-Express memory map */
+#define MPC86XX_PCIE_LOWER_IO        0x00000000
+#define MPC86XX_PCIE_UPPER_IO        0x00ffffff
+
+#define MPC86XX_PCIE_LOWER_MEM       0x80000000
+#define MPC86XX_PCIE_UPPER_MEM       0x9fffffff
+
+#define MPC86XX_PCIE_IO_BASE         0xe2000000
+#define MPC86XX_PCIE_MEM_OFFSET      0x00000000
+
+#define MPC86XX_PCIE_IO_SIZE         0x01000000
+
+#define PCIE1_CFG_ADDR_OFFSET    (0x8000)
+#define PCIE1_CFG_DATA_OFFSET    (0x8004)
+
+#define PCIE2_CFG_ADDR_OFFSET    (0x9000)
+#define PCIE2_CFG_DATA_OFFSET    (0x9004)
+
+#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET
+#define MPC86xx_PCIE_SIZE	(0x1000)
+
+#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
+
+#endif	/* __MPC8641_HPCN_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
new file mode 100644
index 000000000000..e3c9e4f417d3
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2006 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.
+ */
+
+#ifndef __MPC86XX_H__
+#define __MPC86XX_H__
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc86xx_* files. Mostly for use by mpc86xx_setup().
+ */
+
+extern int __init add_bridge(struct device_node *dev);
+
+extern void __init setup_indirect_pcie(struct pci_controller *hose,
+				       u32 cfg_addr, u32 cfg_data);
+extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose,
+					     void __iomem *cfg_addr,
+					     void __iomem *cfg_data);
+
+extern void __init mpc86xx_smp_init(void);
+
+#endif	/* __MPC86XX_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
new file mode 100644
index 000000000000..483c21df181e
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -0,0 +1,326 @@
+/*
+ * MPC86xx HPCN board specific routines
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+#include <asm/i8259.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ */
+
+static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO error/write-port unit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO outbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO inbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO outbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO inbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO outbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO inbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+	0x0,						/* External  4: */
+	0x0,						/* External  5: */
+	0x0,						/* External  6: */
+	0x0,						/* External  7: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis FPGA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI 8259 INTR Cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad ETH PHY */
+	0x0,						/* External 11: */
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+};
+
+
+void __init
+mpc86xx_hpcn_init_irq(void)
+{
+	struct mpic *mpic1;
+	phys_addr_t openpic_paddr;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
+
+	/* Alloc mpic structure and per isu has 16 INT entries. */
+	mpic1 = mpic_alloc(openpic_paddr,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250,
+			mpc86xx_hpcn_openpic_initsenses,
+			sizeof(mpc86xx_hpcn_openpic_initsenses),
+			" MPIC     ");
+	BUG_ON(mpic1 == NULL);
+
+	/* 48 Internal Interrupts */
+	mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200);
+	mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400);
+	mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600);
+
+	/* 16 External interrupts */
+	mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000);
+
+	mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+	mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL);
+	i8259_init(0, I8259_OFFSET);
+#endif
+}
+
+
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 *      PCI IDSEL/INTPIN->INTLINE
+		 *       A      B      C      D
+		 */
+		{PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 17 -- PCI Slot 1 */
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 18 -- PCI Slot 2 */
+		{0, 0, 0, 0},			/* IDSEL 19 */
+		{0, 0, 0, 0},			/* IDSEL 20 */
+		{0, 0, 0, 0},			/* IDSEL 21 */
+		{0, 0, 0, 0},			/* IDSEL 22 */
+		{0, 0, 0, 0},			/* IDSEL 23 */
+		{0, 0, 0, 0},			/* IDSEL 24 */
+		{0, 0, 0, 0},			/* IDSEL 25 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},	/* IDSEL 26 -- PCI Bridge*/
+		{PIRQC, 0, 0, 0},		/* IDSEL 27 -- LAN */
+		{PIRQE, PIRQF, PIRQH, PIRQ7},	/* IDSEL 28 -- USB 1.1 */
+		{PIRQE, PIRQF, PIRQG, 0},	/* IDSEL 29 -- Audio & Modem */
+		{PIRQH, 0, 0, 0},		/* IDSEL 30 -- LPC & PMU*/
+		{PIRQD, 0, 0, 0},		/* IDSEL 31 -- ATA */
+	};
+
+	const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
+}
+
+
+int
+mpc86xx_exclude_device(u_char bus, u_char devfn)
+{
+#if !defined(CONFIG_PCI)
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+
+static void __init
+mpc86xx_hpcn_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
+
+	np = of_find_node_by_type(NULL, "cpu");
+	if (np != 0) {
+		unsigned int *fp;
+
+		fp = (int *)get_property(np, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 50000000 / HZ;
+		of_node_put(np);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc86xx_map_irq;
+	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+#endif
+
+	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
+
+#ifdef  CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_SMP
+	mpc86xx_smp_init();
+#endif
+}
+
+
+void
+mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	uint memsize = total_memory;
+	const char *model = "";
+	uint svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "Machine\t\t: %s\n", model);
+	of_node_put(root);
+
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc86xx_hpcn_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "mpc86xx"))
+		return 1;	/* Looks good */
+
+	return 0;
+}
+
+
+void
+mpc86xx_restart(char *cmd)
+{
+	void __iomem *rstcr;
+
+	rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
+
+	local_irq_disable();
+
+	/* Assert reset request to Reset Control Register */
+	out_be32(rstcr, 0x2);
+
+	/* not reached */
+}
+
+
+long __init
+mpc86xx_time_init(void)
+{
+	unsigned int temp;
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	temp = mfspr(SPRN_HID0);
+	temp |= HID0_TBEN;
+	mtspr(SPRN_HID0, temp);
+	asm volatile("isync");
+
+	return 0;
+}
+
+
+define_machine(mpc86xx_hpcn) {
+	.name			= "MPC86xx HPCN",
+	.probe			= mpc86xx_hpcn_probe,
+	.setup_arch		= mpc86xx_hpcn_setup_arch,
+	.init_IRQ		= mpc86xx_hpcn_init_irq,
+	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= mpc86xx_restart,
+	.time_init		= mpc86xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
new file mode 100644
index 000000000000..a2f4f730213e
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
@@ -0,0 +1,173 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * 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.
+ *
+ * "Temporary" MPC8548 Errata file -
+ * The standard indirect_pci code should work with future silicon versions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "mpc86xx.h"
+
+#define PCI_CFG_OUT out_be32
+
+/* ERRATA PCI-Ex 14 PCIE Controller timeout */
+#define PCIE_FIX		out_be32(hose->cfg_addr+0x4, 0x0400ffff)
+
+
+static int
+indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u32 temp;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Possible artifact of CDCpp50937 needs further investigation */
+	if (devfn != 0x0 && bus->number == 0xff)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	PCIE_FIX;
+	if (bus->number == 0xff) {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000000 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	} else {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000001 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	}
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+	cfg_data = hose->cfg_data;
+	PCIE_FIX;
+	temp = in_le32(cfg_data);
+	switch (len) {
+	case 1:
+		*val = (temp >> (((offset & 3))*8)) & 0xff;
+		break;
+	case 2:
+		*val = (temp >> (((offset & 3))*8)) & 0xffff;
+		break;
+	default:
+		*val = temp;
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+		      int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u32 temp;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Possible artifact of CDCpp50937 needs further investigation */
+	if (devfn != 0x0 && bus->number == 0xff)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	PCIE_FIX;
+	if (bus->number == 0xff) {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000000 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	} else {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000001 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+        }
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+	cfg_data = hose->cfg_data;
+	switch (len) {
+	case 1:
+		PCIE_FIX;
+		temp = in_le32(cfg_data);
+		temp = (temp & ~(0xff << ((offset & 3) * 8))) |
+			(val << ((offset & 3) * 8));
+		PCIE_FIX;
+		out_le32(cfg_data, temp);
+		break;
+	case 2:
+		PCIE_FIX;
+		temp = in_le32(cfg_data);
+		temp = (temp & ~(0xffff << ((offset & 3) * 8)));
+		temp |= (val << ((offset & 3) * 8)) ;
+		PCIE_FIX;
+		out_le32(cfg_data, temp);
+		break;
+	default:
+		PCIE_FIX;
+		out_le32(cfg_data, val);
+		break;
+	}
+	PCIE_FIX;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pcie_ops = {
+	indirect_read_config_pcie,
+	indirect_write_config_pcie
+};
+
+void __init
+setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+	void __iomem * cfg_data)
+{
+	hose->cfg_addr = cfg_addr;
+	hose->cfg_data = cfg_data;
+	hose->ops = &indirect_pcie_ops;
+}
+
+void __init
+setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	unsigned long base = cfg_addr & PAGE_MASK;
+	void __iomem *mbase, *addr, *data;
+
+	mbase = ioremap(base, PAGE_SIZE);
+	addr = mbase + (cfg_addr & ~PAGE_MASK);
+	if ((cfg_data & PAGE_MASK) != base)
+		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+	data = mbase + (cfg_data & ~PAGE_MASK);
+	setup_indirect_pcie_nomap(hose, addr, data);
+}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
new file mode 100644
index 000000000000..944ec4b71416
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -0,0 +1,117 @@
+/*
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ *         Zhang Wei <wei.zhang@freescale.com>
+ *
+ * Copyright 2006 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/pci-bridge.h>
+#include <asm-powerpc/mpic.h>
+#include <asm/mpc86xx.h>
+#include <asm/cacheflush.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+extern void __secondary_start_mpc86xx(void);
+extern unsigned long __secondary_hold_acknowledge;
+
+
+static void __init
+smp_86xx_release_core(int nr)
+{
+	void *mcm_vaddr;
+	unsigned long vaddr, pcr;
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	/*
+	 * Startup Core #nr.
+	 */
+	mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
+			    MPC86xx_MCM_SIZE);
+	vaddr = (unsigned long)mcm_vaddr +  MCM_PORT_CONFIG_OFFSET;
+	pcr = in_be32((volatile unsigned *)vaddr);
+	pcr |= 1 << (nr + 24);
+	out_be32((volatile unsigned *)vaddr, pcr);
+}
+
+
+static void __init
+smp_86xx_kick_cpu(int nr)
+{
+	unsigned int save_vector;
+	unsigned long target, flags;
+	int n = 0;
+	volatile unsigned int *vector
+		 = (volatile unsigned int *)(KERNELBASE + 0x100);
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
+
+	local_irq_save(flags);
+	local_irq_disable();
+
+	/* Save reset vector */
+	save_vector = *vector;
+
+	/* Setup fake reset vector to call __secondary_start_mpc86xx. */
+	target = (unsigned long) __secondary_start_mpc86xx;
+	create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
+
+	/* Kick that CPU */
+	smp_86xx_release_core(nr);
+
+	/* Wait a bit for the CPU to take the exception. */
+	while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))
+		mdelay(1);
+
+	/* Restore the exception vector */
+	*vector = save_vector;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+	local_irq_restore(flags);
+
+	pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
+}
+
+
+static void __init
+smp_86xx_setup_cpu(int cpu_nr)
+{
+	mpic_setup_this_cpu();
+}
+
+
+struct smp_ops_t smp_86xx_ops = {
+	.message_pass = smp_mpic_message_pass,
+	.probe = smp_mpic_probe,
+	.kick_cpu = smp_86xx_kick_cpu,
+	.setup_cpu = smp_86xx_setup_cpu,
+	.take_timebase = smp_generic_take_timebase,
+	.give_timebase = smp_generic_give_timebase,
+};
+
+
+void __init
+mpc86xx_smp_init(void)
+{
+	smp_ops = &smp_86xx_ops;
+}
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
new file mode 100644
index 000000000000..5180df7c75bc
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -0,0 +1,325 @@
+/*
+ * MPC86XX pci setup code
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 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.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/immap_86xx.h>
+#include <asm/pci-bridge.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
+struct pcie_outbound_window_regs {
+	uint    pexotar;               /* 0x.0 - PCI Express outbound translation address register */
+	uint    pexotear;              /* 0x.4 - PCI Express outbound translation extended address register */
+	uint    pexowbar;              /* 0x.8 - PCI Express outbound window base address register */
+	char    res1[4];
+	uint    pexowar;               /* 0x.10 - PCI Express outbound window attributes register */
+	char    res2[12];
+};
+
+struct pcie_inbound_window_regs {
+	uint    pexitar;               /* 0x.0 - PCI Express inbound translation address register */
+	char    res1[4];
+	uint    pexiwbar;              /* 0x.8 - PCI Express inbound window base address register */
+	uint    pexiwbear;             /* 0x.c - PCI Express inbound window base extended address register */
+	uint    pexiwar;               /* 0x.10 - PCI Express inbound window attributes register */
+	char    res2[12];
+};
+
+static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc)
+{
+	volatile struct ccsr_pex *pcie;
+	volatile struct pcie_outbound_window_regs *pcieow;
+	volatile struct pcie_inbound_window_regs *pcieiw;
+	int i = 0;
+
+	DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start,
+			rsrc->end - rsrc->start + 1);
+	pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+
+	/* Disable all windows (except pexowar0 since its ignored) */
+	pcie->pexowar1 = 0;
+	pcie->pexowar2 = 0;
+ 	pcie->pexowar3 = 0;
+ 	pcie->pexowar4 = 0;
+ 	pcie->pexiwar1 = 0;
+ 	pcie->pexiwar2 = 0;
+ 	pcie->pexiwar3 = 0;
+
+ 	pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1;
+ 	pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1;
+
+ 	/* Setup outbound MEM window */
+ 	for(i = 0; i < 3; i++)
+ 		if (hose->mem_resources[i].flags & IORESOURCE_MEM){
+ 			DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n",
+ 				hose->mem_resources[i].start,
+ 				hose->mem_resources[i].end
+ 				  - hose->mem_resources[i].start + 1);
+ 			pcieow->pexotar = (hose->mem_resources[i].start) >> 12
+ 				& 0x000fffff;
+ 			pcieow->pexotear = 0;
+ 			pcieow->pexowbar = (hose->mem_resources[i].start) >> 12
+ 				& 0x000fffff;
+ 			/* Enable, Mem R/W */
+ 			pcieow->pexowar = 0x80044000 |
+ 				(__ilog2(hose->mem_resources[i].end
+ 					 - hose->mem_resources[i].start + 1)
+ 				 - 1);
+ 			pcieow++;
+ 		}
+
+ 	/* Setup outbound IO window */
+ 	if (hose->io_resource.flags & IORESOURCE_IO){
+ 		DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n",
+ 			hose->io_resource.start,
+ 			hose->io_resource.end - hose->io_resource.start + 1,
+ 			hose->io_base_phys);
+ 		pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff;
+ 		pcieow->pexotear = 0;
+ 		pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff;
+ 		/* Enable, IO R/W */
+ 		pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end
+ 					- hose->io_resource.start + 1) - 1);
+ 	}
+
+ 	/* Setup 2G inbound Memory Window @ 0 */
+ 	pcieiw->pexitar = 0x00000000;
+ 	pcieiw->pexiwbar = 0x00000000;
+ 	/* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
+ 	pcieiw->pexiwar = 0xa0f5501e;
+}
+
+static void __init
+mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
+{
+	volatile struct ccsr_pex *pcie;
+	u16 cmd;
+	unsigned int temps;
+
+	DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
+			pcie_offset, pcie_size);
+
+	pcie = ioremap(pcie_offset, pcie_size);
+
+	early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+	    | PCI_COMMAND_IO;
+	early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
+
+	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+
+	/* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
+	early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
+	temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
+	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
+}
+
+int __init add_bridge(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct resource rsrc;
+	int *bus_range;
+	int has_address = 0;
+	int primary = 0;
+
+	DBG("Adding PCIE host bridge %s\n", dev->full_name);
+
+	/* Fetch host bridge registers address */
+	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+	/* Get bus range if any */
+	bus_range = (int *) get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int))
+		printk(KERN_WARNING "Can't get bus-range for %s, assume"
+		       " bus 0\n", dev->full_name);
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return -ENOMEM;
+	hose->arch_data = dev;
+	hose->set_cfg_type = 1;
+
+	/* last_busno = 0xfe cause by MPC8641 PCIE bug */
+	hose->first_busno = bus_range ? bus_range[0] : 0x0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+
+	setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+
+	/* Setup the PCIE host controller. */
+	mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
+
+	if ((rsrc.start & 0xfffff) == 0x8000)
+		primary = 1;
+
+	printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
+	       "Firmware bus number: %d->%d\n",
+		rsrc.start, hose->first_busno, hose->last_busno);
+
+	DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+		hose, hose->cfg_addr, hose->cfg_data);
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(hose, dev, primary);
+
+	/* Setup PEX window registers */
+	setup_pcie_atmu(hose, &rsrc);
+
+	return 0;
+}
+
+static void __devinit quirk_ali1575(struct pci_dev *dev)
+{
+	unsigned short temp;
+
+	/*
+	 * ALI1575 interrupts route table setup:
+	 *
+	 * IRQ pin   IRQ#
+	 * PIRQA ---- 3
+	 * PIRQB ---- 4
+	 * PIRQC ---- 5
+	 * PIRQD ---- 6
+	 * PIRQE ---- 9
+	 * PIRQF ---- 10
+	 * PIRQG ---- 11
+	 * PIRQH ---- 12
+	 *
+	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
+	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
+	 */
+	pci_write_config_dword(dev, 0x48, 0xb9317542);
+
+	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
+	pci_write_config_byte(dev, 0x86, 0x0c);
+
+	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
+	pci_write_config_byte(dev, 0x87, 0x0d);
+
+	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x88, 0x0f);
+
+	/* USB 2.0 controller, interrupt: PIRQ7 */
+	pci_write_config_byte(dev, 0x74, 0x06);
+
+	/* Audio controller, interrupt: PIRQE */
+	pci_write_config_byte(dev, 0x8a, 0x0c);
+
+	/* Modem controller, interrupt: PIRQF */
+	pci_write_config_byte(dev, 0x8b, 0x0d);
+
+	/* HD audio controller, interrupt: PIRQG */
+	pci_write_config_byte(dev, 0x8c, 0x0e);
+
+	/* Serial ATA interrupt: PIRQD */
+	pci_write_config_byte(dev, 0x8d, 0x0b);
+
+	/* SMB interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x8e, 0x0f);
+
+	/* PMU ACPI SCI interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x8f, 0x0f);
+
+	/* Primary PATA IDE IRQ: 14
+	 * Secondary PATA IDE IRQ: 15
+	 */
+	pci_write_config_byte(dev, 0x44, 0x3d);
+	pci_write_config_byte(dev, 0x75, 0x0f);
+
+	/* Set IRQ14 and IRQ15 to legacy IRQs */
+	pci_read_config_word(dev, 0x46, &temp);
+	temp |= 0xc000;
+	pci_write_config_word(dev, 0x46, temp);
+
+	/* Set i8259 interrupt trigger
+	 * IRQ 3:  Level
+	 * IRQ 4:  Level
+	 * IRQ 5:  Level
+	 * IRQ 6:  Level
+	 * IRQ 7:  Level
+	 * IRQ 9:  Level
+	 * IRQ 10: Level
+	 * IRQ 11: Level
+	 * IRQ 12: Level
+	 * IRQ 14: Edge
+	 * IRQ 15: Edge
+	 */
+	outb(0xfa, 0x4d0);
+	outb(0x1e, 0x4d1);
+}
+
+static void __devinit quirk_uli5288(struct pci_dev *dev)
+{
+	unsigned char c;
+
+	pci_read_config_byte(dev,0x83,&c);
+	c |= 0x80;
+	pci_write_config_byte(dev, 0x83, c);
+
+	pci_write_config_byte(dev, 0x09, 0x01);
+	pci_write_config_byte(dev, 0x0a, 0x06);
+
+	pci_read_config_byte(dev,0x83,&c);
+	c &= 0x7f;
+	pci_write_config_byte(dev, 0x83, c);
+
+	pci_read_config_byte(dev,0x84,&c);
+	c |= 0x01;
+	pci_write_config_byte(dev, 0x84, c);
+}
+
+static void __devinit quirk_uli5229(struct pci_dev *dev)
+{
+	unsigned short temp;
+	pci_write_config_word(dev, 0x04, 0x0405);
+	pci_read_config_word(dev, 0x4a, &temp);
+	temp |= 0x1000;
+	pci_write_config_word(dev, 0x4a, temp);
+}
+
+static void __devinit early_uli5249(struct pci_dev *dev)
+{
+	unsigned char temp;
+	pci_write_config_word(dev, 0x04, 0x0007);
+	pci_read_config_byte(dev, 0x7c, &temp);
+	pci_write_config_byte(dev, 0x7c, 0x80);
+	pci_write_config_byte(dev, 0x09, 0x01);
+	pci_write_config_byte(dev, 0x7c, temp);
+	dev->class |= 0x1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index c4f6b0d2d140..292863694562 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_PPC_CHRP)		+= chrp/
 obj-$(CONFIG_4xx)		+= 4xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_PPC_85xx)		+= 85xx/
+obj-$(CONFIG_PPC_86xx)		+= 86xx/
 obj-$(CONFIG_PPC_PSERIES)	+= pseries/
 obj-$(CONFIG_PPC_ISERIES)	+= iseries/
 obj-$(CONFIG_PPC_MAPLE)		+= maple/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 6a02d51086c8..352bbbacde9a 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -5,15 +5,24 @@ config SPU_FS
 	tristate "SPU file system"
 	default m
 	depends on PPC_CELL
+	select SPU_BASE
 	help
 	  The SPU file system is used to access Synergistic Processing
 	  Units on machines implementing the Broadband Processor
 	  Architecture.
 
+config SPU_BASE
+	bool
+	default n
+
 config SPUFS_MMAP
 	bool
 	depends on SPU_FS && SPARSEMEM
 	select MEMORY_HOTPLUG
 	default y
 
+config CBE_RAS
+	bool "RAS features for bare metal Cell BE"
+	default y
+
 endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index e570bad06394..c89cdd67383b 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -1,16 +1,15 @@
-obj-y			+= interrupt.o iommu.o setup.o spider-pic.o
-obj-y			+= pervasive.o
+obj-$(CONFIG_PPC_CELL_NATIVE)		+= interrupt.o iommu.o setup.o \
+					   cbe_regs.o spider-pic.o pervasive.o
+obj-$(CONFIG_CBE_RAS)			+= ras.o
 
-obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_SPU_FS)	+= spu-base.o spufs/
-
-spu-base-y		+= spu_base.o spu_priv1.o
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_CELL_NATIVE)		+= smp.o
+endif
 
 # needed only when building loadable spufs.ko
-spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
-obj-y			+= $(spufs-modular-m)
-
-# always needed in kernel
-spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
-obj-y			+= $(spufs-builtin-y) $(spufs-builtin-m)
+spufs-modular-$(CONFIG_SPU_FS)		+= spu_syscalls.o
+spu-priv1-$(CONFIG_PPC_CELL_NATIVE)	+= spu_priv1_mmio.o
 
+obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
+					   $(spufs-modular-m) \
+					   $(spu-priv1-y) spufs/
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
new file mode 100644
index 000000000000..2dfde61c8412
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -0,0 +1,128 @@
+/*
+ * cbe_regs.c
+ *
+ * Accessor routines for the various MMIO register blocks of the CBE
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+
+#include <linux/config.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/ptrace.h>
+
+#include "cbe_regs.h"
+
+#define MAX_CBE		2
+
+/*
+ * Current implementation uses "cpu" nodes. We build our own mapping
+ * array of cpu numbers to cpu nodes locally for now to allow interrupt
+ * time code to have a fast path rather than call of_get_cpu_node(). If
+ * we implement cpu hotplug, we'll have to install an appropriate norifier
+ * in order to release references to the cpu going away
+ */
+static struct cbe_regs_map
+{
+	struct device_node *cpu_node;
+	struct cbe_pmd_regs __iomem *pmd_regs;
+	struct cbe_iic_regs __iomem *iic_regs;
+} cbe_regs_maps[MAX_CBE];
+static int cbe_regs_map_count;
+
+static struct cbe_thread_map
+{
+	struct device_node *cpu_node;
+	struct cbe_regs_map *regs;
+} cbe_thread_map[NR_CPUS];
+
+static struct cbe_regs_map *cbe_find_map(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < cbe_regs_map_count; i++)
+		if (cbe_regs_maps[i].cpu_node == np)
+			return &cbe_regs_maps[i];
+	return NULL;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
+{
+	struct cbe_regs_map *map = cbe_find_map(np);
+	if (map == NULL)
+		return NULL;
+	return map->pmd_regs;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
+{
+	struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+	if (map == NULL)
+		return NULL;
+	return map->pmd_regs;
+}
+
+
+struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
+{
+	struct cbe_regs_map *map = cbe_find_map(np);
+	if (map == NULL)
+		return NULL;
+	return map->iic_regs;
+}
+struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
+{
+	struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+	if (map == NULL)
+		return NULL;
+	return map->iic_regs;
+}
+
+void __init cbe_regs_init(void)
+{
+	int i;
+	struct device_node *cpu;
+
+	/* Build local fast map of CPUs */
+	for_each_cpu(i)
+		cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
+
+	/* Find maps for each device tree CPU */
+	for_each_node_by_type(cpu, "cpu") {
+		struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
+
+		/* That hack must die die die ! */
+		struct address_prop {
+			unsigned long address;
+			unsigned int len;
+		} __attribute__((packed)) *prop;
+
+
+		if (cbe_regs_map_count > MAX_CBE) {
+			printk(KERN_ERR "cbe_regs: More BE chips than supported"
+			       "!\n");
+			cbe_regs_map_count--;
+			return;
+		}
+		map->cpu_node = cpu;
+		for_each_cpu(i)
+			if (cbe_thread_map[i].cpu_node == cpu)
+				cbe_thread_map[i].regs = map;
+
+		prop = (struct address_prop *)get_property(cpu, "pervasive",
+							   NULL);
+		if (prop != NULL)
+			map->pmd_regs = ioremap(prop->address, prop->len);
+
+		prop = (struct address_prop *)get_property(cpu, "iic",
+							   NULL);
+		if (prop != NULL)
+			map->iic_regs = ioremap(prop->address, prop->len);
+	}
+}
+
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
new file mode 100644
index 000000000000..e76e4a6af5bc
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -0,0 +1,129 @@
+/*
+ * cbe_regs.h
+ *
+ * This file is intended to hold the various register definitions for CBE
+ * on-chip system devices (memory controller, IO controller, etc...)
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+#ifndef CBE_REGS_H
+#define CBE_REGS_H
+
+/*
+ *
+ * Some HID register definitions
+ *
+ */
+
+/* CBE specific HID0 bits */
+#define HID0_CBE_THERM_WAKEUP	0x0000020000000000ul
+#define HID0_CBE_SYSERR_WAKEUP	0x0000008000000000ul
+#define HID0_CBE_THERM_INT_EN	0x0000000400000000ul
+#define HID0_CBE_SYSERR_INT_EN	0x0000000200000000ul
+
+
+/*
+ *
+ * Pervasive unit register definitions
+ *
+ */
+
+struct cbe_pmd_regs {
+	u8 pad_0x0000_0x0800[0x0800 - 0x0000];			/* 0x0000 */
+
+	/* Thermal Sensor Registers */
+	u64  ts_ctsr1;						/* 0x0800 */
+	u64  ts_ctsr2;						/* 0x0808 */
+	u64  ts_mtsr1;						/* 0x0810 */
+	u64  ts_mtsr2;						/* 0x0818 */
+	u64  ts_itr1;						/* 0x0820 */
+	u64  ts_itr2;						/* 0x0828 */
+	u64  ts_gitr;						/* 0x0830 */
+	u64  ts_isr;						/* 0x0838 */
+	u64  ts_imr;						/* 0x0840 */
+	u64  tm_cr1;						/* 0x0848 */
+	u64  tm_cr2;						/* 0x0850 */
+	u64  tm_simr;						/* 0x0858 */
+	u64  tm_tpr;						/* 0x0860 */
+	u64  tm_str1;						/* 0x0868 */
+	u64  tm_str2;						/* 0x0870 */
+	u64  tm_tsr;						/* 0x0878 */
+
+	/* Power Management */
+	u64  pm_control;					/* 0x0880 */
+#define CBE_PMD_PAUSE_ZERO_CONTROL		0x10000
+	u64  pm_status;						/* 0x0888 */
+
+	/* Time Base Register */
+	u64  tbr;						/* 0x0890 */
+
+	u8   pad_0x0898_0x0c00 [0x0c00 - 0x0898];		/* 0x0898 */
+
+	/* Fault Isolation Registers */
+	u64  checkstop_fir;					/* 0x0c00 */
+	u64  recoverable_fir;
+	u64  spec_att_mchk_fir;
+	u64  fir_mode_reg;
+	u64  fir_enable_mask;
+
+	u8   pad_0x0c28_0x1000 [0x1000 - 0x0c28];		/* 0x0c28 */
+};
+
+extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
+extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
+
+/*
+ *
+ * IIC unit register definitions
+ *
+ */
+
+struct cbe_iic_pending_bits {
+	u32 data;
+	u8 flags;
+	u8 class;
+	u8 source;
+	u8 prio;
+};
+
+#define CBE_IIC_IRQ_VALID	0x80
+#define CBE_IIC_IRQ_IPI		0x40
+
+struct cbe_iic_thread_regs {
+	struct cbe_iic_pending_bits pending;
+	struct cbe_iic_pending_bits pending_destr;
+	u64 generate;
+	u64 prio;
+};
+
+struct cbe_iic_regs {
+	u8	pad_0x0000_0x0400[0x0400 - 0x0000];		/* 0x0000 */
+
+	/* IIC interrupt registers */
+	struct	cbe_iic_thread_regs thread[2];			/* 0x0400 */
+	u64     iic_ir;						/* 0x0440 */
+	u64     iic_is;						/* 0x0448 */
+
+	u8	pad_0x0450_0x0500[0x0500 - 0x0450];		/* 0x0450 */
+
+	/* IOC FIR */
+	u64	ioc_fir_reset;					/* 0x0500 */
+	u64	ioc_fir_set;
+	u64	ioc_checkstop_enable;
+	u64	ioc_fir_error_mask;
+	u64	ioc_syserr_enable;
+	u64	ioc_fir;
+
+	u8	pad_0x0530_0x1000[0x1000 - 0x0530];		/* 0x0530 */
+};
+
+extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
+extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
+
+
+/* Init this module early */
+extern void cbe_regs_init(void);
+
+
+#endif /* CBE_REGS_H */
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 978be1c30c1b..f4e2d8805c9e 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -33,29 +33,10 @@
 #include <asm/ptrace.h>
 
 #include "interrupt.h"
-
-struct iic_pending_bits {
-	u32 data;
-	u8 flags;
-	u8 class;
-	u8 source;
-	u8 prio;
-};
-
-enum iic_pending_flags {
-	IIC_VALID = 0x80,
-	IIC_IPI   = 0x40,
-};
-
-struct iic_regs {
-	struct iic_pending_bits pending;
-	struct iic_pending_bits pending_destr;
-	u64 generate;
-	u64 prio;
-};
+#include "cbe_regs.h"
 
 struct iic {
-	struct iic_regs __iomem *regs;
+	struct cbe_iic_thread_regs __iomem *regs;
 	u8 target_id;
 };
 
@@ -115,7 +96,7 @@ static struct hw_interrupt_type iic_pic = {
 	.end = iic_end,
 };
 
-static int iic_external_get_irq(struct iic_pending_bits pending)
+static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
 {
 	int irq;
 	unsigned char node, unit;
@@ -136,8 +117,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending)
 		 * One of these units can be connected
 		 * to an external interrupt controller.
 		 */
-		if (pending.prio > 0x3f ||
-		    pending.class != 2)
+		if (pending.class != 2)
 			break;
 		irq = IIC_EXT_OFFSET
 			+ spider_get_irq(node)
@@ -168,15 +148,15 @@ int iic_get_irq(struct pt_regs *regs)
 {
 	struct iic *iic;
 	int irq;
-	struct iic_pending_bits pending;
+	struct cbe_iic_pending_bits pending;
 
 	iic = &__get_cpu_var(iic);
 	*(unsigned long *) &pending = 
 		in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
 
 	irq = -1;
-	if (pending.flags & IIC_VALID) {
-		if (pending.flags & IIC_IPI) {
+	if (pending.flags & CBE_IIC_IRQ_VALID) {
+		if (pending.flags & CBE_IIC_IRQ_IPI) {
 			irq = IIC_IPI_OFFSET + (pending.prio >> 4);
 /*
 			if (irq > 0x80)
@@ -226,7 +206,7 @@ static int setup_iic_hardcoded(void)
 			regs += 0x20;
 
 		printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
-		iic->regs = ioremap(regs, sizeof(struct iic_regs));
+		iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
 	}
 
@@ -267,12 +247,12 @@ static int setup_iic(void)
 		}
 
  		iic = &per_cpu(iic, np[0]);
- 		iic->regs = ioremap(regs[0], sizeof(struct iic_regs));
+ 		iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
  		printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
 
  		iic = &per_cpu(iic, np[1]);
- 		iic->regs = ioremap(regs[2], sizeof(struct iic_regs));
+ 		iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
  		printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
 
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index a49ceb799a8e..a35004e14c69 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -473,6 +473,16 @@ static int cell_dma_supported(struct device *dev, u64 mask)
 	return mask < 0x100000000ull;
 }
 
+static struct dma_mapping_ops cell_iommu_ops = {
+	.alloc_coherent = cell_alloc_coherent,
+	.free_coherent = cell_free_coherent,
+	.map_single = cell_map_single,
+	.unmap_single = cell_unmap_single,
+	.map_sg = cell_map_sg,
+	.unmap_sg = cell_unmap_sg,
+	.dma_supported = cell_dma_supported,
+};
+
 void cell_init_iommu(void)
 {
 	int setup_bus = 0;
@@ -498,11 +508,5 @@ void cell_init_iommu(void)
 		}
 	}
 
-	pci_dma_ops.alloc_coherent = cell_alloc_coherent;
-	pci_dma_ops.free_coherent = cell_free_coherent;
-	pci_dma_ops.map_single = cell_map_single;
-	pci_dma_ops.unmap_single = cell_unmap_single;
-	pci_dma_ops.map_sg = cell_map_sg;
-	pci_dma_ops.unmap_sg = cell_unmap_sg;
-	pci_dma_ops.dma_supported = cell_dma_supported;
+	pci_dma_ops = cell_iommu_ops;
 }
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 7eed8c624517..695ac4e1617e 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -37,36 +37,28 @@
 #include <asm/reg.h>
 
 #include "pervasive.h"
+#include "cbe_regs.h"
 
 static DEFINE_SPINLOCK(cbe_pervasive_lock);
-struct cbe_pervasive {
-	struct pmd_regs __iomem *regs;
-	unsigned int thread;
-};
-
-/* can't use per_cpu from setup_arch */
-static struct cbe_pervasive cbe_pervasive[NR_CPUS];
 
 static void __init cbe_enable_pause_zero(void)
 {
 	unsigned long thread_switch_control;
 	unsigned long temp_register;
-	struct cbe_pervasive *p;
-	int thread;
+	struct cbe_pmd_regs __iomem *pregs;
 
 	spin_lock_irq(&cbe_pervasive_lock);
-	p = &cbe_pervasive[smp_processor_id()];
-
-	if (!cbe_pervasive->regs)
+	pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
+	if (pregs == NULL)
 		goto out;
 
 	pr_debug("Power Management: CPU %d\n", smp_processor_id());
 
 	 /* Enable Pause(0) control bit */
-	temp_register = in_be64(&p->regs->pm_control);
+	temp_register = in_be64(&pregs->pm_control);
 
-	out_be64(&p->regs->pm_control,
-		 temp_register|PMD_PAUSE_ZERO_CONTROL);
+	out_be64(&pregs->pm_control,
+		 temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
 
 	/* Enable DEC and EE interrupt request */
 	thread_switch_control  = mfspr(SPRN_TSC_CELL);
@@ -75,25 +67,16 @@ static void __init cbe_enable_pause_zero(void)
 	switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) {
 	case CTRL_CT0:
 		thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
-		thread = 0;
 		break;
 	case CTRL_CT1:
 		thread_switch_control |= TSC_CELL_DEC_ENABLE_1;
-		thread = 1;
 		break;
 	default:
 		printk(KERN_WARNING "%s: unknown configuration\n",
 			__FUNCTION__);
-		thread = -1;
 		break;
 	}
 
-	if (p->thread != thread)
-		printk(KERN_WARNING "%s: device tree inconsistant, "
-				     "cpu %i: %d/%d\n", __FUNCTION__,
-				     smp_processor_id(),
-				     p->thread, thread);
-
 	mtspr(SPRN_TSC_CELL, thread_switch_control);
 
 out:
@@ -104,6 +87,11 @@ static void cbe_idle(void)
 {
 	unsigned long ctrl;
 
+	/* Why do we do that on every idle ? Couldn't that be done once for
+	 * all or do we lose the state some way ? Also, the pm_control
+	 * register setting, that can't be set once at boot ? We really want
+	 * to move that away in order to implement a simple powersave
+	 */
 	cbe_enable_pause_zero();
 
 	while (1) {
@@ -152,8 +140,15 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
 		timer_interrupt(regs);
 		break;
 	case SRR1_WAKEMT:
-		/* no action required */
 		break;
+#ifdef CONFIG_CBE_RAS
+	case SRR1_WAKESYSERR:
+		cbe_system_error_exception(regs);
+		break;
+	case SRR1_WAKETHERM:
+		cbe_thermal_exception(regs);
+		break;
+#endif /* CONFIG_CBE_RAS */
 	default:
 		/* do system reset */
 		return 0;
@@ -162,68 +157,11 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
 	return 1;
 }
 
-static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p)
-{
-	struct device_node *node;
-	unsigned int *int_servers;
-	char *addr;
-	unsigned long real_address;
-	unsigned int size;
-
-	struct pmd_regs __iomem *pmd_mmio_area;
-	int hardid, thread;
-	int proplen;
-
-	pmd_mmio_area = NULL;
-	hardid = get_hard_smp_processor_id(cpu);
-	for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) {
-		int_servers = (void *) get_property(node,
-				"ibm,ppc-interrupt-server#s", &proplen);
-		if (!int_servers) {
-			printk(KERN_WARNING "%s misses "
-				"ibm,ppc-interrupt-server#s property",
-				node->full_name);
-			continue;
-		}
-		for (thread = 0; thread < proplen / sizeof (int); thread++) {
-			if (hardid == int_servers[thread]) {
-				addr = get_property(node, "pervasive", NULL);
-				goto found;
-			}
-		}
-	}
-
-	printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu);
-	return -EINVAL;
-
-found:
-	real_address = *(unsigned long*) addr;
-	addr += sizeof (unsigned long);
-	size = *(unsigned int*) addr;
-
-	pr_debug("pervasive area for CPU %d at %lx, size %x\n",
-			cpu, real_address, size);
-	p->regs = ioremap(real_address, size);
-	p->thread = thread;
-	return 0;
-}
-
-void __init cell_pervasive_init(void)
+void __init cbe_pervasive_init(void)
 {
-	struct cbe_pervasive *p;
-	int cpu;
-	int ret;
-
 	if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
 		return;
 
-	for_each_possible_cpu(cpu) {
-		p = &cbe_pervasive[cpu];
-		ret = cbe_find_pmd_mmio(cpu, p);
-		if (ret)
-			return;
-	}
-
 	ppc_md.idle_loop = cbe_idle;
 	ppc_md.system_reset_exception = cbe_system_reset_exception;
 }
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index da1fb85ca3e8..7b50947f8044 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -25,38 +25,9 @@
 #ifndef PERVASIVE_H
 #define PERVASIVE_H
 
-struct pmd_regs {
-	u8 pad_0x0000_0x0800[0x0800 - 0x0000];			/* 0x0000 */
-
-	/* Thermal Sensor Registers */
-	u64  ts_ctsr1;						/* 0x0800 */
-	u64  ts_ctsr2;						/* 0x0808 */
-	u64  ts_mtsr1;						/* 0x0810 */
-	u64  ts_mtsr2;						/* 0x0818 */
-	u64  ts_itr1;						/* 0x0820 */
-	u64  ts_itr2;						/* 0x0828 */
-	u64  ts_gitr;						/* 0x0830 */
-	u64  ts_isr;						/* 0x0838 */
-	u64  ts_imr;						/* 0x0840 */
-	u64  tm_cr1;						/* 0x0848 */
-	u64  tm_cr2;						/* 0x0850 */
-	u64  tm_simr;						/* 0x0858 */
-	u64  tm_tpr;						/* 0x0860 */
-	u64  tm_str1;						/* 0x0868 */
-	u64  tm_str2;						/* 0x0870 */
-	u64  tm_tsr;						/* 0x0878 */
-
-	/* Power Management */
-	u64  pm_control;					/* 0x0880 */
-#define PMD_PAUSE_ZERO_CONTROL		0x10000
-	u64  pm_status;						/* 0x0888 */
-
-	/* Time Base Register */
-	u64  tbr;						/* 0x0890 */
-
-	u8   pad_0x0898_0x1000 [0x1000 - 0x0898];		/* 0x0898 */
-};
-
-void __init cell_pervasive_init(void);
+extern void cbe_pervasive_init(void);
+extern void cbe_system_error_exception(struct pt_regs *regs);
+extern void cbe_maintenance_exception(struct pt_regs *regs);
+extern void cbe_thermal_exception(struct pt_regs *regs);
 
 #endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
new file mode 100644
index 000000000000..033ad6e2827b
--- /dev/null
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -0,0 +1,112 @@
+#define DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+#include "ras.h"
+#include "cbe_regs.h"
+
+
+static void dump_fir(int cpu)
+{
+	struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu);
+	struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu);
+
+	if (pregs == NULL)
+		return;
+
+	/* Todo: do some nicer parsing of bits and based on them go down
+	 * to other sub-units FIRs and not only IIC
+	 */
+	printk(KERN_ERR "Global Checkstop FIR    : 0x%016lx\n",
+	       in_be64(&pregs->checkstop_fir));
+	printk(KERN_ERR "Global Recoverable FIR  : 0x%016lx\n",
+	       in_be64(&pregs->checkstop_fir));
+	printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n",
+	       in_be64(&pregs->spec_att_mchk_fir));
+
+	if (iregs == NULL)
+		return;
+	printk(KERN_ERR "IOC FIR                 : 0x%016lx\n",
+	       in_be64(&iregs->ioc_fir));
+
+}
+
+void cbe_system_error_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu);
+	dump_fir(cpu);
+	dump_stack();
+}
+
+void cbe_maintenance_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * Nothing implemented for the maintenance interrupt at this point
+	 */
+
+	printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu);
+	dump_stack();
+}
+
+void cbe_thermal_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * Nothing implemented for the thermal interrupt at this point
+	 */
+
+	printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu);
+	dump_stack();
+}
+
+static int cbe_machine_check_handler(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu);
+	dump_fir(cpu);
+
+	/* No recovery from this code now, lets continue */
+	return 0;
+}
+
+void __init cbe_ras_init(void)
+{
+	unsigned long hid0;
+
+	/*
+	 * Enable System Error & thermal interrupts and wakeup conditions
+	 */
+
+	hid0 = mfspr(SPRN_HID0);
+	hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP |
+		HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP;
+	mtspr(SPRN_HID0, hid0);
+	mb();
+
+	/*
+	 * Install machine check handler. Leave setting of precise mode to
+	 * what the firmware did for now
+	 */
+	ppc_md.machine_check_exception = cbe_machine_check_handler;
+	mb();
+
+	/*
+	 * For now, we assume that IOC_FIR is already set to forward some
+	 * error conditions to the System Error handler. If that is not true
+	 * then it will have to be fixed up here.
+	 */
+}
diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h
new file mode 100644
index 000000000000..eb7ee54c82a0
--- /dev/null
+++ b/arch/powerpc/platforms/cell/ras.h
@@ -0,0 +1,9 @@
+#ifndef RAS_H
+#define RAS_H
+
+extern void cbe_system_error_exception(struct pt_regs *regs);
+extern void cbe_maintenance_exception(struct pt_regs *regs);
+extern void cbe_thermal_exception(struct pt_regs *regs);
+extern void cbe_ras_init(void);
+
+#endif /* RAS_H */
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fd3e5609e3e0..3d1831d331e5 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -49,10 +49,13 @@
 #include <asm/ppc-pci.h>
 #include <asm/irq.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 
 #include "interrupt.h"
 #include "iommu.h"
+#include "cbe_regs.h"
 #include "pervasive.h"
+#include "ras.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -81,6 +84,15 @@ static void __init cell_setup_arch(void)
 {
 	ppc_md.init_IRQ       = iic_init_IRQ;
 	ppc_md.get_irq        = iic_get_irq;
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops         = &spu_priv1_mmio_ops;
+#endif
+
+	cbe_regs_init();
+
+#ifdef CONFIG_CBE_RAS
+	cbe_ras_init();
+#endif
 
 #ifdef CONFIG_SMP
 	smp_init_cell();
@@ -98,7 +110,7 @@ static void __init cell_setup_arch(void)
 	init_pci_config_tokens();
 	find_and_init_phbs();
 	spider_init_IRQ();
-	cell_pervasive_init();
+	cbe_pervasive_init();
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index ad141fe8d52d..db82f503ba2c 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -34,10 +34,15 @@
 #include <asm/prom.h>
 #include <linux/mutex.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/mmu_context.h>
 
 #include "interrupt.h"
 
+const struct spu_priv1_ops *spu_priv1_ops;
+
+EXPORT_SYMBOL_GPL(spu_priv1_ops);
+
 static int __spu_trap_invalid_dma(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
@@ -71,7 +76,7 @@ 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;
+	u64 esid, vsid, llp;
 
 	pr_debug("%s\n", __FUNCTION__);
 
@@ -91,9 +96,14 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
 	}
 
 	esid = (ea & ESID_MASK) | SLB_ESID_V;
-	vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER;
+#ifdef CONFIG_HUGETLB_PAGE
 	if (in_hugepage_area(mm->context, ea))
-		vsid |= SLB_VSID_L;
+		llp = mmu_psize_defs[mmu_huge_psize].sllp;
+	else
+#endif
+		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
+			SLB_VSID_USER | llp;
 
 	out_be64(&priv2->slb_index_W, spu->slb_replace);
 	out_be64(&priv2->slb_vsid_RW, vsid);
@@ -130,57 +140,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
 	spu->dar = ea;
 	spu->dsisr = dsisr;
 	mb();
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_mailbox(struct spu *spu)
-{
-	if (spu->ibox_callback)
-		spu->ibox_callback(spu);
-
-	/* atomically disable SPU mailbox interrupts */
-	spin_lock(&spu->register_lock);
-	spu_int_mask_and(spu, 2, ~0x1);
-	spin_unlock(&spu->register_lock);
-	return 0;
-}
-
-static int __spu_trap_stop(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->stop_code = in_be32(&spu->problem->spu_status_R);
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_halt(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->stop_code = in_be32(&spu->problem->spu_status_R);
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_tag_group(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->mfc_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_spubox(struct spu *spu)
-{
-	if (spu->wbox_callback)
-		spu->wbox_callback(spu);
-
-	/* atomically disable SPU mailbox interrupts */
-	spin_lock(&spu->register_lock);
-	spu_int_mask_and(spu, 2, ~0x10);
-	spin_unlock(&spu->register_lock);
+	spu->stop_callback(spu);
 	return 0;
 }
 
@@ -191,8 +151,7 @@ spu_irq_class_0(int irq, void *data, struct pt_regs *regs)
 
 	spu = data;
 	spu->class_0_pending = 1;
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
+	spu->stop_callback(spu);
 
 	return IRQ_HANDLED;
 }
@@ -270,29 +229,38 @@ spu_irq_class_2(int irq, void *data, struct pt_regs *regs)
 	unsigned long mask;
 
 	spu = data;
+	spin_lock(&spu->register_lock);
 	stat = spu_int_stat_get(spu, 2);
 	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));
+	/* 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);
 
-	stat &= mask;
-
 	if (stat & 1)  /* PPC core mailbox */
-		__spu_trap_mailbox(spu);
+		spu->ibox_callback(spu);
 
 	if (stat & 2) /* SPU stop-and-signal */
-		__spu_trap_stop(spu);
+		spu->stop_callback(spu);
 
 	if (stat & 4) /* SPU halted */
-		__spu_trap_halt(spu);
+		spu->stop_callback(spu);
 
 	if (stat & 8) /* DMA tag group complete */
-		__spu_trap_tag_group(spu);
+		spu->mfc_callback(spu);
 
 	if (stat & 0x10) /* SPU mailbox threshold */
-		__spu_trap_spubox(spu);
+		spu->wbox_callback(spu);
 
-	spu_int_stat_clear(spu, 2, stat);
 	return stat ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -512,14 +480,6 @@ int spu_irq_class_1_bottom(struct spu *spu)
 	return ret;
 }
 
-void spu_irq_setaffinity(struct spu *spu, int cpu)
-{
-	u64 target = iic_get_target_id(cpu);
-	u64 route = target << 48 | target << 32 | target << 16;
-	spu_int_route_set(spu, route);
-}
-EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-
 static int __init find_spu_node_id(struct device_node *spe)
 {
 	unsigned int *id;
@@ -649,6 +609,46 @@ out:
 	return ret;
 }
 
+struct sysdev_class spu_sysdev_class = {
+	set_kset_name("spu")
+};
+
+static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+	return sprintf(buf, "%d\n", spu->isrc);
+
+}
+static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL);
+
+extern int attach_sysdev_to_node(struct sys_device *dev, int nid);
+
+static int spu_create_sysdev(struct spu *spu)
+{
+	int ret;
+
+	spu->sysdev.id = spu->number;
+	spu->sysdev.cls = &spu_sysdev_class;
+	ret = sysdev_register(&spu->sysdev);
+	if (ret) {
+		printk(KERN_ERR "Can't register SPU %d with sysfs\n",
+				spu->number);
+		return ret;
+	}
+
+	sysdev_create_file(&spu->sysdev, &attr_isrc);
+	sysfs_add_device_to_node(&spu->sysdev, spu->nid);
+
+	return 0;
+}
+
+static void spu_destroy_sysdev(struct spu *spu)
+{
+	sysdev_remove_file(&spu->sysdev, &attr_isrc);
+	sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
+	sysdev_unregister(&spu->sysdev);
+}
+
 static int __init create_spu(struct device_node *spe)
 {
 	struct spu *spu;
@@ -656,7 +656,7 @@ static int __init create_spu(struct device_node *spe)
 	static int number;
 
 	ret = -ENOMEM;
-	spu = kmalloc(sizeof (*spu), GFP_KERNEL);
+	spu = kzalloc(sizeof (*spu), GFP_KERNEL);
 	if (!spu)
 		goto out;
 
@@ -668,33 +668,20 @@ static int __init create_spu(struct device_node *spe)
 	spu->nid = of_node_to_nid(spe);
 	if (spu->nid == -1)
 		spu->nid = 0;
-
-	spu->stop_code = 0;
-	spu->slb_replace = 0;
-	spu->mm = NULL;
-	spu->ctx = NULL;
-	spu->rq = NULL;
-	spu->pid = 0;
-	spu->class_0_pending = 0;
-	spu->flags = 0UL;
-	spu->dar = 0UL;
-	spu->dsisr = 0UL;
 	spin_lock_init(&spu->register_lock);
-
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
 	spu_mfc_sr1_set(spu, 0x33);
-
-	spu->ibox_callback = NULL;
-	spu->wbox_callback = NULL;
-	spu->stop_callback = NULL;
-	spu->mfc_callback = NULL;
-
 	mutex_lock(&spu_mutex);
+
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
 		goto out_unmap;
 
+	ret = spu_create_sysdev(spu);
+	if (ret)
+		goto out_free_irqs;
+
 	list_add(&spu->list, &spu_list);
 	mutex_unlock(&spu_mutex);
 
@@ -703,6 +690,9 @@ static int __init create_spu(struct device_node *spe)
 		spu->problem, spu->priv1, spu->priv2, spu->number);
 	goto out;
 
+out_free_irqs:
+	spu_free_irqs(spu);
+
 out_unmap:
 	mutex_unlock(&spu_mutex);
 	spu_unmap(spu);
@@ -716,6 +706,7 @@ static void destroy_spu(struct spu *spu)
 {
 	list_del_init(&spu->list);
 
+	spu_destroy_sysdev(spu);
 	spu_free_irqs(spu);
 	spu_unmap(spu);
 	kfree(spu);
@@ -728,6 +719,7 @@ static void cleanup_spu_base(void)
 	list_for_each_entry_safe(spu, tmp, &spu_list, list)
 		destroy_spu(spu);
 	mutex_unlock(&spu_mutex);
+	sysdev_class_unregister(&spu_sysdev_class);
 }
 module_exit(cleanup_spu_base);
 
@@ -736,6 +728,11 @@ static int __init init_spu_base(void)
 	struct device_node *node;
 	int ret;
 
+	/* create sysdev class for spus */
+	ret = sysdev_class_register(&spu_sysdev_class);
+	if (ret)
+		return ret;
+
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
 			node; node = of_find_node_by_type(node, "spe")) {
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index b47fcc5ddb78..47ec3be3edcd 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -34,307 +34,19 @@
  */
 
 void *spu_syscall_table[] = {
-	[__NR_restart_syscall]		sys_ni_syscall, /* sys_restart_syscall */
-	[__NR_exit]			sys_ni_syscall, /* sys_exit */
-	[__NR_fork]			sys_ni_syscall, /* ppc_fork */
-	[__NR_read]			sys_read,
-	[__NR_write]			sys_write,
-	[__NR_open]			sys_open,
-	[__NR_close]			sys_close,
-	[__NR_waitpid]			sys_waitpid,
-	[__NR_creat]			sys_creat,
-	[__NR_link]			sys_link,
-	[__NR_unlink]			sys_unlink,
-	[__NR_execve]			sys_ni_syscall, /* sys_execve */
-	[__NR_chdir]			sys_chdir,
-	[__NR_time]			sys_time,
-	[__NR_mknod]			sys_mknod,
-	[__NR_chmod]			sys_chmod,
-	[__NR_lchown]			sys_lchown,
-	[__NR_break]			sys_ni_syscall,
-	[__NR_oldstat]			sys_ni_syscall,
-	[__NR_lseek]			sys_lseek,
-	[__NR_getpid]			sys_getpid,
-	[__NR_mount]			sys_ni_syscall, /* sys_mount */
-	[__NR_umount]			sys_ni_syscall,
-	[__NR_setuid]			sys_setuid,
-	[__NR_getuid]			sys_getuid,
-	[__NR_stime]			sys_stime,
-	[__NR_ptrace]			sys_ni_syscall, /* sys_ptrace */
-	[__NR_alarm]			sys_alarm,
-	[__NR_oldfstat]			sys_ni_syscall,
-	[__NR_pause]			sys_ni_syscall, /* sys_pause */
-	[__NR_utime]			sys_ni_syscall, /* sys_utime */
-	[__NR_stty]			sys_ni_syscall,
-	[__NR_gtty]			sys_ni_syscall,
-	[__NR_access]			sys_access,
-	[__NR_nice]			sys_nice,
-	[__NR_ftime]			sys_ni_syscall,
-	[__NR_sync]			sys_sync,
-	[__NR_kill]			sys_kill,
-	[__NR_rename]			sys_rename,
-	[__NR_mkdir]			sys_mkdir,
-	[__NR_rmdir]			sys_rmdir,
-	[__NR_dup]			sys_dup,
-	[__NR_pipe]			sys_pipe,
-	[__NR_times]			sys_times,
-	[__NR_prof]			sys_ni_syscall,
-	[__NR_brk]			sys_brk,
-	[__NR_setgid]			sys_setgid,
-	[__NR_getgid]			sys_getgid,
-	[__NR_signal]			sys_ni_syscall, /* sys_signal */
-	[__NR_geteuid]			sys_geteuid,
-	[__NR_getegid]			sys_getegid,
-	[__NR_acct]			sys_ni_syscall, /* sys_acct */
-	[__NR_umount2]			sys_ni_syscall, /* sys_umount */
-	[__NR_lock]			sys_ni_syscall,
-	[__NR_ioctl]			sys_ioctl,
-	[__NR_fcntl]			sys_fcntl,
-	[__NR_mpx]			sys_ni_syscall,
-	[__NR_setpgid]			sys_setpgid,
-	[__NR_ulimit]			sys_ni_syscall,
-	[__NR_oldolduname]		sys_ni_syscall,
-	[__NR_umask]			sys_umask,
-	[__NR_chroot]			sys_chroot,
-	[__NR_ustat]			sys_ni_syscall, /* sys_ustat */
-	[__NR_dup2]			sys_dup2,
-	[__NR_getppid]			sys_getppid,
-	[__NR_getpgrp]			sys_getpgrp,
-	[__NR_setsid]			sys_setsid,
-	[__NR_sigaction]		sys_ni_syscall,
-	[__NR_sgetmask]			sys_sgetmask,
-	[__NR_ssetmask]			sys_ssetmask,
-	[__NR_setreuid]			sys_setreuid,
-	[__NR_setregid]			sys_setregid,
-	[__NR_sigsuspend]		sys_ni_syscall,
-	[__NR_sigpending]		sys_ni_syscall,
-	[__NR_sethostname]		sys_sethostname,
-	[__NR_setrlimit]		sys_setrlimit,
-	[__NR_getrlimit]		sys_ni_syscall,
-	[__NR_getrusage]		sys_getrusage,
-	[__NR_gettimeofday]		sys_gettimeofday,
-	[__NR_settimeofday]		sys_settimeofday,
-	[__NR_getgroups]		sys_getgroups,
-	[__NR_setgroups]		sys_setgroups,
-	[__NR_select]			sys_ni_syscall,
-	[__NR_symlink]			sys_symlink,
-	[__NR_oldlstat]			sys_ni_syscall,
-	[__NR_readlink]			sys_readlink,
-	[__NR_uselib]			sys_ni_syscall, /* sys_uselib */
-	[__NR_swapon]			sys_ni_syscall, /* sys_swapon */
-	[__NR_reboot]			sys_ni_syscall, /* sys_reboot */
-	[__NR_readdir]			sys_ni_syscall,
-	[__NR_mmap]			sys_mmap,
-	[__NR_munmap]			sys_munmap,
-	[__NR_truncate]			sys_truncate,
-	[__NR_ftruncate]		sys_ftruncate,
-	[__NR_fchmod]			sys_fchmod,
-	[__NR_fchown]			sys_fchown,
-	[__NR_getpriority]		sys_getpriority,
-	[__NR_setpriority]		sys_setpriority,
-	[__NR_profil]			sys_ni_syscall,
-	[__NR_statfs]			sys_ni_syscall, /* sys_statfs */
-	[__NR_fstatfs]			sys_ni_syscall, /* sys_fstatfs */
-	[__NR_ioperm]			sys_ni_syscall,
-	[__NR_socketcall]		sys_socketcall,
-	[__NR_syslog]			sys_syslog,
-	[__NR_setitimer]		sys_setitimer,
-	[__NR_getitimer]		sys_getitimer,
-	[__NR_stat]			sys_newstat,
-	[__NR_lstat]			sys_newlstat,
-	[__NR_fstat]			sys_newfstat,
-	[__NR_olduname]			sys_ni_syscall,
-	[__NR_iopl]			sys_ni_syscall,
-	[__NR_vhangup]			sys_vhangup,
-	[__NR_idle]			sys_ni_syscall,
-	[__NR_vm86]			sys_ni_syscall,
-	[__NR_wait4]			sys_wait4,
-	[__NR_swapoff]			sys_ni_syscall, /* sys_swapoff */
-	[__NR_sysinfo]			sys_sysinfo,
-	[__NR_ipc]			sys_ni_syscall, /* sys_ipc */
-	[__NR_fsync]			sys_fsync,
-	[__NR_sigreturn]		sys_ni_syscall,
-	[__NR_clone]			sys_ni_syscall, /* ppc_clone */
-	[__NR_setdomainname]		sys_setdomainname,
-	[__NR_uname]			ppc_newuname,
-	[__NR_modify_ldt]		sys_ni_syscall,
-	[__NR_adjtimex]			sys_adjtimex,
-	[__NR_mprotect]			sys_mprotect,
-	[__NR_sigprocmask]		sys_ni_syscall,
-	[__NR_create_module]		sys_ni_syscall,
-	[__NR_init_module]		sys_ni_syscall, /* sys_init_module */
-	[__NR_delete_module]		sys_ni_syscall, /* sys_delete_module */
-	[__NR_get_kernel_syms]		sys_ni_syscall,
-	[__NR_quotactl]			sys_ni_syscall, /* sys_quotactl */
-	[__NR_getpgid]			sys_getpgid,
-	[__NR_fchdir]			sys_fchdir,
-	[__NR_bdflush]			sys_bdflush,
-	[__NR_sysfs]			sys_ni_syscall, /* sys_sysfs */
-	[__NR_personality]		ppc64_personality,
-	[__NR_afs_syscall]		sys_ni_syscall,
-	[__NR_setfsuid]			sys_setfsuid,
-	[__NR_setfsgid]			sys_setfsgid,
-	[__NR__llseek]			sys_llseek,
-	[__NR_getdents]			sys_getdents,
-	[__NR__newselect]		sys_select,
-	[__NR_flock]			sys_flock,
-	[__NR_msync]			sys_msync,
-	[__NR_readv]			sys_readv,
-	[__NR_writev]			sys_writev,
-	[__NR_getsid]			sys_getsid,
-	[__NR_fdatasync]		sys_fdatasync,
-	[__NR__sysctl]			sys_ni_syscall, /* sys_sysctl */
-	[__NR_mlock]			sys_mlock,
-	[__NR_munlock]			sys_munlock,
-	[__NR_mlockall]			sys_mlockall,
-	[__NR_munlockall]		sys_munlockall,
-	[__NR_sched_setparam]		sys_sched_setparam,
-	[__NR_sched_getparam]		sys_sched_getparam,
-	[__NR_sched_setscheduler]	sys_sched_setscheduler,
-	[__NR_sched_getscheduler]	sys_sched_getscheduler,
-	[__NR_sched_yield]		sys_sched_yield,
-	[__NR_sched_get_priority_max]	sys_sched_get_priority_max,
-	[__NR_sched_get_priority_min]	sys_sched_get_priority_min,
-	[__NR_sched_rr_get_interval]	sys_sched_rr_get_interval,
-	[__NR_nanosleep]		sys_nanosleep,
-	[__NR_mremap]			sys_mremap,
-	[__NR_setresuid]		sys_setresuid,
-	[__NR_getresuid]		sys_getresuid,
-	[__NR_query_module]		sys_ni_syscall,
-	[__NR_poll]			sys_poll,
-	[__NR_nfsservctl]		sys_ni_syscall, /* sys_nfsservctl */
-	[__NR_setresgid]		sys_setresgid,
-	[__NR_getresgid]		sys_getresgid,
-	[__NR_prctl]			sys_prctl,
-	[__NR_rt_sigreturn]		sys_ni_syscall, /* ppc64_rt_sigreturn */
-	[__NR_rt_sigaction]		sys_ni_syscall, /* sys_rt_sigaction */
-	[__NR_rt_sigprocmask]		sys_ni_syscall, /* sys_rt_sigprocmask */
-	[__NR_rt_sigpending]		sys_ni_syscall, /* sys_rt_sigpending */
-	[__NR_rt_sigtimedwait]		sys_ni_syscall, /* sys_rt_sigtimedwait */
-	[__NR_rt_sigqueueinfo]		sys_ni_syscall, /* sys_rt_sigqueueinfo */
-	[__NR_rt_sigsuspend]		sys_ni_syscall, /* sys_rt_sigsuspend */
-	[__NR_pread64]			sys_pread64,
-	[__NR_pwrite64]			sys_pwrite64,
-	[__NR_chown]			sys_chown,
-	[__NR_getcwd]			sys_getcwd,
-	[__NR_capget]			sys_capget,
-	[__NR_capset]			sys_capset,
-	[__NR_sigaltstack]		sys_ni_syscall, /* sys_sigaltstack */
-	[__NR_sendfile]			sys_sendfile64,
-	[__NR_getpmsg]			sys_ni_syscall,
-	[__NR_putpmsg]			sys_ni_syscall,
-	[__NR_vfork]			sys_ni_syscall, /* ppc_vfork */
-	[__NR_ugetrlimit]		sys_getrlimit,
-	[__NR_readahead]		sys_readahead,
-	[192]				sys_ni_syscall,
-	[193]				sys_ni_syscall,
-	[194]				sys_ni_syscall,
-	[195]				sys_ni_syscall,
-	[196]				sys_ni_syscall,
-	[197]				sys_ni_syscall,
-	[__NR_pciconfig_read]		sys_ni_syscall, /* sys_pciconfig_read */
-	[__NR_pciconfig_write]		sys_ni_syscall, /* sys_pciconfig_write */
-	[__NR_pciconfig_iobase]		sys_ni_syscall, /* sys_pciconfig_iobase */
-	[__NR_multiplexer]		sys_ni_syscall,
-	[__NR_getdents64]		sys_getdents64,
-	[__NR_pivot_root]		sys_pivot_root,
-	[204]				sys_ni_syscall,
-	[__NR_madvise]			sys_madvise,
-	[__NR_mincore]			sys_mincore,
-	[__NR_gettid]			sys_gettid,
-	[__NR_tkill]			sys_tkill,
-	[__NR_setxattr]			sys_setxattr,
-	[__NR_lsetxattr]		sys_lsetxattr,
-	[__NR_fsetxattr]		sys_fsetxattr,
-	[__NR_getxattr]			sys_getxattr,
-	[__NR_lgetxattr]		sys_lgetxattr,
-	[__NR_fgetxattr]		sys_fgetxattr,
-	[__NR_listxattr]		sys_listxattr,
-	[__NR_llistxattr]		sys_llistxattr,
-	[__NR_flistxattr]		sys_flistxattr,
-	[__NR_removexattr]		sys_removexattr,
-	[__NR_lremovexattr]		sys_lremovexattr,
-	[__NR_fremovexattr]		sys_fremovexattr,
-	[__NR_futex]			sys_futex,
-	[__NR_sched_setaffinity]	sys_sched_setaffinity,
-	[__NR_sched_getaffinity]	sys_sched_getaffinity,
-	[224]				sys_ni_syscall,
-	[__NR_tuxcall]			sys_ni_syscall,
-	[226]				sys_ni_syscall,
-	[__NR_io_setup]			sys_io_setup,
-	[__NR_io_destroy]		sys_io_destroy,
-	[__NR_io_getevents]		sys_io_getevents,
-	[__NR_io_submit]		sys_io_submit,
-	[__NR_io_cancel]		sys_io_cancel,
-	[__NR_set_tid_address]		sys_ni_syscall, /* sys_set_tid_address */
-	[__NR_fadvise64]		sys_fadvise64,
-	[__NR_exit_group]		sys_ni_syscall, /* sys_exit_group */
-	[__NR_lookup_dcookie]		sys_ni_syscall, /* sys_lookup_dcookie */
-	[__NR_epoll_create]		sys_epoll_create,
-	[__NR_epoll_ctl]		sys_epoll_ctl,
-	[__NR_epoll_wait]		sys_epoll_wait,
-	[__NR_remap_file_pages]		sys_remap_file_pages,
-	[__NR_timer_create]		sys_timer_create,
-	[__NR_timer_settime]		sys_timer_settime,
-	[__NR_timer_gettime]		sys_timer_gettime,
-	[__NR_timer_getoverrun]		sys_timer_getoverrun,
-	[__NR_timer_delete]		sys_timer_delete,
-	[__NR_clock_settime]		sys_clock_settime,
-	[__NR_clock_gettime]		sys_clock_gettime,
-	[__NR_clock_getres]		sys_clock_getres,
-	[__NR_clock_nanosleep]		sys_clock_nanosleep,
-	[__NR_swapcontext]		sys_ni_syscall, /* ppc64_swapcontext */
-	[__NR_tgkill]			sys_tgkill,
-	[__NR_utimes]			sys_utimes,
-	[__NR_statfs64]			sys_statfs64,
-	[__NR_fstatfs64]		sys_fstatfs64,
-	[254]				sys_ni_syscall,
-	[__NR_rtas]			ppc_rtas,
-	[256]				sys_ni_syscall,
-	[257]				sys_ni_syscall,
-	[258]				sys_ni_syscall,
-	[__NR_mbind]			sys_ni_syscall, /* sys_mbind */
-	[__NR_get_mempolicy]		sys_ni_syscall, /* sys_get_mempolicy */
-	[__NR_set_mempolicy]		sys_ni_syscall, /* sys_set_mempolicy */
-	[__NR_mq_open]			sys_ni_syscall, /* sys_mq_open */
-	[__NR_mq_unlink]		sys_ni_syscall, /* sys_mq_unlink */
-	[__NR_mq_timedsend]		sys_ni_syscall, /* sys_mq_timedsend */
-	[__NR_mq_timedreceive]		sys_ni_syscall, /* sys_mq_timedreceive */
-	[__NR_mq_notify]		sys_ni_syscall, /* sys_mq_notify */
-	[__NR_mq_getsetattr]		sys_ni_syscall, /* sys_mq_getsetattr */
-	[__NR_kexec_load]		sys_ni_syscall, /* sys_kexec_load */
-	[__NR_add_key]			sys_ni_syscall, /* sys_add_key */
-	[__NR_request_key]		sys_ni_syscall, /* sys_request_key */
-	[__NR_keyctl]			sys_ni_syscall, /* sys_keyctl */
-	[__NR_waitid]			sys_ni_syscall, /* sys_waitid */
-	[__NR_ioprio_set]		sys_ni_syscall, /* sys_ioprio_set */
-	[__NR_ioprio_get]		sys_ni_syscall, /* sys_ioprio_get */
-	[__NR_inotify_init]		sys_ni_syscall, /* sys_inotify_init */
-	[__NR_inotify_add_watch]	sys_ni_syscall, /* sys_inotify_add_watch */
-	[__NR_inotify_rm_watch]		sys_ni_syscall, /* sys_inotify_rm_watch */
-	[__NR_spu_run]			sys_ni_syscall, /* sys_spu_run */
-	[__NR_spu_create]		sys_ni_syscall, /* sys_spu_create */
-	[__NR_pselect6]			sys_ni_syscall, /* sys_pselect */
-	[__NR_ppoll]			sys_ni_syscall, /* sys_ppoll */
-	[__NR_unshare]			sys_unshare,
-	[__NR_splice]			sys_splice,
-	[__NR_tee]			sys_tee,
-	[__NR_vmsplice]			sys_vmsplice,
-	[__NR_openat]			sys_openat,
-	[__NR_mkdirat]			sys_mkdirat,
-	[__NR_mknodat]			sys_mknodat,
-	[__NR_fchownat]			sys_fchownat,
-	[__NR_futimesat]		sys_futimesat,
-	[__NR_newfstatat]		sys_newfstatat,
-	[__NR_unlinkat]			sys_unlinkat,
-	[__NR_renameat]			sys_renameat,
-	[__NR_linkat]			sys_linkat,
-	[__NR_symlinkat]		sys_symlinkat,
-	[__NR_readlinkat]		sys_readlinkat,
-	[__NR_fchmodat]			sys_fchmodat,
-	[__NR_faccessat]		sys_faccessat,
-	[__NR_get_robust_list]		sys_get_robust_list,
-	[__NR_set_robust_list]		sys_set_robust_list,
+#define SYSCALL(func)		sys_ni_syscall,
+#define COMPAT_SYS(func)	sys_ni_syscall,
+#define PPC_SYS(func)		sys_ni_syscall,
+#define OLDSYS(func)		sys_ni_syscall,
+#define SYS32ONLY(func)		sys_ni_syscall,
+#define SYSX(f, f3264, f32)	sys_ni_syscall,
+
+#define SYSCALL_SPU(func)	sys_##func,
+#define COMPAT_SYS_SPU(func)	sys_##func,
+#define PPC_SYS_SPU(func)	ppc_##func,
+#define SYSX_SPU(f, f3264, f32)	f,
+
+#include <asm/systbl.h>
 };
 
 long spu_sys_callback(struct spu_syscall_block *s)
diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c
deleted file mode 100644
index b2656421c7b5..000000000000
--- a/arch/powerpc/platforms/cell/spu_priv1.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * access to SPU privileged registers
- */
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/spu.h>
-
-void spu_int_mask_and(struct spu *spu, int class, u64 mask)
-{
-	u64 old_mask;
-
-	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
-	out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_and);
-
-void spu_int_mask_or(struct spu *spu, int class, u64 mask)
-{
-	u64 old_mask;
-
-	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
-	out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_or);
-
-void spu_int_mask_set(struct spu *spu, int class, u64 mask)
-{
-	out_be64(&spu->priv1->int_mask_RW[class], mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_set);
-
-u64 spu_int_mask_get(struct spu *spu, int class)
-{
-	return in_be64(&spu->priv1->int_mask_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_get);
-
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
-{
-	out_be64(&spu->priv1->int_stat_RW[class], stat);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_clear);
-
-u64 spu_int_stat_get(struct spu *spu, int class)
-{
-	return in_be64(&spu->priv1->int_stat_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_get);
-
-void spu_int_route_set(struct spu *spu, u64 route)
-{
-	out_be64(&spu->priv1->int_route_RW, route);
-}
-EXPORT_SYMBOL_GPL(spu_int_route_set);
-
-u64 spu_mfc_dar_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_dar_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
-
-u64 spu_mfc_dsisr_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_dsisr_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
-
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
-{
-	out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
-
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
-{
-	out_be64(&spu->priv1->mfc_sdr_RW, sdr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
-
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
-{
-	out_be64(&spu->priv1->mfc_sr1_RW, sr1);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
-
-u64 spu_mfc_sr1_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_sr1_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
-
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
-{
-	out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
-
-u64 spu_mfc_tclass_id_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_tclass_id_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
-
-void spu_tlb_invalidate(struct spu *spu)
-{
-	out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
-}
-EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
-
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
-{
-	out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
-
-u64 spu_resource_allocation_groupID_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->resource_allocation_groupID_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
-
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
-{
-	out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
-
-u64 spu_resource_allocation_enable_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->resource_allocation_enable_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
new file mode 100644
index 000000000000..71b69f0a1a48
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -0,0 +1,159 @@
+/*
+ * spu hypervisor abstraction for direct hardware access.
+ *
+ *  (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *  Copyright 2006 Sony 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; version 2 of the License.
+ *
+ *  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 <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+
+#include "interrupt.h"
+
+static void int_mask_and(struct spu *spu, int class, u64 mask)
+{
+	u64 old_mask;
+
+	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+	out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
+}
+
+static void int_mask_or(struct spu *spu, int class, u64 mask)
+{
+	u64 old_mask;
+
+	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+	out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
+}
+
+static void int_mask_set(struct spu *spu, int class, u64 mask)
+{
+	out_be64(&spu->priv1->int_mask_RW[class], mask);
+}
+
+static u64 int_mask_get(struct spu *spu, int class)
+{
+	return in_be64(&spu->priv1->int_mask_RW[class]);
+}
+
+static void int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+	out_be64(&spu->priv1->int_stat_RW[class], stat);
+}
+
+static u64 int_stat_get(struct spu *spu, int class)
+{
+	return in_be64(&spu->priv1->int_stat_RW[class]);
+}
+
+static void cpu_affinity_set(struct spu *spu, int cpu)
+{
+	u64 target = iic_get_target_id(cpu);
+	u64 route = target << 48 | target << 32 | target << 16;
+	out_be64(&spu->priv1->int_route_RW, route);
+}
+
+static u64 mfc_dar_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_dar_RW);
+}
+
+static u64 mfc_dsisr_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_dsisr_RW);
+}
+
+static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+	out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
+}
+
+static void mfc_sdr_set(struct spu *spu, u64 sdr)
+{
+	out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+}
+
+static void mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+	out_be64(&spu->priv1->mfc_sr1_RW, sr1);
+}
+
+static u64 mfc_sr1_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_sr1_RW);
+}
+
+static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+	out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
+}
+
+static u64 mfc_tclass_id_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_tclass_id_RW);
+}
+
+static void tlb_invalidate(struct spu *spu)
+{
+	out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
+}
+
+static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+	out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
+}
+
+static u64 resource_allocation_groupID_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->resource_allocation_groupID_RW);
+}
+
+static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+	out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
+}
+
+static u64 resource_allocation_enable_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->resource_allocation_enable_RW);
+}
+
+const struct spu_priv1_ops spu_priv1_mmio_ops =
+{
+	.int_mask_and = int_mask_and,
+	.int_mask_or = int_mask_or,
+	.int_mask_set = int_mask_set,
+	.int_mask_get = int_mask_get,
+	.int_stat_clear = int_stat_clear,
+	.int_stat_get = int_stat_get,
+	.cpu_affinity_set = cpu_affinity_set,
+	.mfc_dar_get = mfc_dar_get,
+	.mfc_dsisr_get = mfc_dsisr_get,
+	.mfc_dsisr_set = mfc_dsisr_set,
+	.mfc_sdr_set = mfc_sdr_set,
+	.mfc_sr1_set = mfc_sr1_set,
+	.mfc_sr1_get = mfc_sr1_get,
+	.mfc_tclass_id_set = mfc_tclass_id_set,
+	.mfc_tclass_id_get = mfc_tclass_id_get,
+	.tlb_invalidate = tlb_invalidate,
+	.resource_allocation_groupID_set = resource_allocation_groupID_set,
+	.resource_allocation_groupID_get = resource_allocation_groupID_get,
+	.resource_allocation_enable_set = resource_allocation_enable_set,
+	.resource_allocation_enable_get = resource_allocation_enable_get,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index a7cddf40e3d9..bb5dc634272c 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,5 +1,7 @@
+obj-y += switch.o
+
 obj-$(CONFIG_SPU_FS) += spufs.o
-spufs-y += inode.o file.o context.o switch.o syscalls.o
+spufs-y += inode.o file.o context.o syscalls.o
 spufs-y += sched.o backing_ops.o hw_ops.o run.o
 
 # Rules to build switch.o with the help of SPU tool chain
@@ -8,11 +10,14 @@ SPU_CC		:= $(SPU_CROSS)gcc
 SPU_AS		:= $(SPU_CROSS)gcc
 SPU_LD		:= $(SPU_CROSS)ld
 SPU_OBJCOPY	:= $(SPU_CROSS)objcopy
-SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include -I$(objtree)/include2
-SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2
+SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include \
+		   -I$(objtree)/include2 -D__KERNEL__
+SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include \
+		   -I$(objtree)/include2 -D__KERNEL__
 SPU_LDFLAGS	:= -N -Ttext=0x0
 
 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
+clean-files := spu_save_dump.h spu_restore_dump.h
 
 # Compile SPU files
       cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $<
@@ -45,7 +50,8 @@ cmd_hexdump   = ( \
 		echo " * Hex-dump auto generated from $*.c." ; \
 		echo " * Do not edit!" ; \
 		echo " */" ; \
-		echo "static unsigned int $*_code[] __page_aligned = {" ; \
+		echo "static unsigned int $*_code[] " \
+			"__attribute__((__aligned__(128))) = {" ; \
 		hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \
 		echo "};" ; \
 		) > $@
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8bb33abfad17..36439c5e9f2d 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -30,7 +30,7 @@
 struct spu_context *alloc_spu_context(void)
 {
 	struct spu_context *ctx;
-	ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
+	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
 		goto out;
 	/* Binding to physical processor deferred
@@ -48,17 +48,7 @@ struct spu_context *alloc_spu_context(void)
 	init_waitqueue_head(&ctx->wbox_wq);
 	init_waitqueue_head(&ctx->stop_wq);
 	init_waitqueue_head(&ctx->mfc_wq);
-	ctx->ibox_fasync = NULL;
-	ctx->wbox_fasync = NULL;
-	ctx->mfc_fasync = NULL;
-	ctx->mfc = NULL;
-	ctx->tagwait = 0;
 	ctx->state = SPU_STATE_SAVED;
-	ctx->local_store = NULL;
-	ctx->cntl = NULL;
-	ctx->signal1 = NULL;
-	ctx->signal2 = NULL;
-	ctx->spu = NULL;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
 	goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 366185e92667..80c02660e617 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -825,6 +825,55 @@ DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
 					spufs_signal2_type_set, "%llu");
 
 #ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x0000);
+}
+
+static struct vm_operations_struct spufs_mss_mmap_vmops = {
+	.nopage = spufs_mss_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_mss_mmap_vmops;
+	return 0;
+}
+#endif
+
+static int spufs_mss_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+
+	file->private_data = i->i_ctx;
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations spufs_mss_fops = {
+	.open	 = spufs_mss_open,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap	 = spufs_mss_mmap,
+#endif
+};
+
+
+#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
@@ -1279,6 +1328,22 @@ static u64 spufs_srr0_get(void *data)
 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
 			"%llx\n")
 
+static u64 spufs_id_get(void *data)
+{
+	struct spu_context *ctx = data;
+	u64 num;
+
+	spu_acquire(ctx);
+	if (ctx->state == SPU_STATE_RUNNABLE)
+		num = ctx->spu->number;
+	else
+		num = (unsigned int)-1;
+	spu_release(ctx);
+
+	return num;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n")
+
 struct tree_descr spufs_dir_contents[] = {
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
@@ -1292,6 +1357,7 @@ struct tree_descr spufs_dir_contents[] = {
 	{ "signal2", &spufs_signal2_fops, 0666, },
 	{ "signal1_type", &spufs_signal1_type, 0666, },
 	{ "signal2_type", &spufs_signal2_type, 0666, },
+	{ "mss", &spufs_mss_fops, 0666, },
 	{ "mfc", &spufs_mfc_fops, 0666, },
 	{ "cntl", &spufs_cntl_fops,  0666, },
 	{ "npc", &spufs_npc_ops, 0666, },
@@ -1301,5 +1367,6 @@ struct tree_descr spufs_dir_contents[] = {
 	{ "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
 	{ "event_mask", &spufs_event_mask_ops, 0666, },
 	{ "srr0", &spufs_srr0_ops, 0666, },
+	{ "phys-id", &spufs_id_ops, 0666, },
 	{},
 };
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index a13a8b5a014d..ede2cac46b6d 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -32,6 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 #include "spufs.h"
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index d9554199afa7..7b4572805db9 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -157,20 +157,12 @@ static void spufs_prune_dir(struct dentry *dir)
 	mutex_unlock(&dir->d_inode->i_mutex);
 }
 
+/* Caller must hold root->i_mutex */
 static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
 {
-	struct spu_context *ctx;
-
 	/* remove all entries */
-	mutex_lock(&root->i_mutex);
 	spufs_prune_dir(dir_dentry);
-	mutex_unlock(&root->i_mutex);
-
-	/* We have to give up the mm_struct */
-	ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
-	spu_forget(ctx);
 
-	/* XXX Do we need to hold i_mutex here ? */
 	return simple_rmdir(root, dir_dentry);
 }
 
@@ -199,16 +191,23 @@ out:
 
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
+	struct spu_context *ctx;
 	struct inode *dir;
 	struct dentry *dentry;
 	int ret;
 
 	dentry = file->f_dentry;
 	dir = dentry->d_parent->d_inode;
+	ctx = SPUFS_I(dentry->d_inode)->i_ctx;
 
+	mutex_lock(&dir->i_mutex);
 	ret = spufs_rmdir(dir, dentry);
+	mutex_unlock(&dir->i_mutex);
 	WARN_ON(ret);
 
+	/* We have to give up the mm_struct */
+	spu_forget(ctx);
+
 	return dcache_dir_close(inode, file);
 }
 
@@ -305,6 +304,10 @@ long spufs_create_thread(struct nameidata *nd,
 	    nd->dentry != nd->dentry->d_sb->s_root)
 		goto out;
 
+	/* all flags are reserved */
+	if (flags)
+		goto out;
+
 	dentry = lookup_create(nd, 1);
 	ret = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
@@ -324,8 +327,13 @@ long spufs_create_thread(struct nameidata *nd,
 	 * in error path of *_open().
 	 */
 	ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
-	if (ret < 0)
-		spufs_rmdir(nd->dentry->d_inode, dentry);
+	if (ret < 0) {
+		WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry));
+		mutex_unlock(&nd->dentry->d_inode->i_mutex);
+		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
+		dput(dentry);
+		goto out;
+	}
 
 out_dput:
 	dput(dentry);
@@ -428,11 +436,11 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
 	return spufs_create_root(sb, data);
 }
 
-static struct super_block *
+static int
 spufs_get_sb(struct file_system_type *fstype, int flags,
-		const char *name, void *data)
+		const char *name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fstype, flags, data, spufs_fill_super);
+	return get_sb_single(fstype, flags, data, spufs_fill_super, mnt);
 }
 
 static struct file_system_type spufs_type = {
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index bf652cd77000..3dcc5d8d66b9 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -43,6 +43,7 @@
 #include <asm/mmu_context.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
+#include <asm/spu_priv1.h>
 #include "spufs.h"
 
 #define SPU_MIN_TIMESLICE 	(100 * HZ / 1000)
@@ -363,7 +364,7 @@ int spu_activate(struct spu_context *ctx, u64 flags)
 	 * We're likely to wait for interrupts on the same
 	 * CPU that we are now on, so send them here.
 	 */
-	spu_irq_setaffinity(spu, raw_smp_processor_id());
+	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 	put_active_spu(spu);
 	return 0;
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
index 1b2355ff7036..15183d209b58 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
@@ -3,229 +3,901 @@
  * Hex-dump auto generated from spu_restore.c.
  * Do not edit!
  */
-static unsigned int spu_restore_code[] __page_aligned = {
-0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
-0x1cd80081, 0x33001180, 0x42030003, 0x33800284,
-0x1c010204, 0x40200000, 0x40200000, 0x40200000,
-0x34000190, 0x34004191, 0x34008192, 0x3400c193,
-0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85,
-0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603,
-0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07,
-0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b,
-0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f,
-0x00003ffc, 0x00000000, 0x00000000, 0x00000000,
-0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204,
-0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202,
-0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682,
-0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f,
-0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204,
-0x04000203, 0x21a00903, 0x40848002, 0x21a00982,
-0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82,
-0x21a00083, 0x40800082, 0x21a00b02, 0x10002818,
-0x40a80002, 0x32800007, 0x4207000c, 0x18008208,
-0x40a0000b, 0x4080020a, 0x40800709, 0x00200000,
-0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000,
-0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185,
-0xb0408584, 0x28830382, 0x1c020387, 0x38828182,
-0xb0408405, 0x1802c408, 0x28828182, 0x217ff886,
-0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102,
-0x04000106, 0x21a00886, 0x04000603, 0x21a00903,
-0x40803c02, 0x21a00982, 0x40800003, 0x04000184,
-0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005,
-0x34208702, 0x21002282, 0x21a00804, 0x21a00886,
-0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102,
-0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04,
-0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83,
-0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02,
-0x34210283, 0x21a00f03, 0x34200284, 0x77400200,
-0x3421c282, 0x21a00702, 0x34218283, 0x21a00083,
-0x34214282, 0x21a00b02, 0x4200480c, 0x00200000,
-0x1c010286, 0x34220284, 0x34220302, 0x0f608203,
-0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000,
-0x18008185, 0x38808183, 0x3b814182, 0x21004e84,
-0x4020007f, 0x35000100, 0x000004e0, 0x000002a0,
-0x000002e8, 0x00000428, 0x00000360, 0x000002e8,
-0x000004a0, 0x00000468, 0x000003c8, 0x00000360,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085,
-0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f,
-0x4020007f, 0x20801203, 0x38810602, 0xb0408586,
-0x28810602, 0x32004180, 0x34204702, 0x21a00382,
-0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203,
-0x40800204, 0x3ec40087, 0x40800405, 0x00200000,
-0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
-0xb060c107, 0x20801203, 0x41004003, 0x38810602,
-0x4020007f, 0xb0408188, 0x4020007f, 0x28810602,
-0x41201002, 0x38814603, 0x10009c09, 0xb060c109,
-0x4020007f, 0x28814603, 0x41193f83, 0x38818602,
-0x60ffc003, 0xb040818a, 0x28818602, 0x32003080,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
-0x41201008, 0x10009c14, 0x40800405, 0x3ac10609,
-0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b,
-0x20801203, 0x38810602, 0xb0408409, 0x28810602,
-0x38814603, 0xb060c40a, 0x4020007f, 0x28814603,
-0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b,
-0x28818602, 0x32002380, 0x409ffe02, 0x30801204,
-0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607,
-0x3ac18608, 0xb0810103, 0x41004002, 0x20801204,
-0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107,
-0x4020007f, 0x4020007f, 0x28814603, 0x38818602,
-0x4020007f, 0x4020007f, 0xb0408588, 0x28818602,
-0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e,
-0x40800204, 0x30801203, 0x40800405, 0x3ec40087,
-0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
-0xb060c107, 0x20801203, 0x413d8003, 0x38810602,
-0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c,
-0x40800205, 0x30801204, 0x40800406, 0x3ec40083,
-0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002,
-0x20801204, 0x38814603, 0x4020007f, 0x327feb80,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
-0x40800405, 0x1000650a, 0x40800606, 0x3ac10608,
-0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203,
-0x38810602, 0xb0408588, 0x4020007f, 0x327fc980,
-0x00400000, 0x40800003, 0x4020007f, 0x35000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
+static unsigned int spu_restore_code[]  __attribute__((__aligned__(128))) = {
+0x40800000,
+0x409ff801,
+0x24000080,
+0x24fd8081,
+0x1cd80081,
+0x33001180,
+0x42030003,
+0x33800284,
+0x1c010204,
+0x40200000,
+0x40200000,
+0x40200000,
+0x34000190,
+0x34004191,
+0x34008192,
+0x3400c193,
+0x141fc205,
+0x23fffd84,
+0x1c100183,
+0x217ffa85,
+0x3080a000,
+0x3080a201,
+0x3080a402,
+0x3080a603,
+0x3080a804,
+0x3080aa05,
+0x3080ac06,
+0x3080ae07,
+0x3080b008,
+0x3080b209,
+0x3080b40a,
+0x3080b60b,
+0x3080b80c,
+0x3080ba0d,
+0x3080bc0e,
+0x3080be0f,
+0x00003ffc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x01a00182,
+0x3ec00083,
+0xb0a14103,
+0x01a00204,
+0x3ec10082,
+0x4202800e,
+0x04000703,
+0xb0a14202,
+0x21a00803,
+0x3fbf028d,
+0x3f20068d,
+0x3fbe0682,
+0x3fe30102,
+0x21a00882,
+0x3f82028f,
+0x3fe3078f,
+0x3fbf0784,
+0x3f200204,
+0x3fbe0204,
+0x3fe30204,
+0x04000203,
+0x21a00903,
+0x40848002,
+0x21a00982,
+0x40800003,
+0x21a00a03,
+0x40802002,
+0x21a00a82,
+0x21a00083,
+0x40800082,
+0x21a00b02,
+0x10002818,
+0x42a00002,
+0x32800007,
+0x4207000c,
+0x18008208,
+0x40a0000b,
+0x4080020a,
+0x40800709,
+0x00200000,
+0x42070002,
+0x3ac30384,
+0x1cffc489,
+0x00200000,
+0x18008383,
+0x38830382,
+0x4cffc486,
+0x3ac28185,
+0xb0408584,
+0x28830382,
+0x1c020387,
+0x38828182,
+0xb0408405,
+0x1802c408,
+0x28828182,
+0x217ff886,
+0x04000583,
+0x21a00803,
+0x3fbe0682,
+0x3fe30102,
+0x04000106,
+0x21a00886,
+0x04000603,
+0x21a00903,
+0x40803c02,
+0x21a00982,
+0x40800003,
+0x04000184,
+0x21a00a04,
+0x40802202,
+0x21a00a82,
+0x42028005,
+0x34208702,
+0x21002282,
+0x21a00804,
+0x21a00886,
+0x3fbf0782,
+0x3f200102,
+0x3fbe0102,
+0x3fe30102,
+0x21a00902,
+0x40804003,
+0x21a00983,
+0x21a00a04,
+0x40805a02,
+0x21a00a82,
+0x40800083,
+0x21a00b83,
+0x01a00c02,
+0x01a00d83,
+0x3420c282,
+0x21a00e02,
+0x34210283,
+0x21a00f03,
+0x34200284,
+0x77400200,
+0x3421c282,
+0x21a00702,
+0x34218283,
+0x21a00083,
+0x34214282,
+0x21a00b02,
+0x4200480c,
+0x00200000,
+0x1c010286,
+0x34220284,
+0x34220302,
+0x0f608203,
+0x5c024204,
+0x3b81810b,
+0x42013c02,
+0x00200000,
+0x18008185,
+0x38808183,
+0x3b814182,
+0x21004e84,
+0x4020007f,
+0x35000100,
+0x000004e0,
+0x000002a0,
+0x000002e8,
+0x00000428,
+0x00000360,
+0x000002e8,
+0x000004a0,
+0x00000468,
+0x000003c8,
+0x00000360,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40085,
+0x10009c09,
+0x3ac10606,
+0xb060c105,
+0x4020007f,
+0x4020007f,
+0x20801203,
+0x38810602,
+0xb0408586,
+0x28810602,
+0x32004180,
+0x34204702,
+0x21a00382,
+0x4020007f,
+0x327fdc80,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x40800405,
+0x00200000,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x41004003,
+0x38810602,
+0x4020007f,
+0xb0408188,
+0x4020007f,
+0x28810602,
+0x41201002,
+0x38814603,
+0x10009c09,
+0xb060c109,
+0x4020007f,
+0x28814603,
+0x41193f83,
+0x38818602,
+0x60ffc003,
+0xb040818a,
+0x28818602,
+0x32003080,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x41201008,
+0x10009c14,
+0x40800405,
+0x3ac10609,
+0x40800606,
+0x3ac1460a,
+0xb060c107,
+0x3ac1860b,
+0x20801203,
+0x38810602,
+0xb0408409,
+0x28810602,
+0x38814603,
+0xb060c40a,
+0x4020007f,
+0x28814603,
+0x41193f83,
+0x38818602,
+0x60ffc003,
+0xb040818b,
+0x28818602,
+0x32002380,
+0x409ffe02,
+0x30801204,
+0x40800205,
+0x3ec40083,
+0x40800406,
+0x3ac14607,
+0x3ac18608,
+0xb0810103,
+0x41004002,
+0x20801204,
+0x4020007f,
+0x38814603,
+0x10009c0b,
+0xb060c107,
+0x4020007f,
+0x4020007f,
+0x28814603,
+0x38818602,
+0x4020007f,
+0x4020007f,
+0xb0408588,
+0x28818602,
+0x4020007f,
+0x32001780,
+0x409ffe02,
+0x1000640e,
+0x40800204,
+0x30801203,
+0x40800405,
+0x3ec40087,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x413d8003,
+0x38810602,
+0x4020007f,
+0x327fd780,
+0x409ffe02,
+0x10007f0c,
+0x40800205,
+0x30801204,
+0x40800406,
+0x3ec40083,
+0x3ac14607,
+0x3ac18608,
+0xb0810103,
+0x413d8002,
+0x20801204,
+0x38814603,
+0x4020007f,
+0x327feb80,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x40800405,
+0x1000650a,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x38810602,
+0xb0408588,
+0x4020007f,
+0x327fc980,
+0x00400000,
+0x40800003,
+0x4020007f,
+0x35000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
index 39e54003f1df..b9f81ac8a632 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
+++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
@@ -3,189 +3,741 @@
  * Hex-dump auto generated from spu_save.c.
  * Do not edit!
  */
-static unsigned int spu_save_code[] __page_aligned = {
-0x20805000, 0x20805201, 0x20805402, 0x20805603,
-0x20805804, 0x20805a05, 0x20805c06, 0x20805e07,
-0x20806008, 0x20806209, 0x2080640a, 0x2080660b,
-0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f,
-0x4201c003, 0x33800184, 0x1c010204, 0x40200000,
-0x24000190, 0x24004191, 0x24008192, 0x2400c193,
-0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85,
-0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
-0x1cd80081, 0x33000180, 0x00000000, 0x00000000,
-0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204,
-0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583,
-0x34218682, 0x3ed80684, 0xb0408184, 0x24218682,
-0x01a00603, 0x00200000, 0x34214682, 0x3ed40684,
-0xb0408184, 0x40800003, 0x24214682, 0x21a00083,
-0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e,
-0x40a80002, 0x32800008, 0x4205c00c, 0x00200000,
-0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709,
-0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183,
-0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404,
-0x1cffc489, 0x00200000, 0x18008403, 0x38830402,
-0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402,
-0x1c020408, 0x38828182, 0xb0408385, 0x1802c387,
-0x28828182, 0x217ff886, 0x04000582, 0x32800007,
-0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285,
-0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903,
-0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06,
-0x40801202, 0x21a00a82, 0x73000003, 0x24200683,
-0x01a00404, 0x00200000, 0x34204682, 0x3ec40683,
-0xb0408203, 0x24204682, 0x01a00783, 0x00200000,
-0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682,
-0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204,
-0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002,
-0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82,
-0x04000683, 0x21a00803, 0x21a00885, 0x21a00904,
-0x40848002, 0x21a00982, 0x21a00a06, 0x40801002,
-0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000,
-0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83,
-0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003,
-0x4020007f, 0x35000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
+static unsigned int spu_save_code[]  __attribute__((__aligned__(128))) = {
+0x20805000,
+0x20805201,
+0x20805402,
+0x20805603,
+0x20805804,
+0x20805a05,
+0x20805c06,
+0x20805e07,
+0x20806008,
+0x20806209,
+0x2080640a,
+0x2080660b,
+0x2080680c,
+0x20806a0d,
+0x20806c0e,
+0x20806e0f,
+0x4201c003,
+0x33800184,
+0x1c010204,
+0x40200000,
+0x24000190,
+0x24004191,
+0x24008192,
+0x2400c193,
+0x141fc205,
+0x23fffd84,
+0x1c100183,
+0x217ffb85,
+0x40800000,
+0x409ff801,
+0x24000080,
+0x24fd8081,
+0x1cd80081,
+0x33000180,
+0x00000000,
+0x00000000,
+0x01a00182,
+0x3ec00083,
+0xb1c38103,
+0x01a00204,
+0x3ec10082,
+0x4201400d,
+0xb1c38202,
+0x01a00583,
+0x34218682,
+0x3ed80684,
+0xb0408184,
+0x24218682,
+0x01a00603,
+0x00200000,
+0x34214682,
+0x3ed40684,
+0xb0408184,
+0x40800003,
+0x24214682,
+0x21a00083,
+0x40800082,
+0x21a00b02,
+0x4020007f,
+0x1000251e,
+0x42a00002,
+0x32800008,
+0x4205c00c,
+0x00200000,
+0x40a0000b,
+0x3f82070f,
+0x4080020a,
+0x40800709,
+0x3fe3078f,
+0x3fbf0783,
+0x3f200183,
+0x3fbe0183,
+0x3fe30187,
+0x18008387,
+0x4205c002,
+0x3ac30404,
+0x1cffc489,
+0x00200000,
+0x18008403,
+0x38830402,
+0x4cffc486,
+0x3ac28185,
+0xb0408584,
+0x28830402,
+0x1c020408,
+0x38828182,
+0xb0408385,
+0x1802c387,
+0x28828182,
+0x217ff886,
+0x04000582,
+0x32800007,
+0x21a00802,
+0x3fbf0705,
+0x3f200285,
+0x3fbe0285,
+0x3fe30285,
+0x21a00885,
+0x04000603,
+0x21a00903,
+0x40803c02,
+0x21a00982,
+0x04000386,
+0x21a00a06,
+0x40801202,
+0x21a00a82,
+0x73000003,
+0x24200683,
+0x01a00404,
+0x00200000,
+0x34204682,
+0x3ec40683,
+0xb0408203,
+0x24204682,
+0x01a00783,
+0x00200000,
+0x3421c682,
+0x3edc0684,
+0xb0408184,
+0x2421c682,
+0x21a00806,
+0x21a00885,
+0x3fbf0784,
+0x3f200204,
+0x3fbe0204,
+0x3fe30204,
+0x21a00904,
+0x40804002,
+0x21a00982,
+0x21a00a06,
+0x40805a02,
+0x21a00a82,
+0x04000683,
+0x21a00803,
+0x21a00885,
+0x21a00904,
+0x40848002,
+0x21a00982,
+0x21a00a06,
+0x40801002,
+0x21a00a82,
+0x21a00a06,
+0x40806602,
+0x00200000,
+0x35800009,
+0x21a00a82,
+0x40800083,
+0x21a00b83,
+0x01a00c02,
+0x01a00d83,
+0x00003ffb,
+0x40800003,
+0x4020007f,
+0x35000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 1726bfe38ee0..b30e55dab832 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -46,6 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 
@@ -622,12 +623,17 @@ static inline void save_ppuint_mb(struct spu_state *csa, struct spu *spu)
 static inline void save_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	int i;
 
 	/* Save, Step 42:
-	 *     Save the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Save CH 1, without channel count */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW);
+
+	/* Save the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -718,13 +724,15 @@ static inline void invalidate_slbs(struct spu_state *csa, struct spu *spu)
 
 static inline void get_kernel_slb(u64 ea, u64 slb[2])
 {
-	slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
-	slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
+	u64 llp;
 
-	/* Large pages are used for kernel text/data, but not vmalloc.  */
-	if (cpu_has_feature(CPU_FTR_16M_PAGE)
-	    && REGION_ID(ea) == KERNEL_REGION_ID)
-		slb[0] |= SLB_VSID_L;
+	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) << 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)
@@ -1103,13 +1111,18 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
 static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	u64 idx;
 	int i;
 
 	/* Restore, Step 20:
-	 *     Reset the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Reset CH 1 */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	out_be64(&priv2->spu_chnldata_RW, 0UL);
+
+	/* Reset the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -1570,12 +1583,17 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu)
 static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	int i;
 
 	/* Restore, Step 59:
-	 *     Restore the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Restore CH 1 without count */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]);
+
+	/* Restore the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -2074,6 +2092,7 @@ int spu_save(struct spu_state *prev, struct spu *spu)
 	}
 	return rc;
 }
+EXPORT_SYMBOL_GPL(spu_save);
 
 /**
  * spu_restore - SPU context restore, with harvest and locking.
@@ -2090,7 +2109,6 @@ int spu_restore(struct spu_state *new, struct spu *spu)
 
 	acquire_spu_lock(spu);
 	harvest(NULL, spu);
-	spu->stop_code = 0;
 	spu->dar = 0;
 	spu->dsisr = 0;
 	spu->slb_replace = 0;
@@ -2103,6 +2121,7 @@ int spu_restore(struct spu_state *new, struct spu *spu)
 	}
 	return rc;
 }
+EXPORT_SYMBOL_GPL(spu_restore);
 
 /**
  * spu_harvest - SPU harvest (reset) operation
@@ -2125,6 +2144,7 @@ static void init_prob(struct spu_state *csa)
 	csa->spu_chnlcnt_RW[28] = 1;
 	csa->spu_chnlcnt_RW[30] = 1;
 	csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP;
+	csa->prob.mb_stat_R = 0x000400;
 }
 
 static void init_priv1(struct spu_state *csa)
@@ -2193,6 +2213,7 @@ void spu_init_csa(struct spu_state *csa)
 	init_priv1(csa);
 	init_priv2(csa);
 }
+EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
@@ -2203,3 +2224,4 @@ void spu_fini_csa(struct spu_state *csa)
 
 	vfree(csa->lscsa);
 }
+EXPORT_SYMBOL_GPL(spu_fini_csa);
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index ce8c0b943fa0..dee4eb4d8bec 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,9 +1,11 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.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_IBMVIO) += vio.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_VIOPATH) += viopath.o
 obj-$(CONFIG_MODULES) += ksyms.o
+
+$(obj)/dt_mod.o:	$(obj)/dt.o
+	@$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index 59d4e0ad5cf3..dbdf69850ed9 100644
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ b/arch/powerpc/platforms/iseries/call_pci.h
@@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
 	return retVal.rc;
 }
 
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u32 *value)
+{
+	struct HvCallPci_DsaAddr dsa;
+	struct HvCallPci_LoadReturn retVal;
+
+	*((u64*)&dsa) = 0;
+
+	dsa.busNumber = busNumber;
+	dsa.subBusNumber = subBusNumber;
+	dsa.deviceId = deviceId;
+
+	HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
+
+	*value = retVal.value;
+
+	return retVal.rc;
+}
+
 static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
 		u8 deviceId, u32 offset, u8 value)
 {
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644
index 000000000000..d3444aabe76e
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -0,0 +1,615 @@
+/*
+ *    Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
+ *
+ *    Description:
+ *      This file contains all the routines to build a flattened device
+ *      tree for a legacy iSeries machine.
+ *
+ *      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.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/threads.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>	/* ETH_ALEN */
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/lppaca.h>
+#include <asm/cputable.h>
+#include <asm/abs_addr.h>
+#include <asm/system.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
+#include <asm/udbg.h>
+
+#include "processor_vpd.h"
+#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * These are created by the linker script at the start and end
+ * of the section containing all the strings from this file.
+ */
+extern char __dt_strings_start[];
+extern char __dt_strings_end[];
+
+struct iseries_flat_dt {
+	struct boot_param_header header;
+	u64 reserve_map[2];
+};
+
+static void * __initdata dt_data;
+
+/*
+ * Putting these strings here keeps them out of the section
+ * that we rename to .dt_strings using objcopy and capture
+ * for the strings blob of the flattened device tree.
+ */
+static char __initdata device_type_cpu[] = "cpu";
+static char __initdata device_type_memory[] = "memory";
+static char __initdata device_type_serial[] = "serial";
+static char __initdata device_type_network[] = "network";
+static char __initdata device_type_block[] = "block";
+static char __initdata device_type_byte[] = "byte";
+static char __initdata device_type_pci[] = "pci";
+static char __initdata device_type_vdevice[] = "vdevice";
+static char __initdata device_type_vscsi[] = "vscsi";
+
+static struct iseries_flat_dt * __init dt_init(void)
+{
+	struct iseries_flat_dt *dt;
+	unsigned long str_len;
+
+	str_len = __dt_strings_end - __dt_strings_start;
+	dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
+	dt->header.off_mem_rsvmap =
+		offsetof(struct iseries_flat_dt, reserve_map);
+	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
+	dt->header.off_dt_struct = dt->header.off_dt_strings
+		+ ALIGN(str_len, 8);
+	dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
+	dt->header.dt_strings_size = str_len;
+
+	/* There is no notion of hardware cpu id on iSeries */
+	dt->header.boot_cpuid_phys = smp_processor_id();
+
+	memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
+			str_len);
+
+	dt->header.magic = OF_DT_HEADER;
+	dt->header.version = 0x10;
+	dt->header.last_comp_version = 0x10;
+
+	dt->reserve_map[0] = 0;
+	dt->reserve_map[1] = 0;
+
+	return dt;
+}
+
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+	*((u32 *)dt_data) = value;
+	dt_data += sizeof(u32);
+}
+
+#ifdef notyet
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+	*((u64 *)dt_data) = value;
+	dt_data += sizeof(u64);
+}
+#endif
+
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
+		int len)
+{
+	memcpy(dt_data, data, len);
+	dt_data += ALIGN(len, 4);
+}
+
+static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
+{
+	dt_push_u32(dt, OF_DT_BEGIN_NODE);
+	dt_push_bytes(dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+		const void *data, int len)
+{
+	unsigned long offset;
+
+	dt_push_u32(dt, OF_DT_PROP);
+
+	/* Length of the data */
+	dt_push_u32(dt, len);
+
+	offset = name - __dt_strings_start;
+
+	/* The offset of the properties name in the string blob. */
+	dt_push_u32(dt, (u32)offset);
+
+	/* The actual data. */
+	dt_push_bytes(dt, data, len);
+}
+
+static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
+		const char *data)
+{
+	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+		u32 data)
+{
+	dt_prop(dt, name, &data, sizeof(u32));
+}
+
+#ifdef notyet
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+		u64 data)
+{
+	dt_prop(dt, name, &data, sizeof(u64));
+}
+#endif
+
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
+		const char *name, u64 *data, int n)
+{
+	dt_prop(dt, name, data, sizeof(u64) * n);
+}
+
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
+		const char *name, u32 *data, int n)
+{
+	dt_prop(dt, name, data, sizeof(u32) * n);
+}
+
+#ifdef notyet
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
+{
+	dt_prop(dt, name, NULL, 0);
+}
+#endif
+
+static void __init dt_cpus(struct iseries_flat_dt *dt)
+{
+	unsigned char buf[32];
+	unsigned char *p;
+	unsigned int i, index;
+	struct IoHriProcessorVpd *d;
+	u32 pft_size[2];
+
+	/* yuck */
+	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+	p = strchr(buf, ' ');
+	if (!p) p = buf + strlen(buf);
+
+	dt_start_node(dt, "cpus");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
+	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (lppaca[i].dyn_proc_status >= 2)
+			continue;
+
+		snprintf(p, 32 - (p - buf), "@%d", i);
+		dt_start_node(dt, buf);
+
+		dt_prop_str(dt, "device_type", device_type_cpu);
+
+		index = lppaca[i].dyn_hv_phys_proc_index;
+		d = &xIoHriProcessorVpd[index];
+
+		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+		/* magic conversions to Hz copied from old code */
+		dt_prop_u32(dt, "clock-frequency",
+			((1UL << 34) * 1000000) / d->xProcFreq);
+		dt_prop_u32(dt, "timebase-frequency",
+			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+		dt_prop_u32(dt, "reg", i);
+
+		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
+		dt_end_node(dt);
+	}
+
+	dt_end_node(dt);
+}
+
+static void __init dt_model(struct iseries_flat_dt *dt)
+{
+	char buf[16] = "IBM,";
+
+	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+	buf[11] = '\0';
+	dt_prop_str(dt, "system-id", buf);
+
+	/* "IBM," + machineType[0:4] */
+	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+	buf[8] = '\0';
+	dt_prop_str(dt, "model", buf);
+
+	dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
+static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
+		const char *name, u32 reg, int unit,
+		const char *type, const char *compat, int end)
+{
+	char buf[32];
+
+	snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
+	dt_start_node(dt, buf);
+	dt_prop_str(dt, "device_type", type);
+	if (compat)
+		dt_prop_str(dt, "compatible", compat);
+	dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
+	if (unit >= 0)
+		dt_prop_u32(dt, "linux,unit_address", unit);
+	if (end)
+		dt_end_node(dt);
+}
+
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
+{
+	u32 reg = 0;
+	HvLpIndexMap vlan_map;
+	int i;
+
+	dt_start_node(dt, "vdevice");
+	dt_prop_str(dt, "device_type", device_type_vdevice);
+	dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
+	reg++;
+
+	dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
+			"IBM,v-scsi", 1);
+	reg++;
+
+	vlan_map = HvLpConfig_getVirtualLanIndexMap();
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+		unsigned char mac_addr[ETH_ALEN];
+
+		if ((vlan_map & (0x8000 >> i)) == 0)
+			continue;
+		dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
+				"IBM,iSeries-l-lan", 0);
+		mac_addr[0] = 0x02;
+		mac_addr[1] = 0x01;
+		mac_addr[2] = 0xff;
+		mac_addr[3] = i;
+		mac_addr[4] = 0xff;
+		mac_addr[5] = HvLpConfig_getLpIndex_outline();
+		dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop_u32(dt, "max-frame-size", 9000);
+		dt_prop_u32(dt, "address-bits", 48);
+
+		dt_end_node(dt);
+	}
+	reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+		dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
+				"IBM,iSeries-viodasd", 1);
+	reg += HVMAXARCHITECTEDVIRTUALDISKS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+		dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
+				"IBM,iSeries-viocd", 1);
+	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+		dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
+				"IBM,iSeries-viotape", 1);
+
+	dt_end_node(dt);
+}
+
+struct pci_class_name {
+	u16 code;
+	const char *name;
+	const char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+	struct pci_class_name *cp;
+
+	for (cp = pci_class_name;
+			cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+		if (cp->code == class_code)
+			return cp;
+	return NULL;
+}
+
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+		HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
+{
+	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+	u16 vendor_id;
+	u16 device_id;
+	u32 class_id;
+	int err;
+	char buf[32];
+	u32 reg[5];
+	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+	u8 devfn;
+	struct pci_class_name *cp;
+
+	/*
+	 * Connect all functions of any device found.
+	 */
+	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+		for (function = 0; function < 8; function++) {
+			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+					function);
+			err = HvCallXm_connectBusUnit(bus, sub_bus,
+					agent_id, 0);
+			if (err) {
+				if (err != 0x302)
+					DBG("connectBusUnit(%x, %x, %x) %x\n",
+						bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_VENDOR_ID, &vendor_id);
+			if (err) {
+				DBG("ReadVendor(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_DEVICE_ID, &device_id);
+			if (err) {
+				DBG("ReadDevice(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+					PCI_CLASS_REVISION , &class_id);
+			if (err) {
+				DBG("ReadClass(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+					function);
+			cp = dt_find_pci_class_name(class_id >> 16);
+			if (cp && cp->name)
+				strncpy(buf, cp->name, sizeof(buf) - 1);
+			else
+				snprintf(buf, sizeof(buf), "pci%x,%x",
+						vendor_id, device_id);
+			buf[sizeof(buf) - 1] = '\0';
+			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+					"@%x", PCI_SLOT(devfn));
+			buf[sizeof(buf) - 1] = '\0';
+			if (function != 0)
+				snprintf(buf + strlen(buf),
+					sizeof(buf) - strlen(buf),
+					",%x", function);
+			dt_start_node(dt, buf);
+			reg[0] = (bus << 16) | (devfn << 8);
+			reg[1] = 0;
+			reg[2] = 0;
+			reg[3] = 0;
+			reg[4] = 0;
+			dt_prop_u32_list(dt, "reg", reg, 5);
+			if (cp && (cp->type || cp->name))
+				dt_prop_str(dt, "device_type",
+					cp->type ? cp->type : cp->name);
+			dt_prop_u32(dt, "vendor-id", vendor_id);
+			dt_prop_u32(dt, "device-id", device_id);
+			dt_prop_u32(dt, "class-code", class_id >> 8);
+			dt_prop_u32(dt, "revision-id", class_id & 0xff);
+			dt_prop_u32(dt, "linux,subbus", sub_bus);
+			dt_prop_u32(dt, "linux,agent-id", agent_id);
+			dt_prop_u32(dt, "linux,logical-slot-number",
+					bridge_info->logicalSlotNumber);
+			dt_end_node(dt);
+
+		}
+	}
+}
+
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+		HvSubBusNumber sub_bus, int id_sel)
+{
+	struct HvCallPci_BridgeInfo bridge_info;
+	HvAgentId agent_id;
+	int function;
+	int ret;
+
+	/* Note: hvSubBus and irq is always be 0 at this level! */
+	for (function = 0; function < 8; ++function) {
+		agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+		if (ret != 0) {
+			if (ret != 0xb)
+				DBG("connectBusUnit(%x, %x, %x) %x\n",
+						bus, sub_bus, agent_id, ret);
+			continue;
+		}
+		DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
+				bus, id_sel, function, agent_id);
+		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+				iseries_hv_addr(&bridge_info),
+				sizeof(struct HvCallPci_BridgeInfo));
+		if (ret != 0)
+			continue;
+		DBG("bridge info: type %x subbus %x "
+			"maxAgents %x maxsubbus %x logslot %x\n",
+			bridge_info.busUnitInfo.deviceType,
+			bridge_info.subBusNumber,
+			bridge_info.maxAgents,
+			bridge_info.maxSubBusNumber,
+			bridge_info.logicalSlotNumber);
+		if (bridge_info.busUnitInfo.deviceType ==
+				HvCallPci_BridgeDevice)
+			scan_bridge_slot(dt, bus, &bridge_info);
+		else
+			DBG("PCI: Invalid Bridge Configuration(0x%02X)",
+				bridge_info.busUnitInfo.deviceType);
+	}
+}
+
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+	struct HvCallPci_DeviceInfo dev_info;
+	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
+	int err;
+	int id_sel;
+	const int max_agents = 8;
+
+	/*
+	 * Probe for EADs Bridges
+	 */
+	for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+		err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+				iseries_hv_addr(&dev_info),
+				sizeof(struct HvCallPci_DeviceInfo));
+		if (err) {
+			if (err != 0x302)
+				DBG("getDeviceInfo(%x, %x, %x) %x\n",
+						bus, sub_bus, id_sel, err);
+			continue;
+		}
+		if (dev_info.deviceType != HvCallPci_NodeDevice) {
+			DBG("PCI: Invalid System Configuration"
+					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
+					dev_info.deviceType, bus, id_sel);
+			continue;
+		}
+		scan_bridge(dt, bus, sub_bus, id_sel);
+	}
+}
+
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
+{
+	HvBusNumber bus;
+	char buf[32];
+	u32 buses[2];
+	int phb_num = 0;
+
+	/* Check all possible buses. */
+	for (bus = 0; bus < 256; bus++) {
+		int err = HvCallXm_testBus(bus);
+
+		if (err) {
+			/*
+			 * Check for Unexpected Return code, a clue that
+			 * something has gone wrong.
+			 */
+			if (err != 0x0301)
+				DBG("Unexpected Return on Probe(0x%02X) "
+						"0x%04X\n", bus, err);
+			continue;
+		}
+		DBG("bus %d appears to exist\n", bus);
+		snprintf(buf, 32, "pci@%d", phb_num);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", device_type_pci);
+		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+		dt_prop_u32(dt, "#address-cells", 3);
+		dt_prop_u32(dt, "#size-cells", 2);
+		buses[0] = buses[1] = bus;
+		dt_prop_u32_list(dt, "bus-range", buses, 2);
+		scan_phb(dt, bus);
+		dt_end_node(dt);
+		phb_num++;
+	}
+}
+
+static void dt_finish(struct iseries_flat_dt *dt)
+{
+	dt_push_u32(dt, OF_DT_END);
+	dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
+	klimit = ALIGN((unsigned long)dt_data, 8);
+}
+
+void * __init build_flat_dt(unsigned long phys_mem_size)
+{
+	struct iseries_flat_dt *iseries_dt;
+	u64 tmp[2];
+
+	iseries_dt = dt_init();
+
+	dt_start_node(iseries_dt, "");
+
+	dt_prop_u32(iseries_dt, "#address-cells", 2);
+	dt_prop_u32(iseries_dt, "#size-cells", 2);
+	dt_model(iseries_dt);
+
+	/* /memory */
+	dt_start_node(iseries_dt, "memory@0");
+	dt_prop_str(iseries_dt, "device_type", device_type_memory);
+	tmp[0] = 0;
+	tmp[1] = phys_mem_size;
+	dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
+	dt_end_node(iseries_dt);
+
+	/* /chosen */
+	dt_start_node(iseries_dt, "chosen");
+	dt_prop_str(iseries_dt, "bootargs", cmd_line);
+	dt_end_node(iseries_dt);
+
+	dt_cpus(iseries_dt);
+
+	dt_vdevices(iseries_dt);
+	dt_pci_devices(iseries_dt);
+
+	dt_end_node(iseries_dt);
+
+	dt_finish(iseries_dt);
+
+	return iseries_dt;
+}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index bea0b703f409..e3bd2015f2c9 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -4,6 +4,7 @@
  * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, iSeries-specific parts.
  *
@@ -31,42 +32,37 @@
 #include <asm/tce.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/iseries/hv_call_xm.h>
-
-#include "iommu.h"
-
-extern struct list_head iSeries_Global_Device_List;
-
+#include <asm/iseries/iommu.h>
 
 static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
 		unsigned long uaddr, enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 tce, rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
 	while (npages--) {
-		tce.te_word = 0;
-		tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		if (tbl->it_type == TCE_VB) {
 			/* Virtual Bus */
-			tce.te_bits.tb_valid = 1;
-			tce.te_bits.tb_allio = 1;
+			tce |= TCE_VALID|TCE_ALLIO;
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_rdwr = 1;
+				tce |= TCE_VB_WRITE;
 		} else {
 			/* PCI Bus */
-			tce.te_bits.tb_rdwr = 1; /* Read allowed */
+			tce |= TCE_PCI_READ; /* Read allowed */
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_pciwr = 1;
+				tce |= TCE_PCI_WRITE;
 		}
 
-		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
-				tce.te_word);
+		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
 		if (rc)
 			panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
 					rc);
@@ -124,7 +120,7 @@ void iommu_table_getparms_iSeries(unsigned long busno,
 
 	/* itc_size is in pages worth of table, it_size is in # of entries */
 	tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
-			sizeof(union tce_entry)) >> TCE_PAGE_FACTOR;
+			TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
 	tbl->it_busno = parms->itc_busno;
 	tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
 	tbl->it_index = parms->itc_index;
@@ -142,10 +138,15 @@ void iommu_table_getparms_iSeries(unsigned long busno,
  */
 static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		struct iommu_table *it = pdn->iommu_table;
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
+		struct iommu_table *it;
+
+		if (pdn == NULL)
+			continue;
+		it = pdn->iommu_table;
 		if ((it != NULL) &&
 		    (it->it_type == TCE_PCI) &&
 		    (it->it_offset == tbl->it_offset) &&
@@ -161,15 +162,18 @@ void iommu_devnode_init_iSeries(struct device_node *dn)
 {
 	struct iommu_table *tbl;
 	struct pci_dn *pdn = PCI_DN(dn);
+	u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL);
+
+	BUG_ON(lsn == NULL);
 
 	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-	iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl);
+	iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
 
 	/* Look for existing tce table */
 	pdn->iommu_table = iommu_table_find(tbl);
 	if (pdn->iommu_table == NULL)
-		pdn->iommu_table = iommu_init_table(tbl);
+		pdn->iommu_table = iommu_init_table(tbl, -1);
 	else
 		kfree(tbl);
 }
diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h
deleted file mode 100644
index cb5658fbe657..000000000000
--- a/arch/powerpc/platforms/iseries/iommu.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _PLATFORMS_ISERIES_IOMMU_H
-#define _PLATFORMS_ISERIES_IOMMU_H
-
-/*
- * Copyright (C) 2005  Stephen Rothwell, 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; 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
- */
-
-struct device_node;
-struct iommu_table;
-
-/* Creates table for an individual device node */
-extern void iommu_devnode_init_iSeries(struct device_node *dn);
-
-/* Get table parameters from HV */
-extern void iommu_table_getparms_iSeries(unsigned long busno,
-		unsigned char slotno, unsigned char virtbus,
-		struct iommu_table *tbl);
-
-#endif /* _PLATFORMS_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc24e6c..62bbbcf5ded3 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -42,6 +42,7 @@
 #include <asm/iseries/it_lp_queue.h>
 
 #include "irq.h"
+#include "pci.h"
 #include "call_pci.h"
 
 #if defined(CONFIG_SMP)
@@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_handler = {
  * Note that sub_bus is always 0 (at the moment at least).
  */
 int __init iSeries_allocate_IRQ(HvBusNumber bus,
-		HvSubBusNumber sub_bus, HvAgentId dev_id)
+		HvSubBusNumber sub_bus, u32 bsubbus)
 {
 	int virtirq;
 	unsigned int realirq;
-	u8 idsel = (dev_id >> 4);
-	u8 function = dev_id & 7;
+	u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
+	u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
 
 	realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
 		+ function;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index b9c801ba5a47..188aa808abd7 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -2,7 +2,7 @@
 #define	_ISERIES_IRQ_H
 
 extern void iSeries_init_IRQ(void);
-extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
 extern void iSeries_activate_IRQs(void);
 extern int iSeries_get_irq(struct pt_regs *);
 
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index d771b8ee857d..1a2c2a50f922 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -45,7 +45,6 @@
 
 #include "setup.h"
 
-extern int piranha_simulator;
 static int mf_initialized;
 
 /*
@@ -658,7 +657,7 @@ static void mf_clear_src(void)
 
 void __init mf_display_progress(u16 value)
 {
-	if (piranha_simulator || !mf_initialized)
+	if (!mf_initialized)
 		return;
 
 	if (0xFFFF == value)
@@ -1295,9 +1294,6 @@ __initcall(mf_proc_init);
  */
 void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
 {
-	if (piranha_simulator)
-		return;
-
 	mf_get_rtc(rtc_tm);
 	rtc_tm->tm_mon--;
 }
@@ -1316,9 +1312,6 @@ unsigned long iSeries_get_boot_time(void)
 {
 	struct rtc_time tm;
 
-	if (piranha_simulator)
-		return 0;
-
 	mf_get_boot_rtc(&tm);
 	return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday,
 		      tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index a19833b880e4..35bcc98111f5 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -37,36 +37,18 @@
 
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
+#include <asm/iseries/iommu.h>
 
 #include <asm/ppc-pci.h>
 
 #include "irq.h"
 #include "pci.h"
 #include "call_pci.h"
-#include "iommu.h"
-
-extern unsigned long io_page_mask;
 
 /*
  * Forward declares of prototypes.
  */
 static struct device_node *find_Device_Node(int bus, int devfn);
-static void scan_PHB_slots(struct pci_controller *Phb);
-static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
-static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
-
-LIST_HEAD(iSeries_Global_Device_List);
-
-static int DeviceCount;
-
-/* Counters and control flags. */
-static long Pci_Io_Read_Count;
-static long Pci_Io_Write_Count;
-#if 0
-static long Pci_Cfg_Read_Count;
-static long Pci_Cfg_Write_Count;
-#endif
-static long Pci_Error_Count;
 
 static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
 static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
@@ -81,41 +63,19 @@ static struct pci_ops iSeries_pci_ops;
 #define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
 #define BASE_IO_MEMORY		0xE000000000000000UL
 
-static unsigned long max_io_memory = 0xE000000000000000UL;
+static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
 
 /*
  * Lookup Tables.
  */
-static struct device_node **iomm_table;
-static u8 *iobar_table;
+static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
+static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-/*
- * Static and Global variables
- */
-static char *pci_io_text = "iSeries PCI I/O";
+static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
 /*
- * iomm_table_initialize
- *
- * Allocates and initalizes the Address Translation Table and Bar
- * Tables to get them ready for use.  Must be called before any
- * I/O space is handed out to the device BARs.
- */
-static void iomm_table_initialize(void)
-{
-	spin_lock(&iomm_table_lock);
-	iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	spin_unlock(&iomm_table_lock);
-	if ((iomm_table == NULL) || (iobar_table == NULL))
-		panic("PCI: I/O tables allocation failed.\n");
-}
-
-/*
  * iomm_table_allocate_entry
  *
  * Adds pci_dev entry in address translation table
@@ -142,9 +102,8 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
 	 */
 	spin_lock(&iomm_table_lock);
 	bar_res->name = pci_io_text;
-	bar_res->start =
+	bar_res->start = BASE_IO_MEMORY +
 		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
-	bar_res->start += BASE_IO_MEMORY;
 	bar_res->end = bar_res->start + bar_size - 1;
 	/*
 	 * Allocate the number of table entries needed for BAR.
@@ -156,7 +115,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
 		++current_iomm_table_entry;
 	}
 	max_io_memory = BASE_IO_MEMORY +
-		(IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
 	spin_unlock(&iomm_table_lock);
 }
 
@@ -173,13 +132,10 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
  */
 static void allocate_device_bars(struct pci_dev *dev)
 {
-	struct resource *bar_res;
 	int bar_num;
 
-	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
-		bar_res = &dev->resource[bar_num];
+	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
 		iomm_table_allocate_entry(dev, bar_num);
-	}
 }
 
 /*
@@ -199,34 +155,7 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
 }
 
 /*
- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
- */
-static struct device_node *build_device_node(HvBusNumber Bus,
-		HvSubBusNumber SubBus, int AgentId, int Function)
-{
-	struct device_node *node;
-	struct pci_dn *pdn;
-
-	node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
-	memset(node, 0, sizeof(struct device_node));
-	pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
-	if (pdn == NULL) {
-		kfree(node);
-		return NULL;
-	}
-	node->data = pdn;
-	pdn->node = node;
-	list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
-	pdn->busno = Bus;
-	pdn->bussubno = SubBus;
-	pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
-	return node;
-}
-
-/*
- * unsigned long __init find_and_init_phbs(void)
+ * iSeries_pcibios_init
  *
  * Description:
  *   This function checks for all possible system PCI host bridges that connect
@@ -234,50 +163,42 @@ static struct device_node *build_device_node(HvBusNumber Bus,
  *   ownership status.  A pci_controller is built for any bus which is partially
  *   owned or fully owned by this guest partition.
  */
-unsigned long __init find_and_init_phbs(void)
+void iSeries_pcibios_init(void)
 {
 	struct pci_controller *phb;
-	HvBusNumber bus;
-
-	/* Check all possible buses. */
-	for (bus = 0; bus < 256; bus++) {
-		int ret = HvCallXm_testBus(bus);
-		if (ret == 0) {
-			printk("bus %d appears to exist\n", bus);
+	struct device_node *root = of_find_node_by_path("/");
+	struct device_node *node = NULL;
 
-			phb = pcibios_alloc_controller(NULL);
-			if (phb == NULL)
-				return -ENOMEM;
-
-			phb->pci_mem_offset = phb->local_number = bus;
-			phb->first_busno = bus;
-			phb->last_busno = bus;
-			phb->ops = &iSeries_pci_ops;
-
-			/* Find and connect the devices. */
-			scan_PHB_slots(phb);
-		}
-		/*
-		 * Check for Unexpected Return code, a clue that something
-		 * has gone wrong.
-		 */
-		else if (ret != 0x0301)
-			printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
-			       bus, ret);
+	if (root == NULL) {
+		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+				"of device tree\n");
+		return;
+	}
+	while ((node = of_get_next_child(root, node)) != NULL) {
+		HvBusNumber bus;
+		u32 *busp;
+
+		if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
+			continue;
+
+		busp = (u32 *)get_property(node, "bus-range", NULL);
+		if (busp == NULL)
+			continue;
+		bus = *busp;
+		printk("bus %d appears to exist\n", bus);
+		phb = pcibios_alloc_controller(node);
+		if (phb == NULL)
+			continue;
+
+		phb->pci_mem_offset = phb->local_number = bus;
+		phb->first_busno = bus;
+		phb->last_busno = bus;
+		phb->ops = &iSeries_pci_ops;
 	}
-	return 0;
-}
 
-/*
- * iSeries_pcibios_init
- *
- * Chance to initialize and structures or variable before PCI Bus walk.
- */
-void iSeries_pcibios_init(void)
-{
-	iomm_table_initialize();
-	find_and_init_phbs();
-	io_page_mask = -1;
+	of_node_put(root);
+
+	pci_devs_phb_init();
 }
 
 /*
@@ -299,6 +220,34 @@ void __init iSeries_pci_final_fixup(void)
 		       pdev->bus->number, pdev->devfn, node);
 
 		if (node != NULL) {
+			struct pci_dn *pdn = PCI_DN(node);
+			u32 *agent;
+
+			agent = (u32 *)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;
@@ -308,7 +257,6 @@ void __init iSeries_pci_final_fixup(void)
 		} else
 			printk("PCI: Device Tree not found for 0x%016lX\n",
 					(unsigned long)pdev);
-		pdev->irq = PCI_DN(node)->Irq;
 	}
 	iSeries_activate_IRQs();
 	mf_display_src(0xC9000200);
@@ -323,148 +271,6 @@ void pcibios_fixup_resources(struct pci_dev *pdev)
 }
 
 /*
- * Loop through each node function to find usable EADs bridges.
- */
-static void scan_PHB_slots(struct pci_controller *Phb)
-{
-	struct HvCallPci_DeviceInfo *DevInfo;
-	HvBusNumber bus = Phb->local_number;	/* System Bus */
-	const HvSubBusNumber SubBus = 0;	/* EADs is always 0. */
-	int HvRc = 0;
-	int IdSel;
-	const int MaxAgents = 8;
-
-	DevInfo = (struct HvCallPci_DeviceInfo*)
-		kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
-	if (DevInfo == NULL)
-		return;
-
-	/*
-	 * Probe for EADs Bridges
-	 */
-	for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
-		HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
-				iseries_hv_addr(DevInfo),
-				sizeof(struct HvCallPci_DeviceInfo));
-		if (HvRc == 0) {
-			if (DevInfo->deviceType == HvCallPci_NodeDevice)
-				scan_EADS_bridge(bus, SubBus, IdSel);
-			else
-				printk("PCI: Invalid System Configuration(0x%02X)"
-				       " for bus 0x%02x id 0x%02x.\n",
-				       DevInfo->deviceType, bus, IdSel);
-		}
-		else
-			pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
-	}
-	kfree(DevInfo);
-}
-
-static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
-		int IdSel)
-{
-	struct HvCallPci_BridgeInfo *BridgeInfo;
-	HvAgentId AgentId;
-	int Function;
-	int HvRc;
-
-	BridgeInfo = (struct HvCallPci_BridgeInfo *)
-		kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
-	if (BridgeInfo == NULL)
-		return;
-
-	/* Note: hvSubBus and irq is always be 0 at this level! */
-	for (Function = 0; Function < 8; ++Function) {
-		AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-		HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
-		if (HvRc == 0) {
-			printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
-			       bus, IdSel, Function, AgentId);
-			/*  Connect EADs: 0x18.00.12 = 0x00 */
-			HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
-					iseries_hv_addr(BridgeInfo),
-					sizeof(struct HvCallPci_BridgeInfo));
-			if (HvRc == 0) {
-				printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
-					BridgeInfo->busUnitInfo.deviceType,
-					BridgeInfo->subBusNumber,
-					BridgeInfo->maxAgents,
-					BridgeInfo->maxSubBusNumber,
-					BridgeInfo->logicalSlotNumber);
-				if (BridgeInfo->busUnitInfo.deviceType ==
-						HvCallPci_BridgeDevice)  {
-					/* Scan_Bridge_Slot...: 0x18.00.12 */
-					scan_bridge_slot(bus, BridgeInfo);
-				} else
-					printk("PCI: Invalid Bridge Configuration(0x%02X)",
-						BridgeInfo->busUnitInfo.deviceType);
-			}
-		} else if (HvRc != 0x000B)
-			pci_Log_Error("EADs Connect",
-					bus, SubBus, AgentId, HvRc);
-	}
-	kfree(BridgeInfo);
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static int scan_bridge_slot(HvBusNumber Bus,
-		struct HvCallPci_BridgeInfo *BridgeInfo)
-{
-	struct device_node *node;
-	HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
-	u16 VendorId = 0;
-	int HvRc = 0;
-	u8 Irq = 0;
-	int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
-	int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
-	HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
-
-	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
-	Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
-
-	/*
-	 * Connect all functions of any device found.
-	 */
-	for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
-		for (Function = 0; Function < 8; ++Function) {
-			HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-			HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
-					AgentId, Irq);
-			if (HvRc != 0) {
-				pci_Log_Error("Connect Bus Unit",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-
-			HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
-						      PCI_VENDOR_ID, &VendorId);
-			if (HvRc != 0) {
-				pci_Log_Error("Read Vendor",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-			printk("read vendor ID: %x\n", VendorId);
-
-			/* FoundDevice: 0x18.28.10 = 0x12AE */
-			HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
-						      PCI_INTERRUPT_LINE, Irq);
-			if (HvRc != 0)
-				pci_Log_Error("PciCfgStore Irq Failed!",
-					      Bus, SubBus, AgentId, HvRc);
-
-			++DeviceCount;
-			node = build_device_node(Bus, SubBus, EADsIdSel, Function);
-			PCI_DN(node)->Irq = Irq;
-			PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
-
-		} /* for (Function = 0; Function < 8; ++Function) */
-	} /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
-	return HvRc;
-}
-
-/*
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
@@ -509,11 +315,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio);
  */
 static struct device_node *find_Device_Node(int bus, int devfn)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
+
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		if ((bus == pdn->busno) && (devfn == pdn->devfn))
-			return pdn->node;
+		if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
+			return node;
 	}
 	return NULL;
 }
@@ -625,7 +433,6 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
 	if (ret != 0)  {
 		struct pci_dn *pdn = PCI_DN(DevNode);
 
-		++Pci_Error_Count;
 		(*retry)++;
 		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
 				TextHdr, pdn->busno, pdn->devfn,
@@ -707,7 +514,6 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 		return 0xff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
 	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
 
@@ -737,7 +543,6 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 		return 0xffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
@@ -768,7 +573,6 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 		return 0xffffffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
@@ -806,7 +610,6 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
 	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
@@ -834,7 +637,6 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
 	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
@@ -862,7 +664,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
 	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index a6fd9bedb074..617c724c4590 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -50,7 +50,6 @@
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/mf.h>
-#include <asm/iseries/it_exp_vpd_panel.h>
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/lpar_map.h>
 #include <asm/udbg.h>
@@ -81,9 +80,6 @@ extern void iSeries_pci_final_fixup(void);
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-/* Global Variables */
-int piranha_simulator;
-
 extern int rd_size;		/* Defined in drivers/block/rd.c */
 extern unsigned long embedded_sysmap_start;
 extern unsigned long embedded_sysmap_end;
@@ -91,8 +87,6 @@ extern unsigned long embedded_sysmap_end;
 extern unsigned long iSeries_recal_tb;
 extern unsigned long iSeries_recal_titan;
 
-static unsigned long cmd_mem_limit;
-
 struct MemoryBlock {
 	unsigned long absStart;
 	unsigned long absEnd;
@@ -340,8 +334,6 @@ static void __init iSeries_init_early(void)
 #ifdef CONFIG_SMP
 	smp_init_iSeries();
 #endif
-	if (itLpNaca.xPirEnvironMode == 0)
-		piranha_simulator = 1;
 
 	/* Associate Lp Event Queue 0 with processor 0 */
 	HvCallEvent_setLpEventQueueInterruptProc(0, 0);
@@ -536,10 +528,10 @@ static void __init iSeries_setup_arch(void)
 {
 	if (get_lppaca()->shared_proc) {
 		ppc_md.idle_loop = iseries_shared_idle;
-		printk(KERN_INFO "Using shared processor idle loop\n");
+		printk(KERN_DEBUG "Using shared processor idle loop\n");
 	} else {
 		ppc_md.idle_loop = iseries_dedicated_idle;
-		printk(KERN_INFO "Using dedicated idle loop\n");
+		printk(KERN_DEBUG "Using dedicated idle loop\n");
 	}
 
 	/* Setup the Lp Event Queue */
@@ -714,243 +706,6 @@ define_machine(iseries) {
 	/* XXX Implement enable_pmcs for iSeries */
 };
 
-struct blob {
-	unsigned char data[PAGE_SIZE];
-	unsigned long next;
-};
-
-struct iseries_flat_dt {
-	struct boot_param_header header;
-	u64 reserve_map[2];
-	struct blob dt;
-	struct blob strings;
-};
-
-struct iseries_flat_dt iseries_dt;
-
-void dt_init(struct iseries_flat_dt *dt)
-{
-	dt->header.off_mem_rsvmap =
-		offsetof(struct iseries_flat_dt, reserve_map);
-	dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
-	dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
-	dt->header.totalsize = sizeof(struct iseries_flat_dt);
-	dt->header.dt_strings_size = sizeof(struct blob);
-
-	/* There is no notion of hardware cpu id on iSeries */
-	dt->header.boot_cpuid_phys = smp_processor_id();
-
-	dt->dt.next = (unsigned long)&dt->dt.data;
-	dt->strings.next = (unsigned long)&dt->strings.data;
-
-	dt->header.magic = OF_DT_HEADER;
-	dt->header.version = 0x10;
-	dt->header.last_comp_version = 0x10;
-
-	dt->reserve_map[0] = 0;
-	dt->reserve_map[1] = 0;
-}
-
-void dt_check_blob(struct blob *b)
-{
-	if (b->next >= (unsigned long)&b->next) {
-		DBG("Ran out of space in flat device tree blob!\n");
-		BUG();
-	}
-}
-
-void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
-{
-	*((u32*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u32);
-
-	dt_check_blob(&dt->dt);
-}
-
-void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
-{
-	*((u64*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u64);
-
-	dt_check_blob(&dt->dt);
-}
-
-unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
-{
-	unsigned long start = blob->next - (unsigned long)blob->data;
-
-	memcpy((char *)blob->next, data, len);
-	blob->next = _ALIGN(blob->next + len, 4);
-
-	dt_check_blob(blob);
-
-	return start;
-}
-
-void dt_start_node(struct iseries_flat_dt *dt, char *name)
-{
-	dt_push_u32(dt, OF_DT_BEGIN_NODE);
-	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
-}
-
-#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-
-void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
-{
-	unsigned long offset;
-
-	dt_push_u32(dt, OF_DT_PROP);
-
-	/* Length of the data */
-	dt_push_u32(dt, len);
-
-	/* Put the property name in the string blob. */
-	offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
-
-	/* The offset of the properties name in the string blob. */
-	dt_push_u32(dt, (u32)offset);
-
-	/* The actual data. */
-	dt_push_bytes(&dt->dt, data, len);
-}
-
-void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
-{
-	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
-}
-
-void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u32));
-}
-
-void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u64));
-}
-
-void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
-}
-
-void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
-}
-
-void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
-{
-	dt_prop(dt, name, NULL, 0);
-}
-
-void dt_cpus(struct iseries_flat_dt *dt)
-{
-	unsigned char buf[32];
-	unsigned char *p;
-	unsigned int i, index;
-	struct IoHriProcessorVpd *d;
-	u32 pft_size[2];
-
-	/* yuck */
-	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
-	p = strchr(buf, ' ');
-	if (!p) p = buf + strlen(buf);
-
-	dt_start_node(dt, "cpus");
-	dt_prop_u32(dt, "#address-cells", 1);
-	dt_prop_u32(dt, "#size-cells", 0);
-
-	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
-	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (lppaca[i].dyn_proc_status >= 2)
-			continue;
-
-		snprintf(p, 32 - (p - buf), "@%d", i);
-		dt_start_node(dt, buf);
-
-		dt_prop_str(dt, "device_type", "cpu");
-
-		index = lppaca[i].dyn_hv_phys_proc_index;
-		d = &xIoHriProcessorVpd[index];
-
-		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
-		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
-
-		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
-		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
-
-		/* magic conversions to Hz copied from old code */
-		dt_prop_u32(dt, "clock-frequency",
-			((1UL << 34) * 1000000) / d->xProcFreq);
-		dt_prop_u32(dt, "timebase-frequency",
-			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
-
-		dt_prop_u32(dt, "reg", i);
-
-		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
-
-		dt_end_node(dt);
-	}
-
-	dt_end_node(dt);
-}
-
-void dt_model(struct iseries_flat_dt *dt)
-{
-	char buf[16] = "IBM,";
-
-	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
-	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
-	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
-	buf[11] = '\0';
-	dt_prop_str(dt, "system-id", buf);
-
-	/* "IBM," + machineType[0:4] */
-	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
-	buf[8] = '\0';
-	dt_prop_str(dt, "model", buf);
-
-	dt_prop_str(dt, "compatible", "IBM,iSeries");
-}
-
-void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
-{
-	u64 tmp[2];
-
-	dt_init(dt);
-
-	dt_start_node(dt, "");
-
-	dt_prop_u32(dt, "#address-cells", 2);
-	dt_prop_u32(dt, "#size-cells", 2);
-	dt_model(dt);
-
-	/* /memory */
-	dt_start_node(dt, "memory@0");
-	dt_prop_str(dt, "name", "memory");
-	dt_prop_str(dt, "device_type", "memory");
-	tmp[0] = 0;
-	tmp[1] = phys_mem_size;
-	dt_prop_u64_list(dt, "reg", tmp, 2);
-	dt_end_node(dt);
-
-	/* /chosen */
-	dt_start_node(dt, "chosen");
-	dt_prop_str(dt, "bootargs", cmd_line);
-	if (cmd_mem_limit)
-		dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
-	dt_end_node(dt);
-
-	dt_cpus(dt);
-
-	dt_end_node(dt);
-
-	dt_push_u32(dt, OF_DT_END);
-}
-
 void * __init iSeries_early_setup(void)
 {
 	unsigned long phys_mem_size;
@@ -965,28 +720,8 @@ void * __init iSeries_early_setup(void)
 
 	iSeries_get_cmdline();
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-	/* Parse early parameters, in particular mem=x */
-	parse_early_param();
-
-	build_flat_dt(&iseries_dt, phys_mem_size);
-
-	return (void *) __pa(&iseries_dt);
-}
-
-/*
- * On iSeries we just parse the mem=X option from the command line.
- * On pSeries it's a bit more complicated, see prom_init_mem()
- */
-static int __init early_parsemem(char *p)
-{
-	if (p)
-		cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
-	return 0;
+	return (void *) __pa(build_flat_dt(phys_mem_size));
 }
-early_param("mem", early_parsemem);
 
 static void hvputc(char c)
 {
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 5213044ec411..0a47ac53c959 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -21,4 +21,6 @@ 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);
 
+extern void *build_flat_dt(unsigned long phys_mem_size);
+
 #endif /* __ISERIES_SETUP_H__ */
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
deleted file mode 100644
index ad36ab0639f0..000000000000
--- a/arch/powerpc/platforms/iseries/vio.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
- *
- *    Copyright (c) 2005 Stephen Rothwell, 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.
- */
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/init.h>
-
-#include <asm/vio.h>
-#include <asm/iommu.h>
-#include <asm/tce.h>
-#include <asm/abs_addr.h>
-#include <asm/page.h>
-#include <asm/iseries/vio.h>
-#include <asm/iseries/hv_types.h>
-#include <asm/iseries/hv_lp_config.h>
-#include <asm/iseries/hv_call_xm.h>
-
-#include "iommu.h"
-
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
-
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
-
-static void __init iommu_vio_init(void)
-{
-	iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
-	veth_iommu_table.it_size /= 2;
-	vio_iommu_table = veth_iommu_table;
-	vio_iommu_table.it_offset += veth_iommu_table.it_size;
-
-	if (!iommu_init_table(&veth_iommu_table))
-		printk("Virtual Bus VETH TCE table failed.\n");
-	if (!iommu_init_table(&vio_iommu_table))
-		printk("Virtual Bus VIO TCE table failed.\n");
-}
-
-/**
- * vio_register_device_iseries: - Register a new iSeries vio device.
- * @voidev:	The device to register.
- */
-static struct vio_dev *__init vio_register_device_iseries(char *type,
-		uint32_t unit_num)
-{
-	struct vio_dev *viodev;
-
-	/* allocate a vio_dev for this device */
-	viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (!viodev)
-		return NULL;
-	memset(viodev, 0, sizeof(struct vio_dev));
-
-	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
-
-	viodev->name = viodev->dev.bus_id;
-	viodev->type = type;
-	viodev->unit_address = unit_num;
-	viodev->iommu_table = &vio_iommu_table;
-	if (vio_register_device(viodev) == NULL) {
-		kfree(viodev);
-		return NULL;
-	}
-	return viodev;
-}
-
-void __init probe_bus_iseries(void)
-{
-	HvLpIndexMap vlan_map;
-	struct vio_dev *viodev;
-	int i;
-
-	/* there is only one of each of these */
-	vio_register_device_iseries("viocons", 0);
-	vio_register_device_iseries("vscsi", 0);
-
-	vlan_map = HvLpConfig_getVirtualLanIndexMap();
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
-		if ((vlan_map & (0x8000 >> i)) == 0)
-			continue;
-		viodev = vio_register_device_iseries("vlan", i);
-		/* veth is special and has it own iommu_table */
-		viodev->iommu_table = &veth_iommu_table;
-	}
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
-		vio_register_device_iseries("viodasd", i);
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
-		vio_register_device_iseries("viocd", i);
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
-		vio_register_device_iseries("viotape", i);
-}
-
-/**
- * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
- *	vio_device_id
- */
-static int vio_match_device_iseries(const struct vio_device_id *id,
-		const struct vio_dev *dev)
-{
-	return strncmp(dev->type, id->type, strlen(id->type)) == 0;
-}
-
-static struct vio_bus_ops vio_bus_ops_iseries = {
-	.match = vio_match_device_iseries,
-};
-
-/**
- * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
- */
-static int __init vio_bus_init_iseries(void)
-{
-	int err;
-
-	err = vio_bus_init(&vio_bus_ops_iseries);
-	if (err == 0) {
-		iommu_vio_init();
-		vio_bus_device.iommu_table = &vio_iommu_table;
-		iSeries_vio_dev = &vio_bus_device.dev;
-		probe_bus_iseries();
-	}
-	return err;
-}
-
-__initcall(vio_bus_init_iseries);
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 85d6c93659cc..9a4efc0c3b29 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -437,9 +437,6 @@ void __init maple_pci_init(void)
 
 	/* Tell pci.c to not change any resource allocations.  */
 	pci_probe_only = 1;
-	
-	/* Allow all IO */
-	io_page_mask = -1;
 }
 
 int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 24c0aef4ea39..a0505ea48a86 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -189,7 +189,7 @@ void __init maple_setup_arch(void)
 	conswitchp = &dummy_con;
 #endif
 
-	printk(KERN_INFO "Using native/NAP idle loop\n");
+	printk(KERN_DEBUG "Using native/NAP idle loop\n");
 }
 
 /* 
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index cfd6527a0d7e..af2a8f9f1222 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -314,7 +314,7 @@ static int pmu_set_cpu_speed(int low_speed)
  		_set_L3CR(save_l3cr);
 
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 #ifdef DEBUG_FREQ
 	printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index a5063cd675c5..85e00cb0006e 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2510,7 +2510,7 @@ found:
 		if (get_property(np, "flush-on-lock", NULL))
 			break;
 		powersave_nap = 1;
-		printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+		printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
 		break;
 	}
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index ea179afea632..80035853467b 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1068,9 +1068,6 @@ void __init pmac_pci_init(void)
 	/* Tell pci.c to not use the common resource allocation mechanism */
 	pci_probe_only = 1;
 
-	/* Allow all IO */
-	io_page_mask = -1;
-
 #else /* CONFIG_PPC64 */
 	init_p2pbridge();
 	fixup_nec_usb2();
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index f08173b0f065..047f954a89eb 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -871,10 +871,17 @@ int pmf_register_irq_client(struct device_node *target,
 	spin_unlock_irqrestore(&pmf_lock, flags);
 	if (func == NULL)
 		return -ENODEV;
+
+	/* guard against manipulations of list */
 	mutex_lock(&pmf_irq_mutex);
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_enable(func);
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_add(&client->link, &func->irq_clients);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+
 	client->func = func;
 	mutex_unlock(&pmf_irq_mutex);
 
@@ -885,12 +892,19 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client);
 void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
 	struct pmf_function *func = client->func;
+	unsigned long flags;
 
 	BUG_ON(func == NULL);
 
+	/* guard against manipulations of list */
 	mutex_lock(&pmf_irq_mutex);
 	client->func = NULL;
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_del(&client->link);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_disable(func);
 	mutex_unlock(&pmf_irq_mutex);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index b9200fb07815..9cc7db7a8bdc 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -458,7 +458,7 @@ static int pmac_pm_finish(suspend_state_t state)
 	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
 
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 930898635c9f..e5e0ff466904 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,8 +1,11 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS		+= -mno-minimal-toc
+endif
+
 obj-y			:= pci.o lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
 			   firmware.o
 obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_IBMVIO)	+= vio.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index d4a402c5866c..98c23aec85be 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -304,6 +304,8 @@ void __init pci_addr_cache_build(void)
 		pci_addr_cache_insert_device(dev);
 
 		dn = pci_device_to_OF_node(dev);
+		if (!dn)
+			continue;
 		pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
 		PCI_DN(dn)->pcidev = dev;
 	}
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 1fba695e32e8..0ec9a5445b95 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -23,9 +23,8 @@
  *
  */
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -202,7 +201,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
 
 static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 {
-	int rc;
+	int cnt, rc;
+
+	/* pcibios will clear the counter; save the value */
+	cnt = pe_dn->eeh_freeze_count;
+
 	if (bus)
 		pcibios_remove_pci_devices(bus);
 
@@ -241,6 +244,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 		ssleep (5);
 		pcibios_add_pci_devices(bus);
 	}
+	pe_dn->eeh_freeze_count = cnt;
 
 	return 0;
 }
@@ -250,23 +254,29 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
  */
 #define MAX_WAIT_FOR_RECOVERY 15
 
-void handle_eeh_events (struct eeh_event *event)
+struct pci_dn * handle_eeh_events (struct eeh_event *event)
 {
 	struct device_node *frozen_dn;
 	struct pci_dn *frozen_pdn;
 	struct pci_bus *frozen_bus;
 	int rc = 0;
 	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-	const char *pci_str, *drv_str;
+	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) {
-		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
-		        pci_name(event->dev));
-		return;
+
+		location = (char *) get_property(event->dn, "ibm,loc-code", NULL);
+		location = location ? location : "unknown";
+		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
+		                "for location=%s pci addr=%s\n",
+		        location, pci_name(event->dev));
+		return NULL;
 	}
+	location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL);
+	location = location ? location : "unknown";
 
 	/* There are two different styles for coming up with the PE.
 	 * In the old style, it was the highest EEH-capable device
@@ -278,9 +288,10 @@ void handle_eeh_events (struct eeh_event *event)
 		frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);
 
 	if (!frozen_bus) {
-		printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
-		        frozen_dn->full_name);
-		return;
+		printk(KERN_ERR "EEH: Cannot find PCI bus "
+		        "for location=%s dn=%s\n",
+		        location, frozen_dn->full_name);
+		return NULL;
 	}
 
 #if 0
@@ -314,8 +325,9 @@ void handle_eeh_events (struct eeh_event *event)
 
 	eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
 	printk(KERN_WARNING
-	   "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
-		frozen_pdn->eeh_freeze_count, drv_str, pci_str);
+	   "EEH: This PCI device has failed %d times since last reboot: "
+		"location=%s driver=%s pci addr=%s\n",
+		frozen_pdn->eeh_freeze_count, location, drv_str, pci_str);
 
 	/* Walk the various device drivers attached to this slot through
 	 * a reset sequence, giving each an opportunity to do what it needs
@@ -355,7 +367,7 @@ void handle_eeh_events (struct eeh_event *event)
 	/* Tell all device drivers that they can resume operations */
 	pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
 
-	return;
+	return frozen_pdn;
 	
 excess_failures:
 	/*
@@ -364,17 +376,18 @@ excess_failures:
 	 * due to actual, failed cards.
 	 */
 	printk(KERN_ERR
-	   "EEH: PCI device %s - %s has failed %d times \n"
-	   "and has been permanently disabled.  Please try reseating\n"
-	   "this device or replacing it.\n",
-		drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+	   "EEH: PCI device at location=%s driver=%s pci addr=%s \n"
+		"has failed %d times and has been permanently disabled. \n"
+		"Please try reseating this device or replacing it.\n",
+		location, drv_str, pci_str, frozen_pdn->eeh_freeze_count);
 	goto perm_error;
 
 hard_fail:
 	printk(KERN_ERR
-	   "EEH: Unable to recover from failure of PCI device %s - %s\n"
+	   "EEH: Unable to recover from failure of PCI device "
+	   "at location=%s driver=%s pci addr=%s \n"
 	   "Please try reseating this device or replacing it.\n",
-		drv_str, pci_str);
+		location, drv_str, pci_str);
 
 perm_error:
 	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
@@ -384,6 +397,8 @@ perm_error:
 
 	/* Shut down the device drivers for good. */
 	pcibios_remove_pci_devices(frozen_bus);
+
+	return NULL;
 }
 
 /* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 40020c65c89e..8f2d12935b99 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -18,6 +18,7 @@
  * Copyright (c) 2005 Linas Vepstas <linas@linas.org>
  */
 
+#include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
@@ -56,38 +57,43 @@ static int eeh_event_handler(void * dummy)
 {
 	unsigned long flags;
 	struct eeh_event	*event;
+	struct pci_dn *pdn;
 
 	daemonize ("eehd");
+	set_current_state(TASK_INTERRUPTIBLE);
 
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
+	spin_lock_irqsave(&eeh_eventlist_lock, flags);
+	event = NULL;
 
-		spin_lock_irqsave(&eeh_eventlist_lock, flags);
-		event = NULL;
+	/* Unqueue the event, get ready to process. */
+	if (!list_empty(&eeh_eventlist)) {
+		event = list_entry(eeh_eventlist.next, struct eeh_event, list);
+		list_del(&event->list);
+	}
+	spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
 
-		/* Unqueue the event, get ready to process. */
-		if (!list_empty(&eeh_eventlist)) {
-			event = list_entry(eeh_eventlist.next, struct eeh_event, list);
-			list_del(&event->list);
-		}
-		spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+	if (event == NULL)
+		return 0;
 
-		if (event == NULL)
-			break;
+	/* Serialize processing of EEH events */
+	mutex_lock(&eeh_event_mutex);
+	eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
 
-		/* Serialize processing of EEH events */
-		mutex_lock(&eeh_event_mutex);
-		eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+	printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
+	       pci_name(event->dev));
 
-		printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-		       pci_name(event->dev));
+	pdn = handle_eeh_events(event);
 
-		handle_eeh_events(event);
+	eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
+	pci_dev_put(event->dev);
+	kfree(event);
+	mutex_unlock(&eeh_event_mutex);
 
-		eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-		pci_dev_put(event->dev);
-		kfree(event);
-		mutex_unlock(&eeh_event_mutex);
+	/* If there are no new errors after an hour, clear the counter. */
+	if (pdn && pdn->eeh_freeze_count>0) {
+		msleep_interruptible (3600*1000);
+		if (pdn->eeh_freeze_count>0)
+			pdn->eeh_freeze_count--;
 	}
 
 	return 0;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 2643078433f0..d03a8b078f9d 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1,23 +1,24 @@
 /*
  * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
  *
- * Rewrite, cleanup: 
+ * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
  *
- * 
+ *
  * 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
@@ -49,52 +50,46 @@
 
 #define DBG(fmt...)
 
-static void tce_build_pSeries(struct iommu_table *tbl, long index, 
-			      long npages, unsigned long uaddr, 
+static void tce_build_pSeries(struct iommu_table *tbl, long index,
+			      long npages, unsigned long uaddr,
 			      enum dma_data_direction direction)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	t.te_rdwr = 1; // Read allowed 
+	proto_tce = TCE_PCI_READ; // Read allowed
 
 	if (direction != DMA_TO_DEVICE)
-		t.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
-	tp = ((union tce_entry *)tbl->it_base) + index;
+	tcep = ((u64 *)tbl->it_base) + index;
 
 	while (npages--) {
 		/* can't move this out since we might cross LMB boundary */
-		t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	
-		tp->te_word = t.te_word;
+		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		uaddr += TCE_PAGE_SIZE;
-		tp++;
+		tcep++;
 	}
 }
 
 
 static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 *tcep;
 
 	npages <<= TCE_PAGE_FACTOR;
 	index <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	tp  = ((union tce_entry *)tbl->it_base) + index;
-		
-	while (npages--) {
-		tp->te_word = t.te_word;
-		
-		tp++;
-	}
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--)
+		*(tcep++) = 0;
 }
 
 
@@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 proto_tce, tce;
+	u64 rpn;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12, 
-				   tce.te_word );
-		
+		tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
+
 		if (rc && printk_ratelimit()) {
 			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
+			printk("\ttce val = 0x%lx\n", tce );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
-			
+
 		tcenum++;
-		tce.te_rpn++;
+		rpn++;
 	}
 }
 
-static DEFINE_PER_CPU(void *, tce_page) = NULL;
+static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
 
 static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
 				     enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce, *tcep;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 	long l, limit;
 
 	if (TCE_PAGE_FACTOR == 0 && npages == 1)
@@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 	 * from iommu_alloc{,_sg}()
 	 */
 	if (!tcep) {
-		tcep = (void *)__get_free_page(GFP_ATOMIC);
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep)
 			return tce_build_pSeriesLP(tbl, tcenum, npages,
@@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	/* We can map max one pageful of TCEs at a time */
 	do {
@@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 		 * Set up the page with TCE data, looping through and setting
 		 * the values.
 		 */
-		limit = min_t(long, npages, 4096/sizeof(union tce_entry));
+		limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
 
 		for (l = 0; l < limit; l++) {
-			tcep[l] = tce;
-			tce.te_rpn++;
+			tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+			rpn++;
 		}
 
 		rc = plpar_tce_put_indirect((u64)tbl->it_index,
@@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+		printk("\ttce[0] val = 0x%lx\n", tcep[0]);
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
@@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index,
-				   (u64)tcenum << 12,
-				   tce.te_word);
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
 
 		if (rc && printk_ratelimit()) {
 			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
 
@@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
 static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
-	rc = plpar_tce_stuff((u64)tbl->it_index,
-			   (u64)tcenum << 12,
-			   tce.te_word,
-			   npages);
+	rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
 
 	if (rc && printk_ratelimit()) {
 		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
 		printk("\trc      = %ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce val = 0x%lx\n", tce.te_word );
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
 
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
-				 struct iommu_table *tbl) 
+				 struct iommu_table *tbl)
 {
 	struct device_node *node;
 	unsigned long *basep;
@@ -275,16 +257,16 @@ static void iommu_table_setparms(struct pci_controller *phb,
 	memset((void *)tbl->it_base, 0, *sizep);
 
 	tbl->it_busno = phb->bus->number;
-	
+
 	/* Units of tce entries */
 	tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
-	
+
 	/* Test if we are going over 2GB of DMA space */
 	if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
 		udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
-		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
+		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
 	}
-	
+
 	phb->dma_window_base_cur += phb->dma_window_size;
 
 	/* Set the tce table size - measured in entries */
@@ -299,30 +281,22 @@ static void iommu_table_setparms(struct pci_controller *phb,
  * iommu_table_setparms_lpar
  *
  * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
- *
- * ToDo: properly interpret the ibm,dma-window property.  The definition is:
- *	logical-bus-number	(1 word)
- *	phys-address		(#address-cells words)
- *	size			(#cell-size words)
- *
- * Currently we hard code these sizes (more or less).
  */
 static void iommu_table_setparms_lpar(struct pci_controller *phb,
 				      struct device_node *dn,
 				      struct iommu_table *tbl,
-				      unsigned int *dma_window)
+				      unsigned char *dma_window)
 {
+	unsigned long offset, size;
+
 	tbl->it_busno  = PCI_DN(dn)->bussubno;
+	of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
 
-	/* TODO: Parse field size properties properly. */
-	tbl->it_size   = (((unsigned long)dma_window[4] << 32) |
-			   (unsigned long)dma_window[5]) >> PAGE_SHIFT;
-	tbl->it_offset = (((unsigned long)dma_window[2] << 32) |
-			   (unsigned long)dma_window[3]) >> PAGE_SHIFT;
 	tbl->it_base   = 0;
-	tbl->it_index  = dma_window[0];
 	tbl->it_blocksize  = 16;
 	tbl->it_type = TCE_PCI;
+	tbl->it_offset = offset >> PAGE_SHIFT;
+	tbl->it_size = size >> PAGE_SHIFT;
 }
 
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
@@ -357,13 +331,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 	if (isa_dn_orig)
 		of_node_put(isa_dn_orig);
 
-	/* Count number of direct PCI children of the PHB.
-	 * All PCI device nodes have class-code property, so it's
-	 * an easy way to find them.
-	 */
+	/* Count number of direct PCI children of the PHB. */
 	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
-		if (get_property(tmp, "class-code", NULL))
-			children++;
+		children++;
 
 	DBG("Children: %d\n", children);
 
@@ -394,10 +364,11 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 	pci->phb->dma_window_size = 0x8000000ul;
 	pci->phb->dma_window_base_cur = 0x8000000ul;
 
-	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+	tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+			   pci->phb->node);
 
 	iommu_table_setparms(pci->phb, dn, tbl);
-	pci->iommu_table = iommu_init_table(tbl);
+	pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 
 	/* Divide the rest (1.75GB) among the children */
 	pci->phb->dma_window_size = 0x80000000ul;
@@ -414,7 +385,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
 	struct iommu_table *tbl;
 	struct device_node *dn, *pdn;
 	struct pci_dn *ppci;
-	unsigned int *dma_window = NULL;
+	unsigned char *dma_window = NULL;
 
 	DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
 
@@ -422,7 +393,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
 
 	/* Find nearest ibm,dma-window, walking up the device tree */
 	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
-		dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+		dma_window = get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window != NULL)
 			break;
 	}
@@ -440,12 +411,12 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
 
 		ppci->bussubno = bus->number;
 
-		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
-						    GFP_KERNEL);
-	
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   ppci->phb->node);
+
 		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 
-		ppci->iommu_table = iommu_init_table(tbl);
+		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
 	}
 
 	if (pdn != dn)
@@ -468,9 +439,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
 	 */
 	if (!dev->bus->self) {
 		DBG(" --> first child, no bridge. Allocating iommu table.\n");
-		tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   PCI_DN(dn)->phb->node);
 		iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
-		PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
+		PCI_DN(dn)->iommu_table = iommu_init_table(tbl,
+						PCI_DN(dn)->phb->node);
 
 		return;
 	}
@@ -516,7 +489,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
 {
 	struct device_node *pdn, *dn;
 	struct iommu_table *tbl;
-	int *dma_window = NULL;
+	unsigned char *dma_window = NULL;
 	struct pci_dn *pci;
 
 	DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
@@ -531,8 +504,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
 
 	for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
 	     pdn = pdn->parent) {
-		dma_window = (unsigned int *)
-			get_property(pdn, "ibm,dma-window", NULL);
+		dma_window = get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window)
 			break;
 	}
@@ -553,12 +525,12 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
 		/* iommu_table_setparms_lpar needs bussubno. */
 		pci->bussubno = pci->phb->bus->number;
 
-		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
-						    GFP_KERNEL);
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   pci->phb->node);
 
 		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
 
-		pci->iommu_table = iommu_init_table(tbl);
+		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 	}
 
 	if (pdn != dn)
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index e0000ce769e5..2e4e04042d85 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -348,7 +348,7 @@ static int enable_surveillance(int timeout)
 		return 0;
 
 	if (error == -EINVAL) {
-		printk(KERN_INFO "rtasd: surveillance not supported\n");
+		printk(KERN_DEBUG "rtasd: surveillance not supported\n");
 		return 0;
 	}
 
@@ -440,7 +440,7 @@ static int rtasd(void *unused)
 		goto error;
 	}
 
-	printk(KERN_INFO "RTAS daemon started\n");
+	printk(KERN_DEBUG "RTAS daemon started\n");
 
 	DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
 
@@ -487,7 +487,7 @@ static int __init rtas_init(void)
 
 	/* No RTAS */
 	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
-		printk(KERN_INFO "rtasd: no event-scan on system\n");
+		printk(KERN_DEBUG "rtasd: no event-scan on system\n");
 		return -ENODEV;
 	}
 
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 50643496eb63..77a5bb1d9c30 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -107,9 +107,9 @@ static ssize_t scanlog_read(struct file *file, char __user *buf,
 			/* Break to sleep default time */
 			break;
 		    default:
-			if (status > 9900 && status <= 9905) {
-				wait_time = rtas_extended_busy_delay_time(status);
-			} else {
+			/* Assume extended busy */
+			wait_time = rtas_busy_delay_time(status);
+			if (!wait_time) {
 				printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
 				return -EIO;
 			}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 3ba87835757e..1e28518c6121 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -235,14 +235,14 @@ static void __init pSeries_setup_arch(void)
 	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
 		vpa_init(boot_cpuid);
 		if (get_lppaca()->shared_proc) {
-			printk(KERN_INFO "Using shared processor idle loop\n");
+			printk(KERN_DEBUG "Using shared processor idle loop\n");
 			ppc_md.power_save = pseries_shared_idle_sleep;
 		} else {
-			printk(KERN_INFO "Using dedicated idle loop\n");
+			printk(KERN_DEBUG "Using dedicated idle loop\n");
 			ppc_md.power_save = pseries_dedicated_idle_sleep;
 		}
 	} else {
-		printk(KERN_INFO "Using default idle loop\n");
+		printk(KERN_DEBUG "Using default idle loop\n");
 	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
deleted file mode 100644
index 8e53e04ada8b..000000000000
--- a/arch/powerpc/platforms/pseries/vio.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
- *
- *    Copyright (c) 2003-2005 IBM Corp.
- *     Dave Engebretsen engebret@us.ibm.com
- *     Santiago Leon santil@us.ibm.com
- *     Hollis Blanchard <hollisb@us.ibm.com>
- *     Stephen Rothwell
- *
- *      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/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/kobject.h>
-#include <asm/iommu.h>
-#include <asm/dma.h>
-#include <asm/prom.h>
-#include <asm/vio.h>
-#include <asm/hvcall.h>
-#include <asm/tce.h>
-
-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
-
-static void probe_bus_pseries(void)
-{
-	struct device_node *node_vroot, *of_node;
-
-	node_vroot = find_devices("vdevice");
-	if ((node_vroot == NULL) || (node_vroot->child == NULL))
-		/* this machine doesn't do virtual IO, and that's ok */
-		return;
-
-	/*
-	 * Create struct vio_devices for each virtual device in the device tree.
-	 * Drivers will associate with them later.
-	 */
-	for (of_node = node_vroot->child; of_node != NULL;
-			of_node = of_node->sibling) {
-		printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
-		vio_register_device_node(of_node);
-	}
-}
-
-/**
- * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
- *	vio_device_id
- */
-static int vio_match_device_pseries(const struct vio_device_id *id,
-		const struct vio_dev *dev)
-{
-	return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
-			device_is_compatible(dev->dev.platform_data, id->compat);
-}
-
-static void vio_release_device_pseries(struct device *dev)
-{
-	/* XXX free TCE table */
-	of_node_put(dev->platform_data);
-}
-
-static ssize_t viodev_show_devspec(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct device_node *of_node = dev->platform_data;
-
-	return sprintf(buf, "%s\n", of_node->full_name);
-}
-DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
-
-static void vio_unregister_device_pseries(struct vio_dev *viodev)
-{
-	device_remove_file(&viodev->dev, &dev_attr_devspec);
-}
-
-static struct vio_bus_ops vio_bus_ops_pseries = {
-	.match = vio_match_device_pseries,
-	.unregister_device = vio_unregister_device_pseries,
-	.release_device = vio_release_device_pseries,
-};
-
-/**
- * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
- */
-static int __init vio_bus_init_pseries(void)
-{
-	int err;
-
-	err = vio_bus_init(&vio_bus_ops_pseries);
-	if (err == 0)
-		probe_bus_pseries();
-	return err;
-}
-
-__initcall(vio_bus_init_pseries);
-
-/**
- * vio_build_iommu_table: - gets the dma information from OF and
- *	builds the TCE tree.
- * @dev: the virtual device.
- *
- * Returns a pointer to the built tce tree, or NULL if it can't
- * find property.
-*/
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
-{
-	unsigned int *dma_window;
-	struct iommu_table *newTceTable;
-	unsigned long offset;
-	int dma_window_property_size;
-
-	dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
-	if(!dma_window) {
-		return NULL;
-	}
-
-	newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-	/*  There should be some code to extract the phys-encoded offset
-		using prom_n_addr_cells(). However, according to a comment
-		on earlier versions, it's always zero, so we don't bother */
-	offset = dma_window[1] >>  PAGE_SHIFT;
-
-	/* TCE table size - measured in tce entries */
-	newTceTable->it_size		= dma_window[4] >> PAGE_SHIFT;
-	/* offset for VIO should always be 0 */
-	newTceTable->it_offset		= offset;
-	newTceTable->it_busno		= 0;
-	newTceTable->it_index		= (unsigned long)dma_window[0];
-	newTceTable->it_type		= TCE_VB;
-
-	return iommu_init_table(newTceTable);
-}
-
-/**
- * vio_register_device_node: - Register a new vio device.
- * @of_node:	The OF node for this device.
- *
- * Creates and initializes a vio_dev structure from the data in
- * of_node (dev.platform_data) and adds it to the list of virtual devices.
- * Returns a pointer to the created vio_dev or NULL if node has
- * NULL device_type or compatible fields.
- */
-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
-{
-	struct vio_dev *viodev;
-	unsigned int *unit_address;
-	unsigned int *irq_p;
-
-	/* we need the 'device_type' property, in order to match with drivers */
-	if ((NULL == of_node->type)) {
-		printk(KERN_WARNING
-			"%s: node %s missing 'device_type'\n", __FUNCTION__,
-			of_node->name ? of_node->name : "<unknown>");
-		return NULL;
-	}
-
-	unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
-	if (!unit_address) {
-		printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
-			of_node->name ? of_node->name : "<unknown>");
-		return NULL;
-	}
-
-	/* allocate a vio_dev for this node */
-	viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (!viodev) {
-		return NULL;
-	}
-	memset(viodev, 0, sizeof(struct vio_dev));
-
-	viodev->dev.platform_data = of_node_get(of_node);
-
-	viodev->irq = NO_IRQ;
-	irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
-	if (irq_p) {
-		int virq = virt_irq_create_mapping(*irq_p);
-		if (virq == NO_IRQ) {
-			printk(KERN_ERR "Unable to allocate interrupt "
-			       "number for %s\n", of_node->full_name);
-		} else
-			viodev->irq = irq_offset_up(virq);
-	}
-
-	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
-	viodev->name = of_node->name;
-	viodev->type = of_node->type;
-	viodev->unit_address = *unit_address;
-	viodev->iommu_table = vio_build_iommu_table(viodev);
-
-	/* register with generic device framework */
-	if (vio_register_device(viodev) == NULL) {
-		/* XXX free TCE table */
-		kfree(viodev);
-		return NULL;
-	}
-	device_create_file(&viodev->dev, &dev_attr_devspec);
-
-	return viodev;
-}
-EXPORT_SYMBOL(vio_register_device_node);
-
-/**
- * vio_get_attribute: - get attribute for virtual device
- * @vdev:	The vio device to get property.
- * @which:	The property/attribute to be extracted.
- * @length:	Pointer to length of returned data size (unused if NULL).
- *
- * Calls prom.c's get_property() to return the value of the
- * attribute specified by the preprocessor constant @which
-*/
-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
-{
-	return get_property(vdev->dev.platform_data, (char*)which, length);
-}
-EXPORT_SYMBOL(vio_get_attribute);
-
-/* vio_find_name() - internal because only vio.c knows how we formatted the
- * kobject name
- * XXX once vio_bus_type.devices is actually used as a kset in
- * drivers/base/bus.c, this function should be removed in favor of
- * "device_find(kobj_name, &vio_bus_type)"
- */
-static struct vio_dev *vio_find_name(const char *kobj_name)
-{
-	struct kobject *found;
-
-	found = kset_find_obj(&devices_subsys.kset, kobj_name);
-	if (!found)
-		return NULL;
-
-	return to_vio_dev(container_of(found, struct device, kobj));
-}
-
-/**
- * vio_find_node - find an already-registered vio_dev
- * @vnode: device_node of the virtual device we're looking for
- */
-struct vio_dev *vio_find_node(struct device_node *vnode)
-{
-	uint32_t *unit_address;
-	char kobj_name[BUS_ID_SIZE];
-
-	/* construct the kobject name from the device node */
-	unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
-	if (!unit_address)
-		return NULL;
-	snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
-
-	return vio_find_name(kobj_name);
-}
-EXPORT_SYMBOL(vio_find_node);
-
-int vio_enable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_enable_interrupts);
-
-int vio_disable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d60ea30fed6..b14f9b5c114e 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -522,7 +522,7 @@ nextnode:
 
 	np = of_find_node_by_type(NULL, "interrupt-controller");
 	if (!np) {
-		printk(KERN_WARNING "xics: no ISA interrupt controller\n");
+		printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
 		xics_irq_8259_cascade_real = -1;
 		xics_irq_8259_cascade = -1;
 	} else {
@@ -641,23 +641,26 @@ void xics_teardown_cpu(int secondary)
 	ops->cppr_info(cpu, 0x00);
 	iosync();
 
+	/* Clear IPI */
+	ops->qirr_info(cpu, 0xff);
+
+	/*
+	 * we need to EOI the IPI if we got here from kexec down IPI
+	 *
+	 * probably need to check all the other interrupts too
+	 * should we be flagging idle loop instead?
+	 * or creating some task to be scheduled?
+	 */
+	ops->xirr_info_set(cpu, XICS_IPI);
+
 	/*
 	 * Some machines need to have at least one cpu in the GIQ,
 	 * so leave the master cpu in the group.
 	 */
-	if (secondary) {
-		/*
-		 * we need to EOI the IPI if we got here from kexec down IPI
-		 *
-		 * probably need to check all the other interrupts too
-		 * should we be flagging idle loop instead?
-		 * or creating some task to be scheduled?
-		 */
-		ops->xirr_info_set(cpu, XICS_IPI);
+	if (secondary)
 		rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
 			(1UL << interrupt_server_size) - 1 -
 			default_distrib_server, 0);
-	}
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 4c2b356774ea..cef95b023730 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,3 +1,7 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS			+= -mno-minimal-toc
+endif
+
 obj-$(CONFIG_MPIC)		+= mpic.o
 obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 38087bd6e3cf..6232091cc72b 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -246,7 +246,7 @@ static void iommu_table_dart_setup(void)
 	iommu_table_dart.it_base = (unsigned long)dart_vbase;
 	iommu_table_dart.it_index = 0;
 	iommu_table_dart.it_blocksize = 1;
-	iommu_init_table(&iommu_table_dart);
+	iommu_init_table(&iommu_table_dart, -1);
 
 	/* Reserve the last page of the DART to avoid possible prefetch
 	 * past the DART mapped area
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ceb584682fa3..71a3275935ec 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -372,7 +372,7 @@ static int __init fsl_usb_of_init(void)
 {
 	struct device_node *np;
 	unsigned int i;
-	struct platform_device *usb_dev;
+	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
 	int ret;
 
 	for (np = NULL, i = 0;
@@ -393,15 +393,15 @@ static int __init fsl_usb_of_init(void)
 		r[1].end = np->intrs[0].line;
 		r[1].flags = IORESOURCE_IRQ;
 
-		usb_dev =
-		    platform_device_register_simple("fsl-usb2-mph", i, r, 2);
-		if (IS_ERR(usb_dev)) {
-			ret = PTR_ERR(usb_dev);
+		usb_dev_mph =
+		    platform_device_register_simple("fsl-ehci", i, r, 2);
+		if (IS_ERR(usb_dev_mph)) {
+			ret = PTR_ERR(usb_dev_mph);
 			goto err;
 		}
 
-		usb_dev->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask;
+		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
+		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
 
 		usb_data.operating_mode = FSL_USB2_MPH_HOST;
 
@@ -417,31 +417,14 @@ static int __init fsl_usb_of_init(void)
 		usb_data.phy_mode = determine_usb_phy(prop);
 
 		ret =
-		    platform_device_add_data(usb_dev, &usb_data,
+		    platform_device_add_data(usb_dev_mph, &usb_data,
 					     sizeof(struct
 						    fsl_usb2_platform_data));
 		if (ret)
-			goto unreg;
+			goto unreg_mph;
 	}
 
-	return 0;
-
-unreg:
-	platform_device_unregister(usb_dev);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
-static int __init fsl_usb_dr_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i;
-	struct platform_device *usb_dev;
-	int ret;
-
-	for (np = NULL, i = 0;
+	for (np = NULL;
 	     (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
 	     i++) {
 		struct resource r[2];
@@ -453,21 +436,21 @@ static int __init fsl_usb_dr_of_init(void)
 
 		ret = of_address_to_resource(np, 0, &r[0]);
 		if (ret)
-			goto err;
+			goto unreg_mph;
 
 		r[1].start = np->intrs[0].line;
 		r[1].end = np->intrs[0].line;
 		r[1].flags = IORESOURCE_IRQ;
 
-		usb_dev =
-		    platform_device_register_simple("fsl-usb2-dr", i, r, 2);
-		if (IS_ERR(usb_dev)) {
-			ret = PTR_ERR(usb_dev);
+		usb_dev_dr =
+		    platform_device_register_simple("fsl-ehci", i, r, 2);
+		if (IS_ERR(usb_dev_dr)) {
+			ret = PTR_ERR(usb_dev_dr);
 			goto err;
 		}
 
-		usb_dev->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask;
+		usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
+		usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
 
 		usb_data.operating_mode = FSL_USB2_DR_HOST;
 
@@ -475,19 +458,22 @@ static int __init fsl_usb_dr_of_init(void)
 		usb_data.phy_mode = determine_usb_phy(prop);
 
 		ret =
-		    platform_device_add_data(usb_dev, &usb_data,
+		    platform_device_add_data(usb_dev_dr, &usb_data,
 					     sizeof(struct
 						    fsl_usb2_platform_data));
 		if (ret)
-			goto unreg;
+			goto unreg_dr;
 	}
-
 	return 0;
 
-unreg:
-	platform_device_unregister(usb_dev);
+unreg_dr:
+	if (usb_dev_dr)
+		platform_device_unregister(usb_dev_dr);
+unreg_mph:
+	if (usb_dev_mph)
+		platform_device_unregister(usb_dev_mph);
 err:
 	return ret;
 }
 
-arch_initcall(fsl_usb_dr_of_init);
+arch_initcall(fsl_usb_of_init);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7dcdfcb3c984..bffe50d02c99 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -829,7 +829,27 @@ void __init mpic_init(struct mpic *mpic)
 	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
 }
 
+void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
+{
+	u32 v;
+
+	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
+	v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK;
+	v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio);
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+}
 
+void __init mpic_set_serial_int(struct mpic *mpic, int enable)
+{
+	u32 v;
+
+	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
+	if (enable)
+		v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
+	else
+		v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+}
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index e9a8f5d1dfcd..b55de4f42aec 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -40,6 +40,10 @@ config GENERIC_NVRAM
 	bool
 	default y
 
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
 config SCHED_NO_NO_OMIT_FRAME_POINTER
 	bool
 	default y
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index 80c84d562fa4..2f995f712ec5 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -5,7 +5,7 @@
 CFLAGS_kbd.o	:= -Idrivers/char
 CFLAGS_vreset.o := -Iarch/ppc/boot/include
 
-zlib  := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
+zlib  := inffast.c inflate.c inftrees.c
 	 
 lib-y += $(zlib:.c=.o) div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 386e000bcb73..c9bd184a295a 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -583,7 +583,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
 		mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
 		pmd = pmd_offset(pgd_offset(mm, address), address);
 		if (!pmd_none(*pmd))
-			add_hash_page(mm->context, address, pmd_val(*pmd));
+			add_hash_page(mm->context.id, address, pmd_val(*pmd));
 	}
 #endif
 }
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index b4a4b3f02a1c..8784f3715032 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -30,7 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-mm_context_t next_mmu_context;
+unsigned long next_mmu_context;
 unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
 #ifdef FEW_CONTEXTS
 atomic_t nr_free_contexts;
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index 6c3dc3c44c86..606b023196a2 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -42,7 +42,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
 
 	if (Hash != 0) {
 		ptephys = __pa(ptep) & PAGE_MASK;
-		flush_hash_pages(mm->context, addr, ptephys, 1);
+		flush_hash_pages(mm->context.id, addr, ptephys, 1);
 	}
 }
 
@@ -102,7 +102,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start,
 	pmd_t *pmd;
 	unsigned long pmd_end;
 	int count;
-	unsigned int ctx = mm->context;
+	unsigned int ctx = mm->context.id;
 
 	if (Hash == 0) {
 		_tlbia();
@@ -166,7 +166,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
 	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
 	if (!pmd_none(*pmd))
-		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
+		flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
 	FINISH_FLUSH;
 }
 
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 174ddbc9758b..293bd489e7d9 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -183,7 +183,7 @@ config IBM_EMAC4
 
 config BIOS_FIXUP
 	bool
-	depends on BUBINGA || EP405 || SYCAMORE || WALNUT
+	depends on BUBINGA || EP405 || SYCAMORE || WALNUT || CPCI405
 	default y
 
 # OAK doesn't exist but wanted to keep this around for any future 403GCX boards
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c
index 6571e39fbe48..970b69831e6f 100644
--- a/arch/ppc/platforms/4xx/cpci405.c
+++ b/arch/ppc/platforms/4xx/cpci405.c
@@ -1,10 +1,12 @@
 /*
  * Board setup routines for the esd CPCI-405 cPCI Board.
  *
- * Author: Stefan Roese
- *         stefan.roese@esd-electronics.com
+ * Copyright 2001-2006 esd electronic system design - hannover germany
  *
- * Copyright 2001 esd electronic system design - hannover germany
+ * Authors: Matthias Fuchs
+ *          matthias.fuchs@esd-electronics.com
+ *          Stefan Roese
+ *          stefan.roese@esd-electronics.com
  *
  * 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
@@ -20,9 +22,17 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/todc.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 #include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <platforms/4xx/ibm405gp.h>
 
+#ifdef CONFIG_GEN_RTC
 void *cpci405_nvram;
+#endif
+
+extern bd_t __res;
 
 /*
  * Some IRQs unique to CPCI-405.
@@ -36,18 +46,69 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 	 *      A       B       C       D
 	 */
 	{
-		{28,	28,	28,	28},	/* IDSEL 15 - cPCI slot 8 */
-		{29,	29,	29,	29},	/* IDSEL 16 - cPCI slot 7 */
-		{30,	30,	30,	30},	/* IDSEL 17 - cPCI slot 6 */
-		{27,	27,	27,	27},	/* IDSEL 18 - cPCI slot 5 */
-		{28,	28,	28,	28},	/* IDSEL 19 - cPCI slot 4 */
-		{29,	29,	29,	29},	/* IDSEL 20 - cPCI slot 3 */
-		{30,	30,	30,	30},	/* IDSEL 21 - cPCI slot 2 */
+		{28,	29,	30,	27},	/* IDSEL 15 - cPCI slot 8 */
+		{29,	30,	27,	28},	/* IDSEL 16 - cPCI slot 7 */
+		{30,	27,	28,	29},	/* IDSEL 17 - cPCI slot 6 */
+		{27,	28,	29,	30},	/* IDSEL 18 - cPCI slot 5 */
+		{28,	29,	30,	27},	/* IDSEL 19 - cPCI slot 4 */
+		{29,	30,	27,	28},	/* IDSEL 20 - cPCI slot 3 */
+		{30,	27,	28,	29},	/* IDSEL 21 - cPCI slot 2 */
         };
 	const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
 	return PCI_IRQ_TABLE_LOOKUP;
 };
 
+/* The serial clock for the chip is an internal clock determined by
+ * different clock speeds/dividers.
+ * Calculate the proper input baud rate and setup the serial driver.
+ */
+static void __init
+cpci405_early_serial_map(void)
+{
+	u32 uart_div;
+	int uart_clock;
+	struct uart_port port;
+
+         /* Calculate the serial clock input frequency
+          *
+          * The uart clock is the cpu frequency (provided in the board info
+          * structure) divided by the external UART Divisor.
+          */
+	uart_div = ((mfdcr(DCRN_CHCR_BASE) & CHR0_UDIV) >> 1) + 1;
+	uart_clock = __res.bi_procfreq / uart_div;
+
+	/* Setup serial port access */
+	memset(&port, 0, sizeof(port));
+#if defined(CONFIG_UART0_TTYS0)
+	port.membase = (void*)UART0_IO_BASE;
+	port.irq = UART0_INT;
+#else
+	port.membase = (void*)UART1_IO_BASE;
+	port.irq = UART1_INT;
+#endif
+	port.uartclk = uart_clock;
+	port.regshift = 0;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+#if defined(CONFIG_UART0_TTYS0)
+	port.membase = (void*)UART1_IO_BASE;
+	port.irq = UART1_INT;
+#else
+	port.membase = (void*)UART0_IO_BASE;
+	port.irq = UART0_INT;
+#endif
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+}
+
 void __init
 cpci405_setup_arch(void)
 {
@@ -55,14 +116,68 @@ cpci405_setup_arch(void)
 
 	ibm_ocp_set_emac(0, 0);
 
-	TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+        cpci405_early_serial_map();
+
+#ifdef CONFIG_GEN_RTC
+	TODC_INIT(TODC_TYPE_MK48T35,
+		  cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+#endif
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	unsigned int bar_response, bar;
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+	out_le32((void *) &(pcip->ptm2la), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+	}
 }
 
 void __init
 cpci405_map_io(void)
 {
 	ppc4xx_map_io();
+
+#ifdef CONFIG_GEN_RTC
 	cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE);
+#endif
 }
 
 void __init
@@ -74,9 +189,11 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	ppc_md.setup_arch = cpci405_setup_arch;
 	ppc_md.setup_io_mappings = cpci405_map_io;
 
+#ifdef CONFIG_GEN_RTC
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
 	ppc_md.get_rtc_time = todc_get_rtc_time;
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
 }
diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h
index e27f7cb650d8..f5a5c0cd062d 100644
--- a/arch/ppc/platforms/4xx/cpci405.h
+++ b/arch/ppc/platforms/4xx/cpci405.h
@@ -1,37 +1,29 @@
 /*
  * CPCI-405 board specific definitions
  *
- * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com)
+ * Copyright 2001-2006 esd electronic system design - hannover germany
+ *
+ * Authors: Matthias Fuchs
+ *          matthias.fuchs@esd-electronics.com
+ *          Stefan Roese
+ *          stefan.roese@esd-electronics.com
  */
 
 #ifdef __KERNEL__
-#ifndef __ASM_CPCI405_H__
-#define __ASM_CPCI405_H__
+#ifndef __CPCI405_H__
+#define __CPCI405_H__
 
 #include <linux/config.h>
-
-/* We have a 405GP core */
 #include <platforms/4xx/ibm405gp.h>
-
 #include <asm/ppcboot.h>
 
-#ifndef __ASSEMBLY__
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 /* Map for the NVRAM space */
 #define CPCI405_NVRAM_PADDR	((uint)0xf0200000)
 #define CPCI405_NVRAM_SIZE	((uint)32*1024)
 
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD		201600
-#else
-#define BASE_BAUD		691200
-#endif
+#define BASE_BAUD		0
 
-#define PPC4xx_MACHINE_NAME "esd CPCI-405"
+#define PPC4xx_MACHINE_NAME     "esd CPCI-405"
 
-#endif /* !__ASSEMBLY__ */
-#endif	/* __ASM_CPCI405_H__ */
+#endif	/* __CPCI405_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index c9e0aeeca3d8..4368dc3f3c30 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -379,13 +379,12 @@ mpc85xx_cds_pcibios_fixup(void)
                                         PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
                 dev->irq = 10;
                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
-		pci_dev_put(dev);
-        }
 
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+		if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                         PCI_DEVICE_ID_VIA_82C586_2, dev))) {
-                dev->irq = 11;
-                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+	                dev->irq = 11;
+	                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		}
 		pci_dev_put(dev);
         }
 }
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 1af2c000fcfa..5c4932ca8e9b 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -186,7 +186,7 @@ struct platform_device ppc_sys_platform_devices[] = {
 		},
 	},
 	[MPC83xx_USB2_DR] = {
-		.name = "fsl-usb2-dr",
+		.name = "fsl-ehci",
 		.id	= 1,
 		.num_resources	 = 2,
 		.resource = (struct resource[]) {
@@ -203,8 +203,8 @@ struct platform_device ppc_sys_platform_devices[] = {
 		},
 	},
 	[MPC83xx_USB2_MPH] = {
-		.name = "fsl-usb2-mph",
-		.id	= 1,
+		.name = "fsl-ehci",
+		.id	= 2,
 		.num_resources	 = 2,
 		.resource = (struct resource[]) {
 			{
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 01c5c082f970..821a141889de 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -446,6 +446,14 @@ config NO_IDLE_HZ_INIT
 	  The HZ timer is switched off in idle by default. That means the
 	  HZ timer is already disabled at boot time.
 
+config S390_HYPFS_FS
+	bool "s390 hypervisor file system support"
+	select SYS_HYPERVISOR
+	default y
+	help
+	  This is a virtual file system intended to provide accounting
+	  information in an s390 hypervisor environment.
+
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 7bb16fb97d4f..b3791fb094a8 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -76,7 +76,7 @@ LDFLAGS_vmlinux := -e start
 head-y		:= arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
 
 core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
-		   arch/$(ARCH)/appldata/
+		   arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/
 libs-y		+= arch/$(ARCH)/lib/
 drivers-y	+= drivers/s390/
 drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
new file mode 100644
index 000000000000..f4b00cd81f7c
--- /dev/null
+++ b/arch/s390/hypfs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux hypfs filesystem routines.
+#
+
+obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
+
+s390_hypfs-objs := inode.o hypfs_diag.o
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
new file mode 100644
index 000000000000..ea5567be00fc
--- /dev/null
+++ b/arch/s390/hypfs/hypfs.h
@@ -0,0 +1,30 @@
+/*
+ *  fs/hypfs/hypfs.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_H_
+#define _HYPFS_H_
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+#define REG_FILE_MODE    0440
+#define UPDATE_FILE_MODE 0220
+#define DIR_MODE         0550
+
+extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+				  const char *name);
+
+extern struct dentry *hypfs_create_u64(struct super_block *sb,
+				       struct dentry *dir, const char *name,
+				       __u64 value);
+
+extern struct dentry *hypfs_create_str(struct super_block *sb,
+				       struct dentry *dir, const char *name,
+				       char *string);
+
+#endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
new file mode 100644
index 000000000000..efa74af7f04a
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -0,0 +1,696 @@
+/*
+ *  fs/hypfs/hypfs_diag.c
+ *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
+ *    implementation.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+
+#define LPAR_NAME_LEN 8		/* lpar name len in diag 204 data */
+#define CPU_NAME_LEN 16		/* type name len of cpus in diag224 name table */
+#define TMP_SIZE 64		/* size of temporary buffers */
+
+/* diag 204 subcodes */
+enum diag204_sc {
+	SUBC_STIB4 = 4,
+	SUBC_RSI = 5,
+	SUBC_STIB6 = 6,
+	SUBC_STIB7 = 7
+};
+
+/* The two available diag 204 data formats */
+enum diag204_format {
+	INFO_SIMPLE = 0,
+	INFO_EXT = 0x00010000
+};
+
+/* bit is set in flags, when physical cpu info is included in diag 204 data */
+#define LPAR_PHYS_FLG  0x80
+
+static char *diag224_cpu_names;			/* diag 224 name table */
+static enum diag204_sc diag204_store_sc;	/* used subcode for store */
+static enum diag204_format diag204_info_type;	/* used diag 204 data format */
+
+static void *diag204_buf;		/* 4K aligned buffer for diag204 data */
+static void *diag204_buf_vmalloc;	/* vmalloc pointer for diag204 data */
+static int diag204_buf_pages;		/* number of pages for diag204 data */
+
+/*
+ * DIAG 204 data structures and member access functions.
+ *
+ * Since we have two different diag 204 data formats for old and new s390
+ * machines, we do not access the structs directly, but use getter functions for
+ * each struct member instead. This should make the code more readable.
+ */
+
+/* Time information block */
+
+struct info_blk_hdr {
+	__u8  npar;
+	__u8  flags;
+	__u16 tslice;
+	__u16 phys_cpus;
+	__u16 this_part;
+	__u64 curtod;
+} __attribute__ ((packed));
+
+struct x_info_blk_hdr {
+	__u8  npar;
+	__u8  flags;
+	__u16 tslice;
+	__u16 phys_cpus;
+	__u16 this_part;
+	__u64 curtod1;
+	__u64 curtod2;
+	char reserved[40];
+} __attribute__ ((packed));
+
+static inline int info_blk_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct info_blk_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_info_blk_hdr);
+}
+
+static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->npar;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->npar;
+}
+
+static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->flags;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->flags;
+}
+
+static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->phys_cpus;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->phys_cpus;
+}
+
+/* Partition header */
+
+struct part_hdr {
+	__u8 pn;
+	__u8 cpus;
+	char reserved[6];
+	char part_name[LPAR_NAME_LEN];
+} __attribute__ ((packed));
+
+struct x_part_hdr {
+	__u8  pn;
+	__u8  cpus;
+	__u8  rcpus;
+	__u8  pflag;
+	__u32 mlu;
+	char  part_name[LPAR_NAME_LEN];
+	char  lpc_name[8];
+	char  os_name[8];
+	__u64 online_cs;
+	__u64 online_es;
+	__u8  upid;
+	char  reserved1[3];
+	__u32 group_mlu;
+	char  group_name[8];
+	char  reserved2[32];
+} __attribute__ ((packed));
+
+static inline int part_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct part_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_part_hdr);
+}
+
+static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct part_hdr *)hdr)->cpus;
+	else /* INFO_EXT */
+		return ((struct x_part_hdr *)hdr)->rcpus;
+}
+
+static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
+				       char *name)
+{
+	if (type == INFO_SIMPLE)
+		memcpy(name, ((struct part_hdr *)hdr)->part_name,
+		       LPAR_NAME_LEN);
+	else /* INFO_EXT */
+		memcpy(name, ((struct x_part_hdr *)hdr)->part_name,
+		       LPAR_NAME_LEN);
+	EBCASC(name, LPAR_NAME_LEN);
+	name[LPAR_NAME_LEN] = 0;
+	strstrip(name);
+}
+
+struct cpu_info {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	__u8  cflag;
+	__u16 weight;
+	__u64 acc_time;
+	__u64 lp_time;
+} __attribute__ ((packed));
+
+struct x_cpu_info {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	__u8  cflag;
+	__u16 weight;
+	__u64 acc_time;
+	__u64 lp_time;
+	__u16 min_weight;
+	__u16 cur_weight;
+	__u16 max_weight;
+	char  reseved2[2];
+	__u64 online_time;
+	__u64 wait_time;
+	__u32 pma_weight;
+	__u32 polar_weight;
+	char  reserved3[40];
+} __attribute__ ((packed));
+
+/* CPU info block */
+
+static inline int cpu_info__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct cpu_info);
+	else /* INFO_EXT */
+		return sizeof(struct x_cpu_info);
+}
+
+static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->ctidx;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->ctidx;
+}
+
+static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->cpu_addr;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->cpu_addr;
+}
+
+static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->acc_time;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->acc_time;
+}
+
+static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->lp_time;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->lp_time;
+}
+
+static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return 0;	/* online_time not available in simple info */
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->online_time;
+}
+
+/* Physical header */
+
+struct phys_hdr {
+	char reserved1[1];
+	__u8 cpus;
+	char reserved2[6];
+	char mgm_name[8];
+} __attribute__ ((packed));
+
+struct x_phys_hdr {
+	char reserved1[1];
+	__u8 cpus;
+	char reserved2[6];
+	char mgm_name[8];
+	char reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct phys_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_phys_hdr);
+}
+
+static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_hdr *)hdr)->cpus;
+	else /* INFO_EXT */
+		return ((struct x_phys_hdr *)hdr)->cpus;
+}
+
+/* Physical CPU info block */
+
+struct phys_cpu {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	char  reserved2[3];
+	__u64 mgm_time;
+	char  reserved3[8];
+} __attribute__ ((packed));
+
+struct x_phys_cpu {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	char  reserved2[3];
+	__u64 mgm_time;
+	char  reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_cpu__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct phys_cpu);
+	else /* INFO_EXT */
+		return sizeof(struct x_phys_cpu);
+}
+
+static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->cpu_addr;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->cpu_addr;
+}
+
+static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->mgm_time;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->mgm_time;
+}
+
+static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->ctidx;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->ctidx;
+}
+
+/* Diagnose 204 functions */
+
+static int diag204(unsigned long subcode, unsigned long size, void *addr)
+{
+	register unsigned long _subcode asm("0") = subcode;
+	register unsigned long _size asm("1") = size;
+
+	asm volatile ("   diag    %2,%0,0x204\n"
+		      "0: \n" ".section __ex_table,\"a\"\n"
+#ifndef __s390x__
+		      "    .align 4\n"
+		      "    .long  0b,0b\n"
+#else
+		      "    .align 8\n"
+		      "    .quad  0b,0b\n"
+#endif
+		      ".previous":"+d" (_subcode), "+d"(_size)
+		      :"d"(addr)
+		      :"memory");
+	if (_subcode)
+		return -1;
+	else
+		return _size;
+}
+
+/*
+ * For the old diag subcode 4 with simple data format we have to use real
+ * memory. If we use subcode 6 or 7 with extended data format, we can (and
+ * should) use vmalloc, since we need a lot of memory in that case. Currently
+ * up to 93 pages!
+ */
+
+static void diag204_free_buffer(void)
+{
+	if (!diag204_buf)
+		return;
+	if (diag204_buf_vmalloc) {
+		vfree(diag204_buf_vmalloc);
+		diag204_buf_vmalloc = NULL;
+	} else {
+		free_pages((unsigned long) diag204_buf, 0);
+	}
+	diag204_buf_pages = 0;
+	diag204_buf = NULL;
+}
+
+static void *diag204_alloc_vbuf(int pages)
+{
+	/* The buffer has to be page aligned! */
+	diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
+	if (!diag204_buf_vmalloc)
+		return ERR_PTR(-ENOMEM);
+	diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc
+				& ~0xfffUL) + 0x1000;
+	diag204_buf_pages = pages;
+	return diag204_buf;
+}
+
+static void *diag204_alloc_rbuf(void)
+{
+	diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
+	if (diag204_buf)
+		return ERR_PTR(-ENOMEM);
+	diag204_buf_pages = 1;
+	return diag204_buf;
+}
+
+static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
+{
+	if (diag204_buf) {
+		*pages = diag204_buf_pages;
+		return diag204_buf;
+	}
+	if (fmt == INFO_SIMPLE) {
+		*pages = 1;
+		return diag204_alloc_rbuf();
+	} else {/* INFO_EXT */
+		*pages = diag204(SUBC_RSI | INFO_EXT, 0, 0);
+		if (*pages <= 0)
+			return ERR_PTR(-ENOSYS);
+		else
+			return diag204_alloc_vbuf(*pages);
+	}
+}
+
+/*
+ * diag204_probe() has to find out, which type of diagnose 204 implementation
+ * we have on our machine. Currently there are three possible scanarios:
+ *   - subcode 4   + simple data format (only one page)
+ *   - subcode 4-6 + extended data format
+ *   - subcode 4-7 + extended data format
+ *
+ * Subcode 5 is used to retrieve the size of the data, provided by subcodes
+ * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition
+ * to subcode 6 it provides also information about secondary cpus.
+ * In order to get as much information as possible, we first try
+ * subcode 7, then 6 and if both fail, we use subcode 4.
+ */
+
+static int diag204_probe(void)
+{
+	void *buf;
+	int pages, rc;
+
+	buf = diag204_get_buffer(INFO_EXT, &pages);
+	if (!IS_ERR(buf)) {
+		if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) {
+			diag204_store_sc = SUBC_STIB7;
+			diag204_info_type = INFO_EXT;
+			goto out;
+		}
+		if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) {
+			diag204_store_sc = SUBC_STIB7;
+			diag204_info_type = INFO_EXT;
+			goto out;
+		}
+		diag204_free_buffer();
+	}
+
+	/* subcodes 6 and 7 failed, now try subcode 4 */
+
+	buf = diag204_get_buffer(INFO_SIMPLE, &pages);
+	if (IS_ERR(buf)) {
+		rc = PTR_ERR(buf);
+		goto fail_alloc;
+	}
+	if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) {
+		diag204_store_sc = SUBC_STIB4;
+		diag204_info_type = INFO_SIMPLE;
+		goto out;
+	} else {
+		rc = -ENOSYS;
+		goto fail_store;
+	}
+out:
+	rc = 0;
+fail_store:
+	diag204_free_buffer();
+fail_alloc:
+	return rc;
+}
+
+static void *diag204_store(void)
+{
+	void *buf;
+	int pages;
+
+	buf = diag204_get_buffer(diag204_info_type, &pages);
+	if (IS_ERR(buf))
+		goto out;
+	if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0)
+		return ERR_PTR(-ENOSYS);
+out:
+	return buf;
+}
+
+/* Diagnose 224 functions */
+
+static void diag224(void *ptr)
+{
+	asm volatile("   diag    %0,%1,0x224\n"
+		     : :"d" (0), "d"(ptr) : "memory");
+}
+
+static int diag224_get_name_table(void)
+{
+	/* memory must be below 2GB */
+	diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!diag224_cpu_names)
+		return -ENOMEM;
+	diag224(diag224_cpu_names);
+	EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
+	return 0;
+}
+
+static void diag224_delete_name_table(void)
+{
+	kfree(diag224_cpu_names);
+}
+
+static int diag224_idx2name(int index, char *name)
+{
+	memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
+		CPU_NAME_LEN);
+	name[CPU_NAME_LEN] = 0;
+	strstrip(name);
+	return 0;
+}
+
+__init int hypfs_diag_init(void)
+{
+	int rc;
+
+	if (diag204_probe()) {
+		printk(KERN_ERR "hypfs: diag 204 not working.");
+		return -ENODATA;
+	}
+	rc = diag224_get_name_table();
+	if (rc) {
+		diag224_delete_name_table();
+		printk(KERN_ERR "hypfs: could not get name table.\n");
+	}
+	return rc;
+}
+
+__exit void hypfs_diag_exit(void)
+{
+	diag224_delete_name_table();
+	diag204_free_buffer();
+}
+
+/*
+ * Functions to create the directory structure
+ * *******************************************
+ */
+
+static int hypfs_create_cpu_files(struct super_block *sb,
+				  struct dentry *cpus_dir, void *cpu_info)
+{
+	struct dentry *cpu_dir;
+	char buffer[TMP_SIZE];
+	void *rc;
+
+	snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
+							    cpu_info));
+	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+			      cpu_info__acc_time(diag204_info_type, cpu_info) -
+			      cpu_info__lp_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	rc = hypfs_create_u64(sb, cpu_dir, "cputime",
+			      cpu_info__lp_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	if (diag204_info_type == INFO_EXT) {
+		rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",
+				      cpu_info__online_time(diag204_info_type,
+							    cpu_info));
+		if (IS_ERR(rc))
+			return PTR_ERR(rc);
+	}
+	diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
+	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	return 0;
+}
+
+static void *hypfs_create_lpar_files(struct super_block *sb,
+				     struct dentry *systems_dir, void *part_hdr)
+{
+	struct dentry *cpus_dir;
+	struct dentry *lpar_dir;
+	char lpar_name[LPAR_NAME_LEN + 1];
+	void *cpu_info;
+	int i;
+
+	part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
+	lpar_name[LPAR_NAME_LEN] = 0;
+	lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);
+	if (IS_ERR(lpar_dir))
+		return lpar_dir;
+	cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");
+	if (IS_ERR(cpus_dir))
+		return cpus_dir;
+	cpu_info = part_hdr + part_hdr__size(diag204_info_type);
+	for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
+		int rc;
+		rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
+		if (rc)
+			return ERR_PTR(rc);
+		cpu_info += cpu_info__size(diag204_info_type);
+	}
+	return cpu_info;
+}
+
+static int hypfs_create_phys_cpu_files(struct super_block *sb,
+				       struct dentry *cpus_dir, void *cpu_info)
+{
+	struct dentry *cpu_dir;
+	char buffer[TMP_SIZE];
+	void *rc;
+
+	snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
+							    cpu_info));
+	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+	if (IS_ERR(cpu_dir))
+		return PTR_ERR(cpu_dir);
+	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+			      phys_cpu__mgm_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
+	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	return 0;
+}
+
+static void *hypfs_create_phys_files(struct super_block *sb,
+				     struct dentry *parent_dir, void *phys_hdr)
+{
+	int i;
+	void *cpu_info;
+	struct dentry *cpus_dir;
+
+	cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");
+	if (IS_ERR(cpus_dir))
+		return cpus_dir;
+	cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
+	for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
+		int rc;
+		rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
+		if (rc)
+			return ERR_PTR(rc);
+		cpu_info += phys_cpu__size(diag204_info_type);
+	}
+	return cpu_info;
+}
+
+int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
+{
+	struct dentry *systems_dir, *hyp_dir;
+	void *time_hdr, *part_hdr;
+	int i, rc;
+	void *buffer, *ptr;
+
+	buffer = diag204_store();
+	if (IS_ERR(buffer))
+		return PTR_ERR(buffer);
+
+	systems_dir = hypfs_mkdir(sb, root, "systems");
+	if (IS_ERR(systems_dir)) {
+		rc = PTR_ERR(systems_dir);
+		goto err_out;
+	}
+	time_hdr = (struct x_info_blk_hdr *)buffer;
+	part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
+	for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
+		part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
+		if (IS_ERR(part_hdr)) {
+			rc = PTR_ERR(part_hdr);
+			goto err_out;
+		}
+	}
+	if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {
+		ptr = hypfs_create_phys_files(sb, root, part_hdr);
+		if (IS_ERR(ptr)) {
+			rc = PTR_ERR(ptr);
+			goto err_out;
+		}
+	}
+	hyp_dir = hypfs_mkdir(sb, root, "hyp");
+	if (IS_ERR(hyp_dir)) {
+		rc = PTR_ERR(hyp_dir);
+		goto err_out;
+	}
+	ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");
+	if (IS_ERR(ptr)) {
+		rc = PTR_ERR(ptr);
+		goto err_out;
+	}
+	rc = 0;
+
+err_out:
+	return rc;
+}
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
new file mode 100644
index 000000000000..793dea6b9bb6
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_diag.h
@@ -0,0 +1,16 @@
+/*
+ *  fs/hypfs/hypfs_diag.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_DIAG_H_
+#define _HYPFS_DIAG_H_
+
+extern int hypfs_diag_init(void);
+extern void hypfs_diag_exit(void);
+extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+
+#endif /* _HYPFS_DIAG_H_ */
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
new file mode 100644
index 000000000000..18c091925ea5
--- /dev/null
+++ b/arch/s390/hypfs/inode.c
@@ -0,0 +1,491 @@
+/*
+ *  fs/hypfs/inode.c
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/vfs.h>
+#include <linux/pagemap.h>
+#include <linux/gfp.h>
+#include <linux/time.h>
+#include <linux/parser.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+#include "hypfs_diag.h"
+
+#define HYPFS_MAGIC 0x687970	/* ASCII 'hyp' */
+#define TMP_SIZE 64		/* size of temporary buffers */
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+					       struct dentry *dir);
+
+struct hypfs_sb_info {
+	uid_t uid;			/* uid used for files and dirs */
+	gid_t gid;			/* gid used for files and dirs */
+	struct dentry *update_file;	/* file to trigger update */
+	time_t last_update;		/* last update time in secs since 1970 */
+	struct mutex lock;		/* lock to protect update process */
+};
+
+static struct file_operations hypfs_file_ops;
+static struct file_system_type hypfs_type;
+static struct super_operations hypfs_s_ops;
+
+/* start of list of all dentries, which have to be deleted on update */
+static struct dentry *hypfs_last_dentry;
+
+static void hypfs_update_update(struct super_block *sb)
+{
+	struct hypfs_sb_info *sb_info = sb->s_fs_info;
+	struct inode *inode = sb_info->update_file->d_inode;
+
+	sb_info->last_update = get_seconds();
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+/* directory tree removal functions */
+
+static void hypfs_add_dentry(struct dentry *dentry)
+{
+	dentry->d_fsdata = hypfs_last_dentry;
+	hypfs_last_dentry = dentry;
+}
+
+static void hypfs_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+
+	parent = dentry->d_parent;
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		simple_rmdir(parent->d_inode, dentry);
+	else
+		simple_unlink(parent->d_inode, dentry);
+	d_delete(dentry);
+	dput(dentry);
+}
+
+static void hypfs_delete_tree(struct dentry *root)
+{
+	while (hypfs_last_dentry) {
+		struct dentry *next_dentry;
+		next_dentry = hypfs_last_dentry->d_fsdata;
+		hypfs_remove(hypfs_last_dentry);
+		hypfs_last_dentry = next_dentry;
+	}
+}
+
+static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+{
+	struct inode *ret = new_inode(sb);
+
+	if (ret) {
+		struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+		ret->i_mode = mode;
+		ret->i_uid = hypfs_info->uid;
+		ret->i_gid = hypfs_info->gid;
+		ret->i_blksize = PAGE_CACHE_SIZE;
+		ret->i_blocks = 0;
+		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+		if (mode & S_IFDIR)
+			ret->i_nlink = 2;
+		else
+			ret->i_nlink = 1;
+	}
+	return ret;
+}
+
+static void hypfs_drop_inode(struct inode *inode)
+{
+	kfree(inode->u.generic_ip);
+	generic_delete_inode(inode);
+}
+
+static int hypfs_open(struct inode *inode, struct file *filp)
+{
+	char *data = filp->f_dentry->d_inode->u.generic_ip;
+	struct hypfs_sb_info *fs_info;
+
+	if (filp->f_mode & FMODE_WRITE) {
+		if (!(inode->i_mode & S_IWUGO))
+			return -EACCES;
+	}
+	if (filp->f_mode & FMODE_READ) {
+		if (!(inode->i_mode & S_IRUGO))
+			return -EACCES;
+	}
+
+	fs_info = inode->i_sb->s_fs_info;
+	if(data) {
+		mutex_lock(&fs_info->lock);
+		filp->private_data = kstrdup(data, GFP_KERNEL);
+		if (!filp->private_data) {
+			mutex_unlock(&fs_info->lock);
+			return -ENOMEM;
+		}
+		mutex_unlock(&fs_info->lock);
+	}
+	return 0;
+}
+
+static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
+			      size_t count, loff_t offset)
+{
+	char *data;
+	size_t len;
+	struct file *filp = iocb->ki_filp;
+
+	data = filp->private_data;
+	len = strlen(data);
+	if (offset > len) {
+		count = 0;
+		goto out;
+	}
+	if (count > len - offset)
+		count = len - offset;
+	if (copy_to_user(buf, data + offset, count)) {
+		count = -EFAULT;
+		goto out;
+	}
+	iocb->ki_pos += count;
+	file_accessed(filp);
+out:
+	return count;
+}
+static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
+			       size_t count, loff_t pos)
+{
+	int rc;
+	struct super_block *sb;
+	struct hypfs_sb_info *fs_info;
+
+	sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
+	fs_info = sb->s_fs_info;
+	/*
+	 * Currently we only allow one update per second for two reasons:
+	 * 1. diag 204 is VERY expensive
+	 * 2. If several processes do updates in parallel and then read the
+	 *    hypfs data, the likelihood of collisions is reduced, if we restrict
+	 *    the minimum update interval. A collision occurs, if during the
+	 *    data gathering of one process another process triggers an update
+	 *    If the first process wants to ensure consistent data, it has
+	 *    to restart data collection in this case.
+	 */
+	mutex_lock(&fs_info->lock);
+	if (fs_info->last_update == get_seconds()) {
+		rc = -EBUSY;
+		goto out;
+	}
+	hypfs_delete_tree(sb->s_root);
+	rc = hypfs_diag_create_files(sb, sb->s_root);
+	if (rc) {
+		printk(KERN_ERR "hypfs: Update failed\n");
+		hypfs_delete_tree(sb->s_root);
+		goto out;
+	}
+	hypfs_update_update(sb);
+	rc = count;
+out:
+	mutex_unlock(&fs_info->lock);
+	return rc;
+}
+
+static int hypfs_release(struct inode *inode, struct file *filp)
+{
+	kfree(filp->private_data);
+	return 0;
+}
+
+enum { opt_uid, opt_gid, opt_err };
+
+static match_table_t hypfs_tokens = {
+	{opt_uid, "uid=%u"},
+	{opt_gid, "gid=%u"},
+	{opt_err, NULL}
+};
+
+static int hypfs_parse_options(char *options, struct super_block *sb)
+{
+	char *str;
+	substring_t args[MAX_OPT_ARGS];
+
+	if (!options)
+		return 0;
+	while ((str = strsep(&options, ",")) != NULL) {
+		int token, option;
+		struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+
+		if (!*str)
+			continue;
+		token = match_token(str, hypfs_tokens, args);
+		switch (token) {
+		case opt_uid:
+			if (match_int(&args[0], &option))
+				return -EINVAL;
+			hypfs_info->uid = option;
+			break;
+		case opt_gid:
+			if (match_int(&args[0], &option))
+				return -EINVAL;
+			hypfs_info->gid = option;
+			break;
+		case opt_err:
+		default:
+			printk(KERN_ERR "hypfs: Unrecognized mount option "
+			       "\"%s\" or missing value\n", str);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *root_inode;
+	struct dentry *root_dentry;
+	int rc = 0;
+	struct hypfs_sb_info *sbi;
+
+	sbi = kzalloc(sizeof(struct hypfs_sb_info), GFP_KERNEL);
+	if (!sbi)
+		return -ENOMEM;
+	mutex_init(&sbi->lock);
+	sbi->uid = current->uid;
+	sbi->gid = current->gid;
+	sb->s_fs_info = sbi;
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = HYPFS_MAGIC;
+	sb->s_op = &hypfs_s_ops;
+	if (hypfs_parse_options(data, sb)) {
+		rc = -EINVAL;
+		goto err_alloc;
+	}
+	root_inode = hypfs_make_inode(sb, S_IFDIR | 0755);
+	if (!root_inode) {
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+	root_inode->i_op = &simple_dir_inode_operations;
+	root_inode->i_fop = &simple_dir_operations;
+	root_dentry = d_alloc_root(root_inode);
+	if (!root_dentry) {
+		iput(root_inode);
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+	rc = hypfs_diag_create_files(sb, root_dentry);
+	if (rc)
+		goto err_tree;
+	sbi->update_file = hypfs_create_update_file(sb, root_dentry);
+	if (IS_ERR(sbi->update_file)) {
+		rc = PTR_ERR(sbi->update_file);
+		goto err_tree;
+	}
+	hypfs_update_update(sb);
+	sb->s_root = root_dentry;
+	return 0;
+
+err_tree:
+	hypfs_delete_tree(root_dentry);
+	d_genocide(root_dentry);
+	dput(root_dentry);
+err_alloc:
+	kfree(sbi);
+	return rc;
+}
+
+static int hypfs_get_super(struct file_system_type *fst, int flags,
+			const char *devname, void *data, struct vfsmount *mnt)
+{
+	return get_sb_single(fst, flags, data, hypfs_fill_super, mnt);
+}
+
+static void hypfs_kill_super(struct super_block *sb)
+{
+	struct hypfs_sb_info *sb_info = sb->s_fs_info;
+
+	hypfs_delete_tree(sb->s_root);
+	hypfs_remove(sb_info->update_file);
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
+	kill_litter_super(sb);
+}
+
+static struct dentry *hypfs_create_file(struct super_block *sb,
+					struct dentry *parent, const char *name,
+					char *data, mode_t mode)
+{
+	struct dentry *dentry;
+	struct inode *inode;
+	struct qstr qname;
+
+	qname.name = name;
+	qname.len = strlen(name);
+	qname.hash = full_name_hash(name, qname.len);
+	dentry = lookup_one_len(name, parent, strlen(name));
+	if (IS_ERR(dentry))
+		return ERR_PTR(-ENOMEM);
+	inode = hypfs_make_inode(sb, mode);
+	if (!inode) {
+		dput(dentry);
+		return ERR_PTR(-ENOMEM);
+	}
+	if (mode & S_IFREG) {
+		inode->i_fop = &hypfs_file_ops;
+		if (data)
+			inode->i_size = strlen(data);
+		else
+			inode->i_size = 0;
+	} else if (mode & S_IFDIR) {
+		inode->i_op = &simple_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		parent->d_inode->i_nlink++;
+	} else
+		BUG();
+	inode->u.generic_ip = data;
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	return dentry;
+}
+
+struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+			   const char *name)
+{
+	struct dentry *dentry;
+
+	dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE);
+	if (IS_ERR(dentry))
+		return dentry;
+	hypfs_add_dentry(dentry);
+	parent->d_inode->i_nlink++;
+	return dentry;
+}
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+					       struct dentry *dir)
+{
+	struct dentry *dentry;
+
+	dentry = hypfs_create_file(sb, dir, "update", NULL,
+				   S_IFREG | UPDATE_FILE_MODE);
+	/*
+	 * We do not put the update file on the 'delete' list with
+	 * hypfs_add_dentry(), since it should not be removed when the tree
+	 * is updated.
+	 */
+	return dentry;
+}
+
+struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
+				const char *name, __u64 value)
+{
+	char *buffer;
+	char tmp[TMP_SIZE];
+	struct dentry *dentry;
+
+	snprintf(tmp, TMP_SIZE, "%lld\n", (unsigned long long int)value);
+	buffer = kstrdup(tmp, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	dentry =
+	    hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+	if (IS_ERR(dentry)) {
+		kfree(buffer);
+		return ERR_PTR(-ENOMEM);
+	}
+	hypfs_add_dentry(dentry);
+	return dentry;
+}
+
+struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir,
+				const char *name, char *string)
+{
+	char *buffer;
+	struct dentry *dentry;
+
+	buffer = kmalloc(strlen(string) + 2, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	sprintf(buffer, "%s\n", string);
+	dentry =
+	    hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+	if (IS_ERR(dentry)) {
+		kfree(buffer);
+		return ERR_PTR(-ENOMEM);
+	}
+	hypfs_add_dentry(dentry);
+	return dentry;
+}
+
+static struct file_operations hypfs_file_ops = {
+	.open		= hypfs_open,
+	.release	= hypfs_release,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+	.aio_read	= hypfs_aio_read,
+	.aio_write	= hypfs_aio_write,
+};
+
+static struct file_system_type hypfs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "s390_hypfs",
+	.get_sb		= hypfs_get_super,
+	.kill_sb	= hypfs_kill_super
+};
+
+static struct super_operations hypfs_s_ops = {
+	.statfs		= simple_statfs,
+	.drop_inode	= hypfs_drop_inode,
+};
+
+static decl_subsys(s390, NULL, NULL);
+
+static int __init hypfs_init(void)
+{
+	int rc;
+
+	if (MACHINE_IS_VM)
+		return -ENODATA;
+	if (hypfs_diag_init()) {
+		rc = -ENODATA;
+		goto fail_diag;
+	}
+	kset_set_kset_s(&s390_subsys, hypervisor_subsys);
+	rc = subsystem_register(&s390_subsys);
+	if (rc)
+		goto fail_sysfs;
+	rc = register_filesystem(&hypfs_type);
+	if (rc)
+		goto fail_filesystem;
+	return 0;
+
+fail_filesystem:
+	subsystem_unregister(&s390_subsys);
+fail_sysfs:
+	hypfs_diag_exit();
+fail_diag:
+	printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc);
+	return rc;
+}
+
+static void __exit hypfs_exit(void)
+{
+	hypfs_diag_exit();
+	unregister_filesystem(&hypfs_type);
+	subsystem_unregister(&s390_subsys);
+}
+
+module_init(hypfs_init)
+module_exit(hypfs_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Holzheu <holzheu@de.ibm.com>");
+MODULE_DESCRIPTION("s390 Hypervisor Filesystem");
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index 3ea8929e483b..9e2ffc45c0e0 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -407,7 +407,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void __user *)((sp - frame_size) & -8ul);
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 1b83e21841b5..6616ee05c313 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -12,7 +12,7 @@ obj-y    := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \
 	    sys_sparc.o sunos_asm.o systbls.o \
 	    time.o windows.o cpu.o devices.o sclow.o \
 	    tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o semaphore.o
+	    unaligned.o muldiv.o semaphore.o prom.o of_device.o
 
 obj-$(CONFIG_PCI) += pcic.o
 obj-$(CONFIG_SUN4) += sun4setup.o
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 5c3529ceb5d6..a7a4892956c8 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -20,6 +20,7 @@
 #include <asm/ebus.h>
 #include <asm/io.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/bpp.h>
 
 struct linux_ebus *ebus_chain = NULL;
@@ -83,79 +84,81 @@ int __init ebus_blacklist_irq(char *name)
 	return 0;
 }
 
-void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
-				struct linux_ebus_child *dev)
+void __init fill_ebus_child(struct device_node *dp,
+			    struct linux_ebus_child *dev)
 {
-	int regs[PROMREG_MAX];
-	int irqs[PROMREG_MAX];
-	char lbuf[128];
+	int *regs;
+	int *irqs;
 	int i, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
-
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	if (len == -1) len = 0;
+	dev->prom_node = dp;
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs)
+		len = 0;
 	dev->num_addrs = len / sizeof(regs[0]);
 
 	for (i = 0; i < dev->num_addrs; i++) {
 		if (regs[i] >= dev->parent->num_addrs) {
 			prom_printf("UGH: property for %s was %d, need < %d\n",
-				    dev->prom_name, len, dev->parent->num_addrs);
+				    dev->prom_node->name, len,
+				    dev->parent->num_addrs);
 			panic(__FUNCTION__);
 		}
-		dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
+
+		/* XXX resource */
+		dev->resource[i].start =
+			dev->parent->resource[regs[i]].start;
 	}
 
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
 		dev->num_irqs = 1;
-	} else if ((len = prom_getproperty(node, "interrupts",
-	    (char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
-		dev->num_irqs = 0;
-		dev->irqs[0] = 0;
-		if (dev->parent->num_irqs != 0) {
-			dev->num_irqs = 1;
-			dev->irqs[0] = dev->parent->irqs[0];
-/* P3 */ /* printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
-		}
 	} else {
-		dev->num_irqs = len / sizeof(irqs[0]);
-		if (irqs[0] == 0 || irqs[0] >= 8) {
-			/*
-			 * XXX Zero is a valid pin number...
-			 * This works as long as Ebus is not wired to INTA#.
-			 */
-			printk("EBUS: %s got bad irq %d from PROM\n",
-			    dev->prom_name, irqs[0]);
+		irqs = of_get_property(dp, "interrupts", &len);
+		if (!irqs) {
 			dev->num_irqs = 0;
 			dev->irqs[0] = 0;
+			if (dev->parent->num_irqs != 0) {
+				dev->num_irqs = 1;
+				dev->irqs[0] = dev->parent->irqs[0];
+			}
 		} else {
-			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+			dev->num_irqs = len / sizeof(irqs[0]);
+			if (irqs[0] == 0 || irqs[0] >= 8) {
+				/*
+				 * XXX Zero is a valid pin number...
+				 * This works as long as Ebus is not wired
+				 * to INTA#.
+				 */
+				printk("EBUS: %s got bad irq %d from PROM\n",
+				       dev->prom_node->name, irqs[0]);
+				dev->num_irqs = 0;
+				dev->irqs[0] = 0;
+			} else {
+				dev->irqs[0] =
+					pcic_pin_to_irq(irqs[0],
+							dev->prom_node->name);
+			}
 		}
 	}
 }
 
-void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
+void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
 {
-	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_prom_registers *regs;
 	struct linux_ebus_child *child;
-	int irqs[PROMINTR_MAX];
-	char lbuf[128];
+	int *irqs;
 	int i, n, len;
 	unsigned long baseaddr;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
+	dev->prom_node = dp;
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	regs = of_get_property(dp, "reg", &len);
 	if (len % sizeof(struct linux_prom_registers)) {
 		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
-			    dev->prom_name, len,
+			    dev->prom_node->name, len,
 			    (int)sizeof(struct linux_prom_registers));
 		panic(__FUNCTION__);
 	}
@@ -197,7 +200,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 			if ((baseaddr = (unsigned long) ioremap(baseaddr,
 			    regs[i].reg_size)) == 0) {
 				panic("ebus: unable to remap dev %s",
-				    dev->prom_name);
+				      dev->prom_node->name);
 			}
 		}
 		dev->resource[i].start = baseaddr;	/* XXX Unaligned */
@@ -206,29 +209,43 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
 		dev->num_irqs = 1;
-	} else if ((len = prom_getproperty(node, "interrupts",
-	    (char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
-		dev->num_irqs = 0;
-		if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
-			 dev->num_irqs = 1;
-/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
-		}
 	} else {
-		dev->num_irqs = 1;  /* dev->num_irqs = len / sizeof(irqs[0]); */
-		if (irqs[0] == 0 || irqs[0] >= 8) {
-			/* See above for the parent. XXX */
-			printk("EBUS: %s got bad irq %d from PROM\n",
-			    dev->prom_name, irqs[0]);
+		irqs = of_get_property(dp, "interrupts", &len);
+		if (!irqs) {
 			dev->num_irqs = 0;
-			dev->irqs[0] = 0;
+			if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
+				dev->num_irqs = 1;
+/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
+			}
 		} else {
-			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+			dev->num_irqs = 1;  /* dev->num_irqs = len / sizeof(irqs[0]); */
+			if (irqs[0] == 0 || irqs[0] >= 8) {
+				/* See above for the parent. XXX */
+				printk("EBUS: %s got bad irq %d from PROM\n",
+				       dev->prom_node->name, irqs[0]);
+				dev->num_irqs = 0;
+				dev->irqs[0] = 0;
+			} else {
+				dev->irqs[0] =
+					pcic_pin_to_irq(irqs[0],
+							dev->prom_node->name);
+			}
 		}
 	}
 
-	if ((node = prom_getchild(node))) {
+	dev->ofdev.node = dp;
+	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+	dev->ofdev.dev.bus = &ebus_bus_type;
+	strcpy(dev->ofdev.dev.bus_id, dp->path_component_name);
+
+	/* Register with core */
+	if (of_device_register(&dev->ofdev) != 0)
+		printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+		       dev->ofdev.dev.bus_id);
+
+	if ((dp = dp->child) != NULL) {
 		dev->children = (struct linux_ebus_child *)
 			ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -236,9 +253,9 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 		child->next = NULL;
 		child->parent = dev;
 		child->bus = dev->bus;
-		fill_ebus_child(node, &regs[0], child);
+		fill_ebus_child(dp, child);
 
-		while ((node = prom_getsibling(node)) != 0) {
+		while ((dp = dp->sibling) != NULL) {
 			child->next = (struct linux_ebus_child *)
 				ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -246,51 +263,49 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 			child->next = NULL;
 			child->parent = dev;
 			child->bus = dev->bus;
-			fill_ebus_child(node, &regs[0], child);
+			fill_ebus_child(dp, child);
 		}
 	}
 }
 
 void __init ebus_init(void)
 {
-	struct linux_prom_pci_registers regs[PROMREG_MAX];
+	struct linux_prom_pci_registers *regs;
 	struct linux_pbm_info *pbm;
 	struct linux_ebus_device *dev;
 	struct linux_ebus *ebus;
 	struct ebus_system_entry *sp;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
-	char lbuf[128];
+	struct device_node *dp;
 	unsigned long addr, *base;
 	unsigned short pci_command;
-	int nd, len, ebusnd;
-	int reg, nreg;
+	int len, reg, nreg;
 	int num_ebus = 0;
 
-	prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf));
+	dp = of_find_node_by_path("/");
 	for (sp = ebus_blacklist; sp->esname != NULL; sp++) {
-		if (strcmp(lbuf, sp->esname) == 0) {
+		if (strcmp(dp->name, sp->esname) == 0) {
 			ebus_blackp = sp->ipt;
 			break;
 		}
 	}
 
 	pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL);
-	if (!pdev) {
+	if (!pdev)
 		return;
-	}
+
 	cookie = pdev->sysdata;
-	ebusnd = cookie->prom_node;
+	dp = cookie->prom_node;
 
 	ebus_chain = ebus = (struct linux_ebus *)
 			ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = NULL;
 
-	while (ebusnd) {
+	while (dp) {
+		struct device_node *nd;
 
-		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
-		ebus->prom_node = ebusnd;
-		strcpy(ebus->prom_name, lbuf);
+		ebus->prom_node = dp;
 		ebus->self = pdev;
 		ebus->parent = pbm = cookie->pbm;
 
@@ -299,9 +314,8 @@ void __init ebus_init(void)
 		pci_command |= PCI_COMMAND_MASTER;
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 
-		len = prom_getproperty(ebusnd, "reg", (void *)regs,
-				       sizeof(regs));
-		if (len == 0 || len == -1) {
+		regs = of_get_property(dp, "reg", &len);
+		if (!regs) {
 			prom_printf("%s: can't find reg property\n",
 				    __FUNCTION__);
 			prom_halt();
@@ -317,7 +331,18 @@ void __init ebus_init(void)
 			*base++ = addr;
 		}
 
-		nd = prom_getchild(ebusnd);
+		ebus->ofdev.node = dp;
+		ebus->ofdev.dev.parent = &pdev->dev;
+		ebus->ofdev.dev.bus = &ebus_bus_type;
+		strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&ebus->ofdev) != 0)
+			printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+			       ebus->ofdev.dev.bus_id);
+
+
+		nd = dp->child;
 		if (!nd)
 			goto next_ebus;
 
@@ -330,7 +355,7 @@ void __init ebus_init(void)
 		dev->bus = ebus;
 		fill_ebus_device(nd, dev);
 
-		while ((nd = prom_getsibling(nd)) != 0) {
+		while ((nd = nd->sibling) != NULL) {
 			dev->next = (struct linux_ebus_device *)
 				ebus_alloc(sizeof(struct linux_ebus_device));
 
@@ -348,7 +373,7 @@ void __init ebus_init(void)
 			break;
 
 		cookie = pdev->sysdata;
-		ebusnd = cookie->prom_node;
+		dp = cookie->prom_node;
 
 		ebus->next = (struct linux_ebus *)
 			ebus_alloc(sizeof(struct linux_ebus));
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f9ff29734848..ae4c667c906f 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -39,6 +39,8 @@
 #include <asm/io.h>
 #include <asm/vaddrs.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/sbus.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
@@ -224,10 +226,54 @@ static void _sparc_free_io(struct resource *res)
 
 #ifdef CONFIG_SBUS
 
-void sbus_set_sbus64(struct sbus_dev *sdev, int x) {
+void sbus_set_sbus64(struct sbus_dev *sdev, int x)
+{
 	printk("sbus_set_sbus64: unsupported\n");
 }
 
+extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
+void __init sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+	struct linux_prom_irqs irqs[PROMINTR_MAX];
+	int len;
+
+	len = prom_getproperty(sdev->prom_node, "intr",
+			       (char *)irqs, sizeof(irqs));
+	if (len != -1) {
+		sdev->num_irqs = len / 8;
+		if (sdev->num_irqs == 0) {
+			sdev->irqs[0] = 0;
+		} else if (sparc_cpu_model == sun4d) {
+			for (len = 0; len < sdev->num_irqs; len++)
+				sdev->irqs[len] =
+					sun4d_build_irq(sdev, irqs[len].pri);
+		} else {
+			for (len = 0; len < sdev->num_irqs; len++)
+				sdev->irqs[len] = irqs[len].pri;
+		}
+	} else {
+		int interrupts[PROMINTR_MAX];
+
+		/* No "intr" node found-- check for "interrupts" node.
+		 * This node contains SBus interrupt levels, not IPLs
+		 * as in "intr", and no vector values.  We convert
+		 * SBus interrupt levels to PILs (platform specific).
+		 */
+		len = prom_getproperty(sdev->prom_node, "interrupts",
+				       (char *)interrupts, sizeof(interrupts));
+		if (len == -1) {
+			sdev->irqs[0] = 0;
+			sdev->num_irqs = 0;
+		} else {
+			sdev->num_irqs = len / sizeof(int);
+			for (len = 0; len < sdev->num_irqs; len++) {
+				sdev->irqs[len] =
+					sbint_to_irq(sdev, interrupts[len]);
+			}
+		}
+	} 
+}
+
 /*
  * Allocate a chunk of memory suitable for DMA.
  * Typically devices use them for control blocks.
@@ -414,6 +460,89 @@ void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg,
 {
 	printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
 }
+
+/* Support code for sbus_init().  */
+/*
+ * XXX This functions appears to be a distorted version of
+ * prom_sbus_ranges_init(), with all sun4d stuff cut away.
+ * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
+ */
+/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
+void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
+{
+	int parent_node = pn->node;
+
+	if (sparc_cpu_model == sun4d) {
+		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
+		int num_iounit_ranges, len;
+
+		len = prom_getproperty(parent_node, "ranges",
+				       (char *) iounit_ranges,
+				       sizeof (iounit_ranges));
+		if (len != -1) {
+			num_iounit_ranges =
+				(len / sizeof(struct linux_prom_ranges));
+			prom_adjust_ranges(sbus->sbus_ranges,
+					   sbus->num_sbus_ranges,
+					   iounit_ranges, num_iounit_ranges);
+		}
+	}
+}
+
+void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
+{
+	struct device_node *parent = dp->parent;
+
+	if (sparc_cpu_model != sun4d &&
+	    parent != NULL &&
+	    !strcmp(parent->name, "iommu")) {
+		extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
+
+		iommu_init(parent->node, sbus);
+	}
+
+	if (sparc_cpu_model == sun4d) {
+		extern void iounit_init(int sbi_node, int iounit_node,
+					struct sbus_bus *sbus);
+
+		iounit_init(dp->node, parent->node, sbus);
+	}
+}
+
+void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
+{
+	if (sparc_cpu_model == sun4d) {
+		struct device_node *parent = dp->parent;
+
+		sbus->devid = of_getintprop_default(parent, "device-id", 0);
+		sbus->board = of_getintprop_default(parent, "board#", 0);
+	}
+}
+
+int __init sbus_arch_preinit(void)
+{
+	extern void register_proc_sparc_ioport(void);
+
+	register_proc_sparc_ioport();
+
+#ifdef CONFIG_SUN4
+	{
+		extern void sun4_dvma_init(void);
+		sun4_dvma_init();
+	}
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+void __init sbus_arch_postinit(void)
+{
+	if (sparc_cpu_model == sun4d) {
+		extern void sun4d_init_sbi_irq(void);
+		sun4d_init_sbi_irq();
+	}
+}
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
new file mode 100644
index 000000000000..001b8673b4bd
--- /dev/null
+++ b/arch/sparc/kernel/of_device.c
@@ -0,0 +1,268 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+					const struct of_device *dev)
+{
+	if (!dev->node)
+		return NULL;
+	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+		int match = 1;
+		if (matches->name[0])
+			match &= dev->node->name
+				&& !strcmp(matches->name, dev->node->name);
+		if (matches->type[0])
+			match &= dev->node->type
+				&& !strcmp(matches->type, dev->node->type);
+		if (matches->compatible[0])
+			match &= of_device_is_compatible(dev->node,
+							 matches->compatible);
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+	const struct of_device_id * matches = of_drv->match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+	struct device *tmp;
+
+	if (!dev)
+		return NULL;
+	tmp = get_device(&dev->dev);
+	if (tmp)
+		return to_of_device(tmp);
+	else
+		return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+	if (dev)
+		put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct of_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_of_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->match_table, of_dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->suspend)
+		error = drv->suspend(of_dev, state);
+	return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->resume)
+		error = drv->resume(of_dev);
+	return error;
+}
+
+#ifdef CONFIG_PCI
+struct bus_type ebus_bus_type = {
+       .name	= "ebus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name	= "sbus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+#endif
+
+static int __init of_bus_driver_init(void)
+{
+	int err = 0;
+
+#ifdef CONFIG_PCI
+	if (!err)
+		err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+	if (!err)
+		err = bus_register(&sbus_bus_type);
+#endif
+	return 0;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = bus;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct of_device *ofdev;
+
+	ofdev = to_of_device(dev);
+	return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+	struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+	kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+	int rc;
+
+	BUG_ON(ofdev->node == NULL);
+
+	rc = device_register(&ofdev->dev);
+	if (rc)
+		return rc;
+
+	device_create_file(&ofdev->dev, &dev_attr_devspec);
+
+	return 0;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+	device_remove_file(&ofdev->dev, &dev_attr_devspec);
+	device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent,
+					    struct bus_type *bus)
+{
+	struct of_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev->dev.parent = parent;
+	dev->dev.bus = bus;
+	dev->dev.release = of_release_dev;
+
+	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 42002b742deb..bcfdddd0418a 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -31,6 +31,7 @@
 
 #include <asm/irq.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/pcic.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
@@ -665,7 +666,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
 		/* cookies */
 		pcp = pci_devcookie_alloc();
 		pcp->pbm = &pcic->pbm;
-		pcp->prom_node = node;
+		pcp->prom_node = of_find_node_by_phandle(node);
 		dev->sysdata = pcp;
 
 		/* fixing I/O to look like memory */
@@ -896,13 +897,6 @@ static inline unsigned long get_irqmask(int irq_nr)
 	return 1 << irq_nr;
 }
 
-static inline char *pcic_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	sprintf(buff, "%d", irq);
-	return buff;
-}
-
 static void pcic_disable_irq(unsigned int irq_nr)
 {
 	unsigned long mask, flags;
@@ -955,7 +949,6 @@ void __init sun4m_pci_init_IRQ(void)
 	BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);
 }
 
 int pcibios_assign_resource(struct pci_dev *pdev, int resource)
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
new file mode 100644
index 000000000000..63b2b9bd778e
--- /dev/null
+++ b/arch/sparc/kernel/prom.c
@@ -0,0 +1,474 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc32 by David S. Miller davem@davemloft.net
+ *
+ *      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/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+
+static struct device_node *allnodes;
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+	const char* cp;
+	int cplen, l;
+
+	cp = (char *) of_get_property(device, "compatible", &cplen);
+	if (cp == NULL)
+		return 0;
+	while (cplen > 0) {
+		if (strncmp(cp, compat, strlen(compat)) == 0)
+			return 1;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+	struct device_node *np;
+
+	if (!node)
+		return NULL;
+
+	np = node->parent;
+
+	return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	struct device_node *next;
+
+	next = prev ? prev->sibling : node->child;
+	for (; next != 0; next = next->sibling) {
+		break;
+	}
+
+	return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+	struct device_node *np = allnodes;
+
+	for (; np != 0; np = np->allnext) {
+		if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != NULL; np = np->allnext)
+		if (np->name != NULL && strcmp(np->name, name) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext)
+		if (np->type != 0 && strcmp(np->type, type) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compatible)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext) {
+		if (type != NULL
+		    && !(np->type != 0 && strcmp(np->type, type) == 0))
+			continue;
+		if (of_device_is_compatible(np, compatible))
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+				  int *lenp)
+{
+	struct property *pp;
+
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (strcmp(pp->name, name) == 0) {
+			if (lenp != 0)
+				*lenp = pp->length;
+			break;
+		}
+	}
+	return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+	struct property *pp = of_find_property(np,name,lenp);
+	return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+	struct property *prop;
+	int len;
+
+	prop = of_find_property(np, name, &len);
+	if (!prop || len != 4)
+		return def;
+
+	return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	prom_early_allocated += size;
+
+	return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+	if (!dp)
+		return 0;
+
+	return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ */
+static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *rprop;
+
+	rprop = of_find_property(dp, "reg", NULL);
+	if (!rprop)
+		return;
+
+	regs = rprop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io, regs->phys_addr);
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io,
+		regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_pci_registers *regs;
+	struct property *prop;
+	unsigned int devfn;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	devfn = (regs->phys_hi >> 8) & 0xff;
+	if (devfn & 0x07) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			devfn >> 3,
+			devfn & 0x07);
+	} else {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name,
+			devfn >> 3);
+	}
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io, regs->phys_addr);
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct device_node *parent = dp->parent;
+
+	if (parent != NULL) {
+		if (!strcmp(parent->type, "pci") ||
+		    !strcmp(parent->type, "pciex"))
+			return pci_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "sbus"))
+			return sbus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "ebus"))
+			return ebus_path_component(dp, tmp_buf);
+
+		/* "isa" is handled with platform naming */
+	}
+
+	/* Use platform naming convention.  */
+	return sparc32_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+	char tmp_buf[64], *n;
+
+	tmp_buf[0] = '\0';
+	__build_path_component(dp, tmp_buf);
+	if (tmp_buf[0] == '\0')
+		strcpy(tmp_buf, dp->name);
+
+	n = prom_early_alloc(strlen(tmp_buf) + 1);
+	strcpy(n, tmp_buf);
+
+	return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+	int len, ourlen, plen;
+	char *n;
+
+	plen = strlen(dp->parent->full_name);
+	ourlen = strlen(dp->path_component_name);
+	len = ourlen + plen + 2;
+
+	n = prom_early_alloc(len);
+	strcpy(n, dp->parent->full_name);
+	if (!is_root_node(dp->parent)) {
+		strcpy(n + plen, "/");
+		plen++;
+	}
+	strcpy(n + plen, dp->path_component_name);
+
+	return n;
+}
+
+static struct property * __init build_one_prop(phandle node, char *prev)
+{
+	static struct property *tmp = NULL;
+	struct property *p;
+	int len;
+
+	if (tmp) {
+		p = tmp;
+		memset(p, 0, sizeof(*p) + 32);
+		tmp = NULL;
+	} else
+		p = prom_early_alloc(sizeof(struct property) + 32);
+
+	p->name = (char *) (p + 1);
+	if (prev == NULL) {
+		prom_firstprop(node, p->name);
+	} else {
+		prom_nextprop(node, prev, p->name);
+	}
+	if (strlen(p->name) == 0) {
+		tmp = p;
+		return NULL;
+	}
+	p->length = prom_getproplen(node, p->name);
+	if (p->length <= 0) {
+		p->length = 0;
+	} else {
+		p->value = prom_early_alloc(p->length);
+		len = prom_getproperty(node, p->name, p->value, p->length);
+	}
+	return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+	struct property *head, *tail;
+
+	head = tail = build_one_prop(node, NULL);
+	while(tail) {
+		tail->next = build_one_prop(node, tail->name);
+		tail = tail->next;
+	}
+
+	return head;
+}
+
+static char * __init get_one_property(phandle node, char *name)
+{
+	char *buf = "<NULL>";
+	int len;
+
+	len = prom_getproplen(node, name);
+	if (len > 0) {
+		buf = prom_early_alloc(len);
+		len = prom_getproperty(node, name, buf, len);
+	}
+
+	return buf;
+}
+
+static struct device_node * __init create_node(phandle node)
+{
+	struct device_node *dp;
+
+	if (!node)
+		return NULL;
+
+	dp = prom_early_alloc(sizeof(*dp));
+
+	kref_init(&dp->kref);
+
+	dp->name = get_one_property(node, "name");
+	dp->type = get_one_property(node, "device_type");
+	dp->node = node;
+
+	/* Build interrupts later... */
+
+	dp->properties = build_prop_list(node);
+
+	return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+	struct device_node *dp;
+
+	dp = create_node(node);
+	if (dp) {
+		*(*nextp) = dp;
+		*nextp = &dp->allnext;
+
+		dp->parent = parent;
+		dp->path_component_name = build_path_component(dp);
+		dp->full_name = build_full_name(dp);
+
+		dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+		dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+	}
+
+	return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+	struct device_node **nextp;
+
+	allnodes = create_node(prom_root_node);
+	allnodes->path_component_name = "";
+	allnodes->full_name = "/";
+
+	nextp = &allnodes->allnext;
+	allnodes->child = build_tree(allnodes,
+				     prom_getchild(allnodes->node),
+				     &nextp);
+	printk("PROM: Built device tree with %u bytes of memory.\n",
+	       prom_early_allocated);
+}
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 3509e4305532..a893a9cc9534 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -31,6 +31,7 @@
 #include <linux/console.h>
 #include <linux/spinlock.h>
 #include <linux/root_dev.h>
+#include <linux/cpu.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -331,7 +332,7 @@ void __init setup_arch(char **cmdline_p)
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
 	ROOT_DEV = old_decode_dev(root_dev);
-#ifdef CONFIG_BLK_DEV_INITRD
+#ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
 	rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
@@ -348,6 +349,8 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.context = (unsigned long) NO_CONTEXT;
 	init_task.thread.kregs = &fake_swapper_regs;
 
+	smp_setup_cpu_possible_map();
+
 	paging_init();
 }
 
@@ -389,6 +392,8 @@ console_initcall(set_preferred_console);
 extern char *sparc_cpu_type;
 extern char *sparc_fpu_type;
 
+static int ncpus_probed;
+
 static int show_cpuinfo(struct seq_file *m, void *__unused)
 {
 	seq_printf(m,
@@ -411,7 +416,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
 		   romvec->pv_printrev >> 16,
 		   romvec->pv_printrev & 0xffff,
 		   &cputypval,
-		   num_possible_cpus(),
+		   ncpus_probed,
 		   num_online_cpus()
 #ifndef CONFIG_SMP
 		   , cpu_data(0).udelay_val/(500000/HZ),
@@ -471,3 +476,30 @@ void sun_do_break(void)
 
 int serial_console = -1;
 int stop_a_enabled = 1;
+
+static int __init topology_init(void)
+{
+	int i, ncpus, err;
+
+	/* Count the number of physically present processors in
+	 * the machine, even on uniprocessor, so that /proc/cpuinfo
+	 * output is consistent with 2.4.x
+	 */
+	ncpus = 0;
+	while (!cpu_find_by_instance(ncpus, NULL, NULL))
+		ncpus++;
+	ncpus_probed = ncpus;
+
+	err = 0;
+	for_each_online_cpu(i) {
+		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+		if (!p)
+			err = -ENOMEM;
+		else
+			register_cpu(p, i, NULL);
+	}
+
+	return err;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 40b42c88e6a7..6135d4faeeeb 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -58,7 +58,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE;
 /* Used to make bitops atomic */
 unsigned char bitops_spinlock = 0;
 
-void __init smp_store_cpu_info(int id)
+void __cpuinit smp_store_cpu_info(int id)
 {
 	int cpu_node;
 
@@ -267,22 +267,18 @@ int setup_profiling_timer(unsigned int multiplier)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	extern void smp4m_boot_cpus(void);
-	int i, cpuid, ncpus, extra;
+	int i, cpuid, extra;
 
 	BUG_ON(sparc_cpu_model != sun4m);
 	printk("Entering SMP Mode...\n");
 
-	ncpus = 1;
 	extra = 0;
 	for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
-		if (cpuid == boot_cpu_id)
-			continue;
-		if (cpuid < NR_CPUS && ncpus++ < max_cpus)
-			cpu_set(cpuid, phys_cpu_present_map);
-		else
+		if (cpuid >= NR_CPUS)
 			extra++;
 	}
-	if (max_cpus >= NR_CPUS && extra)
+	/* i = number of cpus */
+	if (extra && max_cpus > i - extra)
 		printk("Warning: NR_CPUS is too low to start all cpus\n");
 
 	smp_store_cpu_info(boot_cpu_id);
@@ -290,7 +286,25 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 	smp4m_boot_cpus();
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+/* Set this up early so that things like the scheduler can init
+ * properly.  We use the same cpu mask for both the present and
+ * possible cpu map.
+ */
+void __init smp_setup_cpu_possible_map(void)
+{
+	int instance, mid;
+
+	instance = 0;
+	while (!cpu_find_by_instance(instance, NULL, &mid)) {
+		if (mid < NR_CPUS) {
+			cpu_set(mid, phys_cpu_present_map);
+			cpu_set(mid, cpu_present_map);
+		}
+		instance++;
+	}
+}
+
+void __init smp_prepare_boot_cpu(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -306,7 +320,7 @@ void __devinit smp_prepare_boot_cpu(void)
 	cpu_set(cpuid, phys_cpu_present_map);
 }
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	extern int smp4m_boot_one_cpu(int);
 	int ret;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 4b376fae752c..fd7deabf9982 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -163,7 +163,6 @@ EXPORT_SYMBOL(BTFIXUP_CALL(__hard_smp_processor_id));
 #endif
 EXPORT_SYMBOL(BTFIXUP_CALL(enable_irq));
 EXPORT_SYMBOL(BTFIXUP_CALL(disable_irq));
-EXPORT_SYMBOL(BTFIXUP_CALL(__irq_itoa));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 3d6a99073c42..0f2d8d9cbdba 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -198,8 +198,6 @@ static void __init sun4c_init_timers(irqreturn_t (*counter_fn)(int, void *, stru
 static void sun4c_nop(void) {}
 #endif
 
-extern char *sun4m_irq_itoa(unsigned int irq);
-
 void __init sun4c_init_IRQ(void)
 {
 	struct linux_prom_registers int_regs[2];
@@ -238,7 +236,6 @@ void __init sun4c_init_IRQ(void)
 	BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
-	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4c_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index ca656d9bd6fd..9c30e35c88f7 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -560,17 +560,6 @@ void __init sun4d_init_sbi_irq(void)
 	}
 }
 
-static char *sun4d_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	
-	if (irq < (1 << 5))
-		sprintf(buff, "%d", irq);
-	else
-		sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq);
-	return buff;
-}
-
 void __init sun4d_init_IRQ(void)
 {
 	local_irq_disable();
@@ -581,7 +570,6 @@ void __init sun4d_init_IRQ(void)
 	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4d_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 39d712c3c809..a296c13ac18f 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -229,13 +229,6 @@ static void sun4m_load_profile_irq(int cpu, unsigned int limit)
 	sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
 }
 
-char *sun4m_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	sprintf(buff, "%d", irq);
-	return buff;
-}
-
 static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
 {
 	int reg_count, irq, cpu;
@@ -388,7 +381,6 @@ void __init sun4m_init_IRQ(void)
 	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4m_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 70b375a4c2c2..3b32096134aa 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -66,7 +66,7 @@ static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
 static void smp_setup_percpu_timer(void);
 extern void cpu_probe(void);
 
-void __init smp4m_callin(void)
+void __cpuinit smp4m_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -112,13 +112,8 @@ void __init smp4m_callin(void)
 	local_irq_enable();
 
 	cpu_set(cpuid, cpu_online_map);
-	/* last one in gets all the interrupts (for testing) */
-	set_irq_udt(boot_cpu_id);
 }
 
-extern void init_IRQ(void);
-extern void cpu_panic(void);
-
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
@@ -134,7 +129,7 @@ void __init smp4m_boot_cpus(void)
 	local_flush_cache_all();
 }
 
-int smp4m_boot_one_cpu(int i)
+int __cpuinit smp4m_boot_one_cpu(int i)
 {
 	extern unsigned long sun4m_cpu_startup;
 	unsigned long *entry = &sun4m_cpu_startup;
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 898669732466..cfa7d3456634 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -31,6 +31,7 @@
 #include <asm/vaddrs.h>
 #include <asm/pgalloc.h>	/* bug in asm-generic/tlb.h: check_pgt_cache */
 #include <asm/tlb.h>
+#include <asm/prom.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -349,6 +350,7 @@ void __init paging_init(void)
 	protection_map[14] = PAGE_SHARED;
 	protection_map[15] = PAGE_SHARED;
 	btfixup();
+	prom_build_devicetree();
 	device_scan();
 }
 
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 77840c804786..7215849db392 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -144,8 +144,9 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
 	unsigned long start;
 	unsigned long end;
 
-	start = (unsigned long)iopte & PAGE_MASK;
+	start = (unsigned long)iopte;
 	end = PAGE_ALIGN(start + niopte*sizeof(iopte_t));
+	start &= PAGE_MASK;
 	if (viking_mxcc_present) {
 		while(start < end) {
 			viking_mxcc_flush_page(start);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 43a66f5407f4..a7a111db25b2 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -87,6 +87,10 @@ config SYSVIPC_COMPAT
 	depends on COMPAT && SYSVIPC
 	default y
 
+config GENERIC_HARDIRQS
+	bool
+	default y
+
 menu "General machine setup"
 
 config SMP
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f09a70b8aabd..b2f41147d0e4 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc3
-# Fri May 12 12:43:49 2006
+# Linux kernel version: 2.6.17
+# Fri Jun 23 23:17:09 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -87,6 +87,7 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_SYSVIPC_COMPAT=y
+CONFIG_GENERIC_HARDIRQS=y
 
 #
 # General machine setup
@@ -183,6 +184,8 @@ CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
 CONFIG_INET_XFRM_TUNNEL=y
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 CONFIG_TCP_CONG_ADVANCED=y
@@ -198,6 +201,9 @@ CONFIG_TCP_CONG_HSTCP=m
 CONFIG_TCP_CONG_HYBLA=m
 CONFIG_TCP_CONG_VEGAS=m
 CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_COMPOUND=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -207,7 +213,10 @@ CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -260,6 +269,7 @@ CONFIG_VLAN_8021Q=m
 # Network testing
 #
 CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -276,6 +286,7 @@ CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -424,6 +435,7 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
@@ -562,6 +574,7 @@ CONFIG_BNX2=m
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -722,6 +735,7 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -765,6 +779,7 @@ CONFIG_I2C_ALGOBIT=y
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -793,10 +808,12 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
@@ -811,6 +828,7 @@ CONFIG_HWMON=y
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1006,6 +1024,7 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1085,10 +1104,12 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1135,6 +1156,19 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # Misc Linux/SPARC drivers
 #
 CONFIG_SUN_OPENPROMIO=m
@@ -1173,6 +1207,7 @@ CONFIG_FS_POSIX_ACL=y
 # 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
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 6f6816488b04..86c9fe3f3e4a 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -12,7 +12,7 @@ obj-y		:= process.o setup.o cpu.o idprom.o \
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
-		   visemul.o
+		   visemul.o prom.o of_device.o
 
 obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o \
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index 8852c20c8d99..2c42894b188f 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -110,43 +110,82 @@ void auxio_set_lte(int on)
 	}
 }
 
-void __init auxio_probe(void)
+static void __devinit auxio_report_dev(struct device_node *dp)
 {
-        struct sbus_bus *sbus;
-        struct sbus_dev *sdev = NULL;
-
-        for_each_sbus(sbus) {
-                for_each_sbusdev(sdev, sbus) {
-                        if(!strcmp(sdev->prom_name, "auxio"))
-				goto found_sdev;
-                }
-        }
-
-found_sdev:
-	if (sdev) {
-		auxio_devtype  = AUXIO_TYPE_SBUS;
-		auxio_register = sbus_ioremap(&sdev->resource[0], 0,
-					      sdev->reg_addrs[0].reg_size,
-					      "auxiliaryIO");
-	}
+	printk(KERN_INFO "AUXIO: Found device at %s\n",
+	       dp->full_name);
+}
+
+static struct of_device_id auxio_match[] = {
+	{
+		.name = "auxio",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, auxio_match);
+
+#ifdef CONFIG_SBUS
+static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+	auxio_devtype  = AUXIO_TYPE_SBUS;
+	auxio_register = sbus_ioremap(&sdev->resource[0], 0,
+				      sdev->reg_addrs[0].reg_size,
+				      "auxiliaryIO");
+	if (!auxio_register)
+		return -ENODEV;
+
+	auxio_report_dev(dev->node);
+	return 0;
+}
+
+static struct of_platform_driver auxio_sbus_driver = {
+	.name		= "auxio",
+	.match_table	= auxio_match,
+	.probe		= auxio_sbus_probe,
+};
+#endif
+
 #ifdef CONFIG_PCI
-	else {
-		struct linux_ebus *ebus;
-		struct linux_ebus_device *edev = NULL;
-
-		for_each_ebus(ebus) {
-			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_name, "auxio"))
-					goto ebus_done;
-			}
-		}
-	ebus_done:
-		if (edev) {
-			auxio_devtype  = AUXIO_TYPE_EBUS;
-			auxio_register =
-				ioremap(edev->resource[0].start, sizeof(u32));
-		}
-	}
+static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+
+	auxio_devtype  = AUXIO_TYPE_EBUS;
+	auxio_register = ioremap(edev->resource[0].start, sizeof(u32));
+	if (!auxio_register)
+		return -ENODEV;
+
+	auxio_report_dev(dev->node);
+
 	auxio_set_led(AUXIO_LED_ON);
+
+	return 0;
+}
+
+static struct of_platform_driver auxio_ebus_driver = {
+	.name		= "auxio",
+	.match_table	= auxio_match,
+	.probe		= auxio_ebus_probe,
+};
 #endif
+
+static int __init auxio_probe(void)
+{
+#ifdef CONFIG_SBUS
+	of_register_driver(&auxio_sbus_driver, &sbus_bus_type);
+#endif
+#ifdef CONFIG_PCI
+	of_register_driver(&auxio_ebus_driver, &ebus_bus_type);
+#endif
+
+	return 0;
 }
+
+/* Must be after subsys_initcall() so that busses are probed.  Must
+ * be before device_initcall() because things like the floppy driver
+ * need to use the AUXIO register.
+ */
+fs_initcall(auxio_probe);
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index 3d184a784968..b66336db00ee 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -29,28 +29,34 @@ static void central_probe_failure(int line)
 	prom_halt();
 }
 
-static void central_ranges_init(int cnode, struct linux_central *central)
+static void central_ranges_init(struct linux_central *central)
 {
-	int success;
+	struct device_node *dp = central->prom_node;
+	void *pval;
+	int len;
 	
 	central->num_central_ranges = 0;
-	success = prom_getproperty(central->prom_node, "ranges",
-				   (char *) central->central_ranges,
-				   sizeof (central->central_ranges));
-	if (success != -1)
-		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
+	pval = of_get_property(dp, "ranges", &len);
+	if (pval) {
+		memcpy(central->central_ranges, pval, len);
+		central->num_central_ranges =
+			(len / sizeof(struct linux_prom_ranges));
+	}
 }
 
-static void fhc_ranges_init(int fnode, struct linux_fhc *fhc)
+static void fhc_ranges_init(struct linux_fhc *fhc)
 {
-	int success;
+	struct device_node *dp = fhc->prom_node;
+	void *pval;
+	int len;
 	
 	fhc->num_fhc_ranges = 0;
-	success = prom_getproperty(fhc->prom_node, "ranges",
-				   (char *) fhc->fhc_ranges,
-				   sizeof (fhc->fhc_ranges));
-	if (success != -1)
-		fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges));
+	pval = of_get_property(dp, "ranges", &len);
+	if (pval) {
+		memcpy(fhc->fhc_ranges, pval, len);
+		fhc->num_fhc_ranges =
+			(len / sizeof(struct linux_prom_ranges));
+	}
 }
 
 /* Range application routines are exported to various drivers,
@@ -112,15 +118,10 @@ static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
 
 static void probe_other_fhcs(void)
 {
-	struct linux_prom64_registers fpregs[6];
-	char namebuf[128];
-	int node;
+	struct device_node *dp;
+	struct linux_prom64_registers *fpregs;
 
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "fhc");
-	if (node == 0)
-		central_probe_failure(__LINE__);
-	while (node) {
+	for_each_node_by_name(dp, "fhc") {
 		struct linux_fhc *fhc;
 		int board;
 		u32 tmp;
@@ -137,14 +138,12 @@ static void probe_other_fhcs(void)
 		/* Toplevel FHCs have no parent. */
 		fhc->parent = NULL;
 		
-		fhc->prom_node = node;
-		prom_getstring(node, "name", namebuf, sizeof(namebuf));
-		strcpy(fhc->prom_name, namebuf);
-		fhc_ranges_init(node, fhc);
+		fhc->prom_node = dp;
+		fhc_ranges_init(fhc);
 
 		/* Non-central FHC's have 64-bit OBP format registers. */
-		if (prom_getproperty(node, "reg",
-				    (char *)&fpregs[0], sizeof(fpregs)) == -1)
+		fpregs = of_get_property(dp, "reg", NULL);
+		if (!fpregs)
 			central_probe_failure(__LINE__);
 
 		/* Only central FHC needs special ranges applied. */
@@ -155,7 +154,7 @@ static void probe_other_fhcs(void)
 		fhc->fhc_regs.uregs = fpregs[4].phys_addr;
 		fhc->fhc_regs.tregs = fpregs[5].phys_addr;
 
-		board = prom_getintdefault(node, "board#", -1);
+		board = of_getintprop_default(dp, "board#", -1);
 		fhc->board = board;
 
 		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
@@ -179,33 +178,33 @@ static void probe_other_fhcs(void)
 		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 		tmp |= FHC_CONTROL_IXIST;
 		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
-
-		/* Look for the next FHC. */
-		node = prom_getsibling(node);
-		if (node == 0)
-			break;
-		node = prom_searchsiblings(node, "fhc");
-		if (node == 0)
-			break;
 	}
 }
 
 static void probe_clock_board(struct linux_central *central,
 			      struct linux_fhc *fhc,
-			      int cnode, int fnode)
+			      struct device_node *fp)
 {
-	struct linux_prom_registers cregs[3];
-	int clknode, nslots, tmp, nregs;
+	struct device_node *dp;
+	struct linux_prom_registers cregs[3], *pr;
+	int nslots, tmp, nregs;
 
-	clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board");
-	if (clknode == 0 || clknode == -1)
+	dp = fp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "clock-board"))
+			break;
+		dp = dp->sibling;
+	}
+	if (!dp)
 		central_probe_failure(__LINE__);
 
-	nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs));
-	if (nregs == -1)
+	pr = of_get_property(dp, "reg", &nregs);
+	if (!pr)
 		central_probe_failure(__LINE__);
 
+	memcpy(cregs, pr, nregs);
 	nregs /= sizeof(struct linux_prom_registers);
+
 	apply_fhc_ranges(fhc, &cregs[0], nregs);
 	apply_central_ranges(central, &cregs[0], nregs);
 	central->cfreg = prom_reg_to_paddr(&cregs[0]);
@@ -296,13 +295,13 @@ static void init_all_fhc_hw(void)
 
 void central_probe(void)
 {
-	struct linux_prom_registers fpregs[6];
+	struct linux_prom_registers fpregs[6], *pr;
 	struct linux_fhc *fhc;
-	char namebuf[128];
-	int cnode, fnode, err;
+	struct device_node *dp, *fp;
+	int err;
 
-	cnode = prom_finddevice("/central");
-	if (cnode == 0 || cnode == -1) {
+	dp = of_find_node_by_name(NULL, "central");
+	if (!dp) {
 		if (this_is_starfire)
 			starfire_cpu_setup();
 		return;
@@ -321,31 +320,31 @@ void central_probe(void)
 
 	/* First init central. */
 	central_bus->child = fhc;
-	central_bus->prom_node = cnode;
-
-	prom_getstring(cnode, "name", namebuf, sizeof(namebuf));
-	strcpy(central_bus->prom_name, namebuf);
-
-	central_ranges_init(cnode, central_bus);
+	central_bus->prom_node = dp;
+	central_ranges_init(central_bus);
 
 	/* And then central's FHC. */
 	fhc->next = fhc_list;
 	fhc_list = fhc;
 
 	fhc->parent = central_bus;
-	fnode = prom_searchsiblings(prom_getchild(cnode), "fhc");
-	if (fnode == 0 || fnode == -1)
+	fp = dp->child;
+	while (fp) {
+		if (!strcmp(fp->name, "fhc"))
+			break;
+		fp = fp->sibling;
+	}
+	if (!fp)
 		central_probe_failure(__LINE__);
 
-	fhc->prom_node = fnode;
-	prom_getstring(fnode, "name", namebuf, sizeof(namebuf));
-	strcpy(fhc->prom_name, namebuf);
-
-	fhc_ranges_init(fnode, fhc);
+	fhc->prom_node = fp;
+	fhc_ranges_init(fhc);
 
 	/* Now, map in FHC register set. */
-	if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1)
+	pr = of_get_property(fp, "reg", NULL);
+	if (!pr)
 		central_probe_failure(__LINE__);
+	memcpy(fpregs, pr, sizeof(fpregs));
 
 	apply_central_ranges(central_bus, &fpregs[0], 6);
 	
@@ -366,7 +365,7 @@ void central_probe(void)
 	fhc->jtag_master = 0;
 
 	/* Attach the clock board registers for CENTRAL. */
-	probe_clock_board(central_bus, fhc, cnode, fnode);
+	probe_clock_board(central_bus, fhc, fp);
 
 	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 	printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 97cf912f0853..259f37e516f5 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -17,6 +17,7 @@
 #include <asm/spitfire.h>
 #include <asm/chmctrl.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/io.h>
 
 #define CHMCTRL_NDGRPS	2
@@ -67,7 +68,6 @@ struct bank_info {
 struct mctrl_info {
 	struct list_head	list;
 	int			portid;
-	int			index;
 
 	struct obp_mem_layout	layout_prop;
 	int			layout_size;
@@ -339,12 +339,13 @@ static void fetch_decode_regs(struct mctrl_info *mp)
 				 read_mcreg(mp, CHMCTRL_DECODE4));
 }
 
-static int init_one_mctrl(int node, int index)
+static int init_one_mctrl(struct device_node *dp)
 {
 	struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
-	int portid = prom_getintdefault(node, "portid", -1);
-	struct linux_prom64_registers p_reg_prop;
-	int t;
+	int portid = of_getintprop_default(dp, "portid", -1);
+	struct linux_prom64_registers *regs;
+	void *pval;
+	int len;
 
 	if (!mp)
 		return -1;
@@ -353,24 +354,21 @@ static int init_one_mctrl(int node, int index)
 		goto fail;
 
 	mp->portid = portid;
-	mp->layout_size = prom_getproplen(node, "memory-layout");
-	if (mp->layout_size < 0)
+	pval = of_get_property(dp, "memory-layout", &len);
+	mp->layout_size = len;
+	if (!pval)
 		mp->layout_size = 0;
-	if (mp->layout_size > sizeof(mp->layout_prop))
-		goto fail;
-
-	if (mp->layout_size > 0)
-		prom_getproperty(node, "memory-layout",
-				 (char *) &mp->layout_prop,
-				 mp->layout_size);
+	else {
+		if (mp->layout_size > sizeof(mp->layout_prop))
+			goto fail;
+		memcpy(&mp->layout_prop, pval, len);
+	}
 
-	t = prom_getproperty(node, "reg",
-			     (char *) &p_reg_prop,
-			     sizeof(p_reg_prop));
-	if (t < 0 || p_reg_prop.reg_size != 0x48)
+	regs = of_get_property(dp, "reg", NULL);
+	if (!regs || regs->reg_size != 0x48)
 		goto fail;
 
-	mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size);
+	mp->regs = ioremap(regs->phys_addr, regs->reg_size);
 	if (mp->regs == NULL)
 		goto fail;
 
@@ -384,13 +382,11 @@ static int init_one_mctrl(int node, int index)
 
 	fetch_decode_regs(mp);
 
-	mp->index = index;
-
 	list_add(&mp->list, &mctrl_list);
 
 	/* Report the device. */
-	printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n",
-	       mp->index,
+	printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n",
+	       dp->full_name,
 	       mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE"));
 
 	return 0;
@@ -404,34 +400,19 @@ fail:
 	return -1;
 }
 
-static int __init probe_for_string(char *name, int index)
-{
-	int node = prom_getchild(prom_root_node);
-
-	while ((node = prom_searchsiblings(node, name)) != 0) {
-		int ret = init_one_mctrl(node, index);
-
-		if (!ret)
-			index++;
-
-		node = prom_getsibling(node);
-		if (!node)
-			break;
-	}
-
-	return index;
-}
-
 static int __init chmc_init(void)
 {
-	int index;
+	struct device_node *dp;
 
 	/* This driver is only for cheetah platforms. */
 	if (tlb_type != cheetah && tlb_type != cheetah_plus)
 		return -ENODEV;
 
-	index = probe_for_string("memory-controller", 0);
-	index = probe_for_string("mc-us3", index);
+	for_each_node_by_name(dp, "memory-controller")
+		init_one_mctrl(dp);
+
+	for_each_node_by_name(dp, "mc-us3")
+		init_one_mctrl(dp);
 
 	return 0;
 }
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 007e8922cd16..389301c95cb2 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -33,7 +33,7 @@ extern void cpu_probe(void);
 extern void central_probe(void);
 
 u32 sun4v_vdev_devhandle;
-int sun4v_vdev_root;
+struct device_node *sun4v_vdev_root;
 
 struct vdev_intmap {
 	unsigned int phys;
@@ -50,102 +50,68 @@ struct vdev_intmask {
 
 static struct vdev_intmap *vdev_intmap;
 static int vdev_num_intmap;
-static struct vdev_intmask vdev_intmask;
+static struct vdev_intmask *vdev_intmask;
 
 static void __init sun4v_virtual_device_probe(void)
 {
-	struct linux_prom64_registers regs;
-	struct vdev_intmap *ip;
-	int node, sz, err;
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+	struct device_node *dp;
+	int sz;
 
 	if (tlb_type != hypervisor)
 		return;
 
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "virtual-devices");
-	if (!node) {
+	dp = of_find_node_by_name(NULL, "virtual-devices");
+	if (!dp) {
 		prom_printf("SUN4V: Fatal error, no virtual-devices node.\n");
 		prom_halt();
 	}
 
-	sun4v_vdev_root = node;
+	sun4v_vdev_root = dp;
 
-	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
-	sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
+	sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff;
 
-	sz = prom_getproplen(node, "interrupt-map");
-	if (sz <= 0) {
-		prom_printf("SUN4V: Error, no vdev interrupt-map.\n");
-		prom_halt();
-	}
-
-	if ((sz % sizeof(*ip)) != 0) {
-		prom_printf("SUN4V: Bogus interrupt-map property size %d\n",
-			    sz);
-		prom_halt();
-	}
-
-	vdev_intmap = ip = alloc_bootmem_low_pages(sz);
-	if (!vdev_intmap) {
-		prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n");
-		prom_halt();
-	}
-
-	err = prom_getproperty(node, "interrupt-map", (char *) ip, sz);
-	if (err == -1) {
-		prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n");
-		prom_halt();
-	}
-	if (err != sz) {
-		prom_printf("SUN4V: Inconsistent interrupt-map size, "
-			    "proplen(%d) vs getprop(%d).\n", sz,err);
-		prom_halt();
-	}
-
-	vdev_num_intmap = err / sizeof(*ip);
+	prop = of_find_property(dp, "interrupt-map", &sz);
+	vdev_intmap = prop->value;
+	vdev_num_intmap = sz / sizeof(struct vdev_intmap);
 
-	err = prom_getproperty(node, "interrupt-map-mask",
-			       (char *) &vdev_intmask,
-			       sizeof(vdev_intmask));
-	if (err <= 0) {
-		prom_printf("SUN4V: Fatal error, no vdev "
-			    "interrupt-map-mask.\n");
-		prom_halt();
-	}
-	if (err % sizeof(vdev_intmask)) {
-		prom_printf("SUN4V: Bogus interrupt-map-mask "
-			    "property size %d\n", err);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map-mask", NULL);
+	vdev_intmask = prop->value;
 
-	printk("SUN4V: virtual-devices devhandle[%x]\n",
-	       sun4v_vdev_devhandle);
+	printk("%s: Virtual Device Bus devhandle[%x]\n",
+	       dp->full_name, sun4v_vdev_devhandle);
 }
 
-unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
+unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node)
 {
+	struct property *prop;
 	unsigned int irq, reg;
-	int err, i;
+	int i;
 
-	err = prom_getproperty(dev_node, "interrupts",
-			       (char *) &irq, sizeof(irq));
-	if (err <= 0) {
+	prop = of_find_property(dev_node, "interrupts", NULL);
+	if (!prop) {
 		printk("VDEV: Cannot get \"interrupts\" "
-		       "property for OBP node %x\n", dev_node);
+		       "property for OBP node %s\n",
+		       dev_node->full_name);
 		return 0;
 	}
+	irq = *(unsigned int *) prop->value;
 
-	err = prom_getproperty(dev_node, "reg",
-			       (char *) &reg, sizeof(reg));
-	if (err <= 0) {
+	prop = of_find_property(dev_node, "reg", NULL);
+	if (!prop) {
 		printk("VDEV: Cannot get \"reg\" "
-		       "property for OBP node %x\n", dev_node);
+		       "property for OBP node %s\n",
+		       dev_node->full_name);
 		return 0;
 	}
+	reg = *(unsigned int *) prop->value;
 
 	for (i = 0; i < vdev_num_intmap; i++) {
-		if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) &&
-		    vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) {
+		if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) &&
+		    vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) {
 			irq = vdev_intmap[i].cinterrupt;
 			break;
 		}
@@ -153,11 +119,11 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
 
 	if (i == vdev_num_intmap) {
 		printk("VDEV: No matching interrupt map entry "
-		       "for OBP node %x\n", dev_node);
+		       "for OBP node %s\n", dev_node->full_name);
 		return 0;
 	}
 
-	return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
+	return sun4v_build_irq(sun4v_vdev_devhandle, irq);
 }
 
 static const char *cpu_mid_prop(void)
@@ -167,38 +133,44 @@ static const char *cpu_mid_prop(void)
 	return "portid";
 }
 
-static int get_cpu_mid(int prom_node)
+static int get_cpu_mid(struct device_node *dp)
 {
+	struct property *prop;
+
 	if (tlb_type == hypervisor) {
-		struct linux_prom64_registers reg;
+		struct linux_prom64_registers *reg;
+		int len;
 
-		if (prom_getproplen(prom_node, "cpuid") == 4)
-			return prom_getintdefault(prom_node, "cpuid", 0);
+		prop = of_find_property(dp, "cpuid", &len);
+		if (prop && len == 4)
+			return *(int *) prop->value;
 
-		prom_getproperty(prom_node, "reg", (char *) &reg, sizeof(reg));
-		return (reg.phys_addr >> 32) & 0x0fffffffUL;
+		prop = of_find_property(dp, "reg", NULL);
+		reg = prop->value;
+		return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
 	} else {
 		const char *prop_name = cpu_mid_prop();
 
-		return prom_getintdefault(prom_node, prop_name, 0);
+		prop = of_find_property(dp, prop_name, NULL);
+		if (prop)
+			return *(int *) prop->value;
+		return 0;
 	}
 }
 
-static int check_cpu_node(int nd, int *cur_inst,
-			  int (*compare)(int, int, void *), void *compare_arg,
-			  int *prom_node, int *mid)
+static int check_cpu_node(struct device_node *dp, int *cur_inst,
+			  int (*compare)(struct device_node *, int, void *),
+			  void *compare_arg,
+			  struct device_node **dev_node, int *mid)
 {
-	char node_str[128];
-
-	prom_getstring(nd, "device_type", node_str, sizeof(node_str));
-	if (strcmp(node_str, "cpu"))
+	if (strcmp(dp->type, "cpu"))
 		return -ENODEV;
 
-	if (!compare(nd, *cur_inst, compare_arg)) {
-		if (prom_node)
-			*prom_node = nd;
+	if (!compare(dp, *cur_inst, compare_arg)) {
+		if (dev_node)
+			*dev_node = dp;
 		if (mid)
-			*mid = get_cpu_mid(nd);
+			*mid = get_cpu_mid(dp);
 		return 0;
 	}
 
@@ -207,25 +179,18 @@ static int check_cpu_node(int nd, int *cur_inst,
 	return -ENODEV;
 }
 
-static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
-			 int *prom_node, int *mid)
+static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
+			 void *compare_arg,
+			 struct device_node **dev_node, int *mid)
 {
-	int nd, cur_inst, err;
+	struct device_node *dp;
+	int cur_inst;
 
-	nd = prom_root_node;
 	cur_inst = 0;
-
-	err = check_cpu_node(nd, &cur_inst,
-			     compare, compare_arg,
-			     prom_node, mid);
-	if (err == 0)
-		return 0;
-
-	nd = prom_getchild(nd);
-	while ((nd = prom_getsibling(nd)) != 0) {
-		err = check_cpu_node(nd, &cur_inst,
-				     compare, compare_arg,
-				     prom_node, mid);
+	for_each_node_by_type(dp, "cpu") {
+		int err = check_cpu_node(dp, &cur_inst,
+					 compare, compare_arg,
+					 dev_node, mid);
 		if (err == 0)
 			return 0;
 	}
@@ -233,7 +198,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
 	return -ENODEV;
 }
 
-static int cpu_instance_compare(int nd, int instance, void *_arg)
+static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
 {
 	int desired_instance = (int) (long) _arg;
 
@@ -242,27 +207,27 @@ static int cpu_instance_compare(int nd, int instance, void *_arg)
 	return -ENODEV;
 }
 
-int cpu_find_by_instance(int instance, int *prom_node, int *mid)
+int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
 {
 	return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
-			     prom_node, mid);
+			     dev_node, mid);
 }
 
-static int cpu_mid_compare(int nd, int instance, void *_arg)
+static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
 {
 	int desired_mid = (int) (long) _arg;
 	int this_mid;
 
-	this_mid = get_cpu_mid(nd);
+	this_mid = get_cpu_mid(dp);
 	if (this_mid == desired_mid)
 		return 0;
 	return -ENODEV;
 }
 
-int cpu_find_by_mid(int mid, int *prom_node)
+int cpu_find_by_mid(int mid, struct device_node **dev_node)
 {
 	return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
-			     prom_node, NULL);
+			     dev_node, NULL);
 }
 
 void __init device_scan(void)
@@ -274,50 +239,47 @@ void __init device_scan(void)
 
 #ifndef CONFIG_SMP
 	{
-		int err, cpu_node, def;
+		struct device_node *dp;
+		int err, def;
 
-		err = cpu_find_by_instance(0, &cpu_node, NULL);
+		err = cpu_find_by_instance(0, &dp, NULL);
 		if (err) {
 			prom_printf("No cpu nodes, cannot continue\n");
 			prom_halt();
 		}
-		cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
-							    "clock-frequency",
-							    0);
+		cpu_data(0).clock_tick =
+			of_getintprop_default(dp, "clock-frequency", 0);
 
 		def = ((tlb_type == hypervisor) ?
 		       (8 * 1024) :
 		       (16 * 1024));
-		cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
-							     "dcache-size",
-							     def);
+		cpu_data(0).dcache_size = of_getintprop_default(dp,
+								"dcache-size",
+								def);
 
 		def = 32;
 		cpu_data(0).dcache_line_size =
-			prom_getintdefault(cpu_node, "dcache-line-size",
-					   def);
+			of_getintprop_default(dp, "dcache-line-size", def);
 
 		def = 16 * 1024;
-		cpu_data(0).icache_size = prom_getintdefault(cpu_node,
-							     "icache-size",
-							     def);
+		cpu_data(0).icache_size = of_getintprop_default(dp,
+								"icache-size",
+								def);
 
 		def = 32;
 		cpu_data(0).icache_line_size =
-			prom_getintdefault(cpu_node, "icache-line-size",
-					   def);
+			of_getintprop_default(dp, "icache-line-size", def);
 
 		def = ((tlb_type == hypervisor) ?
 		       (3 * 1024 * 1024) :
 		       (4 * 1024 * 1024));
-		cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
-							     "ecache-size",
-							     def);
+		cpu_data(0).ecache_size = of_getintprop_default(dp,
+								"ecache-size",
+								def);
 
 		def = 64;
 		cpu_data(0).ecache_line_size =
-			prom_getintdefault(cpu_node, "ecache-line-size",
-					   def);
+			of_getintprop_default(dp, "ecache-line-size", def);
 		printk("CPU[0]: Caches "
 		       "D[sz(%d):line_sz(%d)] "
 		       "I[sz(%d):line_sz(%d)] "
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index c69504aa638f..98e0a8cbeecd 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -269,10 +269,6 @@ EXPORT_SYMBOL(ebus_dma_enable);
 
 struct linux_ebus *ebus_chain = NULL;
 
-#ifdef CONFIG_SUN_AUXIO
-extern void auxio_probe(void);
-#endif
-
 static inline void *ebus_alloc(size_t size)
 {
 	void *mem;
@@ -283,77 +279,55 @@ static inline void *ebus_alloc(size_t size)
 	return mem;
 }
 
-static void __init ebus_ranges_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_ranges = 0;
-	success = prom_getproperty(ebus->prom_node, "ranges",
-				   (char *)ebus->ebus_ranges,
-				   sizeof(ebus->ebus_ranges));
-	if (success != -1)
-		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
-}
-
-static void __init ebus_intmap_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_intmap = 0;
-	success = prom_getproperty(ebus->prom_node, "interrupt-map",
-				   (char *)ebus->ebus_intmap,
-				   sizeof(ebus->ebus_intmap));
-	if (success == -1)
-		return;
-
-	ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
-
-	success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
-				   (char *)&ebus->ebus_intmask,
-				   sizeof(ebus->ebus_intmask));
-	if (success == -1) {
-		prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
-		prom_halt();
-	}
-}
-
 int __init ebus_intmap_match(struct linux_ebus *ebus,
 			     struct linux_prom_registers *reg,
 			     int *interrupt)
 {
+	struct linux_prom_ebus_intmap *imap;
+	struct linux_prom_ebus_intmask *imask;
 	unsigned int hi, lo, irq;
-	int i;
+	int i, len, n_imap;
+
+	imap = of_get_property(ebus->prom_node, "interrupt-map", &len);
+	if (!imap)
+		return 0;
+	n_imap = len / sizeof(imap[0]);
 
-	if (!ebus->num_ebus_intmap)
+	imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL);
+	if (!imask)
 		return 0;
 
-	hi = reg->which_io & ebus->ebus_intmask.phys_hi;
-	lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
-	irq = *interrupt & ebus->ebus_intmask.interrupt;
-	for (i = 0; i < ebus->num_ebus_intmap; i++) {
-		if ((ebus->ebus_intmap[i].phys_hi == hi) &&
-		    (ebus->ebus_intmap[i].phys_lo == lo) &&
-		    (ebus->ebus_intmap[i].interrupt == irq)) {
-			*interrupt = ebus->ebus_intmap[i].cinterrupt;
+	hi = reg->which_io & imask->phys_hi;
+	lo = reg->phys_addr & imask->phys_lo;
+	irq = *interrupt & imask->interrupt;
+	for (i = 0; i < n_imap; i++) {
+		if ((imap[i].phys_hi == hi) &&
+		    (imap[i].phys_lo == lo) &&
+		    (imap[i].interrupt == irq)) {
+			*interrupt = imap[i].cinterrupt;
 			return 0;
 		}
 	}
 	return -1;
 }
 
-void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
-			    struct linux_ebus_child *dev, int non_standard_regs)
+void __init fill_ebus_child(struct device_node *dp,
+			    struct linux_prom_registers *preg,
+			    struct linux_ebus_child *dev,
+			    int non_standard_regs)
 {
-	int regs[PROMREG_MAX];
-	int irqs[PROMREG_MAX];
+	int *regs;
+	int *irqs;
 	int i, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
-	printk(" (%s)", dev->prom_name);
+	dev->prom_node = dp;
+	printk(" (%s)", dp->name);
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	dev->num_addrs = len / sizeof(regs[0]);
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs)
+		dev->num_addrs = 0;
+	else
+		dev->num_addrs = len / sizeof(regs[0]);
 
 	if (non_standard_regs) {
 		/* This is to handle reg properties which are not
@@ -370,21 +344,21 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
 			int rnum = regs[i];
 			if (rnum >= dev->parent->num_addrs) {
 				prom_printf("UGH: property for %s was %d, need < %d\n",
-					    dev->prom_name, len, dev->parent->num_addrs);
-				panic(__FUNCTION__);
+					    dp->name, len, dev->parent->num_addrs);
+				prom_halt();
 			}
 			dev->resource[i].start = dev->parent->resource[i].start;
 			dev->resource[i].end = dev->parent->resource[i].end;
 			dev->resource[i].flags = IORESOURCE_MEM;
-			dev->resource[i].name = dev->prom_name;
+			dev->resource[i].name = dp->name;
 		}
 	}
 
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	irqs = of_get_property(dp, "interrupts", &len);
+	if (!irqs) {
 		dev->num_irqs = 0;
 		/*
 		 * Oh, well, some PROMs don't export interrupts
@@ -392,8 +366,8 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
 		 *
 		 * Be smart about PS/2 keyboard and mouse.
 		 */
-		if (!strcmp(dev->parent->prom_name, "8042")) {
-			if (!strcmp(dev->prom_name, "kb_ps2")) {
+		if (!strcmp(dev->parent->prom_node->name, "8042")) {
+			if (!strcmp(dev->prom_node->name, "kb_ps2")) {
 				dev->num_irqs = 1;
 				dev->irqs[0] = dev->parent->irqs[0];
 			} else {
@@ -423,32 +397,32 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
 
 static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
 {
-	if (!strcmp(dev->prom_name, "i2c") ||
-	    !strcmp(dev->prom_name, "SUNW,lombus"))
+	if (!strcmp(dev->prom_node->name, "i2c") ||
+	    !strcmp(dev->prom_node->name, "SUNW,lombus"))
 		return 1;
 	return 0;
 }
 
-void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
+void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
 {
-	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_prom_registers *regs;
 	struct linux_ebus_child *child;
-	int irqs[PROMINTR_MAX];
+	int *irqs;
 	int i, n, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
-	printk(" [%s", dev->prom_name);
+	dev->prom_node = dp;
+
+	printk(" [%s", dp->name);
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	if (len == -1) {
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs) {
 		dev->num_addrs = 0;
 		goto probe_interrupts;
 	}
 
 	if (len % sizeof(struct linux_prom_registers)) {
 		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
-			    dev->prom_name, len,
+			    dev->prom_node->name, len,
 			    (int)sizeof(struct linux_prom_registers));
 		prom_halt();
 	}
@@ -466,7 +440,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 		dev->resource[i].end    =
 			(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
 		dev->resource[i].flags  = IORESOURCE_MEM;
-		dev->resource[i].name   = dev->prom_name;
+		dev->resource[i].name   = dev->prom_node->name;
 		request_resource(&dev->bus->self->resource[n],
 				 &dev->resource[i]);
 	}
@@ -475,8 +449,8 @@ probe_interrupts:
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	irqs = of_get_property(dp, "interrupts", &len);
+	if (!irqs) {
 		dev->num_irqs = 0;
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
@@ -497,7 +471,18 @@ probe_interrupts:
 		}
 	}
 
-	if ((node = prom_getchild(node))) {
+	dev->ofdev.node = dp;
+	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+	dev->ofdev.dev.bus = &ebus_bus_type;
+	strcpy(dev->ofdev.dev.bus_id, dp->path_component_name);
+
+	/* Register with core */
+	if (of_device_register(&dev->ofdev) != 0)
+		printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+		       dev->ofdev.dev.bus_id);
+
+	dp = dp->child;
+	if (dp) {
 		printk(" ->");
 		dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -505,18 +490,18 @@ probe_interrupts:
 		child->next = NULL;
 		child->parent = dev;
 		child->bus = dev->bus;
-		fill_ebus_child(node, &regs[0],
-				child, child_regs_nonstandard(dev));
+		fill_ebus_child(dp, regs, child,
+				child_regs_nonstandard(dev));
 
-		while ((node = prom_getsibling(node)) != 0) {
+		while ((dp = dp->sibling) != NULL) {
 			child->next = ebus_alloc(sizeof(struct linux_ebus_child));
 
 			child = child->next;
 			child->next = NULL;
 			child->parent = dev;
 			child->bus = dev->bus;
-			fill_ebus_child(node, &regs[0],
-					child, child_regs_nonstandard(dev));
+			fill_ebus_child(dp, regs, child,
+					child_regs_nonstandard(dev));
 		}
 	}
 	printk("]");
@@ -543,7 +528,8 @@ void __init ebus_init(void)
 	struct linux_ebus *ebus;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
-	int nd, ebusnd, is_rio;
+	struct device_node *dp;
+	int is_rio;
 	int num_ebus = 0;
 
 	pdev = find_next_ebus(NULL, &is_rio);
@@ -553,20 +539,22 @@ void __init ebus_init(void)
 	}
 
 	cookie = pdev->sysdata;
-	ebusnd = cookie->prom_node;
+	dp = cookie->prom_node;
 
 	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = NULL;
 	ebus->is_rio = is_rio;
 
-	while (ebusnd) {
+	while (dp) {
+		struct device_node *child;
+
 		/* SUNW,pci-qfe uses four empty ebuses on it.
 		   I think we should not consider them here,
 		   as they have half of the properties this
 		   code expects and once we do PCI hot-plug,
 		   we'd have to tweak with the ebus_chain
 		   in the runtime after initialization. -jj */
-		if (!prom_getchild (ebusnd)) {
+		if (!dp->child) {
 			pdev = find_next_ebus(pdev, &is_rio);
 			if (!pdev) {
 				if (ebus == ebus_chain) {
@@ -578,22 +566,29 @@ void __init ebus_init(void)
 			}
 			ebus->is_rio = is_rio;
 			cookie = pdev->sysdata;
-			ebusnd = cookie->prom_node;
+			dp = cookie->prom_node;
 			continue;
 		}
 		printk("ebus%d:", num_ebus);
 
-		prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
 		ebus->index = num_ebus;
-		ebus->prom_node = ebusnd;
+		ebus->prom_node = dp;
 		ebus->self = pdev;
 		ebus->parent = pbm = cookie->pbm;
 
-		ebus_ranges_init(ebus);
-		ebus_intmap_init(ebus);
+		ebus->ofdev.node = dp;
+		ebus->ofdev.dev.parent = &pdev->dev;
+		ebus->ofdev.dev.bus = &ebus_bus_type;
+		strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name);
 
-		nd = prom_getchild(ebusnd);
-		if (!nd)
+		/* Register with core */
+		if (of_device_register(&ebus->ofdev) != 0)
+			printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+			       ebus->ofdev.dev.bus_id);
+
+
+		child = dp->child;
+		if (!child)
 			goto next_ebus;
 
 		ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
@@ -602,16 +597,16 @@ void __init ebus_init(void)
 		dev->next = NULL;
 		dev->children = NULL;
 		dev->bus = ebus;
-		fill_ebus_device(nd, dev);
+		fill_ebus_device(child, dev);
 
-		while ((nd = prom_getsibling(nd)) != 0) {
+		while ((child = child->sibling) != NULL) {
 			dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
 
 			dev = dev->next;
 			dev->next = NULL;
 			dev->children = NULL;
 			dev->bus = ebus;
-			fill_ebus_device(nd, dev);
+			fill_ebus_device(child, dev);
 		}
 
 	next_ebus:
@@ -622,7 +617,7 @@ void __init ebus_init(void)
 			break;
 
 		cookie = pdev->sysdata;
-		ebusnd = cookie->prom_node;
+		dp = cookie->prom_node;
 
 		ebus->next = ebus_alloc(sizeof(struct linux_ebus));
 		ebus = ebus->next;
@@ -631,8 +626,4 @@ void __init ebus_init(void)
 		++num_ebus;
 	}
 	pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */
-
-#ifdef CONFIG_SUN_AUXIO
-	auxio_probe();
-#endif
 }
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 6d0b3ed77a02..be85ce2a4ad9 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -22,6 +22,7 @@
 #include <asm/estate.h>
 #include <asm/auxio.h>
 #include <asm/sfafsr.h>
+#include <asm/pil.h>
 
 #define curptr      g6
 
@@ -431,20 +432,16 @@ do_ivec:
 	membar		#Sync
 
 	sethi		%hi(ivector_table), %g2
-	sllx		%g3, 5, %g3
+	sllx		%g3, 3, %g3
 	or		%g2, %lo(ivector_table), %g2
 	add		%g2, %g3, %g3
-	ldub		[%g3 + 0x04], %g4	/* pil */
-	mov		1, %g2
-	sllx		%g2, %g4, %g2
-	sllx		%g4, 2, %g4
 
 	TRAP_LOAD_IRQ_WORK(%g6, %g1)
 
-	lduw		[%g6 + %g4], %g5	/* g5 = irq_work(cpu, pil) */
+	lduw		[%g6], %g5		/* g5 = irq_work(cpu) */
 	stw		%g5, [%g3 + 0x00]	/* bucket->irq_chain = g5 */
-	stw		%g3, [%g6 + %g4]	/* irq_work(cpu, pil) = bucket */
-	wr		%g2, 0x0, %set_softint
+	stw		%g3, [%g6]		/* irq_work(cpu) = bucket */
+	wr		%g0, 1 << PIL_DEVICE_IRQ, %set_softint
 	retry
 do_ivec_xcall:
 	mov		0x50, %g1
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 11e645c9ec50..31e0fbb0d82c 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/bootmem.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -33,6 +34,7 @@
 #include <asm/iommu.h>
 #include <asm/upa.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
 #include <asm/starfire.h>
@@ -42,10 +44,6 @@
 #include <asm/auxio.h>
 #include <asm/head.h>
 
-#ifdef CONFIG_SMP
-static void distribute_irqs(void);
-#endif
-
 /* UPA nodes send interrupt packet to UltraSparc with first data reg
  * value low 5 (7 on Starfire) bits holding the IRQ identifier being
  * delivered.  We must translate this into a non-vector IRQ so we can
@@ -57,10 +55,29 @@ static void distribute_irqs(void);
  * The IVEC handler does not need to act atomically, the PIL dispatch
  * code uses CAS to get an atomic snapshot of the list and clear it
  * at the same time.
+ *
+ * If you make changes to ino_bucket, please update hand coded assembler
+ * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
  */
+struct ino_bucket {
+	/* Next handler in per-CPU IRQ worklist.  We know that
+	 * bucket pointers have the high 32-bits clear, so to
+	 * save space we only store the bits we need.
+	 */
+/*0x00*/unsigned int irq_chain;
 
+	/* Virtual interrupt number assigned to this INO.  */
+/*0x04*/unsigned int virt_irq;
+};
+
+#define NUM_IVECS	(IMAP_INR + 1)
 struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
 
+#define __irq_ino(irq) \
+        (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0])
+#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
+#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
+
 /* This has to be in the main kernel image, it cannot be
  * turned into per-cpu data.  The reason is that the main
  * kernel image is locked into the TLB and this structure
@@ -68,71 +85,82 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY
  * access to this structure takes a TLB miss it could cause
  * the 5-level sparc v9 trap stack to overflow.
  */
-struct irq_work_struct {
-	unsigned int	irq_worklists[16];
-};
-struct irq_work_struct __irq_work[NR_CPUS];
-#define irq_work(__cpu, __pil)	&(__irq_work[(__cpu)].irq_worklists[(__pil)])
+#define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)
 
-static struct irqaction *irq_action[NR_IRQS+1];
+static unsigned int virt_to_real_irq_table[NR_IRQS];
+static unsigned char virt_irq_cur = 1;
 
-/* This only synchronizes entities which modify IRQ handler
- * state and some selected user-level spots that want to
- * read things in the table.  IRQ handler processing orders
- * its' accesses such that no locking is needed.
- */
-static DEFINE_SPINLOCK(irq_action_lock);
+static unsigned char virt_irq_alloc(unsigned int real_irq)
+{
+	unsigned char ent;
+
+	BUILD_BUG_ON(NR_IRQS >= 256);
+
+	ent = virt_irq_cur;
+	if (ent >= NR_IRQS) {
+		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
+		return 0;
+	}
+
+	virt_irq_cur = ent + 1;
+	virt_to_real_irq_table[ent] = real_irq;
 
-static void register_irq_proc (unsigned int irq);
+	return ent;
+}
+
+#if 0 /* Currently unused. */
+static unsigned char real_to_virt_irq(unsigned int real_irq)
+{
+	struct ino_bucket *bucket = __bucket(real_irq);
+
+	return bucket->virt_irq;
+}
+#endif
+
+static unsigned int virt_to_real_irq(unsigned char virt_irq)
+{
+	return virt_to_real_irq_table[virt_irq];
+}
 
 /*
- * Upper 2b of irqaction->flags holds the ino.
- * irqaction->mask holds the smp affinity information.
+ * /proc/interrupts printing:
  */
-#define put_ino_in_irqaction(action, irq) \
-	action->flags &= 0xffffffffffffUL; \
-	if (__bucket(irq) == &pil0_dummy_bucket) \
-		action->flags |= 0xdeadUL << 48;  \
-	else \
-		action->flags |= __irq_ino(irq) << 48;
-#define get_ino_in_irqaction(action)	(action->flags >> 48)
-
-#define put_smpaff_in_irqaction(action, smpaff)	(action)->mask = (smpaff)
-#define get_smpaff_in_irqaction(action) 	((action)->mask)
 
 int show_interrupts(struct seq_file *p, void *v)
 {
+	int i = *(loff_t *) v, j;
+	struct irqaction * action;
 	unsigned long flags;
-	int i = *(loff_t *) v;
-	struct irqaction *action;
-#ifdef CONFIG_SMP
-	int j;
-#endif
 
-	spin_lock_irqsave(&irq_action_lock, flags);
-	if (i <= NR_IRQS) {
-		if (!(action = *(i + irq_action)))
-			goto out_unlock;
-		seq_printf(p, "%3d: ", i);
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
+
+	if (i < NR_IRQS) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
+		if (!action)
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for_each_online_cpu(j) {
-			seq_printf(p, "%10u ",
-				   kstat_cpu(j).irqs[i]);
-		}
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		seq_printf(p, " %s:%lx", action->name,
-			   get_ino_in_irqaction(action));
-		for (action = action->next; action; action = action->next) {
-			seq_printf(p, ", %s:%lx", action->name,
-				   get_ino_in_irqaction(action));
-		}
+		seq_printf(p, " %9s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next)
+			seq_printf(p, ", %s", action->name);
+
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
-out_unlock:
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-
 	return 0;
 }
 
@@ -173,556 +201,365 @@ static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
 	return tid;
 }
 
-/* Now these are always passed a true fully specified sun4u INO. */
-void enable_irq(unsigned int irq)
-{
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long imap, cpuid;
-
-	imap = bucket->imap;
-	if (imap == 0UL)
-		return;
-
-	preempt_disable();
+struct irq_handler_data {
+	unsigned long	iclr;
+	unsigned long	imap;
 
-	/* This gets the physical processor ID, even on uniprocessor,
-	 * so we can always program the interrupt target correctly.
-	 */
-	cpuid = real_hard_smp_processor_id();
-
-	if (tlb_type == hypervisor) {
-		unsigned int ino = __irq_ino(irq);
-		int err;
-
-		err = sun4v_intr_settarget(ino, cpuid);
-		if (err != HV_EOK)
-			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
-			       ino, cpuid, err);
-		err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
-		if (err != HV_EOK)
-			printk("sun4v_intr_setenabled(%x): err(%d)\n",
-			       ino, err);
-	} else {
-		unsigned int tid = sun4u_compute_tid(imap, cpuid);
-
-		/* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
-		 * of this SYSIO's preconfigured IGN in the SYSIO Control
-		 * Register, the hardware just mirrors that value here.
-		 * However for Graphics and UPA Slave devices the full
-		 * IMAP_INR field can be set by the programmer here.
-		 *
-		 * Things like FFB can now be handled via the new IRQ
-		 * mechanism.
-		 */
-		upa_writel(tid | IMAP_VALID, imap);
-	}
-
-	preempt_enable();
-}
+	void		(*pre_handler)(unsigned int, void *, void *);
+	void		*pre_handler_arg1;
+	void		*pre_handler_arg2;
+};
 
-/* This now gets passed true ino's as well. */
-void disable_irq(unsigned int irq)
+static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long imap;
-
-	imap = bucket->imap;
-	if (imap != 0UL) {
-		if (tlb_type == hypervisor) {
-			unsigned int ino = __irq_ino(irq);
-			int err;
-
-			err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
-			if (err != HV_EOK)
-				printk("sun4v_intr_setenabled(%x): "
-				       "err(%d)\n", ino, err);
-		} else {
-			u32 tmp;
-
-			/* NOTE: We do not want to futz with the IRQ clear registers
-			 *       and move the state to IDLE, the SCSI code does call
-			 *       disable_irq() to assure atomicity in the queue cmd
-			 *       SCSI adapter driver code.  Thus we'd lose interrupts.
-			 */
-			tmp = upa_readl(imap);
-			tmp &= ~IMAP_VALID;
-			upa_writel(tmp, imap);
-		}
-	}
-}
+	unsigned int real_irq = virt_to_real_irq(virt_irq);
+	struct ino_bucket *bucket = NULL;
 
-/* The timer is the one "weird" interrupt which is generated by
- * the CPU %tick register and not by some normal vectored interrupt
- * source.  To handle this special case, we use this dummy INO bucket.
- */
-static struct irq_desc pil0_dummy_desc;
-static struct ino_bucket pil0_dummy_bucket = {
-	.irq_info	=	&pil0_dummy_desc,
-};
+	if (likely(real_irq))
+		bucket = __bucket(real_irq);
 
-static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup,
-			    unsigned long iclr, unsigned long imap,
-			    struct ino_bucket *bucket)
-{
-	prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> "
-		    "(%d:%d:%016lx:%016lx), halting...\n",
-		    ino, bucket->pil, bucket->iclr, bucket->imap,
-		    pil, inofixup, iclr, imap);
-	prom_halt();
+	return bucket;
 }
 
-unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
+#ifdef CONFIG_SMP
+static int irq_choose_cpu(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket;
-	int ino;
+	cpumask_t mask = irq_affinity[virt_irq];
+	int cpuid;
 
-	if (pil == 0) {
-		if (iclr != 0UL || imap != 0UL) {
-			prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n",
-				    iclr, imap);
-			prom_halt();
-		}
-		return __irq(&pil0_dummy_bucket);
-	}
+	if (cpus_equal(mask, CPU_MASK_ALL)) {
+		static int irq_rover;
+		static DEFINE_SPINLOCK(irq_rover_lock);
+		unsigned long flags;
 
-	BUG_ON(tlb_type == hypervisor);
+		/* Round-robin distribution... */
+	do_round_robin:
+		spin_lock_irqsave(&irq_rover_lock, flags);
 
-	/* RULE: Both must be specified in all other cases. */
-	if (iclr == 0UL || imap == 0UL) {
-		prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
-			    pil, inofixup, iclr, imap);
-		prom_halt();
-	}
-	
-	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
-	if (ino > NUM_IVECS) {
-		prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
-			    ino, pil, inofixup, iclr, imap);
-		prom_halt();
-	}
+		while (!cpu_online(irq_rover)) {
+			if (++irq_rover >= NR_CPUS)
+				irq_rover = 0;
+		}
+		cpuid = irq_rover;
+		do {
+			if (++irq_rover >= NR_CPUS)
+				irq_rover = 0;
+		} while (!cpu_online(irq_rover));
 
-	bucket = &ivector_table[ino];
-	if (bucket->flags & IBF_ACTIVE)
-		build_irq_error("IRQ: Trying to build active INO bucket.\n",
-				ino, pil, inofixup, iclr, imap, bucket);
+		spin_unlock_irqrestore(&irq_rover_lock, flags);
+	} else {
+		cpumask_t tmp;
 
-	if (bucket->irq_info) {
-		if (bucket->imap != imap || bucket->iclr != iclr)
-			build_irq_error("IRQ: Trying to reinit INO bucket.\n",
-					ino, pil, inofixup, iclr, imap, bucket);
+		cpus_and(tmp, cpu_online_map, mask);
 
-		goto out;
-	}
+		if (cpus_empty(tmp))
+			goto do_round_robin;
 
-	bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
-	if (!bucket->irq_info) {
-		prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
-		prom_halt();
+		cpuid = first_cpu(tmp);
 	}
 
-	/* Ok, looks good, set it up.  Don't touch the irq_chain or
-	 * the pending flag.
-	 */
-	bucket->imap  = imap;
-	bucket->iclr  = iclr;
-	bucket->pil   = pil;
-	bucket->flags = 0;
-
-out:
-	return __irq(bucket);
+	return cpuid;
+}
+#else
+static int irq_choose_cpu(unsigned int virt_irq)
+{
+	return real_hard_smp_processor_id();
 }
+#endif
 
-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
+static void sun4u_irq_enable(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket;
-	unsigned long sysino;
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
 
-	sysino = sun4v_devino_to_sysino(devhandle, devino);
+	if (likely(data)) {
+		unsigned long cpuid, imap;
+		unsigned int tid;
 
-	bucket = &ivector_table[sysino];
+		cpuid = irq_choose_cpu(virt_irq);
+		imap = data->imap;
 
-	/* Catch accidental accesses to these things.  IMAP/ICLR handling
-	 * is done by hypervisor calls on sun4v platforms, not by direct
-	 * register accesses.
-	 *
-	 * But we need to make them look unique for the disable_irq() logic
-	 * in free_irq().
-	 */
-	bucket->imap = ~0UL - sysino;
-	bucket->iclr = ~0UL - sysino;
+		tid = sun4u_compute_tid(imap, cpuid);
 
-	bucket->pil = pil;
-	bucket->flags = flags;
-
-	bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
-	if (!bucket->irq_info) {
-		prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
-		prom_halt();
+		upa_writel(tid | IMAP_VALID, imap);
 	}
-
-	return __irq(bucket);
 }
 
-static void atomic_bucket_insert(struct ino_bucket *bucket)
+static void sun4u_irq_disable(unsigned int virt_irq)
 {
-	unsigned long pstate;
-	unsigned int *ent;
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
 
-	__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
-	__asm__ __volatile__("wrpr %0, %1, %%pstate"
-			     : : "r" (pstate), "i" (PSTATE_IE));
-	ent = irq_work(smp_processor_id(), bucket->pil);
-	bucket->irq_chain = *ent;
-	*ent = __irq(bucket);
-	__asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
-}
-
-static int check_irq_sharing(int pil, unsigned long irqflags)
-{
-	struct irqaction *action, *tmp;
+	if (likely(data)) {
+		unsigned long imap = data->imap;
+		u32 tmp = upa_readl(imap);
 
-	action = *(irq_action + pil);
-	if (action) {
-		if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-			for (tmp = action; tmp->next; tmp = tmp->next)
-				;
-		} else {
-			return -EBUSY;
-		}
+		tmp &= ~IMAP_VALID;
+		upa_writel(tmp, imap);
 	}
-	return 0;
 }
 
-static void append_irq_action(int pil, struct irqaction *action)
+static void sun4u_irq_end(unsigned int virt_irq)
 {
-	struct irqaction **pp = irq_action + pil;
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
 
-	while (*pp)
-		pp = &((*pp)->next);
-	*pp = action;
+	if (likely(data))
+		upa_writel(ICLR_IDLE, data->iclr);
 }
 
-static struct irqaction *get_action_slot(struct ino_bucket *bucket)
+static void sun4v_irq_enable(unsigned int virt_irq)
 {
-	struct irq_desc *desc = bucket->irq_info;
-	int max_irq, i;
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
 
-	max_irq = 1;
-	if (bucket->flags & IBF_PCI)
-		max_irq = MAX_IRQ_DESC_ACTION;
-	for (i = 0; i < max_irq; i++) {
-		struct irqaction *p = &desc->action[i];
-		u32 mask = (1 << i);
+	if (likely(bucket)) {
+		unsigned long cpuid;
+		int err;
 
-		if (desc->action_active_mask & mask)
-			continue;
+		cpuid = irq_choose_cpu(virt_irq);
 
-		desc->action_active_mask |= mask;
-		return p;
+		err = sun4v_intr_settarget(ino, cpuid);
+		if (err != HV_EOK)
+			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
+			       ino, cpuid, err);
+		err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setenabled(%x): err(%d)\n",
+			       ino, err);
 	}
-	return NULL;
 }
 
-int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, const char *name, void *dev_id)
+static void sun4v_irq_disable(unsigned int virt_irq)
 {
-	struct irqaction *action;
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long flags;
-	int pending = 0;
-
-	if (unlikely(!handler))
-		return -EINVAL;
-
-	if (unlikely(!bucket->irq_info))
-		return -ENODEV;
-
-	if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) {
-		/*
-	 	 * This function might sleep, we want to call it first,
-	 	 * outside of the atomic block. In SA_STATIC_ALLOC case,
-		 * random driver's kmalloc will fail, but it is safe.
-		 * If already initialized, random driver will not reinit.
-	 	 * Yes, this might clear the entropy pool if the wrong
-	 	 * driver is attempted to be loaded, without actually
-	 	 * installing a new handler, but is this really a problem,
-	 	 * only the sysadmin is able to do this.
-	 	 */
-		rand_initialize_irq(irq);
-	}
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
 
-	spin_lock_irqsave(&irq_action_lock, flags);
-
-	if (check_irq_sharing(bucket->pil, irqflags)) {
-		spin_unlock_irqrestore(&irq_action_lock, flags);
-		return -EBUSY;
-	}
-
-	action = get_action_slot(bucket);
-	if (!action) { 
-		spin_unlock_irqrestore(&irq_action_lock, flags);
-		return -ENOMEM;
-	}
+	if (likely(bucket)) {
+		int err;
 
-	bucket->flags |= IBF_ACTIVE;
-	pending = 0;
-	if (bucket != &pil0_dummy_bucket) {
-		pending = bucket->pending;
-		if (pending)
-			bucket->pending = 0;
+		err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setenabled(%x): "
+			       "err(%d)\n", ino, err);
 	}
+}
 
-	action->handler = handler;
-	action->flags = irqflags;
-	action->name = name;
-	action->next = NULL;
-	action->dev_id = dev_id;
-	put_ino_in_irqaction(action, irq);
-	put_smpaff_in_irqaction(action, CPU_MASK_NONE);
-
-	append_irq_action(bucket->pil, action);
+static void sun4v_irq_end(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
 
-	enable_irq(irq);
+	if (likely(bucket)) {
+		int err;
 
-	/* We ate the IVEC already, this makes sure it does not get lost. */
-	if (pending) {
-		atomic_bucket_insert(bucket);
-		set_softint(1 << bucket->pil);
+		err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setstate(%x): "
+			       "err(%d)\n", ino, err);
 	}
+}
 
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-
-	if (bucket != &pil0_dummy_bucket)
-		register_irq_proc(__irq_ino(irq));
+static void run_pre_handler(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
 
-#ifdef CONFIG_SMP
-	distribute_irqs();
-#endif
-	return 0;
+	if (likely(data->pre_handler)) {
+		data->pre_handler(__irq_ino(__irq(bucket)),
+				  data->pre_handler_arg1,
+				  data->pre_handler_arg2);
+	}
 }
 
-EXPORT_SYMBOL(request_irq);
+static struct hw_interrupt_type sun4u_irq = {
+	.typename	= "sun4u",
+	.enable		= sun4u_irq_enable,
+	.disable	= sun4u_irq_disable,
+	.end		= sun4u_irq_end,
+};
 
-static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id)
-{
-	struct ino_bucket *bucket = __bucket(irq);
-	struct irqaction *action, **pp;
+static struct hw_interrupt_type sun4u_irq_ack = {
+	.typename	= "sun4u+ack",
+	.enable		= sun4u_irq_enable,
+	.disable	= sun4u_irq_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4u_irq_end,
+};
 
-	pp = irq_action + bucket->pil;
-	action = *pp;
-	if (unlikely(!action))
-		return NULL;
+static struct hw_interrupt_type sun4v_irq = {
+	.typename	= "sun4v",
+	.enable		= sun4v_irq_enable,
+	.disable	= sun4v_irq_disable,
+	.end		= sun4v_irq_end,
+};
 
-	if (unlikely(!action->handler)) {
-		printk("Freeing free IRQ %d\n", bucket->pil);
-		return NULL;
-	}
+static struct hw_interrupt_type sun4v_irq_ack = {
+	.typename	= "sun4v+ack",
+	.enable		= sun4v_irq_enable,
+	.disable	= sun4v_irq_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4v_irq_end,
+};
 
-	while (action && action->dev_id != dev_id) {
-		pp = &action->next;
-		action = *pp;
-	}
+void irq_install_pre_handler(int virt_irq,
+			     void (*func)(unsigned int, void *, void *),
+			     void *arg1, void *arg2)
+{
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
 
-	if (likely(action))
-		*pp = action->next;
+	data->pre_handler = func;
+	data->pre_handler_arg1 = arg1;
+	data->pre_handler_arg2 = arg2;
 
-	return action;
+	desc->handler = (desc->handler == &sun4u_irq ?
+			 &sun4u_irq_ack : &sun4v_irq_ack);
 }
 
-void free_irq(unsigned int irq, void *dev_id)
+unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 {
-	struct irqaction *action;
 	struct ino_bucket *bucket;
-	unsigned long flags;
+	struct irq_handler_data *data;
+	irq_desc_t *desc;
+	int ino;
 
-	spin_lock_irqsave(&irq_action_lock, flags);
+	BUG_ON(tlb_type == hypervisor);
 
-	action = unlink_irq_action(irq, dev_id);
+	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
+	bucket = &ivector_table[ino];
+	if (!bucket->virt_irq) {
+		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+		irq_desc[bucket->virt_irq].handler = &sun4u_irq;
+	}
 
-	spin_unlock_irqrestore(&irq_action_lock, flags);
+	desc = irq_desc + bucket->virt_irq;
+	if (unlikely(desc->handler_data))
+		goto out;
 
-	if (unlikely(!action))
-		return;
+	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!data)) {
+		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
+		prom_halt();
+	}
+	desc->handler_data = data;
 
-	synchronize_irq(irq);
+	data->imap  = imap;
+	data->iclr  = iclr;
 
-	spin_lock_irqsave(&irq_action_lock, flags);
+out:
+	return bucket->virt_irq;
+}
 
-	bucket = __bucket(irq);
-	if (bucket != &pil0_dummy_bucket) {
-		struct irq_desc *desc = bucket->irq_info;
-		int ent, i;
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
+{
+	struct ino_bucket *bucket;
+	struct irq_handler_data *data;
+	unsigned long sysino;
+	irq_desc_t *desc;
 
-		for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {
-			struct irqaction *p = &desc->action[i];
+	BUG_ON(tlb_type != hypervisor);
 
-			if (p == action) {
-				desc->action_active_mask &= ~(1 << i);
-				break;
-			}
-		}
+	sysino = sun4v_devino_to_sysino(devhandle, devino);
+	bucket = &ivector_table[sysino];
+	if (!bucket->virt_irq) {
+		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+		irq_desc[bucket->virt_irq].handler = &sun4v_irq;
+	}
 
-		if (!desc->action_active_mask) {
-			unsigned long imap = bucket->imap;
-
-			/* This unique interrupt source is now inactive. */
-			bucket->flags &= ~IBF_ACTIVE;
-
-			/* See if any other buckets share this bucket's IMAP
-			 * and are still active.
-			 */
-			for (ent = 0; ent < NUM_IVECS; ent++) {
-				struct ino_bucket *bp = &ivector_table[ent];
-				if (bp != bucket	&&
-				    bp->imap == imap	&&
-				    (bp->flags & IBF_ACTIVE) != 0)
-					break;
-			}
+	desc = irq_desc + bucket->virt_irq;
+	if (unlikely(desc->handler_data))
+		goto out;
 
-			/* Only disable when no other sub-irq levels of
-			 * the same IMAP are active.
-			 */
-			if (ent == NUM_IVECS)
-				disable_irq(irq);
-		}
+	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!data)) {
+		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
+		prom_halt();
 	}
+	desc->handler_data = data;
 
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-}
+	/* Catch accidental accesses to these things.  IMAP/ICLR handling
+	 * is done by hypervisor calls on sun4v platforms, not by direct
+	 * register accesses.
+	 */
+	data->imap = ~0UL;
+	data->iclr = ~0UL;
 
-EXPORT_SYMBOL(free_irq);
+out:
+	return bucket->virt_irq;
+}
 
-#ifdef CONFIG_SMP
-void synchronize_irq(unsigned int irq)
+void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq)
 {
-	struct ino_bucket *bucket = __bucket(irq);
-
-#if 0
-	/* The following is how I wish I could implement this.
-	 * Unfortunately the ICLR registers are read-only, you can
-	 * only write ICLR_foo values to them.  To get the current
-	 * IRQ status you would need to get at the IRQ diag registers
-	 * in the PCI/SBUS controller and the layout of those vary
-	 * from one controller to the next, sigh... -DaveM
-	 */
-	unsigned long iclr = bucket->iclr;
-
-	while (1) {
-		u32 tmp = upa_readl(iclr);
-		
-		if (tmp == ICLR_TRANSMIT ||
-		    tmp == ICLR_PENDING) {
-			cpu_relax();
-			continue;
-		}
-		break;
-	}
-#else
-	/* So we have to do this with a INPROGRESS bit just like x86.  */
-	while (bucket->flags & IBF_INPROGRESS)
-		cpu_relax();
-#endif
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned long pstate;
+	unsigned int *ent;
+
+	__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
+	__asm__ __volatile__("wrpr %0, %1, %%pstate"
+			     : : "r" (pstate), "i" (PSTATE_IE));
+	ent = irq_work(smp_processor_id());
+	bucket->irq_chain = *ent;
+	*ent = __irq(bucket);
+	set_softint(1 << PIL_DEVICE_IRQ);
+	__asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
 }
-#endif /* CONFIG_SMP */
 
-static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)
+void ack_bad_irq(unsigned int virt_irq)
 {
-	struct irq_desc *desc = bp->irq_info;
-	unsigned char flags = bp->flags;
-	u32 action_mask, i;
-	int random;
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = 0xdeadbeef;
 
-	bp->flags |= IBF_INPROGRESS;
+	if (bucket)
+		ino = bucket - &ivector_table[0];
 
-	if (unlikely(!(flags & IBF_ACTIVE))) {
-		bp->pending = 1;
-		goto out;
-	}
-
-	if (desc->pre_handler)
-		desc->pre_handler(bp,
-				  desc->pre_handler_arg1,
-				  desc->pre_handler_arg2);
+	printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n",
+	       ino, virt_irq);
+}
 
-	action_mask = desc->action_active_mask;
-	random = 0;
-	for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {
-		struct irqaction *p = &desc->action[i];
-		u32 mask = (1 << i);
+#ifndef CONFIG_SMP
+extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
 
-		if (!(action_mask & mask))
-			continue;
+void timer_irq(int irq, struct pt_regs *regs)
+{
+	unsigned long clr_mask = 1 << irq;
+	unsigned long tick_mask = tick_ops->softint_mask;
 
-		action_mask &= ~mask;
+	if (get_softint() & tick_mask) {
+		irq = 0;
+		clr_mask = tick_mask;
+	}
+	clear_softint(clr_mask);
 
-		if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED)
-			random |= p->flags;
+	irq_enter();
 
-		if (!action_mask)
-			break;
-	}
-	if (bp->pil != 0) {
-		if (tlb_type == hypervisor) {
-			unsigned int ino = __irq_ino(bp);
-			int err;
-
-			err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
-			if (err != HV_EOK)
-				printk("sun4v_intr_setstate(%x): "
-				       "err(%d)\n", ino, err);
-		} else {
-			upa_writel(ICLR_IDLE, bp->iclr);
-		}
+	kstat_this_cpu.irqs[0]++;
+	timer_interrupt(irq, NULL, regs);
 
-		/* Test and add entropy */
-		if (random & SA_SAMPLE_RANDOM)
-			add_interrupt_randomness(irq);
-	}
-out:
-	bp->flags &= ~IBF_INPROGRESS;
+	irq_exit();
 }
+#endif
 
 void handler_irq(int irq, struct pt_regs *regs)
 {
-	struct ino_bucket *bp;
-	int cpu = smp_processor_id();
-
-#ifndef CONFIG_SMP
-	/*
-	 * Check for TICK_INT on level 14 softint.
-	 */
-	{
-		unsigned long clr_mask = 1 << irq;
-		unsigned long tick_mask = tick_ops->softint_mask;
+	struct ino_bucket *bucket;
 
-		if ((irq == 14) && (get_softint() & tick_mask)) {
-			irq = 0;
-			clr_mask = tick_mask;
-		}
-		clear_softint(clr_mask);
-	}
-#else
 	clear_softint(1 << irq);
-#endif
 
 	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
 
 	/* Sliiiick... */
-#ifndef CONFIG_SMP
-	bp = ((irq != 0) ?
-	      __bucket(xchg32(irq_work(cpu, irq), 0)) :
-	      &pil0_dummy_bucket);
-#else
-	bp = __bucket(xchg32(irq_work(cpu, irq), 0));
-#endif
-	while (bp) {
-		struct ino_bucket *nbp = __bucket(bp->irq_chain);
+	bucket = __bucket(xchg32(irq_work(smp_processor_id()), 0));
+	while (bucket) {
+		struct ino_bucket *next = __bucket(bucket->irq_chain);
 
-		bp->irq_chain = 0;
-		process_bucket(irq, bp, regs);
-		bp = nbp;
+		bucket->irq_chain = 0;
+		__do_IRQ(bucket->virt_irq, regs);
+
+		bucket = next;
 	}
+
 	irq_exit();
 }
 
@@ -787,81 +624,6 @@ main_interrupt:
 EXPORT_SYMBOL(sparc_floppy_irq);
 #endif
 
-/* We really don't need these at all on the Sparc.  We only have
- * stubs here because they are exported to modules.
- */
-unsigned long probe_irq_on(void)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off(unsigned long mask)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-#ifdef CONFIG_SMP
-static int retarget_one_irq(struct irqaction *p, int goal_cpu)
-{
-	struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
-
-	while (!cpu_online(goal_cpu)) {
-		if (++goal_cpu >= NR_CPUS)
-			goal_cpu = 0;
-	}
-
-	if (tlb_type == hypervisor) {
-		unsigned int ino = __irq_ino(bucket);
-
-		sun4v_intr_settarget(ino, goal_cpu);
-		sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
-	} else {
-		unsigned long imap = bucket->imap;
-		unsigned int tid = sun4u_compute_tid(imap, goal_cpu);
-
-		upa_writel(tid | IMAP_VALID, imap);
-	}
-
-	do {
-		if (++goal_cpu >= NR_CPUS)
-			goal_cpu = 0;
-	} while (!cpu_online(goal_cpu));
-
-	return goal_cpu;
-}
-
-/* Called from request_irq. */
-static void distribute_irqs(void)
-{
-	unsigned long flags;
-	int cpu, level;
-
-	spin_lock_irqsave(&irq_action_lock, flags);
-	cpu = 0;
-
-	/*
-	 * Skip the timer at [0], and very rare error/power intrs at [15].
-	 * Also level [12], it causes problems on Ex000 systems.
-	 */
-	for (level = 1; level < NR_IRQS; level++) {
-		struct irqaction *p = irq_action[level];
-
-		if (level == 12)
-			continue;
-
-		while(p) {
-			cpu = retarget_one_irq(p, cpu);
-			p = p->next;
-		}
-	}
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-}
-#endif
-
 struct sun5_timer {
 	u64	count0;
 	u64	limit0;
@@ -874,23 +636,29 @@ static u64 prom_limit0, prom_limit1;
 
 static void map_prom_timers(void)
 {
-	unsigned int addr[3];
-	int tnode, err;
+	struct device_node *dp;
+	unsigned int *addr;
 
 	/* PROM timer node hangs out in the top level of device siblings... */
-	tnode = prom_finddevice("/counter-timer");
+	dp = of_find_node_by_path("/");
+	dp = dp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "counter-timer"))
+			break;
+		dp = dp->sibling;
+	}
 
 	/* Assume if node is not present, PROM uses different tick mechanism
 	 * which we should not care about.
 	 */
-	if (tnode == 0 || tnode == -1) {
+	if (!dp) {
 		prom_timers = (struct sun5_timer *) 0;
 		return;
 	}
 
 	/* If PROM is really using this, it must be mapped by him. */
-	err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr));
-	if (err == -1) {
+	addr = of_get_property(dp, "address", NULL);
+	if (!addr) {
 		prom_printf("PROM does not have timer mapped, trying to continue.\n");
 		prom_timers = (struct sun5_timer *) 0;
 		return;
@@ -929,7 +697,7 @@ void init_irqwork_curcpu(void)
 {
 	int cpu = hard_smp_processor_id();
 
-	memset(__irq_work + cpu, 0, sizeof(struct irq_work_struct));
+	trap_block[cpu].irq_worklist = 0;
 }
 
 static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
@@ -1037,6 +805,10 @@ void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int
 	}
 }
 
+static struct irqaction timer_irq_action = {
+	.name = "timer",
+};
+
 /* Only invoked on boot processor. */
 void __init init_IRQ(void)
 {
@@ -1064,109 +836,6 @@ void __init init_IRQ(void)
 			     : /* No outputs */
 			     : "i" (PSTATE_IE)
 			     : "g1");
-}
 
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NUM_IVECS];
-
-#ifdef CONFIG_SMP
-
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	struct ino_bucket *bp = ivector_table + (long)data;
-	struct irq_desc *desc = bp->irq_info;
-	struct irqaction *ap = desc->action;
-	cpumask_t mask;
-	int len;
-
-	mask = get_smpaff_in_irqaction(ap);
-	if (cpus_empty(mask))
-		mask = cpu_online_map;
-
-	len = cpumask_scnprintf(page, count, mask);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static inline void set_intr_affinity(int irq, cpumask_t hw_aff)
-{
-	struct ino_bucket *bp = ivector_table + irq;
-	struct irq_desc *desc = bp->irq_info;
-	struct irqaction *ap = desc->action;
-
-	/* Users specify affinity in terms of hw cpu ids.
-	 * As soon as we do this, handler_irq() might see and take action.
-	 */
-	put_smpaff_in_irqaction(ap, hw_aff);
-
-	/* Migration is simply done by the next cpu to service this
-	 * interrupt.
-	 */
-}
-
-static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-
-	/*
-	 * Do not allow disabling IRQs completely - it's a too easy
-	 * way to make the system unusable accidentally :-) At least
-	 * one online CPU still has to be targeted.
-	 */
-	cpus_and(new_value, new_value, cpu_online_map);
-	if (cpus_empty(new_value))
-		return -EINVAL;
-
-	set_intr_affinity(irq, new_value);
-
-	return full_count;
+	irq_desc[0].action = &timer_irq_action;
 }
-
-#endif
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
-	char name [MAX_NAMELEN];
-
-	if (!root_irq_dir || irq_dir[irq])
-		return;
-
-	memset(name, 0, MAX_NAMELEN);
-	sprintf(name, "%x", irq);
-
-	/* create /proc/irq/1234 */
-	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-
-#ifdef CONFIG_SMP
-	/* XXX SMP affinity not supported on starfire yet. */
-	if (this_is_starfire == 0) {
-		struct proc_dir_entry *entry;
-
-		/* create /proc/irq/1234/smp_affinity */
-		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
-		if (entry) {
-			entry->nlink = 1;
-			entry->data = (void *)(long)irq;
-			entry->read_proc = irq_affinity_read_proc;
-			entry->write_proc = irq_affinity_write_proc;
-		}
-	}
-#endif
-}
-
-void init_irq_proc (void)
-{
-	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", NULL);
-}
-
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
index 30862abee611..6f16dee280a8 100644
--- a/arch/sparc64/kernel/isa.c
+++ b/arch/sparc64/kernel/isa.c
@@ -15,23 +15,19 @@ static void __init fatal_err(const char *reason)
 static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
 {
 	if (child)
-		printk(" (%s)", isa_dev->prom_name);
+		printk(" (%s)", isa_dev->prom_node->name);
 	else
-		printk(" [%s", isa_dev->prom_name);
+		printk(" [%s", isa_dev->prom_node->name);
 }
 
-static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev,
-					struct linux_prom_registers *pregs,
-					int pregs_size)
+static struct linux_prom_registers * __init
+isa_dev_get_resource(struct sparc_isa_device *isa_dev)
 {
+	struct linux_prom_registers *pregs;
 	unsigned long base, len;
 	int prop_len;
 
-	prop_len = prom_getproperty(isa_dev->prom_node, "reg",
-				    (char *) pregs, pregs_size);
-
-	if (prop_len <= 0)
-		return;
+	pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
 
 	/* Only the first one is interesting. */
 	len = pregs[0].reg_size;
@@ -42,10 +38,12 @@ static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev,
 	isa_dev->resource.start = base;
 	isa_dev->resource.end   = (base + len - 1UL);
 	isa_dev->resource.flags = IORESOURCE_IO;
-	isa_dev->resource.name  = isa_dev->prom_name;
+	isa_dev->resource.name  = isa_dev->prom_node->name;
 
 	request_resource(&isa_dev->bus->parent->io_space,
 			 &isa_dev->resource);
+
+	return pregs;
 }
 
 /* I can't believe they didn't put a real INO in the isa device
@@ -74,19 +72,30 @@ static struct {
 static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
 					     struct sparc_isa_bridge *isa_br,
 					     int *interrupt,
-					     struct linux_prom_registers *pregs)
+					     struct linux_prom_registers *reg)
 {
+	struct linux_prom_ebus_intmap *imap;
+	struct linux_prom_ebus_intmap *imask;
 	unsigned int hi, lo, irq;
-	int i;
-
-	hi = pregs->which_io & isa_br->isa_intmask.phys_hi;
-	lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo;
-	irq = *interrupt & isa_br->isa_intmask.interrupt;
-	for (i = 0; i < isa_br->num_isa_intmap; i++) {
-		if ((isa_br->isa_intmap[i].phys_hi == hi) &&
-		    (isa_br->isa_intmap[i].phys_lo == lo) &&
-		    (isa_br->isa_intmap[i].interrupt == irq)) {
-			*interrupt = isa_br->isa_intmap[i].cinterrupt;
+	int i, len, n_imap;
+
+	imap = of_get_property(isa_br->prom_node, "interrupt-map", &len);
+	if (!imap)
+		return 0;
+	n_imap = len / sizeof(imap[0]);
+
+	imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL);
+	if (!imask)
+		return 0;
+
+	hi = reg->which_io & imask->phys_hi;
+	lo = reg->phys_addr & imask->phys_lo;
+	irq = *interrupt & imask->interrupt;
+	for (i = 0; i < n_imap; i++) {
+		if ((imap[i].phys_hi == hi) &&
+		    (imap[i].phys_lo == lo) &&
+		    (imap[i].interrupt == irq)) {
+			*interrupt = imap[i].cinterrupt;
 			return 0;
 		}
 	}
@@ -98,8 +107,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
 {
 	int irq_prop;
 
-	irq_prop = prom_getintdefault(isa_dev->prom_node,
-				      "interrupts", -1);
+	irq_prop = of_getintprop_default(isa_dev->prom_node,
+					 "interrupts", -1);
 	if (irq_prop <= 0) {
 		goto no_irq;
 	} else {
@@ -107,7 +116,8 @@ static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
 		struct pci_pbm_info *pbm;
 		int i;
 
-		if (isa_dev->bus->num_isa_intmap) {
+		if (of_find_property(isa_dev->bus->prom_node,
+				     "interrupt-map", NULL)) {
 			if (!isa_dev_get_irq_using_imap(isa_dev,
 							isa_dev->bus,
 							&irq_prop,
@@ -141,16 +151,15 @@ no_irq:
 
 static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
 {
-	int node = prom_getchild(parent_isa_dev->prom_node);
+	struct device_node *dp = parent_isa_dev->prom_node->child;
 
-	if (node == 0)
+	if (!dp)
 		return;
 
 	printk(" ->");
-	while (node != 0) {
-		struct linux_prom_registers regs[PROMREG_MAX];
+	while (dp) {
+		struct linux_prom_registers *regs;
 		struct sparc_isa_device *isa_dev;
-		int prop_len;
 
 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
 		if (!isa_dev) {
@@ -165,49 +174,46 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
 		parent_isa_dev->child = isa_dev;
 
 		isa_dev->bus = parent_isa_dev->bus;
-		isa_dev->prom_node = node;
-		prop_len = prom_getproperty(node, "name",
-					    (char *) isa_dev->prom_name,
-					    sizeof(isa_dev->prom_name));
-		if (prop_len <= 0) {
-			fatal_err("cannot get child isa_dev OBP node name");
-			prom_halt();
-		}
+		isa_dev->prom_node = dp;
 
-		prop_len = prom_getproperty(node, "compatible",
-					    (char *) isa_dev->compatible,
-					    sizeof(isa_dev->compatible));
-
-		/* Not having this is OK. */
-		if (prop_len <= 0)
-			isa_dev->compatible[0] = '\0';
-
-		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
+		regs = isa_dev_get_resource(isa_dev);
 		isa_dev_get_irq(isa_dev, regs);
 
 		report_dev(isa_dev, 1);
 
-		node = prom_getsibling(node);
+		dp = dp->sibling;
 	}
 }
 
 static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
 {
-	int node = prom_getchild(isa_br->prom_node);
+	struct device_node *dp = isa_br->prom_node->child;
 
-	while (node != 0) {
-		struct linux_prom_registers regs[PROMREG_MAX];
+	while (dp) {
+		struct linux_prom_registers *regs;
 		struct sparc_isa_device *isa_dev;
-		int prop_len;
 
 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
 		if (!isa_dev) {
-			fatal_err("cannot allocate isa_dev");
-			prom_halt();
+			printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
+			return;
 		}
 
 		memset(isa_dev, 0, sizeof(*isa_dev));
 
+		isa_dev->ofdev.node = dp;
+		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+		isa_dev->ofdev.dev.bus = &isa_bus_type;
+		strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&isa_dev->ofdev) != 0) {
+			printk(KERN_DEBUG "isa: device registration error for %s!\n",
+			       isa_dev->ofdev.dev.bus_id);
+			kfree(isa_dev);
+			goto next_sibling;
+		}
+
 		/* Link it in. */
 		isa_dev->next = NULL;
 		if (isa_br->devices == NULL) {
@@ -222,24 +228,9 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
 		}
 
 		isa_dev->bus = isa_br;
-		isa_dev->prom_node = node;
-		prop_len = prom_getproperty(node, "name",
-					    (char *) isa_dev->prom_name,
-					    sizeof(isa_dev->prom_name));
-		if (prop_len <= 0) {
-			fatal_err("cannot get isa_dev OBP node name");
-			prom_halt();
-		}
-
-		prop_len = prom_getproperty(node, "compatible",
-					    (char *) isa_dev->compatible,
-					    sizeof(isa_dev->compatible));
+		isa_dev->prom_node = dp;
 
-		/* Not having this is OK. */
-		if (prop_len <= 0)
-			isa_dev->compatible[0] = '\0';
-
-		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
+		regs = isa_dev_get_resource(isa_dev);
 		isa_dev_get_irq(isa_dev, regs);
 
 		report_dev(isa_dev, 0);
@@ -248,7 +239,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
 
 		printk("]");
 
-		node = prom_getsibling(node);
+	next_sibling:
+		dp = dp->sibling;
 	}
 }
 
@@ -266,7 +258,7 @@ void __init isa_init(void)
 		struct pcidev_cookie *pdev_cookie;
 		struct pci_pbm_info *pbm;
 		struct sparc_isa_bridge *isa_br;
-		int prop_len;
+		struct device_node *dp;
 
 		pdev_cookie = pdev->sysdata;
 		if (!pdev_cookie) {
@@ -275,15 +267,29 @@ void __init isa_init(void)
 			continue;
 		}
 		pbm = pdev_cookie->pbm;
+		dp = pdev_cookie->prom_node;
 
 		isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
 		if (!isa_br) {
-			fatal_err("cannot allocate sparc_isa_bridge");
-			prom_halt();
+			printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
+			return;
 		}
 
 		memset(isa_br, 0, sizeof(*isa_br));
 
+		isa_br->ofdev.node = dp;
+		isa_br->ofdev.dev.parent = &pdev->dev;
+		isa_br->ofdev.dev.bus = &isa_bus_type;
+		strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&isa_br->ofdev) != 0) {
+			printk(KERN_DEBUG "isa: device registration error for %s!\n",
+			       isa_br->ofdev.dev.bus_id);
+			kfree(isa_br);
+			return;
+		}
+
 		/* Link it in. */
 		isa_br->next = isa_chain;
 		isa_chain = isa_br;
@@ -292,33 +298,6 @@ void __init isa_init(void)
 		isa_br->self = pdev;
 		isa_br->index = index++;
 		isa_br->prom_node = pdev_cookie->prom_node;
-		strncpy(isa_br->prom_name, pdev_cookie->prom_name,
-			sizeof(isa_br->prom_name));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "ranges",
-					    (char *) isa_br->isa_ranges,
-					    sizeof(isa_br->isa_ranges));
-		if (prop_len <= 0)
-			isa_br->num_isa_ranges = 0;
-		else
-			isa_br->num_isa_ranges =
-				(prop_len / sizeof(struct linux_prom_isa_ranges));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "interrupt-map",
-					    (char *) isa_br->isa_intmap,
-					    sizeof(isa_br->isa_intmap));
-		if (prop_len <= 0)
-			isa_br->num_isa_intmap = 0;
-		else
-			isa_br->num_isa_intmap =
-				(prop_len / sizeof(struct linux_prom_isa_intmap));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "interrupt-map-mask",
-					    (char *) &(isa_br->isa_intmask),
-					    sizeof(isa_br->isa_intmask));
 
 		printk("isa%d:", isa_br->index);
 
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
new file mode 100644
index 000000000000..566aa343aa62
--- /dev/null
+++ b/arch/sparc64/kernel/of_device.c
@@ -0,0 +1,279 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+					const struct of_device *dev)
+{
+	if (!dev->node)
+		return NULL;
+	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+		int match = 1;
+		if (matches->name[0])
+			match &= dev->node->name
+				&& !strcmp(matches->name, dev->node->name);
+		if (matches->type[0])
+			match &= dev->node->type
+				&& !strcmp(matches->type, dev->node->type);
+		if (matches->compatible[0])
+			match &= of_device_is_compatible(dev->node,
+							 matches->compatible);
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+	const struct of_device_id * matches = of_drv->match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+	struct device *tmp;
+
+	if (!dev)
+		return NULL;
+	tmp = get_device(&dev->dev);
+	if (tmp)
+		return to_of_device(tmp);
+	else
+		return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+	if (dev)
+		put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct of_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_of_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->match_table, of_dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->suspend)
+		error = drv->suspend(of_dev, state);
+	return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->resume)
+		error = drv->resume(of_dev);
+	return error;
+}
+
+#ifdef CONFIG_PCI
+struct bus_type isa_bus_type = {
+       .name	= "isa",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+
+struct bus_type ebus_bus_type = {
+       .name	= "ebus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name	= "sbus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+#endif
+
+static int __init of_bus_driver_init(void)
+{
+	int err = 0;
+
+#ifdef CONFIG_PCI
+	if (!err)
+		err = bus_register(&isa_bus_type);
+	if (!err)
+		err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+	if (!err)
+		err = bus_register(&sbus_bus_type);
+#endif
+	return 0;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = bus;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct of_device *ofdev;
+
+	ofdev = to_of_device(dev);
+	return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+	struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+	kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+	int rc;
+
+	BUG_ON(ofdev->node == NULL);
+
+	rc = device_register(&ofdev->dev);
+	if (rc)
+		return rc;
+
+	device_create_file(&ofdev->dev, &dev_attr_devspec);
+
+	return 0;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+	device_remove_file(&ofdev->dev, &dev_attr_devspec);
+	device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent,
+					    struct bus_type *bus)
+{
+	struct of_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev->dev.parent = parent;
+	dev->dev.bus = bus;
+	dev->dev.release = of_release_dev;
+
+	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index f97ddeb105ac..6c9e3e94abaa 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -22,6 +22,7 @@
 #include <asm/irq.h>
 #include <asm/ebus.h>
 #include <asm/isa.h>
+#include <asm/prom.h>
 
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
@@ -47,12 +48,6 @@ struct pci_controller_info *pci_controller_root = NULL;
 /* Each PCI controller found gets a unique index. */
 int pci_num_controllers = 0;
 
-/* At boot time the user can give the kernel a command
- * line option which controls if and how PCI devices
- * are reordered at PCI bus probing time.
- */
-int pci_device_reorder = 0;
-
 volatile int pci_poke_in_progress;
 volatile int pci_poke_cpu = -1;
 volatile int pci_poke_faulted;
@@ -183,16 +178,16 @@ void pci_config_write32(u32 *addr, u32 val)
 }
 
 /* Probe for all PCI controllers in the system. */
-extern void sabre_init(int, char *);
-extern void psycho_init(int, char *);
-extern void schizo_init(int, char *);
-extern void schizo_plus_init(int, char *);
-extern void tomatillo_init(int, char *);
-extern void sun4v_pci_init(int, char *);
+extern void sabre_init(struct device_node *, const char *);
+extern void psycho_init(struct device_node *, const char *);
+extern void schizo_init(struct device_node *, const char *);
+extern void schizo_plus_init(struct device_node *, const char *);
+extern void tomatillo_init(struct device_node *, const char *);
+extern void sun4v_pci_init(struct device_node *, const char *);
 
 static struct {
 	char *model_name;
-	void (*init)(int, char *);
+	void (*init)(struct device_node *, const char *);
 } pci_controller_table[] __initdata = {
 	{ "SUNW,sabre", sabre_init },
 	{ "pci108e,a000", sabre_init },
@@ -210,7 +205,7 @@ static struct {
 #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
 				  sizeof(pci_controller_table[0]))
 
-static int __init pci_controller_init(char *model_name, int namelen, int node)
+static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
 {
 	int i;
 
@@ -218,18 +213,15 @@ static int __init pci_controller_init(char *model_name, int namelen, int node)
 		if (!strncmp(model_name,
 			     pci_controller_table[i].model_name,
 			     namelen)) {
-			pci_controller_table[i].init(node, model_name);
+			pci_controller_table[i].init(dp, model_name);
 			return 1;
 		}
 	}
-	printk("PCI: Warning unknown controller, model name [%s]\n",
-	       model_name);
-	printk("PCI: Ignoring controller...\n");
 
 	return 0;
 }
 
-static int __init pci_is_controller(char *model_name, int namelen, int node)
+static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
 {
 	int i;
 
@@ -243,36 +235,35 @@ static int __init pci_is_controller(char *model_name, int namelen, int node)
 	return 0;
 }
 
-static int __init pci_controller_scan(int (*handler)(char *, int, int))
+static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
 {
-	char namebuf[64];
-	int node;
+	struct device_node *dp;
 	int count = 0;
 
-	node = prom_getchild(prom_root_node);
-	while ((node = prom_searchsiblings(node, "pci")) != 0) {
+	for_each_node_by_name(dp, "pci") {
+		struct property *prop;
 		int len;
 
-		if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
-		    (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
+		prop = of_find_property(dp, "model", &len);
+		if (!prop)
+			prop = of_find_property(dp, "compatible", &len);
+
+		if (prop) {
+			const char *model = prop->value;
 			int item_len = 0;
 
 			/* Our value may be a multi-valued string in the
 			 * case of some compatible properties. For sanity,
-			 * only try the first one. */
-
-			while (namebuf[item_len] && len) {
+			 * only try the first one.
+			 */
+			while (model[item_len] && len) {
 				len--;
 				item_len++;
 			}
 
-			if (handler(namebuf, item_len, node))
+			if (handler(model, item_len, dp))
 				count++;
 		}
-
-		node = prom_getsibling(node);
-		if (!node)
-			break;
 	}
 
 	return count;
@@ -316,27 +307,6 @@ static void __init pci_scan_each_controller_bus(void)
 		p->scan_bus(p);
 }
 
-/* Reorder the pci_dev chain, so that onboard devices come first
- * and then come the pluggable cards.
- */
-static void __init pci_reorder_devs(void)
-{
-	struct list_head *pci_onboard = &pci_devices;
-	struct list_head *walk = pci_onboard->next;
-
-	while (walk != pci_onboard) {
-		struct pci_dev *pdev = pci_dev_g(walk);
-		struct list_head *walk_next = walk->next;
-
-		if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
-			list_del(walk);
-			list_add(walk, pci_onboard);
-		}
-
-		walk = walk_next;
-	}
-}
-
 extern void clock_probe(void);
 extern void power_init(void);
 
@@ -348,9 +318,6 @@ static int __init pcibios_init(void)
 
 	pci_scan_each_controller_bus();
 
-	if (pci_device_reorder)
-		pci_reorder_devs();
-
 	isa_init();
 	ebus_init();
 	clock_probe();
@@ -439,14 +406,12 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
 }
 EXPORT_SYMBOL(pcibios_bus_to_resource);
 
+extern int pci_irq_verbose;
+
 char * __init pcibios_setup(char *str)
 {
-	if (!strcmp(str, "onboardfirst")) {
-		pci_device_reorder = 1;
-		return NULL;
-	}
-	if (!strcmp(str, "noreorder")) {
-		pci_device_reorder = 0;
+	if (!strcmp(str, "irq_verbose")) {
+		pci_irq_verbose = 1;
 		return NULL;
 	}
 	return str;
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 33dedb1aacd4..b06a2955bf5f 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -9,6 +9,12 @@
 #include <linux/init.h>
 
 #include <asm/pbm.h>
+#include <asm/prom.h>
+
+#include "pci_impl.h"
+
+/* Pass "pci=irq_verbose" on the kernel command line to enable this.  */
+int pci_irq_verbose;
 
 /* Fix self device of BUS and hook it into BUS->self.
  * The pci_scan_bus does not do this for the host bridge.
@@ -28,16 +34,14 @@ void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
 	prom_halt();
 }
 
-/* Find the OBP PROM device tree node for a PCI device.
- * Return zero if not found.
- */
-static int __init find_device_prom_node(struct pci_pbm_info *pbm,
-					struct pci_dev *pdev,
-					int bus_prom_node,
-					struct linux_prom_pci_registers *pregs,
-					int *nregs)
+/* Find the OBP PROM device tree node for a PCI device.  */
+static struct device_node * __init
+find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev,
+		      struct device_node *bus_node,
+		      struct linux_prom_pci_registers **pregs,
+		      int *nregs)
 {
-	int node;
+	struct device_node *dp;
 
 	*nregs = 0;
 
@@ -54,24 +58,30 @@ static int __init find_device_prom_node(struct pci_pbm_info *pbm,
 	     pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO ||
 	     pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
 	     pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD))
-		return bus_prom_node;
-
-	node = prom_getchild(bus_prom_node);
-	while (node != 0) {
-		int err = prom_getproperty(node, "reg",
-					   (char *)pregs,
-					   sizeof(*pregs) * PROMREG_MAX);
-		if (err == 0 || err == -1)
+		return bus_node;
+
+	dp = bus_node->child;
+	while (dp) {
+		struct linux_prom_pci_registers *regs;
+		struct property *prop;
+		int len;
+
+		prop = of_find_property(dp, "reg", &len);
+		if (!prop)
 			goto do_next_sibling;
-		if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
-			*nregs = err / sizeof(*pregs);
-			return node;
+
+		regs = prop->value;
+		if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
+			*pregs = regs;
+			*nregs = len / sizeof(struct linux_prom_pci_registers);
+			return dp;
 		}
 
 	do_next_sibling:
-		node = prom_getsibling(node);
+		dp = dp->sibling;
 	}
-	return 0;
+
+	return NULL;
 }
 
 /* Older versions of OBP on PCI systems encode 64-bit MEM
@@ -128,15 +138,17 @@ static void __init fixup_obp_assignments(struct pci_dev *pdev,
  */
 static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 				      struct pci_dev *pdev,
-				      int bus_prom_node)
+				      struct device_node *bus_node)
 {
-	struct linux_prom_pci_registers pregs[PROMREG_MAX];
+	struct linux_prom_pci_registers *pregs = NULL;
 	struct pcidev_cookie *pcp;
-	int device_prom_node, nregs, err;
+	struct device_node *dp;
+	struct property *prop;
+	int nregs, len;
 
-	device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node,
-						 pregs, &nregs);
-	if (device_prom_node == 0) {
+	dp = find_device_prom_node(pbm, pdev, bus_node,
+				   &pregs, &nregs);
+	if (!dp) {
 		/* If it is not in the OBP device tree then
 		 * there must be a damn good reason for it.
 		 *
@@ -150,45 +162,43 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 		return;
 	}
 
-	pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC);
+	pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC);
 	if (pcp == NULL) {
 		prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
 		prom_halt();
 	}
 	pcp->pbm = pbm;
-	pcp->prom_node = device_prom_node;
-	memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs));
+	pcp->prom_node = dp;
+	memcpy(pcp->prom_regs, pregs,
+	       nregs * sizeof(struct linux_prom_pci_registers));
 	pcp->num_prom_regs = nregs;
-	err = prom_getproperty(device_prom_node, "name",
-			       pcp->prom_name, sizeof(pcp->prom_name));
-	if (err > 0)
-		pcp->prom_name[err] = 0;
-	else
-		pcp->prom_name[0] = 0;
-
-	err = prom_getproperty(device_prom_node,
-			       "assigned-addresses",
-			       (char *)pcp->prom_assignments,
-			       sizeof(pcp->prom_assignments));
-	if (err == 0 || err == -1)
+
+	/* We can't have the pcidev_cookie assignments be just
+	 * direct pointers into the property value, since they
+	 * are potentially modified by the probing process.
+	 */
+	prop = of_find_property(dp, "assigned-addresses", &len);
+	if (!prop) {
 		pcp->num_prom_assignments = 0;
-	else
+	} else {
+		memcpy(pcp->prom_assignments, prop->value, len);
 		pcp->num_prom_assignments =
-			(err / sizeof(pcp->prom_assignments[0]));
+			(len / sizeof(pcp->prom_assignments[0]));
+	}
 
-	if (strcmp(pcp->prom_name, "ebus") == 0) {
-		struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
+	if (strcmp(dp->name, "ebus") == 0) {
+		struct linux_prom_ebus_ranges *erng;
 		int iter;
 
 		/* EBUS is special... */
-		err = prom_getproperty(device_prom_node, "ranges",
-				       (char *)&erng[0], sizeof(erng));
-		if (err == 0 || err == -1) {
+		prop = of_find_property(dp, "ranges", &len);
+		if (!prop) {
 			prom_printf("EBUS: Fatal error, no range property\n");
 			prom_halt();
 		}
-		err = (err / sizeof(erng[0]));
-		for(iter = 0; iter < err; iter++) {
+		erng = prop->value;
+		len = (len / sizeof(erng[0]));
+		for (iter = 0; iter < len; iter++) {
 			struct linux_prom_ebus_ranges *ep = &erng[iter];
 			struct linux_prom_pci_registers *ap;
 
@@ -200,7 +210,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 			ap->size_hi = 0;
 			ap->size_lo = ep->size;
 		}
-		pcp->num_prom_assignments = err;
+		pcp->num_prom_assignments = len;
 	}
 
 	fixup_obp_assignments(pdev, pcp);
@@ -210,7 +220,7 @@ static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 
 void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node)
+				    struct device_node *dp)
 {
 	struct pci_dev *pdev, *pdev_next;
 	struct pci_bus *this_pbus, *pbus_next;
@@ -218,7 +228,7 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 	/* This must be _safe because the cookie fillin
 	   routine can delete devices from the tree.  */
 	list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
-		pdev_cookie_fillin(pbm, pdev, prom_node);
+		pdev_cookie_fillin(pbm, pdev, dp);
 
 	list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
 		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
@@ -241,7 +251,6 @@ static void __init bad_assignment(struct pci_dev *pdev,
 	if (res)
 		prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
 			    res->start, res->end, res->flags);
-	prom_printf("Please email this information to davem@redhat.com\n");
 	if (do_prom_halt)
 		prom_halt();
 }
@@ -273,8 +282,7 @@ __init get_root_resource(struct linux_prom_pci_registers *ap,
 		return &pbm->mem_space;
 
 	default:
-		printk("PCI: What is resource space %x? "
-		       "Tell davem@redhat.com about it!\n", space);
+		printk("PCI: What is resource space %x?\n", space);
 		return NULL;
 	};
 }
@@ -556,9 +564,10 @@ static inline unsigned int pci_slot_swivel(struct pci_pbm_info *pbm,
 
 	ret = ((interrupt - 1 + (PCI_SLOT(pdev->devfn) & 3)) & 3) + 1;
 
-	printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n",
-	       pbm->name, pci_name(toplevel_pdev), pci_name(pdev),
-	       interrupt, PCI_SLOT(pdev->devfn), ret);
+	if (pci_irq_verbose)
+		printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n",
+		       pbm->name, pci_name(toplevel_pdev), pci_name(pdev),
+		       interrupt, PCI_SLOT(pdev->devfn), ret);
 
 	return ret;
 }
@@ -568,58 +577,60 @@ static inline unsigned int pci_apply_intmap(struct pci_pbm_info *pbm,
 					    struct pci_dev *pbus,
 					    struct pci_dev *pdev,
 					    unsigned int interrupt,
-					    unsigned int *cnode)
+					    struct device_node **cnode)
 {
-	struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX];
-	struct linux_prom_pci_intmask imask;
+	struct linux_prom_pci_intmap *imap;
+	struct linux_prom_pci_intmask *imask;
 	struct pcidev_cookie *pbus_pcp = pbus->sysdata;
 	struct pcidev_cookie *pdev_pcp = pdev->sysdata;
 	struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs;
+	struct property *prop;
 	int plen, num_imap, i;
 	unsigned int hi, mid, lo, irq, orig_interrupt;
 
 	*cnode = pbus_pcp->prom_node;
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map",
-				(char *) &imap[0], sizeof(imap));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmap)) != 0) {
 		printk("%s: Device %s interrupt-map has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imap = prop->value;
 	num_imap = plen / sizeof(struct linux_prom_pci_intmap);
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask",
-				(char *) &imask, sizeof(imask));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmask)) != 0) {
 		printk("%s: Device %s interrupt-map-mask has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imask = prop->value;
 
 	orig_interrupt = interrupt;
 
-	hi   = pregs->phys_hi & imask.phys_hi;
-	mid  = pregs->phys_mid & imask.phys_mid;
-	lo   = pregs->phys_lo & imask.phys_lo;
-	irq  = interrupt & imask.interrupt;
+	hi   = pregs->phys_hi & imask->phys_hi;
+	mid  = pregs->phys_mid & imask->phys_mid;
+	lo   = pregs->phys_lo & imask->phys_lo;
+	irq  = interrupt & imask->interrupt;
 
 	for (i = 0; i < num_imap; i++) {
 		if (imap[i].phys_hi  == hi   &&
 		    imap[i].phys_mid == mid  &&
 		    imap[i].phys_lo  == lo   &&
 		    imap[i].interrupt == irq) {
-			*cnode = imap[i].cnode;
+			*cnode = of_find_node_by_phandle(imap[i].cnode);
 			interrupt = imap[i].cinterrupt;
 		}
 	}
 
-	printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n",
-	       pbm->name, pci_name(toplevel_pdev),
-	       pci_name(pbus), pci_name(pdev),
-	       orig_interrupt, interrupt);
+	if (pci_irq_verbose)
+		printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n",
+		       pbm->name, pci_name(toplevel_pdev),
+		       pci_name(pbus), pci_name(pdev),
+		       orig_interrupt, interrupt);
 
 no_intmap:
 	return interrupt;
@@ -633,21 +644,22 @@ no_intmap:
  * all interrupt translations are complete, else we should use that node's
  * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt.
  */
-static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm,
-						    struct pci_dev *pdev,
-						    unsigned int *interrupt)
+static struct device_node * __init
+pci_intmap_match_to_root(struct pci_pbm_info *pbm,
+			 struct pci_dev *pdev,
+			 unsigned int *interrupt)
 {
 	struct pci_dev *toplevel_pdev = pdev;
 	struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata;
-	unsigned int cnode = toplevel_pcp->prom_node;
+	struct device_node *cnode = toplevel_pcp->prom_node;
 
 	while (pdev->bus->number != pbm->pci_first_busno) {
 		struct pci_dev *pbus = pdev->bus->self;
 		struct pcidev_cookie *pcp = pbus->sysdata;
-		int plen;
+		struct property *prop;
 
-		plen = prom_getproplen(pcp->prom_node, "interrupt-map");
-		if (plen <= 0) {
+		prop = of_find_property(pcp->prom_node, "interrupt-map", NULL);
+		if (!prop) {
 			*interrupt = pci_slot_swivel(pbm, toplevel_pdev,
 						     pdev, *interrupt);
 			cnode = pcp->prom_node;
@@ -675,26 +687,29 @@ static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt
 {
 	struct pcidev_cookie *dev_pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
-	struct linux_prom_pci_registers reg[PROMREG_MAX];
+	struct linux_prom_pci_registers *reg;
+	struct device_node *cnode;
+	struct property *prop;
 	unsigned int hi, mid, lo, irq;
-	int i, cnode, plen;
+	int i, plen;
 
 	cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
 	if (cnode == pbm->prom_node)
 		goto success;
 
-	plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg));
-	if (plen <= 0 ||
+	prop = of_find_property(cnode, "reg", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_registers)) != 0) {
-		printk("%s: OBP node %x reg property has bad len %d\n",
-		       pbm->name, cnode, plen);
+		printk("%s: OBP node %s reg property has bad len %d\n",
+		       pbm->name, cnode->full_name, plen);
 		goto fail;
 	}
+	reg = prop->value;
 
-	hi   = reg[0].phys_hi & pbm->pbm_intmask.phys_hi;
-	mid  = reg[0].phys_mid & pbm->pbm_intmask.phys_mid;
-	lo   = reg[0].phys_lo & pbm->pbm_intmask.phys_lo;
-	irq  = *interrupt & pbm->pbm_intmask.interrupt;
+	hi   = reg[0].phys_hi & pbm->pbm_intmask->phys_hi;
+	mid  = reg[0].phys_mid & pbm->pbm_intmask->phys_mid;
+	lo   = reg[0].phys_lo & pbm->pbm_intmask->phys_lo;
+	irq  = *interrupt & pbm->pbm_intmask->interrupt;
 
 	for (i = 0; i < pbm->num_pbm_intmap; i++) {
 		struct linux_prom_pci_intmap *intmap;
@@ -714,9 +729,11 @@ fail:
 	return 0;
 
 success:
-	printk("PCI-IRQ: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
-	       pdev->bus->number, PCI_SLOT(pdev->devfn),
-	       *interrupt);
+	if (pci_irq_verbose)
+		printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
+		       pbm->name,
+		       pdev->bus->number, PCI_SLOT(pdev->devfn),
+		       *interrupt);
 	return 1;
 }
 
@@ -727,8 +744,8 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
 	struct pci_controller_info *p = pbm->parent;
 	unsigned int portid = pbm->portid;
 	unsigned int prom_irq;
-	int prom_node = pcp->prom_node;
-	int err;
+	struct device_node *dp = pcp->prom_node;
+	struct property *prop;
 
 	/* If this is an empty EBUS device, sometimes OBP fails to
 	 * give it a valid fully specified interrupts property.
@@ -739,17 +756,17 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    pdev->device == PCI_DEVICE_ID_SUN_EBUS &&
-	    !prom_getchild(prom_node)) {
+	    !dp->child) {
 		pdev->irq = 0;
 		return;
 	}
 
-	err = prom_getproperty(prom_node, "interrupts",
-			       (char *)&prom_irq, sizeof(prom_irq));
-	if (err == 0 || err == -1) {
+	prop = of_find_property(dp, "interrupts", NULL);
+	if (!prop) {
 		pdev->irq = 0;
 		return;
 	}
+	prom_irq = *(unsigned int *) prop->value;
 
 	if (tlb_type != hypervisor) {
 		/* Fully specified already? */
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 6c3205962544..971e2bea30b4 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
+#include <asm/prom.h>
 
 extern struct pci_controller_info *pci_controller_root;
 
@@ -19,7 +20,7 @@ extern int pci_num_controllers;
 extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
 extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node);
+				    struct device_node *prom_node);
 extern void pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus);
 extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index d17878b145c2..5b2261ebda6f 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -17,6 +17,7 @@
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -276,82 +277,13 @@ static unsigned long __onboard_imap_off[] = {
 	((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
 			(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
 
-/* PCI PSYCHO INO number to Sparc PIL level. */
-static unsigned char psycho_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
-/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
-/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
-/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
-/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
-/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
-/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
-/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
-/*0x20*/5,		/* SCSI				*/
-/*0x21*/5,		/* Ethernet			*/
-/*0x22*/8,		/* Parallel Port		*/
-/*0x23*/13,		/* Audio Record			*/
-/*0x24*/14,		/* Audio Playback		*/
-/*0x25*/15,		/* PowerFail			*/
-/*0x26*/5,		/* second SCSI			*/
-/*0x27*/11,		/* Floppy			*/
-/*0x28*/5,		/* Spare Hardware		*/
-/*0x29*/9,		/* Keyboard			*/
-/*0x2a*/5,		/* Mouse			*/
-/*0x2b*/12,		/* Serial			*/
-/*0x2c*/10,		/* Timer 0			*/
-/*0x2d*/11,		/* Timer 1			*/
-/*0x2e*/15,		/* Uncorrectable ECC		*/
-/*0x2f*/15,		/* Correctable ECC		*/
-/*0x30*/15,		/* PCI Bus A Error		*/
-/*0x31*/15,		/* PCI Bus B Error		*/
-/*0x32*/15,		/* Power Management		*/
-};
-
-static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	ret = psycho_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-
-	return ret;
-}
-
 static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
 				     struct pci_dev *pdev,
 				     unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int inofixup = 0;
 
 	ino &= PCI_IRQ_INO;
 	if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
@@ -367,11 +299,6 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
 	}
 
 	/* Now build the IRQ bucket. */
-	pil = psycho_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
 	imap = pbm->controller_regs + imap_off;
 	imap += 4;
 
@@ -382,10 +309,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
-
-	return __irq(bucket);
+	return build_irq(inofixup, iclr, imap);
 }
 
 /* PSYCHO error handling support. */
@@ -1368,11 +1292,12 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
 #define PSYCHO_MEMSPACE_SIZE	0x07fffffffUL
 
 static void psycho_pbm_init(struct pci_controller_info *p,
-			    int prom_node, int is_pbm_a)
+			    struct device_node *dp, int is_pbm_a)
 {
-	unsigned int busrange[2];
+	unsigned int *busrange;
+	struct property *prop;
 	struct pci_pbm_info *pbm;
-	int err;
+	int len;
 
 	if (is_pbm_a) {
 		pbm = &p->pbm_A;
@@ -1387,10 +1312,14 @@ static void psycho_pbm_init(struct pci_controller_info *p,
 	}
 
 	pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
-	pbm->chip_version =
-		prom_getintdefault(prom_node, "version#", 0);
-	pbm->chip_revision =
-		prom_getintdefault(prom_node, "module-revision#", 0);
+	pbm->chip_version = 0;
+	prop = of_find_property(dp, "version#", NULL);
+	if (prop)
+		pbm->chip_version = *(int *) prop->value;
+	pbm->chip_revision = 0;
+	prop = of_find_property(dp, "module-revision#", NULL);
+	if (prop)
+		pbm->chip_revision = *(int *) prop->value;
 
 	pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
 	pbm->io_space.flags = IORESOURCE_IO;
@@ -1399,45 +1328,36 @@ static void psycho_pbm_init(struct pci_controller_info *p,
 	pbm_register_toplevel_resources(p, pbm);
 
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name,
-		       sizeof(pbm->prom_name));
-
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *)pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err != -1)
+	pbm->prom_node = dp;
+	pbm->name = dp->full_name;
+
+	printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
+	       pbm->name,
+	       pbm->chip_version, pbm->chip_revision);
+
+	prop = of_find_property(dp, "ranges", &len);
+	if (prop) {
+		pbm->pbm_ranges = prop->value;
 		pbm->num_pbm_ranges =
-			(err / sizeof(struct linux_prom_pci_ranges));
-	else
+			(len / sizeof(struct linux_prom_pci_ranges));
+	} else {
 		pbm->num_pbm_ranges = 0;
+	}
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err != -1) {
-		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-		err = prom_getproperty(prom_node, "interrupt-map-mask",
-				       (char *)&pbm->pbm_intmask,
-				       sizeof(pbm->pbm_intmask));
-		if (err == -1) {
-			prom_printf("PSYCHO-PBM: Fatal error, no "
-				    "interrupt-map-mask.\n");
-			prom_halt();
-		}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	if (prop) {
+		pbm->pbm_intmap = prop->value;
+		pbm->num_pbm_intmap =
+			(len / sizeof(struct linux_prom_pci_intmap));
+
+		prop = of_find_property(dp, "interrupt-map-mask", NULL);
+		pbm->pbm_intmask = prop->value;
 	} else {
 		pbm->num_pbm_intmap = 0;
-		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 	}
 
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
@@ -1446,20 +1366,24 @@ static void psycho_pbm_init(struct pci_controller_info *p,
 
 #define PSYCHO_CONFIGSPACE	0x001000000UL
 
-void psycho_init(int node, char *model_name)
+void psycho_init(struct device_node *dp, char *model_name)
 {
-	struct linux_prom64_registers pr_regs[3];
+	struct linux_prom64_registers *pr_regs;
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
+	struct property *prop;
 	u32 upa_portid;
-	int is_pbm_a, err;
+	int is_pbm_a;
 
-	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
+	upa_portid = 0xff;
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (prop)
+		upa_portid = *(u32 *) prop->value;
 
 	for(p = pci_controller_root; p; p = p->next) {
 		if (p->pbm_A.portid == upa_portid) {
-			is_pbm_a = (p->pbm_A.prom_node == 0);
-			psycho_pbm_init(p, node, is_pbm_a);
+			is_pbm_a = (p->pbm_A.prom_node == NULL);
+			psycho_pbm_init(p, dp, is_pbm_a);
 			return;
 		}
 	}
@@ -1489,23 +1413,14 @@ void psycho_init(int node, char *model_name)
 	p->resource_adjust = psycho_resource_adjust;
 	p->pci_ops = &psycho_ops;
 
-	err = prom_getproperty(node, "reg",
-			       (char *)&pr_regs[0],
-			       sizeof(pr_regs));
-	if (err == 0 || err == -1) {
-		prom_printf("PSYCHO: Fatal error, no reg property.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "reg", NULL);
+	pr_regs = prop->value;
 
 	p->pbm_A.controller_regs = pr_regs[2].phys_addr;
 	p->pbm_B.controller_regs = pr_regs[2].phys_addr;
-	printk("PCI: Found PSYCHO, control regs at %016lx\n",
-	       p->pbm_A.controller_regs);
 
 	p->pbm_A.config_space = p->pbm_B.config_space =
 		(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
-	printk("PSYCHO: Shared PCI config space at %016lx\n",
-	       p->pbm_A.config_space);
 
 	/*
 	 * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
@@ -1518,5 +1433,5 @@ void psycho_init(int node, char *model_name)
 	psycho_iommu_init(p);
 
 	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
-	psycho_pbm_init(p, node, is_pbm_a);
+	psycho_pbm_init(p, dp, is_pbm_a);
 }
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index f67bb7f078cf..26f194ce4400 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -19,6 +19,7 @@
 #include <asm/irq.h>
 #include <asm/smp.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -523,78 +524,6 @@ static unsigned long __onboard_imap_off[] = {
 	((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
 			(SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
 
-/* PCI SABRE INO number to Sparc PIL level. */
-static unsigned char sabre_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
-/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
-/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
-/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
-/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
-/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
-/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
-/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
-/*0x20*/5,		/* SCSI				*/
-/*0x21*/5,		/* Ethernet			*/
-/*0x22*/8,		/* Parallel Port		*/
-/*0x23*/13,		/* Audio Record			*/
-/*0x24*/14,		/* Audio Playback		*/
-/*0x25*/15,		/* PowerFail			*/
-/*0x26*/5,		/* second SCSI			*/
-/*0x27*/11,		/* Floppy			*/
-/*0x28*/5,		/* Spare Hardware		*/
-/*0x29*/9,		/* Keyboard			*/
-/*0x2a*/5,		/* Mouse			*/
-/*0x2b*/12,		/* Serial			*/
-/*0x2c*/10,		/* Timer 0			*/
-/*0x2d*/11,		/* Timer 1			*/
-/*0x2e*/15,		/* Uncorrectable ECC		*/
-/*0x2f*/15,		/* Correctable ECC		*/
-/*0x30*/15,		/* PCI Bus A Error		*/
-/*0x31*/15,		/* PCI Bus B Error		*/
-/*0x32*/15,		/* Power Management		*/
-};
-
-static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	if (pdev &&
-	    pdev->vendor == PCI_VENDOR_ID_SUN &&
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 9;
-
-	ret = sabre_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-	return ret;
-}
-
 /* When a device lives behind a bridge deeper in the PCI bus topology
  * than APB, a special sequence must run to make sure all pending DMA
  * transfers at the time of IRQ delivery are visible in the coherency
@@ -602,7 +531,7 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
  * side of the non-APB bridge, then perform a read of Sabre's DMA
  * write-sync register.
  */
-static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
+static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
 {
 	struct pci_dev *pdev = _arg1;
 	unsigned long sync_reg = (unsigned long) _arg2;
@@ -616,10 +545,10 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
 				    struct pci_dev *pdev,
 				    unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int inofixup = 0;
+	int virt_irq;
 
 	ino &= PCI_IRQ_INO;
 	if (ino < SABRE_ONBOARD_IRQ_BASE) {
@@ -635,11 +564,6 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
 	}
 
 	/* Now build the IRQ bucket. */
-	pil = sabre_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
 	imap = pbm->controller_regs + imap_off;
 	imap += 4;
 
@@ -650,23 +574,23 @@ static unsigned int sabre_irq_build(struct pci_pbm_info *pbm,
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
+	virt_irq = build_irq(inofixup, iclr, imap);
 
 	if (pdev) {
 		struct pcidev_cookie *pcp = pdev->sysdata;
 
 		if (pdev->bus->number != pcp->pbm->pci_first_busno) {
 			struct pci_controller_info *p = pcp->pbm->parent;
-			struct irq_desc *d = bucket->irq_info;
 
-			d->pre_handler = sabre_wsync_handler;
-			d->pre_handler_arg1 = pdev;
-			d->pre_handler_arg2 = (void *)
-				p->pbm_A.controller_regs + SABRE_WRSYNC;
+			irq_install_pre_handler(virt_irq,
+						sabre_wsync_handler,
+						pdev,
+						(void *)
+						p->pbm_A.controller_regs +
+						SABRE_WRSYNC);
 		}
 	}
-	return __irq(bucket);
+	return virt_irq;
 }
 
 /* SABRE error handling support. */
@@ -1383,34 +1307,36 @@ static void pbm_register_toplevel_resources(struct pci_controller_info *p,
 					    &pbm->mem_space);
 }
 
-static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
+static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
 {
 	struct pci_pbm_info *pbm;
-	char namebuf[128];
-	u32 busrange[2];
-	int node, simbas_found;
+	struct device_node *node;
+	struct property *prop;
+	u32 *busrange;
+	int len, simbas_found;
 
 	simbas_found = 0;
-	node = prom_getchild(sabre_node);
-	while ((node = prom_searchsiblings(node, "pci")) != 0) {
-		int err;
-
-		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
-		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
+	node = dp->child;
+	while (node != NULL) {
+		if (strcmp(node->name, "pci"))
 			goto next_pci;
 
-		err = prom_getproperty(node, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-		if (err == 0 || err == -1) {
-			prom_printf("APB: Error, cannot get PCI bus-range.\n");
-			prom_halt();
-		}
+		prop = of_find_property(node, "model", NULL);
+		if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
+			goto next_pci;
 
 		simbas_found++;
+
+		prop = of_find_property(node, "bus-range", NULL);
+		busrange = prop->value;
 		if (busrange[0] == 1)
 			pbm = &p->pbm_B;
 		else
 			pbm = &p->pbm_A;
+
+		pbm->name = node->full_name;
+		printk("%s: SABRE PCI Bus Module\n", pbm->name);
+
 		pbm->chip_type = PBM_CHIP_TYPE_SABRE;
 		pbm->parent = p;
 		pbm->prom_node = node;
@@ -1418,83 +1344,68 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
 		pbm->pci_first_busno = busrange[0];
 		pbm->pci_last_busno = busrange[1];
 
-		prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));
-		err = prom_getproperty(node, "ranges",
-				       (char *)pbm->pbm_ranges,
-				       sizeof(pbm->pbm_ranges));
-		if (err != -1)
+		prop = of_find_property(node, "ranges", &len);
+		if (prop) {
+			pbm->pbm_ranges = prop->value;
 			pbm->num_pbm_ranges =
-				(err / sizeof(struct linux_prom_pci_ranges));
-		else
+				(len / sizeof(struct linux_prom_pci_ranges));
+		} else {
 			pbm->num_pbm_ranges = 0;
+		}
 
-		err = prom_getproperty(node, "interrupt-map",
-				       (char *)pbm->pbm_intmap,
-				       sizeof(pbm->pbm_intmap));
-		if (err != -1) {
-			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-			err = prom_getproperty(node, "interrupt-map-mask",
-					       (char *)&pbm->pbm_intmask,
-					       sizeof(pbm->pbm_intmask));
-			if (err == -1) {
-				prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
-				prom_halt();
-			}
+		prop = of_find_property(node, "interrupt-map", &len);
+		if (prop) {
+			pbm->pbm_intmap = prop->value;
+			pbm->num_pbm_intmap =
+				(len / sizeof(struct linux_prom_pci_intmap));
+
+			prop = of_find_property(node, "interrupt-map-mask",
+						NULL);
+			pbm->pbm_intmask = prop->value;
 		} else {
 			pbm->num_pbm_intmap = 0;
-			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 		}
 
 		pbm_register_toplevel_resources(p, pbm);
 
 	next_pci:
-		node = prom_getsibling(node);
-		if (!node)
-			break;
+		node = node->sibling;
 	}
 	if (simbas_found == 0) {
-		int err;
-
 		/* No APBs underneath, probably this is a hummingbird
 		 * system.
 		 */
 		pbm = &p->pbm_A;
 		pbm->parent = p;
-		pbm->prom_node = sabre_node;
+		pbm->prom_node = dp;
 		pbm->pci_first_busno = p->pci_first_busno;
 		pbm->pci_last_busno = p->pci_last_busno;
 
-		prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name));
-		err = prom_getproperty(sabre_node, "ranges",
-				       (char *) pbm->pbm_ranges,
-				       sizeof(pbm->pbm_ranges));
-		if (err != -1)
+		prop = of_find_property(dp, "ranges", &len);
+		if (prop) {
+			pbm->pbm_ranges = prop->value;
 			pbm->num_pbm_ranges =
-				(err / sizeof(struct linux_prom_pci_ranges));
-		else
+				(len / sizeof(struct linux_prom_pci_ranges));
+		} else {
 			pbm->num_pbm_ranges = 0;
+		}
 
-		err = prom_getproperty(sabre_node, "interrupt-map",
-				       (char *) pbm->pbm_intmap,
-				       sizeof(pbm->pbm_intmap));
-
-		if (err != -1) {
-			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-			err = prom_getproperty(sabre_node, "interrupt-map-mask",
-					       (char *)&pbm->pbm_intmask,
-					       sizeof(pbm->pbm_intmask));
-			if (err == -1) {
-				prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
-				prom_halt();
-			}
+		prop = of_find_property(dp, "interrupt-map", &len);
+		if (prop) {
+			pbm->pbm_intmap = prop->value;
+			pbm->num_pbm_intmap =
+				(len / sizeof(struct linux_prom_pci_intmap));
+
+			prop = of_find_property(dp, "interrupt-map-mask",
+						NULL);
+			pbm->pbm_intmask = prop->value;
 		} else {
 			pbm->num_pbm_intmap = 0;
-			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 		}
 
+		pbm->name = dp->full_name;
+		printk("%s: SABRE PCI Bus Module\n", pbm->name);
 
-		sprintf(pbm->name, "SABRE%d PBM%c", p->index,
-			(pbm == &p->pbm_A ? 'A' : 'B'));
 		pbm->io_space.name = pbm->mem_space.name = pbm->name;
 
 		/* Hack up top-level resources. */
@@ -1520,14 +1431,15 @@ static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dm
 	}
 }
 
-void sabre_init(int pnode, char *model_name)
+void sabre_init(struct device_node *dp, char *model_name)
 {
-	struct linux_prom64_registers pr_regs[2];
+	struct linux_prom64_registers *pr_regs;
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	int tsbsize, err;
-	u32 busrange[2];
-	u32 vdma[2];
+	struct property *prop;
+	int tsbsize;
+	u32 *busrange;
+	u32 *vdma;
 	u32 upa_portid, dma_mask;
 	u64 clear_irq;
 
@@ -1535,22 +1447,21 @@ void sabre_init(int pnode, char *model_name)
 	if (!strcmp(model_name, "pci108e,a001"))
 		hummingbird_p = 1;
 	else if (!strcmp(model_name, "SUNW,sabre")) {
-		char compat[64];
+		prop = of_find_property(dp, "compatible", NULL);
+		if (prop) {
+			const char *compat = prop->value;
 
-		if (prom_getproperty(pnode, "compatible",
-				     compat, sizeof(compat)) > 0 &&
-		    !strcmp(compat, "pci108e,a001")) {
-			hummingbird_p = 1;
-		} else {
-			int cpu_node;
+			if (!strcmp(compat, "pci108e,a001"))
+				hummingbird_p = 1;
+		}
+		if (!hummingbird_p) {
+			struct device_node *dp;
 
 			/* Of course, Sun has to encode things a thousand
 			 * different ways, inconsistently.
 			 */
-			cpu_find_by_instance(0, &cpu_node, NULL);
-			if (prom_getproperty(cpu_node, "name",
-					     compat, sizeof(compat)) > 0 &&
-			    !strcmp(compat, "SUNW,UltraSPARC-IIe"))
+			cpu_find_by_instance(0, &dp, NULL);
+			if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
 				hummingbird_p = 1;
 		}
 	}
@@ -1568,7 +1479,10 @@ void sabre_init(int pnode, char *model_name)
 	}
 	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
+	upa_portid = 0xff;
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (prop)
+		upa_portid = *(u32 *) prop->value;
 
 	p->next = pci_controller_root;
 	pci_controller_root = p;
@@ -1586,13 +1500,9 @@ void sabre_init(int pnode, char *model_name)
 	/*
 	 * Map in SABRE register set and report the presence of this SABRE.
 	 */
-	err = prom_getproperty(pnode, "reg",
-			       (char *)&pr_regs[0], sizeof(pr_regs));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get U2P registers "
-			    "from PROM.\n");
-		prom_halt();
-	}
+	
+	prop = of_find_property(dp, "reg", NULL);
+	pr_regs = prop->value;
 
 	/*
 	 * First REG in property is base of entire SABRE register space.
@@ -1600,9 +1510,6 @@ void sabre_init(int pnode, char *model_name)
 	p->pbm_A.controller_regs = pr_regs[0].phys_addr;
 	p->pbm_B.controller_regs = pr_regs[0].phys_addr;
 
-	printk("PCI: Found SABRE, main regs at %016lx\n",
-	       p->pbm_A.controller_regs);
-
 	/* Clear interrupts */
 
 	/* PCI first */
@@ -1621,16 +1528,9 @@ void sabre_init(int pnode, char *model_name)
 	/* Now map in PCI config space for entire SABRE. */
 	p->pbm_A.config_space = p->pbm_B.config_space =
 		(p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
-	printk("SABRE: Shared PCI config space at %016lx\n",
-	       p->pbm_A.config_space);
-
-	err = prom_getproperty(pnode, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get virtual-dma property "
-			    "from PROM.\n");
-		prom_halt();
-	}
+
+	prop = of_find_property(dp, "virtual-dma", NULL);
+	vdma = prop->value;
 
 	dma_mask = vdma[0];
 	switch(vdma[1]) {
@@ -1654,21 +1554,13 @@ void sabre_init(int pnode, char *model_name)
 
 	sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
 
-	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-
-	err = prom_getproperty(pnode, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get PCI bus-range "
-			    " from PROM.\n");
-		prom_halt();
-	}
-
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	p->pci_first_busno = busrange[0];
 	p->pci_last_busno = busrange[1];
 
 	/*
 	 * Look for APB underneath.
 	 */
-	sabre_pbm_init(p, pnode, vdma[0]);
+	sabre_pbm_init(p, dp, vdma[0]);
 }
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 7fe4de03ac2e..f16449ccd7bc 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/upa.h>
 #include <asm/pstate.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -232,105 +233,10 @@ static unsigned long schizo_iclr_offset(unsigned long ino)
 	return SCHIZO_ICLR_BASE + (ino * 8UL);
 }
 
-/* PCI SCHIZO INO number to Sparc PIL level.  This table only matters for
- * INOs which will not have an associated PCI device struct, ie. onboard
- * EBUS devices and PCI controller internal error interrupts.
- */
-static unsigned char schizo_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI slot 0  Int A, B, C, D	*/
-/*0x04*/0, 0, 0, 0,	/* PCI slot 1  Int A, B, C, D	*/
-/*0x08*/0, 0, 0, 0,	/* PCI slot 2  Int A, B, C, D	*/
-/*0x0c*/0, 0, 0, 0,	/* PCI slot 3  Int A, B, C, D	*/
-/*0x10*/0, 0, 0, 0,	/* PCI slot 4  Int A, B, C, D	*/
-/*0x14*/0, 0, 0, 0,	/* PCI slot 5  Int A, B, C, D	*/
-/*0x18*/5,		/* SCSI				*/
-/*0x19*/5,		/* second SCSI			*/
-/*0x1a*/0,		/* UNKNOWN			*/
-/*0x1b*/0,		/* UNKNOWN			*/
-/*0x1c*/8,		/* Parallel			*/
-/*0x1d*/5,		/* Ethernet			*/
-/*0x1e*/8,		/* Firewire-1394		*/
-/*0x1f*/9,		/* USB				*/
-/*0x20*/13,		/* Audio Record			*/
-/*0x21*/14,		/* Audio Playback		*/
-/*0x22*/12,		/* Serial			*/
-/*0x23*/5,		/* EBUS I2C 			*/
-/*0x24*/10,		/* RTC Clock			*/
-/*0x25*/11,		/* Floppy			*/
-/*0x26*/0,		/* UNKNOWN			*/
-/*0x27*/0,		/* UNKNOWN			*/
-/*0x28*/0,		/* UNKNOWN			*/
-/*0x29*/0,		/* UNKNOWN			*/
-/*0x2a*/10,		/* UPA 1			*/
-/*0x2b*/10,		/* UPA 2			*/
-/*0x2c*/0,		/* UNKNOWN			*/
-/*0x2d*/0,		/* UNKNOWN			*/
-/*0x2e*/0,		/* UNKNOWN			*/
-/*0x2f*/0,		/* UNKNOWN			*/
-/*0x30*/15,		/* Uncorrectable ECC		*/
-/*0x31*/15,		/* Correctable ECC		*/
-/*0x32*/15,		/* PCI Bus A Error		*/
-/*0x33*/15,		/* PCI Bus B Error		*/
-/*0x34*/15,		/* Safari Bus Error		*/
-/*0x35*/0,		/* Reserved			*/
-/*0x36*/0,		/* Reserved			*/
-/*0x37*/0,		/* Reserved			*/
-/*0x38*/0,		/* Reserved for NewLink		*/
-/*0x39*/0,		/* Reserved for NewLink		*/
-/*0x3a*/0,		/* Reserved for NewLink		*/
-/*0x3b*/0,		/* Reserved for NewLink		*/
-/*0x3c*/0,		/* Reserved for NewLink		*/
-/*0x3d*/0,		/* Reserved for NewLink		*/
-/*0x3e*/0,		/* Reserved for NewLink		*/
-/*0x3f*/0,		/* Reserved for NewLink		*/
-};
-
-static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	if (pdev &&
-	    pdev->vendor == PCI_VENDOR_ID_SUN &&
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 9;
-
-	ret = schizo_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-
-	return ret;
-}
-
-static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
+static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
 {
 	unsigned long sync_reg = (unsigned long) _arg2;
-	u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO);
+	u64 mask = 1UL << (ino & IMAP_INO);
 	u64 val;
 	int limit;
 
@@ -365,30 +271,33 @@ static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void
 	}
 }
 
+static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_iclr_offset(ino) + 4;
+}
+
+static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_imap_offset(ino) + 4;
+}
+
 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
 				     struct pci_dev *pdev,
 				     unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
-	unsigned long imap_off, iclr_off;
-	int pil, ign_fixup;
+	int ign_fixup;
+	int virt_irq;
 
 	ino &= PCI_IRQ_INO;
-	imap_off = schizo_imap_offset(ino);
 
 	/* Now build the IRQ bucket. */
-	pil = schizo_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
-	imap = pbm->pbm_regs + imap_off;
-	imap += 4;
-
-	iclr_off = schizo_iclr_offset(ino);
-	iclr = pbm->pbm_regs + iclr_off;
-	iclr += 4;
+	imap = schizo_ino_to_imap(pbm, ino);
+	iclr = schizo_ino_to_iclr(pbm, ino);
 
 	/* On Schizo, no inofixup occurs.  This is because each
 	 * INO has it's own IMAP register.  On Psycho and Sabre
@@ -405,19 +314,17 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
 			ign_fixup = (1 << 6);
 	}
 
-	bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
+	virt_irq = build_irq(ign_fixup, iclr, imap);
 
 	if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
-		struct irq_desc *p = bucket->irq_info;
-
-		p->pre_handler = tomatillo_wsync_handler;
-		p->pre_handler_arg1 = ((pbm->chip_version <= 4) ?
-				       (void *) 1 : (void *) 0);
-		p->pre_handler_arg2 = (void *) pbm->sync_reg;
+		irq_install_pre_handler(virt_irq,
+					tomatillo_wsync_handler,
+					((pbm->chip_version <= 4) ?
+					 (void *) 1 : (void *) 0),
+					(void *) pbm->sync_reg);
 	}
 
-	return __irq(bucket);
+	return virt_irq;
 }
 
 /* SCHIZO error handling support. */
@@ -458,7 +365,6 @@ struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
 static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
 {
 	struct pci_pbm_info *pbm;
-	struct ino_bucket *bucket;
 	unsigned long iclr;
 
 	/* Do not clear the interrupt for the other PCI bus.
@@ -476,11 +382,11 @@ static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
 	else
 		pbm = &p->pbm_A;
 
-	irq = schizo_irq_build(pbm, NULL,
-			       (pbm->portid << 6) | (irq & IMAP_INO));
-	bucket = __bucket(irq);
-	iclr = bucket->iclr;
+	schizo_irq_build(pbm, NULL,
+			 (pbm->portid << 6) | (irq & IMAP_INO));
 
+	iclr = schizo_ino_to_iclr(pbm,
+				  (pbm->portid << 6) | (irq & IMAP_INO));
 	upa_writel(ICLR_IDLE, iclr);
 }
 
@@ -1225,7 +1131,6 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1237,8 +1142,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
@@ -1250,8 +1154,7 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
@@ -1264,8 +1167,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_A_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
@@ -1278,8 +1181,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_B_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
@@ -1291,8 +1194,8 @@ static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_SERR_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
@@ -1363,7 +1266,6 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1375,8 +1277,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_CE_INO);
@@ -1387,8 +1288,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
@@ -1399,8 +1299,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
@@ -1411,8 +1310,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
@@ -1423,8 +1321,7 @@ static void schizo_register_error_handlers(struct pci_controller_info *p)
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
 	/* Enable UE and CE interrupts for controller. */
@@ -1560,10 +1457,12 @@ static void __schizo_scan_bus(struct pci_controller_info *p,
 
 	pbm_config_busmastering(&p->pbm_B);
 	p->pbm_B.is_66mhz_capable =
-		prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
+		(of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
+		 != NULL);
 	pbm_config_busmastering(&p->pbm_A);
 	p->pbm_A.is_66mhz_capable =
-		prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
+		(of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
+		 != NULL);
 	pbm_scan_bus(p, &p->pbm_B);
 	pbm_scan_bus(p, &p->pbm_A);
 
@@ -1765,13 +1664,18 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct pci_iommu *iommu = pbm->iommu;
 	unsigned long i, tagbase, database;
+	struct property *prop;
 	u32 vdma[2], dma_mask;
 	u64 control;
-	int err, tsbsize;
+	int tsbsize;
+
+	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
+	if (prop) {
+		u32 *val = prop->value;
 
-	err = prom_getproperty(pbm->prom_node, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if (err == 0 || err == -1) {
+		vdma[0] = val[0];
+		vdma[1] = val[1];
+	} else {
 		/* No property, use default values. */
 		vdma[0] = 0xc0000000;
 		vdma[1] = 0x40000000;
@@ -1882,6 +1786,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 
 static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 {
+	struct property *prop;
 	u64 tmp;
 
 	schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
@@ -1895,7 +1800,8 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 	    pbm->chip_version >= 0x2)
 		tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
 
-	if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
+	prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL);
+	if (!prop)
 		tmp |= SCHIZO_PCICTRL_PARK;
 	else
 		tmp &= ~SCHIZO_PCICTRL_PARK;
@@ -1935,16 +1841,17 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 }
 
 static void schizo_pbm_init(struct pci_controller_info *p,
-			    int prom_node, u32 portid,
+			    struct device_node *dp, u32 portid,
 			    int chip_type)
 {
-	struct linux_prom64_registers pr_regs[4];
-	unsigned int busrange[2];
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+	unsigned int *busrange;
 	struct pci_pbm_info *pbm;
 	const char *chipset_name;
-	u32 ino_bitmap[2];
+	u32 *ino_bitmap;
 	int is_pbm_a;
-	int err;
+	int len;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1972,16 +1879,10 @@ static void schizo_pbm_init(struct pci_controller_info *p,
 	 * 3) PBM PCI config space
 	 * 4) Ichip regs
 	 */
-	err = prom_getproperty(prom_node, "reg",
-			       (char *)&pr_regs[0],
-			       sizeof(pr_regs));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no reg property.\n",
-			    chipset_name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
 
-	is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);
+	is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
 
 	if (is_pbm_a)
 		pbm = &p->pbm_A;
@@ -1990,92 +1891,62 @@ static void schizo_pbm_init(struct pci_controller_info *p,
 
 	pbm->portid = portid;
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
+	pbm->prom_node = dp;
 	pbm->pci_first_slot = 1;
 
 	pbm->chip_type = chip_type;
-	pbm->chip_version =
-		prom_getintdefault(prom_node, "version#", 0);
-	pbm->chip_revision =
-		prom_getintdefault(prom_node, "module-revision#", 0);
-
-	pbm->pbm_regs = pr_regs[0].phys_addr;
-	pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
+	pbm->chip_version = 0;
+	prop = of_find_property(dp, "version#", NULL);
+	if (prop)
+		pbm->chip_version = *(int *) prop->value;
+	pbm->chip_revision = 0;
+	prop = of_find_property(dp, "module-revision#", NULL);
+	if (prop)
+		pbm->chip_revision = *(int *) prop->value;
+
+	pbm->pbm_regs = regs[0].phys_addr;
+	pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
 
 	if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
-		pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL;
+		pbm->sync_reg = regs[3].phys_addr + 0x1a18UL;
 
-	sprintf(pbm->name,
-		(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
-		 "TOMATILLO%d PBM%c" :
-		 "SCHIZO%d PBM%c"),
-		p->index,
-		(pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->name = dp->full_name;
 
-	printk("%s: ver[%x:%x], portid %x, "
-	       "cregs[%lx] pregs[%lx]\n",
+	printk("%s: %s PCI Bus Module ver[%x:%x]\n",
 	       pbm->name,
-	       pbm->chip_version, pbm->chip_revision,
-	       pbm->portid,
-	       pbm->controller_regs,
-	       pbm->pbm_regs);
+	       (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+		"TOMATILLO" : "SCHIZO"),
+	       pbm->chip_version, pbm->chip_revision);
 
 	schizo_pbm_hw_init(pbm);
 
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name,
-		       sizeof(pbm->prom_name));
-
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *) pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ranges property.\n",
-			    pbm->name);
-		prom_halt();
-	}
-
+	prop = of_find_property(dp, "ranges", &len);
+	pbm->pbm_ranges = prop->value;
 	pbm->num_pbm_ranges =
-		(err / sizeof(struct linux_prom_pci_ranges));
+		(len / sizeof(struct linux_prom_pci_ranges));
 
 	schizo_determine_mem_io_space(pbm);
 	pbm_register_toplevel_resources(p, pbm);
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err != -1) {
-		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-		err = prom_getproperty(prom_node, "interrupt-map-mask",
-				       (char *)&pbm->pbm_intmask,
-				       sizeof(pbm->pbm_intmask));
-		if (err == -1) {
-			prom_printf("%s: Fatal error, no "
-				    "interrupt-map-mask.\n", pbm->name);
-			prom_halt();
-		}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	if (prop) {
+		pbm->pbm_intmap = prop->value;
+		pbm->num_pbm_intmap =
+			(len / sizeof(struct linux_prom_pci_intmap));
+
+		prop = of_find_property(dp, "interrupt-map-mask", NULL);
+		pbm->pbm_intmask = prop->value;
 	} else {
 		pbm->num_pbm_intmap = 0;
-		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 	}
 
-	err = prom_getproperty(prom_node, "ino-bitmap",
-			       (char *) &ino_bitmap[0],
-			       sizeof(ino_bitmap));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "ino-bitmap", NULL);
+	ino_bitmap = prop->value;
 	pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
 			   ((u64)ino_bitmap[0] <<  0UL));
 
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
@@ -2093,16 +1964,20 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
 	return (x == y);
 }
 
-static void __schizo_init(int node, char *model_name, int chip_type)
+static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
+	struct property *prop;
 	int is_pbm_a;
 	u32 portid;
 
-	portid = prom_getintdefault(node, "portid", 0xff);
+	portid = 0xff;
+	prop = of_find_property(dp, "portid", NULL);
+	if (prop)
+		portid = *(u32 *) prop->value;
 
-	for(p = pci_controller_root; p; p = p->next) {
+	for (p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
 
 		if (p->pbm_A.prom_node && p->pbm_B.prom_node)
@@ -2113,8 +1988,8 @@ static void __schizo_init(int node, char *model_name, int chip_type)
 		       &p->pbm_B);
 
 		if (portid_compare(pbm->portid, portid, chip_type)) {
-			is_pbm_a = (p->pbm_A.prom_node == 0);
-			schizo_pbm_init(p, node, portid, chip_type);
+			is_pbm_a = (p->pbm_A.prom_node == NULL);
+			schizo_pbm_init(p, dp, portid, chip_type);
 			return;
 		}
 	}
@@ -2155,20 +2030,20 @@ static void __schizo_init(int node, char *model_name, int chip_type)
 	/* Like PSYCHO we have a 2GB aligned area for memory space. */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	schizo_pbm_init(p, node, portid, chip_type);
+	schizo_pbm_init(p, dp, portid, chip_type);
 }
 
-void schizo_init(int node, char *model_name)
+void schizo_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO);
 }
 
-void schizo_plus_init(int node, char *model_name)
+void schizo_plus_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
 }
 
-void tomatillo_init(int node, char *model_name)
+void tomatillo_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO);
 }
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 0c0895202970..b69e2270a721 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -18,6 +18,7 @@
 #include <asm/pstate.h>
 #include <asm/oplib.h>
 #include <asm/hypervisor.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -646,35 +647,37 @@ static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, u
 /* Recursively descend into the OBP device tree, rooted at toplevel_node,
  * looking for a PCI device matching bus and devfn.
  */
-static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
+static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
 {
-	toplevel_node = prom_getchild(toplevel_node);
+	toplevel_node = toplevel_node->child;
 
-	while (toplevel_node != 0) {
-		int ret = obp_find(pregs, toplevel_node, bus, devfn);
+	while (toplevel_node != NULL) {
+		struct linux_prom_pci_registers *regs;
+		struct property *prop;
+		int ret;
 
+		ret = obp_find(toplevel_node, bus, devfn);
 		if (ret != 0)
 			return ret;
 
-		ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
-				       sizeof(*pregs) * PROMREG_MAX);
-		if (ret == 0 || ret == -1)
+		prop = of_find_property(toplevel_node, "reg", NULL);
+		if (!prop)
 			goto next_sibling;
 
-		if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
-		    ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
+		regs = prop->value;
+		if (((regs->phys_hi >> 16) & 0xff) == bus &&
+		    ((regs->phys_hi >> 8) & 0xff) == devfn)
 			break;
 
 	next_sibling:
-		toplevel_node = prom_getsibling(toplevel_node);
+		toplevel_node = toplevel_node->sibling;
 	}
 
-	return toplevel_node;
+	return toplevel_node != NULL;
 }
 
 static int pdev_htab_populate(struct pci_pbm_info *pbm)
 {
-	struct linux_prom_pci_registers pr[PROMREG_MAX];
 	u32 devhandle = pbm->devhandle;
 	unsigned int bus;
 
@@ -685,7 +688,7 @@ static int pdev_htab_populate(struct pci_pbm_info *pbm)
 			unsigned int device = PCI_SLOT(devfn);
 			unsigned int func = PCI_FUNC(devfn);
 
-			if (obp_find(pr, pbm->prom_node, bus, devfn)) {
+			if (obp_find(pbm->prom_node, bus, devfn)) {
 				int err = pdev_htab_add(devhandle, bus,
 							device, func);
 				if (err)
@@ -811,8 +814,7 @@ static void pbm_scan_bus(struct pci_controller_info *p,
 	pci_fixup_host_bridge_self(pbm->pci_bus);
 	pbm->pci_bus->self->sysdata = cookie;
 #endif
-	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
-				pbm->prom_node);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
 	pci_fixup_irq(pbm, pbm->pci_bus);
@@ -822,15 +824,18 @@ static void pbm_scan_bus(struct pci_controller_info *p,
 
 static void pci_sun4v_scan_bus(struct pci_controller_info *p)
 {
-	if (p->pbm_A.prom_node) {
-		p->pbm_A.is_66mhz_capable =
-			prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
+	struct property *prop;
+	struct device_node *dp;
+
+	if ((dp = p->pbm_A.prom_node) != NULL) {
+		prop = of_find_property(dp, "66mhz-capable", NULL);
+		p->pbm_A.is_66mhz_capable = (prop != NULL);
 
 		pbm_scan_bus(p, &p->pbm_A);
 	}
-	if (p->pbm_B.prom_node) {
-		p->pbm_B.is_66mhz_capable =
-			prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
+	if ((dp = p->pbm_B.prom_node) != NULL) {
+		prop = of_find_property(dp, "66mhz-capable", NULL);
+		p->pbm_B.is_66mhz_capable = (prop != NULL);
 
 		pbm_scan_bus(p, &p->pbm_B);
 	}
@@ -843,38 +848,8 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
 					unsigned int devino)
 {
 	u32 devhandle = pbm->devhandle;
-	int pil;
-
-	pil = 5;
-	if (pdev) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			pil = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			pil = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			pil = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			pil = 10;
-			break;
-
-		default:
-			pil = 5;
-			break;
-		};
-	}
-	BUG_ON(PIL_RESERVED(pil));
 
-	return sun4v_build_irq(devhandle, devino, pil, IBF_PCI);
+	return sun4v_build_irq(devhandle, devino);
 }
 
 static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource)
@@ -1012,8 +987,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
 					     HV_PCI_TSBID(0, i),
 					     &io_attrs, &ra);
 		if (ret == HV_EOK) {
-			cnt++;
-			__set_bit(i, arena->map);
+			if (page_in_phys_avail(ra)) {
+				pci_sun4v_iommu_demap(devhandle,
+						      HV_PCI_TSBID(0, i), 1);
+			} else {
+				cnt++;
+				__set_bit(i, arena->map);
+			}
 		}
 	}
 
@@ -1023,13 +1003,18 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
 static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct pci_iommu *iommu = pbm->iommu;
+	struct property *prop;
 	unsigned long num_tsb_entries, sz;
 	u32 vdma[2], dma_mask, dma_offset;
-	int err, tsbsize;
+	int tsbsize;
+
+	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
+	if (prop) {
+		u32 *val = prop->value;
 
-	err = prom_getproperty(pbm->prom_node, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if (err == 0 || err == -1) {
+		vdma[0] = val[0];
+		vdma[1] = val[1];
+	} else {
 		/* No property, use default values. */
 		vdma[0] = 0x80000000;
 		vdma[1] = 0x80000000;
@@ -1081,34 +1066,30 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 	iommu->arena.limit = num_tsb_entries;
 
 	sz = probe_existing_entries(pbm, iommu);
-
-	printk("%s: TSB entries [%lu], existing mapings [%lu]\n",
-	       pbm->name, num_tsb_entries, sz);
+	if (sz)
+		printk("%s: Imported %lu TSB entries from OBP\n",
+		       pbm->name, sz);
 }
 
 static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
 {
-	unsigned int busrange[2];
-	int prom_node = pbm->prom_node;
-	int err;
-
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
-		prom_halt();
-	}
+	struct property *prop;
+	unsigned int *busrange;
+
+	prop = of_find_property(pbm->prom_node, "bus-range", NULL);
+
+	busrange = prop->value;
 
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
 }
 
-static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle)
+static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
 {
 	struct pci_pbm_info *pbm;
-	int err, i;
+	struct property *prop;
+	int len, i;
 
 	if (devhandle & 0x40)
 		pbm = &p->pbm_B;
@@ -1116,32 +1097,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
 		pbm = &p->pbm_A;
 
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
+	pbm->prom_node = dp;
 	pbm->pci_first_slot = 1;
 
 	pbm->devhandle = devhandle;
 
-	sprintf(pbm->name, "SUN4V-PCI%d PBM%c",
-		p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->name = dp->full_name;
 
-	printk("%s: devhandle[%x] prom_node[%x:%x]\n",
-	       pbm->name, pbm->devhandle,
-	       pbm->prom_node, prom_getchild(pbm->prom_node));
-
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name, sizeof(pbm->prom_name));
-
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *) pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ranges property.\n",
-			    pbm->name);
-		prom_halt();
-	}
+	printk("%s: SUN4V PCI Bus Module\n", pbm->name);
 
+	prop = of_find_property(dp, "ranges", &len);
+	pbm->pbm_ranges = prop->value;
 	pbm->num_pbm_ranges =
-		(err / sizeof(struct linux_prom_pci_ranges));
+		(len / sizeof(struct linux_prom_pci_ranges));
 
 	/* Mask out the top 8 bits of the ranges, leaving the real
 	 * physical address.
@@ -1152,24 +1120,13 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
 	pci_sun4v_determine_mem_io_space(pbm);
 	pbm_register_toplevel_resources(p, pbm);
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no interrupt-map property.\n",
-			    pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	pbm->pbm_intmap = prop->value;
+	pbm->num_pbm_intmap =
+		(len / sizeof(struct linux_prom_pci_intmap));
 
-	pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-	err = prom_getproperty(prom_node, "interrupt-map-mask",
-			       (char *)&pbm->pbm_intmask,
-			       sizeof(pbm->pbm_intmask));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
-			    pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map-mask", NULL);
+	pbm->pbm_intmask = prop->value;
 
 	pci_sun4v_get_bus_range(pbm);
 	pci_sun4v_iommu_init(pbm);
@@ -1177,16 +1134,19 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
 	pdev_htab_populate(pbm);
 }
 
-void sun4v_pci_init(int node, char *model_name)
+void sun4v_pci_init(struct device_node *dp, char *model_name)
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	struct linux_prom64_registers regs;
+	struct property *prop;
+	struct linux_prom64_registers *regs;
 	u32 devhandle;
 	int i;
 
-	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
-	devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
+
+	devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
 
 	for (p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
@@ -1199,7 +1159,7 @@ void sun4v_pci_init(int node, char *model_name)
 		       &p->pbm_B);
 
 		if (pbm->devhandle == (devhandle ^ 0x40)) {
-			pci_sun4v_pbm_init(p, node, devhandle);
+			pci_sun4v_pbm_init(p, dp, devhandle);
 			return;
 		}
 	}
@@ -1250,7 +1210,7 @@ void sun4v_pci_init(int node, char *model_name)
 	 */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	pci_sun4v_pbm_init(p, node, devhandle);
+	pci_sun4v_pbm_init(p, dp, devhandle);
 	return;
 
 fatal_memory_error:
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 30bcaf58e3ab..9496c7734014 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -105,76 +105,25 @@ again:
 	return 0;
 }
 
-static int __init has_button_interrupt(unsigned int irq, int prom_node)
+static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
 	if (irq == PCI_IRQ_NONE)
 		return 0;
-	if (!prom_node_has_property(prom_node, "button"))
+	if (!of_find_property(dp, "button", NULL))
 		return 0;
 
 	return 1;
 }
 
-static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
+static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq)
 {
-	struct linux_ebus *ebus;
-	struct linux_ebus_device *edev;
-
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "power")) {
-				*resp = &edev->resource[0];
-				*irq_p = edev->irqs[0];
-				*prom_node_p = edev->prom_node;
-				return 0;
-			}
-		}
-	}
-	return -ENODEV;
-}
-
-static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
-{
-	struct sparc_isa_bridge *isa_bus;
-	struct sparc_isa_device *isa_dev;
-
-	for_each_isa(isa_bus) {
-		for_each_isadev(isa_dev, isa_bus) {
-			if (!strcmp(isa_dev->prom_name, "power")) {
-				*resp = &isa_dev->resource;
-				*irq_p = isa_dev->irq;
-				*prom_node_p = isa_dev->prom_node;
-				return 0;
-			}
-		}
-	}
-	return -ENODEV;
-}
-
-void __init power_init(void)
-{
-	struct resource *res = NULL;
-	unsigned int irq;
-	int prom_node;
-	static int invoked;
-
-	if (invoked)
-		return;
-	invoked = 1;
-
-	if (!power_probe_ebus(&res, &irq, &prom_node))
-		goto found;
-
-	if (!power_probe_isa(&res, &irq, &prom_node))
-		goto found;
-
-	return;
-
-found:
 	power_reg = ioremap(res->start, 0x4);
+
 	printk("power: Control reg at %p ... ", power_reg);
+
 	poweroff_method = machine_halt;  /* able to use the standard halt */
-	if (has_button_interrupt(irq, prom_node)) {
+
+	if (has_button_interrupt(irq, dev->node)) {
 		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
 			printk("Failed to start power daemon.\n");
 			return;
@@ -188,4 +137,52 @@ found:
 		printk("not using powerd.\n");
 	}
 }
+
+static struct of_device_id power_match[] = {
+	{
+		.name = "power",
+	},
+	{},
+};
+
+static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+	struct resource *res = &edev->resource[0];
+	unsigned int irq = edev->irqs[0];
+
+	power_probe_common(dev, res,irq);
+
+	return 0;
+}
+
+static struct of_platform_driver ebus_power_driver = {
+	.name		= "power",
+	.match_table	= power_match,
+	.probe		= ebus_power_probe,
+};
+
+static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sparc_isa_device *idev = to_isa_device(&dev->dev);
+	struct resource *res = &idev->resource;
+	unsigned int irq = idev->irq;
+
+	power_probe_common(dev, res,irq);
+
+	return 0;
+}
+
+static struct of_platform_driver isa_power_driver = {
+	.name		= "power",
+	.match_table	= power_match,
+	.probe		= isa_power_probe,
+};
+
+void __init power_init(void)
+{
+	of_register_driver(&ebus_power_driver, &ebus_bus_type);
+	of_register_driver(&isa_power_driver, &isa_bus_type);
+	return;
+}
 #endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
new file mode 100644
index 000000000000..e9d703eea806
--- /dev/null
+++ b/arch/sparc64/kernel/prom.c
@@ -0,0 +1,650 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc64 by David S. Miller davem@davemloft.net
+ *
+ *      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/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+
+static struct device_node *allnodes;
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+	const char* cp;
+	int cplen, l;
+
+	cp = (char *) of_get_property(device, "compatible", &cplen);
+	if (cp == NULL)
+		return 0;
+	while (cplen > 0) {
+		if (strncmp(cp, compat, strlen(compat)) == 0)
+			return 1;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+	struct device_node *np;
+
+	if (!node)
+		return NULL;
+
+	np = node->parent;
+
+	return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	struct device_node *next;
+
+	next = prev ? prev->sibling : node->child;
+	for (; next != 0; next = next->sibling) {
+		break;
+	}
+
+	return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+	struct device_node *np = allnodes;
+
+	for (; np != 0; np = np->allnext) {
+		if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != NULL; np = np->allnext)
+		if (np->name != NULL && strcmp(np->name, name) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext)
+		if (np->type != 0 && strcmp(np->type, type) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compatible)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext) {
+		if (type != NULL
+		    && !(np->type != 0 && strcmp(np->type, type) == 0))
+			continue;
+		if (of_device_is_compatible(np, compatible))
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+				  int *lenp)
+{
+	struct property *pp;
+
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (strcmp(pp->name, name) == 0) {
+			if (lenp != 0)
+				*lenp = pp->length;
+			break;
+		}
+	}
+	return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+	struct property *pp = of_find_property(np,name,lenp);
+	return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+	struct property *prop;
+	int len;
+
+	prop = of_find_property(np, name, &len);
+	if (!prop || len != 4)
+		return def;
+
+	return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	prom_early_allocated += size;
+
+	return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+	if (!dp)
+		return 0;
+
+	return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ *
+ * As an example, the boot device on my workstation has a full path:
+ *
+ *	/pci@1e,600000/ide@d/disk@0,0:c
+ */
+static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *rprop;
+	u32 high_bits, low_bits, type;
+
+	rprop = of_find_property(dp, "reg", NULL);
+	if (!rprop)
+		return;
+
+	regs = rprop->value;
+	if (!is_root_node(dp->parent)) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			(unsigned int) (regs->phys_addr >> 32UL),
+			(unsigned int) (regs->phys_addr & 0xffffffffUL));
+		return;
+	}
+
+	type = regs->phys_addr >> 60UL;
+	high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL;
+	low_bits = (regs->phys_addr & 0xffffffffUL);
+
+	if (type == 0 || type == 8) {
+		const char *prefix = (type == 0) ? "m" : "i";
+
+		if (low_bits)
+			sprintf(tmp_buf, "%s@%s%x,%x",
+				dp->name, prefix,
+				high_bits, low_bits);
+		else
+			sprintf(tmp_buf, "%s@%s%x",
+				dp->name,
+				prefix,
+				high_bits);
+	} else if (type == 12) {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name, high_bits);
+	}
+}
+
+static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	if (!is_root_node(dp->parent)) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			(unsigned int) (regs->phys_addr >> 32UL),
+			(unsigned int) (regs->phys_addr & 0xffffffffUL));
+		return;
+	}
+
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (!prop)
+		prop = of_find_property(dp, "portid", NULL);
+	if (prop) {
+		unsigned long mask = 0xffffffffUL;
+
+		if (tlb_type >= cheetah)
+			mask = 0x7fffff;
+
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			*(u32 *)prop->value,
+			(unsigned int) (regs->phys_addr & mask));
+	}
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io,
+		regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_pci_registers *regs;
+	struct property *prop;
+	unsigned int devfn;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	devfn = (regs->phys_hi >> 8) & 0xff;
+	if (devfn & 0x07) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			devfn >> 3,
+			devfn & 0x07);
+	} else {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name,
+			devfn >> 3);
+	}
+}
+
+/* "name@UPA_PORTID,offset" */
+static void __init upa_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (!prop)
+		return;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		*(u32 *) prop->value,
+		(unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@reg" */
+static void __init vdev_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x", dp->name, *regs);
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		(unsigned int) (regs->phys_addr >> 32UL),
+		(unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@bus,addr" */
+static void __init i2c_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	/* This actually isn't right... should look at the #address-cells
+	 * property of the i2c bus node etc. etc.
+	 */
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name, regs[0], regs[1]);
+}
+
+/* "name@reg0[,reg1]" */
+static void __init usb_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	if (prop->length == sizeof(u32) || regs[1] == 1) {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name, regs[0]);
+	} else {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name, regs[0], regs[1]);
+	}
+}
+
+/* "name@reg0reg1[,reg2reg3]" */
+static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	if (regs[2] || regs[3]) {
+		sprintf(tmp_buf, "%s@%08x%08x,%04x%08x",
+			dp->name, regs[0], regs[1], regs[2], regs[3]);
+	} else {
+		sprintf(tmp_buf, "%s@%08x%08x",
+			dp->name, regs[0], regs[1]);
+	}
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct device_node *parent = dp->parent;
+
+	if (parent != NULL) {
+		if (!strcmp(parent->type, "pci") ||
+		    !strcmp(parent->type, "pciex"))
+			return pci_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "sbus"))
+			return sbus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "upa"))
+			return upa_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "ebus"))
+			return ebus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->name, "usb") ||
+		    !strcmp(parent->name, "hub"))
+			return usb_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "i2c"))
+			return i2c_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "firewire"))
+			return ieee1394_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "virtual-devices"))
+			return vdev_path_component(dp, tmp_buf);
+
+		/* "isa" is handled with platform naming */
+	}
+
+	/* Use platform naming convention.  */
+	if (tlb_type == hypervisor)
+		return sun4v_path_component(dp, tmp_buf);
+	else
+		return sun4u_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+	char tmp_buf[64], *n;
+
+	tmp_buf[0] = '\0';
+	__build_path_component(dp, tmp_buf);
+	if (tmp_buf[0] == '\0')
+		strcpy(tmp_buf, dp->name);
+
+	n = prom_early_alloc(strlen(tmp_buf) + 1);
+	strcpy(n, tmp_buf);
+
+	return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+	int len, ourlen, plen;
+	char *n;
+
+	plen = strlen(dp->parent->full_name);
+	ourlen = strlen(dp->path_component_name);
+	len = ourlen + plen + 2;
+
+	n = prom_early_alloc(len);
+	strcpy(n, dp->parent->full_name);
+	if (!is_root_node(dp->parent)) {
+		strcpy(n + plen, "/");
+		plen++;
+	}
+	strcpy(n + plen, dp->path_component_name);
+
+	return n;
+}
+
+static struct property * __init build_one_prop(phandle node, char *prev)
+{
+	static struct property *tmp = NULL;
+	struct property *p;
+
+	if (tmp) {
+		p = tmp;
+		memset(p, 0, sizeof(*p) + 32);
+		tmp = NULL;
+	} else
+		p = prom_early_alloc(sizeof(struct property) + 32);
+
+	p->name = (char *) (p + 1);
+	if (prev == NULL) {
+		prom_firstprop(node, p->name);
+	} else {
+		prom_nextprop(node, prev, p->name);
+	}
+	if (strlen(p->name) == 0) {
+		tmp = p;
+		return NULL;
+	}
+	p->length = prom_getproplen(node, p->name);
+	if (p->length <= 0) {
+		p->length = 0;
+	} else {
+		p->value = prom_early_alloc(p->length);
+		prom_getproperty(node, p->name, p->value, p->length);
+	}
+	return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+	struct property *head, *tail;
+
+	head = tail = build_one_prop(node, NULL);
+	while(tail) {
+		tail->next = build_one_prop(node, tail->name);
+		tail = tail->next;
+	}
+
+	return head;
+}
+
+static char * __init get_one_property(phandle node, const char *name)
+{
+	char *buf = "<NULL>";
+	int len;
+
+	len = prom_getproplen(node, name);
+	if (len > 0) {
+		buf = prom_early_alloc(len);
+		prom_getproperty(node, name, buf, len);
+	}
+
+	return buf;
+}
+
+static struct device_node * __init create_node(phandle node)
+{
+	struct device_node *dp;
+
+	if (!node)
+		return NULL;
+
+	dp = prom_early_alloc(sizeof(*dp));
+
+	kref_init(&dp->kref);
+
+	dp->name = get_one_property(node, "name");
+	dp->type = get_one_property(node, "device_type");
+	dp->node = node;
+
+	/* Build interrupts later... */
+
+	dp->properties = build_prop_list(node);
+
+	return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+	struct device_node *dp;
+
+	dp = create_node(node);
+	if (dp) {
+		*(*nextp) = dp;
+		*nextp = &dp->allnext;
+
+		dp->parent = parent;
+		dp->path_component_name = build_path_component(dp);
+		dp->full_name = build_full_name(dp);
+
+		dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+		dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+	}
+
+	return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+	struct device_node **nextp;
+
+	allnodes = create_node(prom_root_node);
+	allnodes->path_component_name = "";
+	allnodes->full_name = "/";
+
+	nextp = &allnodes->allnext;
+	allnodes->child = build_tree(allnodes,
+				     prom_getchild(allnodes->node),
+				     &nextp);
+	printk("PROM: Built device tree with %u bytes of memory.\n",
+	       prom_early_allocated);
+}
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 1d6ffdeabd4c..ac05e0f692ef 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -19,6 +19,7 @@
 #include <asm/cache.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
+#include <asm/prom.h>
 #include <asm/starfire.h>
 
 #include "iommu_common.h"
@@ -691,36 +692,6 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
 	upa_writeq(val, cfg_reg);
 }
 
-/* SBUS SYSIO INO number to Sparc PIL level. */
-static unsigned char sysio_ino_to_pil[] = {
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 0 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 1 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 2 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 3 */
-	5, /* Onboard SCSI */
-	5, /* Onboard Ethernet */
-/*XXX*/	8, /* Onboard BPP */
-	0, /* Bogon */
-       13, /* Audio */
-/*XXX*/15, /* PowerFail */
-	0, /* Bogon */
-	0, /* Bogon */
-       12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */
-       11, /* Floppy */
-	0, /* Spare Hardware (bogon for now) */
-	0, /* Keyboard (bogon for now) */
-	0, /* Mouse (bogon for now) */
-	0, /* Serial (bogon for now) */
-     0, 0, /* Bogon, Bogon */
-       10, /* Timer 0 */
-       11, /* Timer 1 */
-     0, 0, /* Bogon, Bogon */
-       15, /* Uncorrectable SBUS Error */
-       15, /* Correctable SBUS Error */
-       15, /* SBUS Error */
-/*XXX*/ 0, /* Power Management (bogon for now) */
-};
-
 /* INO number to IMAP register offset for SYSIO external IRQ's.
  * This should conform to both Sunfire/Wildfire server and Fusion
  * desktop designs.
@@ -812,21 +783,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
 	struct sbus_iommu *iommu = sbus->iommu;
 	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
 	unsigned long imap, iclr;
-	int pil, sbus_level = 0;
-
-	pil = sysio_ino_to_pil[ino];
-	if (!pil) {
-		printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino);
-		panic("Bad SYSIO IRQ translations...");
-	}
-
-	if (PIL_RESERVED(pil))
-		BUG();
+	int sbus_level = 0;
 
 	imap = sysio_irq_offsets[ino];
 	if (imap == ((unsigned long)-1)) {
-		prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n",
-			    ino, pil);
+		prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
+			    ino);
 		prom_halt();
 	}
 	imap += reg_base;
@@ -860,7 +822,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
 
 		iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
 	}
-	return build_irq(pil, sbus_level, iclr, imap);
+	return build_irq(sbus_level, iclr, imap);
 }
 
 /* Error interrupt handling. */
@@ -1137,24 +1099,25 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
 }
 
 /* Boot time initialization. */
-void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
+static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 {
-	struct linux_prom64_registers rprop;
+	struct linux_prom64_registers *pr;
+	struct device_node *dp;
 	struct sbus_iommu *iommu;
 	unsigned long regs, tsb_base;
 	u64 control;
-	int err, i;
+	int i;
 
-	sbus->portid = prom_getintdefault(sbus->prom_node,
-					  "upa-portid", -1);
+	dp = of_find_node_by_phandle(__node);
 
-	err = prom_getproperty(prom_node, "reg",
-			       (char *)&rprop, sizeof(rprop));
-	if (err < 0) {
+	sbus->portid = of_getintprop_default(dp, "upa-portid", -1);
+
+	pr = of_get_property(dp, "reg", NULL);
+	if (!pr) {
 		prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");
 		prom_halt();
 	}
-	regs = rprop.phys_addr;
+	regs = pr->phys_addr;
 
 	iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC);
 	if (iommu == NULL) {
@@ -1264,3 +1227,50 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
 
 	sysio_register_error_handlers(sbus);
 }
+
+void sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+	struct device_node *dp = of_find_node_by_phandle(sdev->prom_node);
+	struct linux_prom_irqs *irqs;
+
+	irqs = of_get_property(dp, "interrupts", NULL);
+	if (!irqs) {
+		sdev->irqs[0] = 0;
+		sdev->num_irqs = 0;
+	} else {
+		unsigned int pri = irqs[0].pri;
+
+		sdev->num_irqs = 1;
+		if (pri < 0x20)
+			pri += sdev->slot * 8;
+
+		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
+	}
+}
+
+void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
+{
+}
+
+void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
+{
+	sbus_iommu_init(dp->node, sbus);
+}
+
+void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
+{
+}
+
+int __init sbus_arch_preinit(void)
+{
+	return 0;
+}
+
+void __init sbus_arch_postinit(void)
+{
+	extern void firetruck_init(void);
+	extern void clock_probe(void);
+
+	firetruck_init();
+	clock_probe();
+}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 9cf1c88cd774..a6a7d8168346 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -376,12 +376,12 @@ void __init setup_arch(char **cmdline_p)
 	}
 #endif
 
-	smp_setup_cpu_possible_map();
-
 	/* Get boot processor trap_block[] setup.  */
 	init_cur_cpu_trap(current_thread_info());
 
 	paging_init();
+
+	smp_setup_cpu_possible_map();
 }
 
 static int __init set_preferred_console(void)
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index f03d52d0b88d..f62bf3a2de1a 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -39,6 +39,7 @@
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
+#include <asm/prom.h>
 
 extern void calibrate_delay(void);
 
@@ -76,41 +77,42 @@ void smp_bogo(struct seq_file *m)
 
 void __init smp_store_cpu_info(int id)
 {
-	int cpu_node, def;
+	struct device_node *dp;
+	int def;
 
 	/* multiplier and counter set by
 	   smp_setup_percpu_timer()  */
 	cpu_data(id).udelay_val			= loops_per_jiffy;
 
-	cpu_find_by_mid(id, &cpu_node);
-	cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
-						     "clock-frequency", 0);
+	cpu_find_by_mid(id, &dp);
+	cpu_data(id).clock_tick =
+		of_getintprop_default(dp, "clock-frequency", 0);
 
 	def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
-	cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
-						      def);
+	cpu_data(id).dcache_size =
+		of_getintprop_default(dp, "dcache-size", def);
 
 	def = 32;
 	cpu_data(id).dcache_line_size =
-		prom_getintdefault(cpu_node, "dcache-line-size", def);
+		of_getintprop_default(dp, "dcache-line-size", def);
 
 	def = 16 * 1024;
-	cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
-						      def);
+	cpu_data(id).icache_size =
+		of_getintprop_default(dp, "icache-size", def);
 
 	def = 32;
 	cpu_data(id).icache_line_size =
-		prom_getintdefault(cpu_node, "icache-line-size", def);
+		of_getintprop_default(dp, "icache-line-size", def);
 
 	def = ((tlb_type == hypervisor) ?
 	       (3 * 1024 * 1024) :
 	       (4 * 1024 * 1024));
-	cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
-						      def);
+	cpu_data(id).ecache_size =
+		of_getintprop_default(dp, "ecache-size", def);
 
 	def = 64;
 	cpu_data(id).ecache_line_size =
-		prom_getintdefault(cpu_node, "ecache-line-size", def);
+		of_getintprop_default(dp, "ecache-line-size", def);
 
 	printk("CPU[%d]: Caches "
 	       "D[sz(%d):line_sz(%d)] "
@@ -342,10 +344,10 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
 
 		prom_startcpu_cpuid(cpu, entry, cookie);
 	} else {
-		int cpu_node;
+		struct device_node *dp;
 
-		cpu_find_by_mid(cpu, &cpu_node);
-		prom_startcpu(cpu_node, entry, cookie);
+		cpu_find_by_mid(cpu, &dp);
+		prom_startcpu(dp->node, entry, cookie);
 	}
 
 	for (timeout = 0; timeout < 5000000; timeout++) {
@@ -1289,7 +1291,8 @@ int setup_profiling_timer(unsigned int multiplier)
 
 static void __init smp_tune_scheduling(void)
 {
-	int instance, node;
+	struct device_node *dp;
+	int instance;
 	unsigned int def, smallest = ~0U;
 
 	def = ((tlb_type == hypervisor) ?
@@ -1297,10 +1300,10 @@ static void __init smp_tune_scheduling(void)
 	       (4 * 1024 * 1024));
 
 	instance = 0;
-	while (!cpu_find_by_instance(instance, &node, NULL)) {
+	while (!cpu_find_by_instance(instance, &dp, NULL)) {
 		unsigned int val;
 
-		val = prom_getintdefault(node, "ecache-size", def);
+		val = of_getintprop_default(dp, "ecache-size", def);
 		if (val < smallest)
 			smallest = val;
 
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 38e569f786dd..4ac35dd2088b 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -125,9 +125,6 @@ EXPORT_SYMBOL(__write_lock);
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
 
-/* Hard IRQ locking */
-EXPORT_SYMBOL(synchronize_irq);
-
 #if defined(CONFIG_MCOUNT)
 extern void _mcount(void);
 EXPORT_SYMBOL(_mcount);
@@ -175,10 +172,6 @@ EXPORT_SYMBOL(set_bit);
 EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(change_bit);
 
-EXPORT_SYMBOL(ivector_table);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-
 EXPORT_SYMBOL(__flushw_user);
 
 EXPORT_SYMBOL(tlb_type);
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index b49a68bdda43..49703c3c5769 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -5,6 +5,7 @@
 
 #include <asm/cpudata.h>
 #include <asm/intr_queue.h>
+#include <asm/pil.h>
 
 	.text
 	.align	32
@@ -102,23 +103,17 @@ sun4v_dev_mondo:
 
 	/* Get &ivector_table[IVEC] into %g4.  */
 	sethi	%hi(ivector_table), %g4
-	sllx	%g3, 5, %g3
+	sllx	%g3, 3, %g3
 	or	%g4, %lo(ivector_table), %g4
 	add	%g4, %g3, %g4
 
-	/* Load IRQ %pil into %g5.  */
-	ldub	[%g4 + 0x04], %g5
-
 	/* Insert ivector_table[] entry into __irq_work[] queue.  */
-	sllx	%g5, 2, %g3
-	lduw	[%g1 + %g3], %g2	/* g2 = irq_work(cpu, pil) */
+	lduw	[%g1], %g2		/* g2 = irq_work(cpu) */
 	stw	%g2, [%g4 + 0x00]	/* bucket->irq_chain = g2 */
-	stw	%g4, [%g1 + %g3]	/* irq_work(cpu, pil) = bucket */
+	stw	%g4, [%g1]		/* irq_work(cpu) = bucket */
 
 	/* Signal the interrupt by setting (1 << pil) in %softint.  */
-	mov	1, %g2
-	sllx	%g2, %g5, %g2
-	wr	%g2, 0x0, %set_softint
+	wr	%g0, 1 << PIL_DEVICE_IRQ, %set_softint
 
 sun4v_dev_mondo_queue_empty:
 	retry
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index e55b5c6ece02..348b82035561 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -48,6 +48,7 @@
 #include <asm/sections.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
+#include <asm/prom.h>
 
 DEFINE_SPINLOCK(mostek_lock);
 DEFINE_SPINLOCK(rtc_lock);
@@ -457,7 +458,7 @@ static inline void timer_check_rtc(void)
 	}
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ticks, compare, pstate;
 
@@ -755,24 +756,200 @@ retry:
 	return -EOPNOTSUPP;
 }
 
-void __init clock_probe(void)
+static int __init clock_model_matches(char *model)
 {
-	struct linux_prom_registers clk_reg[2];
-	char model[128];
-	int node, busnd = -1, err;
-	unsigned long flags;
-	struct linux_central *cbus;
+	if (strcmp(model, "mk48t02") &&
+	    strcmp(model, "mk48t08") &&
+	    strcmp(model, "mk48t59") &&
+	    strcmp(model, "m5819") &&
+	    strcmp(model, "m5819p") &&
+	    strcmp(model, "m5823") &&
+	    strcmp(model, "ds1287"))
+		return 0;
+
+	return 1;
+}
+
+static void __init __clock_assign_common(void __iomem *addr, char *model)
+{
+	if (model[5] == '0' && model[6] == '2') {
+		mstk48t02_regs = addr;
+	} else if(model[5] == '0' && model[6] == '8') {
+		mstk48t08_regs = addr;
+		mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
+	} else {
+		mstk48t59_regs = addr;
+		mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
+	}
+}
+
+static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg,
+					char *model)
+{
+	unsigned long addr;
+
+	addr = ((unsigned long) clk_reg[0].phys_addr |
+		(((unsigned long) clk_reg[0].which_io) << 32UL));
+
+	__clock_assign_common((void __iomem *) addr, model);
+}
+
+static int __init clock_probe_central(void)
+{
+	struct linux_prom_registers clk_reg[2], *pr;
+	struct device_node *dp;
+	char *model;
+
+	if (!central_bus)
+		return 0;
+
+	/* Get Central FHC's prom node.  */
+	dp = central_bus->child->prom_node;
+
+	/* Then get the first child device below it.  */
+	dp = dp->child;
+
+	while (dp) {
+		model = of_get_property(dp, "model", NULL);
+		if (!model || !clock_model_matches(model))
+			goto next_sibling;
+
+		pr = of_get_property(dp, "reg", NULL);
+		memcpy(clk_reg, pr, sizeof(clk_reg));
+
+		apply_fhc_ranges(central_bus->child, clk_reg, 1);
+		apply_central_ranges(central_bus, clk_reg, 1);
+
+		clock_assign_clk_reg(clk_reg, model);
+		return 1;
+
+	next_sibling:
+		dp = dp->sibling;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PCI
-	struct linux_ebus *ebus = NULL;
-	struct sparc_isa_bridge *isa_br = NULL;
+static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model)
+{
+	if (!strcmp(model, "ds1287") ||
+	    !strcmp(model, "m5819") ||
+	    !strcmp(model, "m5819p") ||
+	    !strcmp(model, "m5823")) {
+		ds1287_regs = res->start;
+	} else {
+		mstk48t59_regs = (void __iomem *) res->start;
+		mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
+	}
+}
+
+static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev)
+{
+	struct device_node *dp = edev->prom_node;
+	char *model;
+
+	model = of_get_property(dp, "model", NULL);
+	if (!clock_model_matches(model))
+		return 0;
+
+	clock_isa_ebus_assign_regs(&edev->resource[0], model);
+
+	return 1;
+}
+
+static int __init clock_probe_ebus(void)
+{
+	struct linux_ebus *ebus;
+
+	for_each_ebus(ebus) {
+		struct linux_ebus_device *edev;
+
+		for_each_ebusdev(edev, ebus) {
+			if (clock_probe_one_ebus_dev(edev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev)
+{
+	struct device_node *dp = idev->prom_node;
+	char *model;
+
+	model = of_get_property(dp, "model", NULL);
+	if (!clock_model_matches(model))
+		return 0;
+
+	clock_isa_ebus_assign_regs(&idev->resource, model);
+
+	return 1;
+}
+
+static int __init clock_probe_isa(void)
+{
+	struct sparc_isa_bridge *isa_br;
+
+	for_each_isa(isa_br) {
+		struct sparc_isa_device *isa_dev;
+
+		for_each_isadev(isa_dev, isa_br) {
+			if (clock_probe_one_isa_dev(isa_dev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_SBUS
+static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev)
+{
+	struct resource *res;
+	char model[64];
+	void __iomem *addr;
+
+	prom_getstring(sdev->prom_node, "model", model, sizeof(model));
+	if (!clock_model_matches(model))
+		return 0;
+
+	res = &sdev->resource[0];
+	addr = sbus_ioremap(res, 0, 0x800UL, "eeprom");
+
+	__clock_assign_common(addr, model);
+
+	return 1;
+}
+
+static int __init clock_probe_sbus(void)
+{
+	struct sbus_bus *sbus;
+
+	for_each_sbus(sbus) {
+		struct sbus_dev *sdev;
+
+		for_each_sbusdev(sdev, sbus) {
+			if (clock_probe_one_sbus_dev(sbus, sdev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
 #endif
+
+void __init clock_probe(void)
+{
 	static int invoked;
+	unsigned long flags;
 
 	if (invoked)
 		return;
 	invoked = 1;
 
-
 	if (this_is_starfire) {
 		xtime.tv_sec = starfire_get_time();
 		xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
@@ -788,183 +965,27 @@ void __init clock_probe(void)
 		return;
 	}
 
-	local_irq_save(flags);
-
-	cbus = central_bus;
-	if (cbus != NULL)
-		busnd = central_bus->child->prom_node;
-
 	/* Check FHC Central then EBUSs then ISA bridges then SBUSs.
 	 * That way we handle the presence of multiple properly.
 	 *
 	 * As a special case, machines with Central must provide the
 	 * timer chip there.
 	 */
+	if (!clock_probe_central() &&
 #ifdef CONFIG_PCI
-	if (ebus_chain != NULL) {
-		ebus = ebus_chain;
-		if (busnd == -1)
-			busnd = ebus->prom_node;
-	}
-	if (isa_chain != NULL) {
-		isa_br = isa_chain;
-		if (busnd == -1)
-			busnd = isa_br->prom_node;
-	}
-#endif
-	if (sbus_root != NULL && busnd == -1)
-		busnd = sbus_root->prom_node;
-
-	if (busnd == -1) {
-		prom_printf("clock_probe: problem, cannot find bus to search.\n");
-		prom_halt();
-	}
-
-	node = prom_getchild(busnd);
-
-	while (1) {
-		if (!node)
-			model[0] = 0;
-		else
-			prom_getstring(node, "model", model, sizeof(model));
-		if (strcmp(model, "mk48t02") &&
-		    strcmp(model, "mk48t08") &&
-		    strcmp(model, "mk48t59") &&
-		    strcmp(model, "m5819") &&
-		    strcmp(model, "m5819p") &&
-		    strcmp(model, "m5823") &&
-		    strcmp(model, "ds1287")) {
-			if (cbus != NULL) {
-				prom_printf("clock_probe: Central bus lacks timer chip.\n");
-				prom_halt();
-			}
-
-		   	if (node != 0)
-				node = prom_getsibling(node);
-#ifdef CONFIG_PCI
-			while ((node == 0) && ebus != NULL) {
-				ebus = ebus->next;
-				if (ebus != NULL) {
-					busnd = ebus->prom_node;
-					node = prom_getchild(busnd);
-				}
-			}
-			while ((node == 0) && isa_br != NULL) {
-				isa_br = isa_br->next;
-				if (isa_br != NULL) {
-					busnd = isa_br->prom_node;
-					node = prom_getchild(busnd);
-				}
-			}
+	    !clock_probe_ebus() &&
+	    !clock_probe_isa() &&
 #endif
-			if (node == 0) {
-				prom_printf("clock_probe: Cannot find timer chip\n");
-				prom_halt();
-			}
-			continue;
-		}
-
-		err = prom_getproperty(node, "reg", (char *)clk_reg,
-				       sizeof(clk_reg));
-		if(err == -1) {
-			prom_printf("clock_probe: Cannot get Mostek reg property\n");
-			prom_halt();
-		}
-
-		if (cbus != NULL) {
-			apply_fhc_ranges(central_bus->child, clk_reg, 1);
-			apply_central_ranges(central_bus, clk_reg, 1);
-		}
-#ifdef CONFIG_PCI
-		else if (ebus != NULL) {
-			struct linux_ebus_device *edev;
-
-			for_each_ebusdev(edev, ebus)
-				if (edev->prom_node == node)
-					break;
-			if (edev == NULL) {
-				if (isa_chain != NULL)
-					goto try_isa_clock;
-				prom_printf("%s: Mostek not probed by EBUS\n",
-					    __FUNCTION__);
-				prom_halt();
-			}
-
-			if (!strcmp(model, "ds1287") ||
-			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p") ||
-			    !strcmp(model, "m5823")) {
-				ds1287_regs = edev->resource[0].start;
-			} else {
-				mstk48t59_regs = (void __iomem *)
-					edev->resource[0].start;
-				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-			}
-			break;
-		}
-		else if (isa_br != NULL) {
-			struct sparc_isa_device *isadev;
-
-try_isa_clock:
-			for_each_isadev(isadev, isa_br)
-				if (isadev->prom_node == node)
-					break;
-			if (isadev == NULL) {
-				prom_printf("%s: Mostek not probed by ISA\n");
-				prom_halt();
-			}
-			if (!strcmp(model, "ds1287") ||
-			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p") ||
-			    !strcmp(model, "m5823")) {
-				ds1287_regs = isadev->resource.start;
-			} else {
-				mstk48t59_regs = (void __iomem *)
-					isadev->resource.start;
-				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-			}
-			break;
-		}
+#ifdef CONFIG_SBUS
+	    !clock_probe_sbus()
 #endif
-		else {
-			if (sbus_root->num_sbus_ranges) {
-				int nranges = sbus_root->num_sbus_ranges;
-				int rngc;
-
-				for (rngc = 0; rngc < nranges; rngc++)
-					if (clk_reg[0].which_io ==
-					    sbus_root->sbus_ranges[rngc].ot_child_space)
-						break;
-				if (rngc == nranges) {
-					prom_printf("clock_probe: Cannot find ranges for "
-						    "clock regs.\n");
-					prom_halt();
-				}
-				clk_reg[0].which_io =
-					sbus_root->sbus_ranges[rngc].ot_parent_space;
-				clk_reg[0].phys_addr +=
-					sbus_root->sbus_ranges[rngc].ot_parent_base;
-			}
-		}
-
-		if(model[5] == '0' && model[6] == '2') {
-			mstk48t02_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-		} else if(model[5] == '0' && model[6] == '8') {
-			mstk48t08_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-			mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
-		} else {
-			mstk48t59_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-		}
-		break;
+		) {
+		printk(KERN_WARNING "No clock chip found.\n");
+		return;
 	}
 
+	local_irq_save(flags);
+
 	if (mstk48t02_regs != NULL) {
 		/* Report a low battery voltage condition. */
 		if (has_low_battery())
@@ -983,12 +1004,14 @@ try_isa_clock:
 /* This is gets the master TICK_INT timer going. */
 static unsigned long sparc64_init_timers(void)
 {
+	struct device_node *dp;
+	struct property *prop;
 	unsigned long clock;
-	int node;
 #ifdef CONFIG_SMP
 	extern void smp_tick_init(void);
 #endif
 
+	dp = of_find_node_by_path("/");
 	if (tlb_type == spitfire) {
 		unsigned long ver, manuf, impl;
 
@@ -999,18 +1022,17 @@ static unsigned long sparc64_init_timers(void)
 		if (manuf == 0x17 && impl == 0x13) {
 			/* Hummingbird, aka Ultra-IIe */
 			tick_ops = &hbtick_operations;
-			node = prom_root_node;
-			clock = prom_getint(node, "stick-frequency");
+			prop = of_find_property(dp, "stick-frequency", NULL);
 		} else {
 			tick_ops = &tick_operations;
-			cpu_find_by_instance(0, &node, NULL);
-			clock = prom_getint(node, "clock-frequency");
+			cpu_find_by_instance(0, &dp, NULL);
+			prop = of_find_property(dp, "clock-frequency", NULL);
 		}
 	} else {
 		tick_ops = &stick_operations;
-		node = prom_root_node;
-		clock = prom_getint(node, "stick-frequency");
+		prop = of_find_property(dp, "stick-frequency", NULL);
 	}
+	clock = *(unsigned int *) prop->value;
 	timer_tick_offset = clock / HZ;
 
 #ifdef CONFIG_SMP
@@ -1020,19 +1042,9 @@ static unsigned long sparc64_init_timers(void)
 	return clock;
 }
 
-static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+static void sparc64_start_timers(void)
 {
 	unsigned long pstate;
-	int err;
-
-	/* Register IRQ handler. */
-	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0,
-			  "timer", NULL);
-
-	if (err) {
-		prom_printf("Serious problem, cannot register TICK_INT\n");
-		prom_halt();
-	}
 
 	/* Guarantee that the following sequences execute
 	 * uninterrupted.
@@ -1116,7 +1128,7 @@ void __init time_init(void)
 	/* Now that the interpolator is registered, it is
 	 * safe to start the timer ticking.
 	 */
-	sparc64_start_timers(timer_interrupt);
+	sparc64_start_timers();
 
 	timer_ticks_per_nsec_quotient =
 		(((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) +
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 563db528e031..1ff34b019f3f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -42,6 +42,7 @@
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#include <asm/prom.h>
 
 ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
 
@@ -807,7 +808,8 @@ extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector
 void __init cheetah_ecache_flush_init(void)
 {
 	unsigned long largest_size, smallest_linesize, order, ver;
-	int node, i, instance;
+	struct device_node *dp;
+	int i, instance, sz;
 
 	/* Scan all cpu device tree nodes, note two values:
 	 * 1) largest E-cache size
@@ -817,14 +819,14 @@ void __init cheetah_ecache_flush_init(void)
 	smallest_linesize = ~0UL;
 
 	instance = 0;
-	while (!cpu_find_by_instance(instance, &node, NULL)) {
+	while (!cpu_find_by_instance(instance, &dp, NULL)) {
 		unsigned long val;
 
-		val = prom_getintdefault(node, "ecache-size",
-					 (2 * 1024 * 1024));
+		val = of_getintprop_default(dp, "ecache-size",
+					    (2 * 1024 * 1024));
 		if (val > largest_size)
 			largest_size = val;
-		val = prom_getintdefault(node, "ecache-line-size", 64);
+		val = of_getintprop_default(dp, "ecache-line-size", 64);
 		if (val < smallest_linesize)
 			smallest_linesize = val;
 		instance++;
@@ -849,16 +851,16 @@ void __init cheetah_ecache_flush_init(void)
 	}
 
 	/* Now allocate error trap reporting scoreboard. */
-	node = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
+	sz = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
 	for (order = 0; order < MAX_ORDER; order++) {
-		if ((PAGE_SIZE << order) >= node)
+		if ((PAGE_SIZE << order) >= sz)
 			break;
 	}
 	cheetah_error_log = (struct cheetah_err_info *)
 		__get_free_pages(GFP_KERNEL, order);
 	if (!cheetah_error_log) {
 		prom_printf("cheetah_ecache_flush_init: Failed to allocate "
-			    "error logging scoreboard (%d bytes).\n", node);
+			    "error logging scoreboard (%d bytes).\n", sz);
 		prom_halt();
 	}
 	memset(cheetah_error_log, 0, PAGE_SIZE << order);
@@ -2544,7 +2546,9 @@ void __init trap_init(void)
 	    (TRAP_PER_CPU_TSB_HUGE !=
 	     offsetof(struct trap_per_cpu, tsb_huge)) ||
 	    (TRAP_PER_CPU_TSB_HUGE_TEMP !=
-	     offsetof(struct trap_per_cpu, tsb_huge_temp)))
+	     offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
+	    (TRAP_PER_CPU_IRQ_WORKLIST !=
+	     offsetof(struct trap_per_cpu, irq_worklist)))
 		trap_per_cpu_offsets_are_bolixed_dave();
 
 	if ((TSB_CONFIG_TSB !=
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 5d901519db55..ee45ca2d7a04 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -58,13 +58,11 @@ tl0_irq2:	BTRAP(0x42)
 tl0_irq3:	BTRAP(0x43)
 tl0_irq4:	BTRAP(0x44)
 #endif
-tl0_irq5:	TRAP_IRQ(handler_irq, 5)  TRAP_IRQ(handler_irq, 6)
-tl0_irq7:	TRAP_IRQ(handler_irq, 7)  TRAP_IRQ(handler_irq, 8)
-tl0_irq9:	TRAP_IRQ(handler_irq, 9)  TRAP_IRQ(handler_irq, 10)
-tl0_irq11:	TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
-tl0_irq13:	TRAP_IRQ(handler_irq, 13)
+tl0_irq5:	TRAP_IRQ(handler_irq, 5)
+tl0_irq6:	BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+tl0_irq10:	BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 #ifndef CONFIG_SMP
-tl0_irq14:	TRAP_IRQ(handler_irq, 14)
+tl0_irq14:	TRAP_IRQ(timer_irq, 14)
 #else
 tl0_irq14:	TICK_SMP_IRQ
 #endif
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 001e8518331f..bb2d68577855 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -279,12 +279,21 @@ static void kernel_mna_trap_fault(void)
 
 asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 {
+	static unsigned long count, last_time;
 	enum direction dir = decode_direction(insn);
 	int size = decode_access_size(insn);
 
 	current_thread_info()->kern_una_regs = regs;
 	current_thread_info()->kern_una_insn = insn;
 
+	if (jiffies - last_time > 5 * HZ)
+		count = 0;
+	if (count < 5) {
+		last_time = jiffies;
+		count++;
+		printk("Kernel unaligned access at TPC[%lx]\n", regs->tpc);
+	}
+
 	if (!ok_for_kernel(insn) || dir == both) {
 		printk("Unsupported unaligned load/store trap for kernel "
 		       "at <%016lx>.\n", regs->tpc);
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 1539a8362b6f..513993414747 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -42,6 +42,7 @@
 #include <asm/sections.h>
 #include <asm/tsb.h>
 #include <asm/hypervisor.h>
+#include <asm/prom.h>
 
 extern void device_scan(void);
 
@@ -101,8 +102,6 @@ static void __init read_obp_memory(const char *property,
 		prom_halt();
 	}
 
-	*num_ents = ents;
-
 	/* Sanitize what we got from the firmware, by page aligning
 	 * everything.
 	 */
@@ -124,6 +123,25 @@ static void __init read_obp_memory(const char *property,
 		regs[i].phys_addr = base;
 		regs[i].reg_size = size;
 	}
+
+	for (i = 0; i < ents; i++) {
+		if (regs[i].reg_size == 0UL) {
+			int j;
+
+			for (j = i; j < ents - 1; j++) {
+				regs[j].phys_addr =
+					regs[j+1].phys_addr;
+				regs[j].reg_size =
+					regs[j+1].reg_size;
+			}
+
+			ents--;
+			i--;
+		}
+	}
+
+	*num_ents = ents;
+
 	sort(regs, ents, sizeof(struct linux_prom64_registers),
 	     cmp_p64, NULL);
 }
@@ -1339,6 +1357,8 @@ void __init paging_init(void)
 
 	kernel_physical_mapping_init();
 
+	prom_build_devicetree();
+
 	{
 		unsigned long zones_size[MAX_NR_ZONES];
 		unsigned long zholes_size[MAX_NR_ZONES];
@@ -1376,7 +1396,7 @@ static void __init taint_real_pages(void)
 		while (old_start < old_end) {
 			int n;
 
-			for (n = 0; pavail_rescan_ents; n++) {
+			for (n = 0; n < pavail_rescan_ents; n++) {
 				unsigned long new_start, new_end;
 
 				new_start = pavail_rescan[n].phys_addr;
@@ -1398,6 +1418,32 @@ static void __init taint_real_pages(void)
 	}
 }
 
+int __init page_in_phys_avail(unsigned long paddr)
+{
+	int i;
+
+	paddr &= PAGE_MASK;
+
+	for (i = 0; i < pavail_rescan_ents; i++) {
+		unsigned long start, end;
+
+		start = pavail_rescan[i].phys_addr;
+		end = start + pavail_rescan[i].reg_size;
+
+		if (paddr >= start && paddr < end)
+			return 1;
+	}
+	if (paddr >= kern_base && paddr < (kern_base + kern_size))
+		return 1;
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (paddr >= __pa(initrd_start) &&
+	    paddr < __pa(PAGE_ALIGN(initrd_end)))
+		return 1;
+#endif
+
+	return 0;
+}
+
 void __init mem_init(void)
 {
 	unsigned long codepages, datapages, initpages;
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 4885ca6cbc77..0f0eb6aa1c40 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -356,7 +356,7 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
 	int error;
 	struct sol_statvfs __user *ss = A(buf);
 
-	error = vfs_statfs(mnt->mnt_sb, &s);
+	error = vfs_statfs(mnt->mnt_root, &s);
 	if (!error) {
 		const char *p = mnt->mnt_sb->s_type->name;
 		int i = 0;
@@ -392,7 +392,7 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
 	int error;
 	struct sol_statvfs64 __user *ss = A(buf);
 			
-	error = vfs_statfs(mnt->mnt_sb, &s);
+	error = vfs_statfs(mnt->mnt_root, &s);
 	if (!error) {
 		const char *p = mnt->mnt_sb->s_type->name;
 		int i = 0;
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 5284996780a7..719c90905a1e 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -23,6 +23,7 @@
 #include <asm/oplib.h>
 #include <asm/idprom.h>
 #include <asm/smp.h>
+#include <asm/prom.h>
 
 #include "conv.h"
 
@@ -194,14 +195,17 @@ static char *machine(void)
 	}
 }
 
-static char *platform(char *buffer)
+static char *platform(char *buffer, int sz)
 {
+	struct device_node *dp = of_find_node_by_path("/");
 	int len;
 
 	*buffer = 0;
-	len = prom_getproperty(prom_root_node, "name", buffer, 256);
-	if(len > 0)
-		buffer[len] = 0;
+	len = strlen(dp->name);
+	if (len > sz)
+		len = sz;
+	memcpy(buffer, dp->name, len);
+	buffer[len] = 0;
 	if (*buffer) {
 		char *p;
 
@@ -213,16 +217,22 @@ static char *platform(char *buffer)
 	return "sun4u";
 }
 
-static char *serial(char *buffer)
+static char *serial(char *buffer, int sz)
 {
-	int node = prom_getchild(prom_root_node);
+	struct device_node *dp = of_find_node_by_path("/options");
 	int len;
 
-	node = prom_searchsiblings(node, "options");
 	*buffer = 0;
-	len = prom_getproperty(node, "system-board-serial#", buffer, 256);
-	if(len > 0)
-		buffer[len] = 0;
+	if (dp) {
+		char *val = of_get_property(dp, "system-board-serial#", &len);
+
+		if (val && len > 0) {
+			if (len > sz)
+				len = sz;
+			memcpy(buffer, val, len);
+			buffer[len] = 0;
+		}
+	}
 	if (!*buffer)
 		return "4512348717234";
 	else
@@ -305,8 +315,8 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
 	case SI_MACHINE: r = machine(); break;
 	case SI_ARCHITECTURE: r = "sparc"; break;
 	case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
-	case SI_HW_SERIAL: r = serial(buffer); break;
-	case SI_PLATFORM: r = platform(buffer); break;
+	case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break;
+	case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break;
 	case SI_SRPC_DOMAIN: r = ""; break;
 	case SI_VERSION: r = "Generic"; break;
 	default: return -EINVAL;
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 5681a8bd370b..bab51d619173 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -49,7 +49,6 @@ config GCOV
 
 config SYSCALL_DEBUG
 	bool "Enable system call debugging"
-	default N
 	depends on DEBUG_INFO
 	help
 	This adds some system debugging to UML, including keeping a ring buffer
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index fc0f0b085ca7..166cb09cae4c 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -69,7 +69,7 @@ static void insert_phys_mapping(struct phys_desc *desc)
 		panic("Physical remapping for %p already present",
 		      desc->virt);
 
-	rb_link_node(&desc->rb, (*n)->rb_parent, n);
+	rb_link_node(&desc->rb, rb_parent(*n), n);
 	rb_insert_color(&desc->rb, &phys_mappings);
 }
 
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 86f51d04c98d..87cdbc560d36 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -87,7 +87,7 @@ void timer_irq(union uml_pt_regs *regs)
 
 void time_init_kern(void)
 {
-	unsigned long long nsecs;
+	long long nsecs;
 
 	nsecs = os_nsecs();
 	set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S
index 11b7bd768cfd..f0c971db47e4 100644
--- a/arch/um/sys-ppc/misc.S
+++ b/arch/um/sys-ppc/misc.S
@@ -23,14 +23,10 @@
 #define CACHE_LINE_SIZE		16
 #define LG_CACHE_LINE_SIZE	4
 #define MAX_COPY_PREFETCH	1
-#elif !defined(CONFIG_PPC64BRIDGE)
+#else
 #define CACHE_LINE_SIZE		32
 #define LG_CACHE_LINE_SIZE	5
 #define MAX_COPY_PREFETCH	4
-#else
-#define CACHE_LINE_SIZE		128
-#define LG_CACHE_LINE_SIZE	7
-#define MAX_COPY_PREFETCH	1
 #endif /* CONFIG_4xx || CONFIG_8xx */
 
 	.text
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
index 633e4e1b825f..17c2d4359b04 100644
--- a/arch/v850/kernel/signal.c
+++ b/arch/v850/kernel/signal.c
@@ -274,7 +274,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 	/* Default to using normal stack */
 	unsigned long sp = regs->gpr[GPR_SP];
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void *)((sp - frame_size) & -8UL);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 408d44a59756..af44130f0d65 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -299,6 +299,7 @@ config X86_64_ACPI_NUMA
        bool "ACPI NUMA detection"
        depends on NUMA
        select ACPI 
+	select PCI
        select ACPI_NUMA
        default y
        help
@@ -389,6 +390,7 @@ config GART_IOMMU
 	bool "K8 GART IOMMU support"
 	default y
 	select SWIOTLB
+	select AGP
 	depends on PCI
 	help
 	  Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors
@@ -401,11 +403,9 @@ config GART_IOMMU
   	  northbridge and a software emulation used on other systems without
 	  hardware IOMMU.  If unsure, say Y.
 
-# need this always enabled with GART_IOMMU for the VIA workaround
+# need this always selected by GART_IOMMU for the VIA workaround
 config SWIOTLB
 	bool
-	default y
-	depends on GART_IOMMU
 
 config X86_MCE
 	bool "Machine check support" if EMBEDDED
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5a92fed2d1d5..4ec594ab1a98 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -696,4 +696,5 @@ ia32_sys_call_table:
 	.quad sys_sync_file_range
 	.quad sys_tee
 	.quad compat_sys_vmsplice
+	.quad compat_sys_move_pages
 ia32_syscall_end:		
diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile
index 4fe97071f297..080b9963f1bc 100644
--- a/arch/x86_64/kernel/acpi/Makefile
+++ b/arch/x86_64/kernel/acpi/Makefile
@@ -4,5 +4,6 @@ obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wakeup.o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
 obj-y			+= processor.o
+processor-y		:= ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o
 endif
 
diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c
deleted file mode 100644
index 3bdc2baa5bb1..000000000000
--- a/arch/x86_64/kernel/acpi/processor.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * arch/x86_64/kernel/acpi/processor.c
- *
- * Copyright (C) 2005 Intel Corporation
- * 	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- * 	- Added _PDC for platforms with Intel CPUs
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-
-#include <acpi/processor.h>
-#include <asm/acpi.h>
-
-static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
-{
-	struct acpi_object_list *obj_list;
-	union acpi_object *obj;
-	u32 *buf;
-
-	/* allocate and initialize pdc. It will be used later. */
-	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-	if (!obj_list) {
-		printk(KERN_ERR "Memory allocation error\n");
-		return;
-	}
-
-	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-	if (!obj) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj_list);
-		return;
-	}
-
-	buf = kmalloc(12, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj);
-		kfree(obj_list);
-		return;
-	}
-
-	buf[0] = ACPI_PDC_REVISION_ID;
-	buf[1] = 1;
-	buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
-
-	obj->type = ACPI_TYPE_BUFFER;
-	obj->buffer.length = 12;
-	obj->buffer.pointer = (u8 *) buf;
-	obj_list->count = 1;
-	obj_list->pointer = obj;
-	pr->pdc = obj_list;
-
-	return;
-}
-
-/* Initialize _PDC data based on the CPU vendor */
-void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
-{
-	unsigned int cpu = pr->id;
-	struct cpuinfo_x86 *c = cpu_data + cpu;
-
-	pr->pdc = NULL;
-	if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST))
-		init_intel_pdc(pr, c);
-
-	return;
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index 867a0ebee177..091bc79c888f 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -35,6 +35,8 @@
 #include <linux/pci.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
+#include <linux/cpumask.h>
+
 #include <asm/mpspec.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -66,7 +68,8 @@ static void init_low_mapping(void)
 	pgd_t *slot0 = pgd_offset(current->mm, 0UL);
 	low_ptr = *slot0;
 	set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
-	flush_tlb_all();
+	WARN_ON(num_online_cpus() != 1);
+	local_flush_tlb();
 }
 
 /**
@@ -92,7 +95,7 @@ int acpi_save_state_mem(void)
 void acpi_restore_state_mem(void)
 {
 	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
-	flush_tlb_all();
+	local_flush_tlb();
 }
 
 /**
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 100a30c40044..29ef99001e05 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -51,7 +51,7 @@ int disable_apic_timer __initdata;
 static cpumask_t timer_interrupt_broadcast_ipi_mask;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer = 0;
+int using_apic_timer __read_mostly = 0;
 
 static void apic_pm_activate(void);
 
diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c
index a5d7e16b928e..44ddb1ec808d 100644
--- a/arch/x86_64/kernel/i387.c
+++ b/arch/x86_64/kernel/i387.c
@@ -24,7 +24,7 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-unsigned int mxcsr_feature_mask = 0xffffffff;
+unsigned int mxcsr_feature_mask __read_mostly = 0xffffffff;
 
 void mxcsr_feature_mask_init(void)
 {
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 655b9192eeb3..b8d5116d7371 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -47,6 +47,7 @@
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
+#include <linux/suspend.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -595,6 +596,100 @@ static void discover_ebda(void)
 		ebda_size = 64*1024;
 }
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+static void __init mark_nosave_page_range(unsigned long start, unsigned long end)
+{
+	struct page *page;
+	while (start <= end) {
+		page = pfn_to_page(start);
+		SetPageNosave(page);
+		start++;
+	}
+}
+
+static void __init e820_nosave_reserved_pages(void)
+{
+	int i;
+	unsigned long r_start = 0, r_end = 0;
+
+	/* Assume e820 map is sorted */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long start, end;
+
+		start = round_down(ei->addr, PAGE_SIZE);
+		end = round_up(ei->addr + ei->size, PAGE_SIZE);
+		if (start >= end)
+			continue;
+		if (ei->type == E820_RESERVED)
+			continue;
+		r_end = start>>PAGE_SHIFT;
+		/* swsusp ignores invalid pfn, ignore these pages here */
+		if (r_end > end_pfn)
+			r_end = end_pfn;
+		if (r_end > r_start)
+			mark_nosave_page_range(r_start, r_end-1);
+		if (r_end >= end_pfn)
+			break;
+		r_start = end>>PAGE_SHIFT;
+	}
+}
+
+static void __init e820_save_acpi_pages(void)
+{
+	int i;
+
+	/* Assume e820 map is sorted */
+	for (i = 0; i < e820.nr_map; i++) {
+		struct e820entry *ei = &e820.map[i];
+		unsigned long start, end;
+
+		start = ei->addr, PAGE_SIZE;
+		end = ei->addr + ei->size;
+		if (start >= end)
+			continue;
+		if (ei->type != E820_ACPI && ei->type != E820_NVS)
+			continue;
+		/*
+		 * If the region is below end_pfn, it will be
+		 * saved/restored by swsusp follow 'RAM' type.
+		 */
+		if (start < (end_pfn << PAGE_SHIFT))
+			start = end_pfn << PAGE_SHIFT;
+		if (end > start)
+			swsusp_add_arch_pages(start, end);
+	}
+}
+
+extern char __start_rodata, __end_rodata;
+/*
+ * BIOS reserved region/hole - no save/restore
+ * ACPI NVS - save/restore
+ * ACPI Data - this is a little tricky, the mem could be used by OS after OS
+ * reads tables from the region, but anyway save/restore the memory hasn't any
+ * side effect and Linux runtime module load/unload might use it.
+ * kernel rodata - no save/restore (kernel rodata isn't changed)
+ */
+static int __init mark_nosave_pages(void)
+{
+	unsigned long pfn_start, pfn_end;
+
+	/* BIOS reserved regions & holes */
+	e820_nosave_reserved_pages();
+
+	/* kernel rodata */
+	pfn_start = round_up(__pa_symbol(&__start_rodata), PAGE_SIZE) >> PAGE_SHIFT;
+	pfn_end = round_down(__pa_symbol(&__end_rodata), PAGE_SIZE) >> PAGE_SHIFT;
+	mark_nosave_page_range(pfn_start, pfn_end-1);
+
+	/* record ACPI Data/NVS as saveable */
+	e820_save_acpi_pages();
+
+	return 0;
+}
+core_initcall(mark_nosave_pages);
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long kernel_end;
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 474df22c6ed2..502fce65e96a 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -30,7 +30,6 @@
 static struct acpi_table_slit *acpi_slit;
 
 static nodemask_t nodes_parsed __initdata;
-static nodemask_t nodes_found __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
 static int found_add_area __initdata;
@@ -38,33 +37,14 @@ int hotadd_percent __initdata = 0;
 #ifndef RESERVE_HOTADD
 #define hotadd_percent 0	/* Ignore all settings */
 #endif
-static u8 pxm2node[256] = { [0 ... 255] = 0xff };
 
 /* Too small nodes confuse the VM badly. Usually they result
    from BIOS bugs. */
 #define NODE_MIN_SIZE (4*1024*1024)
 
-static int node_to_pxm(int n);
-
-int pxm_to_node(int pxm)
-{
-	if ((unsigned)pxm >= 256)
-		return -1;
-	/* Extend 0xff to (int)-1 */
-	return (signed char)pxm2node[pxm];
-}
-
 static __init int setup_node(int pxm)
 {
-	unsigned node = pxm2node[pxm];
-	if (node == 0xff) {
-		if (nodes_weight(nodes_found) >= MAX_NUMNODES)
-			return -1;
-		node = first_unset_node(nodes_found); 
-		node_set(node, nodes_found);
-		pxm2node[pxm] = node;
-	}
-	return pxm2node[pxm];
+	return acpi_map_pxm_to_node(pxm);
 }
 
 static __init int conflicting_nodes(unsigned long start, unsigned long end)
@@ -440,17 +420,6 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
 	return 0;
 }
 
-static int node_to_pxm(int n)
-{
-       int i;
-       if (pxm2node[n] == n)
-               return n;
-       for (i = 0; i < 256; i++)
-               if (pxm2node[i] == n)
-                       return i;
-       return 0;
-}
-
 void __init srat_reserve_add_area(int nodeid)
 {
 	if (found_add_area && nodes_add[nodeid].end) {
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index a2060e4d5de6..3c55c76c6fd5 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -13,7 +13,10 @@
 
 #include "pci.h"
 
-#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
+
 /* Verify the first 16 busses. We assume that systems with more busses
    get MCFG right. */
 #define MAX_CHECK_BUS 16
@@ -175,9 +178,10 @@ void __init pci_mmcfg_init(void)
 		return;
 
 	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
 			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
+				pci_mmcfg_config[0].base_address);
 		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
 		return;
 	}
@@ -190,7 +194,8 @@ void __init pci_mmcfg_init(void)
 	}
 	for (i = 0; i < pci_mmcfg_config_num; ++i) {
 		pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
-		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
+		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
+							 MMCONFIG_APER_MAX);
 		if (!pci_mmcfg_virt[i].virt) {
 			printk("PCI: Cannot map mmconfig aperture for segment %d\n",
 			       pci_mmcfg_config[i].pci_segment_group_number);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index dbeb3504c3c8..848f173db257 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -34,10 +34,6 @@ config GENERIC_HARDIRQS
 	bool
 	default y
 
-config RWSEM_GENERIC_SPINLOCK
-       bool
-       default y
-
 source "init/Kconfig"
 
 menu "Processor type and features"
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
index 9e73bb8aeb7a..d3d2aa2d883a 100644
--- a/arch/xtensa/boot/lib/Makefile
+++ b/arch/xtensa/boot/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for some libs needed by zImage.
 #
 
-zlib	:= infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
+zlib	:= inffast.c inflate.c inftrees.c
 
 lib-y	+= $(zlib:.c=.o) zmem.o
 
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 5c018c503dfa..89e409e9e0de 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1102,7 +1102,7 @@ ENTRY(fast_syscall_sysxtensa)
 	s32i	a7, a2, PT_AREG7
 
 	movi	a7, 4			# sizeof(unsigned int)
-	verify_area a3, a7, a0, a2, .Leac
+	access_ok a0, a3, a7, a2, .Leac
 
 	_beqi	a6, SYSXTENSA_ATOMIC_SET, .Lset
 	_beqi	a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index e252b61e45a5..c494f0826fc5 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -104,7 +104,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
 
 	if (act) {
 		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 			return -EFAULT;
@@ -116,7 +116,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 			return -EFAULT;
@@ -236,7 +236,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 	err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
 	err |= __get_user(buf, &sc->sc_cpstate);
 	if (buf) {
-		if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+		if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
 			goto badframe;
 		err |= restore_cpextra(buf);
 	}
@@ -357,7 +357,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
 	if (regs->depc > 64)
 		panic ("Double exception sys_sigreturn\n");
 
-	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 
 	if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -394,7 +394,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 		return 0;
 	}
 
-	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 
 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -433,7 +433,7 @@ badframe:
 static inline void *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void *)((sp - frame_size) & -16ul);