Selaa lähdekoodia

Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (43 commits)
  [POWERPC] Use little-endian bit from firmware ibm,pa-features property
  [POWERPC] Make sure smp_processor_id works very early in boot
  [POWERPC] U4 DART improvements
  [POWERPC] todc: add support for Time-Of-Day-Clock
  [POWERPC] Make lparcfg.c work when both iseries and pseries are selected
  [POWERPC] Fix idr locking in init_new_context
  [POWERPC] mpc7448hpc2 (taiga) board config file
  [POWERPC] Add tsi108 pci and platform device data register function
  [POWERPC] Add general support for mpc7448hpc2 (Taiga) platform
  [POWERPC] Correct the MAX_CONTEXT definition
  powerpc: minor cleanups for mpc86xx
  [POWERPC] Make sure we select CONFIG_NEW_LEDS if ADB_PMU_LED is set
  [POWERPC] Simplify the code defining the 64-bit CPU features
  [POWERPC] powerpc: kconfig warning fix
  [POWERPC] Consolidate some of kernel/misc*.S
  [POWERPC] Remove unused function call_with_mmu_off
  [POWERPC] update asm-powerpc/time.h
  [POWERPC] Clean up it_lp_queue.h
  [POWERPC] Skip the "copy down" of the kernel if it is already at zero.
  [POWERPC] Add the use of the firmware soft-reset-nmi to kdump.
  ...
Linus Torvalds 19 vuotta sitten
vanhempi
commit
3aa590c6b7
77 muutettua tiedostoa jossa 4086 lisäystä ja 1110 poistoa
  1. 18 5
      arch/powerpc/Kconfig
  2. 8 1
      arch/powerpc/Kconfig.debug
  3. 4 3
      arch/powerpc/configs/cell_defconfig
  4. 923 0
      arch/powerpc/configs/mpc7448_hpc2_defconfig
  5. 2 1
      arch/powerpc/kernel/Makefile
  6. 12 2
      arch/powerpc/kernel/cpu_setup_power4.S
  7. 0 12
      arch/powerpc/kernel/cputable.c
  8. 119 28
      arch/powerpc/kernel/crash.c
  9. 12 50
      arch/powerpc/kernel/head_64.S
  10. 30 0
      arch/powerpc/kernel/iommu.c
  11. 11 0
      arch/powerpc/kernel/legacy_serial.c
  12. 76 71
      arch/powerpc/kernel/lparcfg.c
  13. 3 1
      arch/powerpc/kernel/machine_kexec_64.c
  14. 203 0
      arch/powerpc/kernel/misc.S
  15. 0 156
      arch/powerpc/kernel/misc_32.S
  16. 4 219
      arch/powerpc/kernel/misc_64.S
  17. 0 1
      arch/powerpc/kernel/paca.c
  18. 31 18
      arch/powerpc/kernel/prom.c
  19. 105 14
      arch/powerpc/kernel/rtas.c
  20. 12 10
      arch/powerpc/kernel/setup_64.c
  21. 13 14
      arch/powerpc/kernel/traps.c
  22. 5 2
      arch/powerpc/kernel/udbg.c
  23. 1 2
      arch/powerpc/mm/hash_native_64.c
  24. 43 63
      arch/powerpc/mm/hash_utils_64.c
  25. 2 0
      arch/powerpc/mm/mmu_context_64.c
  26. 1 5
      arch/powerpc/platforms/86xx/Kconfig
  27. 0 3
      arch/powerpc/platforms/86xx/Makefile
  28. 0 1
      arch/powerpc/platforms/86xx/mpc8641_hpcn.h
  29. 5 3
      arch/powerpc/platforms/86xx/mpc86xx.h
  30. 121 8
      arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
  31. 4 6
      arch/powerpc/platforms/86xx/mpc86xx_smp.c
  32. 8 129
      arch/powerpc/platforms/86xx/pci.c
  33. 1 0
      arch/powerpc/platforms/Makefile
  34. 1 1
      arch/powerpc/platforms/cell/Kconfig
  35. 10 6
      arch/powerpc/platforms/cell/setup.c
  36. 4 4
      arch/powerpc/platforms/cell/spu_base.c
  37. 5 5
      arch/powerpc/platforms/cell/spufs/file.c
  38. 4 2
      arch/powerpc/platforms/cell/spufs/switch.c
  39. 15 0
      arch/powerpc/platforms/embedded6xx/Kconfig
  40. 4 0
      arch/powerpc/platforms/embedded6xx/Makefile
  41. 335 0
      arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
  42. 26 0
      arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
  43. 2 0
      arch/powerpc/platforms/iseries/dt.c
  44. 1 3
      arch/powerpc/platforms/iseries/htab.c
  45. 28 27
      arch/powerpc/platforms/iseries/lpevents.c
  46. 0 1
      arch/powerpc/platforms/iseries/proc.c
  47. 2 17
      arch/powerpc/platforms/iseries/setup.c
  48. 2 5
      arch/powerpc/platforms/maple/setup.c
  49. 2 7
      arch/powerpc/platforms/powermac/setup.c
  50. 33 0
      arch/powerpc/platforms/pseries/iommu.c
  51. 1 3
      arch/powerpc/platforms/pseries/lpar.c
  52. 5 5
      arch/powerpc/platforms/pseries/setup.c
  53. 2 0
      arch/powerpc/sysdev/Makefile
  54. 5 1
      arch/powerpc/sysdev/dart.h
  55. 43 6
      arch/powerpc/sysdev/dart_iommu.c
  56. 392 0
      arch/powerpc/sysdev/todc.c
  57. 145 0
      arch/powerpc/sysdev/tsi108_dev.c
  58. 412 0
      arch/powerpc/sysdev/tsi108_pci.c
  59. 8 1
      drivers/ide/Kconfig
  60. 0 125
      drivers/ide/ppc/pmac.c
  61. 12 0
      drivers/macintosh/Kconfig
  62. 1 0
      drivers/macintosh/Makefile
  63. 144 0
      drivers/macintosh/via-pmu-led.c
  64. 20 28
      include/asm-powerpc/cputable.h
  65. 20 20
      include/asm-powerpc/iseries/it_lp_queue.h
  66. 2 0
      include/asm-powerpc/kdump.h
  67. 8 1
      include/asm-powerpc/kexec.h
  68. 2 0
      include/asm-powerpc/machdep.h
  69. 0 1
      include/asm-powerpc/mmu.h
  70. 6 1
      include/asm-powerpc/mmu_context.h
  71. 0 5
      include/asm-powerpc/mpc86xx.h
  72. 3 0
      include/asm-powerpc/rtas.h
  73. 4 2
      include/asm-powerpc/time.h
  74. 487 0
      include/asm-powerpc/todc.h
  75. 109 0
      include/asm-powerpc/tsi108.h
  76. 2 1
      include/asm-powerpc/udbg.h
  77. 2 4
      kernel/kexec.c

+ 18 - 5
arch/powerpc/Kconfig

@@ -340,7 +340,7 @@ config PPC_ISERIES
 
 config EMBEDDED6xx
 	bool "Embedded 6xx/7xx/7xxx-based board"
-	depends on PPC32 && BROKEN
+	depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
 
 config APUS
 	bool "Amiga-APUS"
@@ -417,12 +417,17 @@ config PPC_CELL_NATIVE
 	default n
 
 config PPC_IBM_CELL_BLADE
-	bool "  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
+	select UDBG_RTAS_CONSOLE
+
+config UDBG_RTAS_CONSOLE
+	bool
+	default n
 
 config XICS
 	depends on PPC_PSERIES
@@ -435,7 +440,8 @@ config U3_DART
 	default n
 
 config MPIC
-	depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP
+	depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
+			       || MPC7448HPC2
 	bool
 	default y
 
@@ -561,6 +567,13 @@ config TAU_AVERAGE
 	  /proc/cpuinfo.
 
 	  If in doubt, say N here.
+
+config PPC_TODC
+	depends on EMBEDDED6xx
+	bool "Generic Time-of-day Clock (TODC) support"
+	---help---
+	  This adds support for many TODC/RTC chips.
+
 endmenu
 
 source arch/powerpc/platforms/embedded6xx/Kconfig
@@ -801,7 +814,6 @@ config GENERIC_ISA_DMA
 
 config PPC_I8259
 	bool
-	default y if MPC8641_HPCN
 	default n
 
 config PPC_INDIRECT_PCI
@@ -824,7 +836,8 @@ config MCA
 	bool
 
 config PCI
-	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
+	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) \
+				  || MPC7448HPC2
 	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

+ 8 - 1
arch/powerpc/Kconfig.debug

@@ -134,12 +134,19 @@ config PPC_EARLY_DEBUG_G5
 	help
 	  Select this to enable early debugging for Apple G5 machines.
 
-config PPC_EARLY_DEBUG_RTAS
+config PPC_EARLY_DEBUG_RTAS_PANEL
 	bool "RTAS Panel"
 	depends on PPC_RTAS
 	help
 	  Select this to enable early debugging via the RTAS panel.
 
+config PPC_EARLY_DEBUG_RTAS_CONSOLE
+	bool "RTAS Console"
+	depends on PPC_RTAS
+	select UDBG_RTAS_CONSOLE
+	help
+	  Select this to enable early debugging via the RTAS console.
+
 config PPC_EARLY_DEBUG_MAPLE
 	bool "Maple real mode"
 	depends on PPC_MAPLE

+ 4 - 3
arch/powerpc/configs/cell_defconfig

@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17
-# Mon Jun 19 17:23:03 2006
+# Linux kernel version: 2.6.17-rc6
+# Thu Jun 22 15:28:36 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -1063,7 +1063,8 @@ CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUGGER=y
-# CONFIG_XMON is not set
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set

+ 923 - 0
arch/powerpc/configs/mpc7448_hpc2_defconfig

@@ -0,0 +1,923 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc4
+# Sat May 27 18:45:55 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=y
+
+#
+# Processor support
+#
+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_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+
+#
+# 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_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=y
+# 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"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_ISERIES is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_APUS is not set
+CONFIG_MPIC=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_HDPU is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_MPC7448HPC2=y
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_EV64360 is not set
+CONFIG_TSI108_BRIDGE=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# 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_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_GENERIC_ISA_DMA=y
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+
+#
+# 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
+
+#
+# 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=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 is not set
+# 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
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+CONFIG_SCSI_SATA_MV=y
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIL24 is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 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
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS 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=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE 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_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_TSI108_ETH=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_NET_FC 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
+
+#
+# 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=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=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# 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 is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG 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
+#

+ 2 - 1
arch/powerpc/kernel/Makefile

@@ -50,7 +50,8 @@ extra-$(CONFIG_FSL_BOOKE)	:= head_fsl_booke.o
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-y				+= vmlinux.lds
 
-obj-y				+= time.o prom.o traps.o setup-common.o udbg.o
+obj-y				+= time.o prom.o traps.o setup-common.o \
+				   udbg.o misc.o
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o misc_32.o
 obj-$(CONFIG_PPC64)		+= misc_64.o dma_64.o iommu.o
 obj-$(CONFIG_PPC_MULTIPLATFORM)	+= prom_init.o

+ 12 - 2
arch/powerpc/kernel/cpu_setup_power4.S

@@ -125,7 +125,12 @@ _GLOBAL(__save_cpu_setup)
 	cmpwi	r0,0x44
 	bne	2f
 
-1:	/* Save HID0,1,4 and 5 */
+1:	/* skip if not running in HV mode */
+	mfmsr	r0
+	rldicl.	r0,r0,4,63
+	beq	2f
+
+	/* Save HID0,1,4 and 5 */
 	mfspr	r3,SPRN_HID0
 	std	r3,CS_HID0(r5)
 	mfspr	r3,SPRN_HID1
@@ -159,7 +164,12 @@ _GLOBAL(__restore_cpu_setup)
 	cmpwi	r0,0x44
 	bnelr
 
-1:	/* Before accessing memory, we make sure rm_ci is clear */
+1:	/* skip if not running in HV mode */
+	mfmsr	r0
+	rldicl.	r0,r0,4,63
+	beqlr
+
+	/* Before accessing memory, we make sure rm_ci is clear */
 	li	r0,0
 	mfspr	r3,SPRN_HID4
 	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */

+ 0 - 12
arch/powerpc/kernel/cputable.c

@@ -722,18 +722,6 @@ 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,

+ 119 - 28
arch/powerpc/kernel/crash.c

@@ -24,9 +24,11 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/types.h>
+#include <linux/irq.h>
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
+#include <asm/kexec.h>
 #include <asm/kdump.h>
 #include <asm/lmb.h>
 #include <asm/firmware.h>
@@ -41,6 +43,7 @@
 
 /* This keeps a track of which one is crashing cpu. */
 int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
 							       size_t data_len)
@@ -98,34 +101,66 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
 }
 
 #ifdef CONFIG_SMP
-static atomic_t waiting_for_crash_ipi;
+static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
 
 void crash_ipi_callback(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 
-	if (cpu == crashing_cpu)
-		return;
-
 	if (!cpu_online(cpu))
 		return;
 
-	if (ppc_md.kexec_cpu_down)
-		ppc_md.kexec_cpu_down(1, 1);
-
 	local_irq_disable();
+	if (!cpu_isset(cpu, cpus_in_crash))
+		crash_save_this_cpu(regs, cpu);
+	cpu_set(cpu, cpus_in_crash);
 
-	crash_save_this_cpu(regs, cpu);
-	atomic_dec(&waiting_for_crash_ipi);
+	/*
+	 * Entered via soft-reset - could be the kdump
+	 * process is invoked using soft-reset or user activated
+	 * it if some CPU did not respond to an IPI.
+	 * For soft-reset, the secondary CPU can enter this func
+	 * twice. 1 - using IPI, and 2. soft-reset.
+	 * Tell the kexec CPU that entered via soft-reset and ready
+	 * to go down.
+	 */
+	if (cpu_isset(cpu, cpus_in_sr)) {
+		cpu_clear(cpu, cpus_in_sr);
+		atomic_inc(&enter_on_soft_reset);
+	}
+
+	/*
+	 * Starting the kdump boot.
+	 * This barrier is needed to make sure that all CPUs are stopped.
+	 * If not, soft-reset will be invoked to bring other CPUs.
+	 */
+	while (!cpu_isset(crashing_cpu, cpus_in_crash))
+		cpu_relax();
+
+	if (ppc_md.kexec_cpu_down)
+		ppc_md.kexec_cpu_down(1, 1);
 	kexec_smp_wait();
 	/* NOTREACHED */
 }
 
-static void crash_kexec_prepare_cpus(void)
+/*
+ * Wait until all CPUs are entered via soft-reset.
+ */
+static void crash_soft_reset_check(int cpu)
+{
+	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
+
+	cpu_clear(cpu, cpus_in_sr);
+	while (atomic_read(&enter_on_soft_reset) != ncpus)
+		cpu_relax();
+}
+
+
+static void crash_kexec_prepare_cpus(int cpu)
 {
 	unsigned int msecs;
 
-	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
 
 	crash_send_ipi(crash_ipi_callback);
 	smp_wmb();
@@ -133,14 +168,13 @@ static void crash_kexec_prepare_cpus(void)
 	/*
 	 * FIXME: Until we will have the way to stop other CPUSs reliabally,
 	 * the crash CPU will send an IPI and wait for other CPUs to
-	 * respond. If not, proceed the kexec boot even though we failed to
-	 * capture other CPU states.
+	 * respond.
 	 * Delay of at least 10 seconds.
 	 */
-	printk(KERN_ALERT "Sending IPI to other cpus...\n");
+	printk(KERN_EMERG "Sending IPI to other cpus...\n");
 	msecs = 10000;
-	while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
-		barrier();
+	while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+		cpu_relax();
 		mdelay(1);
 	}
 
@@ -149,18 +183,71 @@ static void crash_kexec_prepare_cpus(void)
 	/*
 	 * FIXME: In case if we do not get all CPUs, one possibility: ask the
 	 * user to do soft reset such that we get all.
-	 * IPI handler is already set by the panic cpu initially. Therefore,
-	 * all cpus could invoke this handler from die() and the panic CPU
-	 * will call machine_kexec() directly from this handler to do
-	 * kexec boot.
+	 * Soft-reset will be used until better mechanism is implemented.
+	 */
+	if (cpus_weight(cpus_in_crash) < ncpus) {
+		printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
+			ncpus - cpus_weight(cpus_in_crash));
+		printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
+		cpus_in_sr = CPU_MASK_NONE;
+		atomic_set(&enter_on_soft_reset, 0);
+		while (cpus_weight(cpus_in_crash) < ncpus)
+			cpu_relax();
+	}
+	/*
+	 * Make sure all CPUs are entered via soft-reset if the kdump is
+	 * invoked using soft-reset.
 	 */
-	if (atomic_read(&waiting_for_crash_ipi))
-		printk(KERN_ALERT "done waiting: %d cpus not responding\n",
-			atomic_read(&waiting_for_crash_ipi));
+	if (cpu_isset(cpu, cpus_in_sr))
+		crash_soft_reset_check(cpu);
 	/* Leave the IPI callback set */
 }
+
+/*
+ * This function will be called by secondary cpus or by kexec cpu
+ * if soft-reset is activated to stop some CPUs.
+ */
+void crash_kexec_secondary(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	unsigned long flags;
+	int msecs = 5;
+
+	local_irq_save(flags);
+	/* Wait 5ms if the kexec CPU is not entered yet. */
+	while (crashing_cpu < 0) {
+		if (--msecs < 0) {
+			/*
+			 * Either kdump image is not loaded or
+			 * kdump process is not started - Probably xmon
+			 * exited using 'x'(exit and recover) or
+			 * kexec_should_crash() failed for all running tasks.
+			 */
+			cpu_clear(cpu, cpus_in_sr);
+			local_irq_restore(flags);
+			return;
+		}
+		mdelay(1);
+		cpu_relax();
+	}
+	if (cpu == crashing_cpu) {
+		/*
+		 * Panic CPU will enter this func only via soft-reset.
+		 * Wait until all secondary CPUs entered and
+		 * then start kexec boot.
+		 */
+		crash_soft_reset_check(cpu);
+		cpu_set(crashing_cpu, cpus_in_crash);
+		if (ppc_md.kexec_cpu_down)
+			ppc_md.kexec_cpu_down(1, 0);
+		machine_kexec(kexec_crash_image);
+		/* NOTREACHED */
+	}
+	crash_ipi_callback(regs);
+}
+
 #else
-static void crash_kexec_prepare_cpus(void)
+static void crash_kexec_prepare_cpus(int cpu)
 {
 	/*
 	 * move the secondarys to us so that we can copy
@@ -171,6 +258,10 @@ static void crash_kexec_prepare_cpus(void)
 	smp_release_cpus();
 }
 
+void crash_kexec_secondary(struct pt_regs *regs)
+{
+	cpus_in_sr = CPU_MASK_NONE;
+}
 #endif
 
 void default_machine_crash_shutdown(struct pt_regs *regs)
@@ -199,14 +290,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
 			desc->chip->disable(irq);
 	}
 
-	if (ppc_md.kexec_cpu_down)
-		ppc_md.kexec_cpu_down(1, 0);
-
 	/*
 	 * Make a note of crashing cpu. Will be used in machine_kexec
 	 * such that another IPI will not be sent.
 	 */
 	crashing_cpu = smp_processor_id();
-	crash_kexec_prepare_cpus();
 	crash_save_this_cpu(regs, crashing_cpu);
+	crash_kexec_prepare_cpus(crashing_cpu);
+	cpu_set(crashing_cpu, cpus_in_crash);
+	if (ppc_md.kexec_cpu_down)
+		ppc_md.kexec_cpu_down(1, 0);
 }

+ 12 - 50
arch/powerpc/kernel/head_64.S

@@ -85,34 +85,6 @@ END_FTR_SECTION(0, 1)
 	/* Catch branch to 0 in real mode */
 	trap
 
-#ifdef CONFIG_PPC_ISERIES
-	/*
-	 * At offset 0x20, there is a pointer to iSeries LPAR data.
-	 * This is required by the hypervisor
-	 */
-	. = 0x20
-	.llong hvReleaseData-KERNELBASE
-
-	/*
-	 * At offset 0x28 and 0x30 are offsets to the mschunks_map
-	 * array (used by the iSeries LPAR debugger to do translation
-	 * between physical addresses and absolute addresses) and
-	 * to the pidhash table (also used by the debugger)
-	 */
-	.llong mschunks_map-KERNELBASE
-	.llong 0	/* pidhash-KERNELBASE SFRXXX */
-
-	/* Offset 0x38 - Pointer to start of embedded System.map */
-	.globl	embedded_sysmap_start
-embedded_sysmap_start:
-	.llong	0
-	/* Offset 0x40 - Pointer to end of embedded System.map */
-	.globl	embedded_sysmap_end
-embedded_sysmap_end:
-	.llong	0
-
-#endif /* CONFIG_PPC_ISERIES */
-
 	/* Secondary processors spin on this value until it goes to 1. */
 	.globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
@@ -124,6 +96,15 @@ __secondary_hold_spinloop:
 __secondary_hold_acknowledge:
 	.llong	0x0
 
+#ifdef CONFIG_PPC_ISERIES
+	/*
+	 * At offset 0x20, there is a pointer to iSeries LPAR data.
+	 * This is required by the hypervisor
+	 */
+	. = 0x20
+	.llong hvReleaseData-KERNELBASE
+#endif /* CONFIG_PPC_ISERIES */
+
 	. = 0x60
 /*
  * The following code is used on pSeries to hold secondary processors
@@ -1602,9 +1583,6 @@ _GLOBAL(__start_initialization_multiplatform)
 	/* Setup some critical 970 SPRs before switching MMU off */
 	bl	.__970_cpu_preinit
 
-	/* cpu # */
-	li	r24,0
-
 	/* Switch off MMU if not already */
 	LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
 	add	r4,r4,r30
@@ -1683,6 +1661,9 @@ _STATIC(__after_prom_start)
 					/*   i.e. where we are running	 */
 					/*	the source addr		 */
 
+	cmpdi	r4,0			/* In some cases the loader may  */
+	beq	.start_here_multiplatform /* have already put us at zero */
+					/* so we can skip the copy.      */
 	LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
 	sub	r5,r5,r27
 
@@ -1962,14 +1943,6 @@ _STATIC(start_here_common)
 	li	r3,0
 	bl	.do_cpu_ftr_fixups
 
-	LOAD_REG_IMMEDIATE(r26, boot_cpuid)
-	lwz	r26,0(r26)
-
-	LOAD_REG_IMMEDIATE(r24, paca)	/* Get base vaddr of paca array  */
-	mulli	r13,r26,PACA_SIZE	/* Calculate vaddr of right paca */
-	add	r13,r13,r24		/* for this processor.		 */
-	mtspr	SPRN_SPRG3,r13
-
 	/* ptr to current */
 	LOAD_REG_IMMEDIATE(r4, init_task)
 	std	r4,PACACURRENT(r13)
@@ -1995,17 +1968,6 @@ _STATIC(start_here_common)
 	/* Not reached */
 	BUG_OPCODE
 
-/* Put the paca pointer into r13 and SPRG3 */
-_GLOBAL(setup_boot_paca)
-	LOAD_REG_IMMEDIATE(r3, boot_cpuid)
-	lwz	r3,0(r3)
-	LOAD_REG_IMMEDIATE(r4, paca) 	/* Get base vaddr of paca array	 */
-	mulli	r3,r3,PACA_SIZE		/* Calculate vaddr of right paca */
-	add	r13,r3,r4		/* for this processor.		 */
-	mtspr	SPRN_SPRG3,r13
-
-	blr
-
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the bss, which is page-aligned.

+ 30 - 0
arch/powerpc/kernel/iommu.c

@@ -38,6 +38,7 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/kdump.h>
 
 #define DBG(...)
 
@@ -440,8 +441,37 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
 
+#ifdef CONFIG_CRASH_DUMP
+	if (ppc_md.tce_get) {
+		unsigned long index, tceval;
+		unsigned long tcecount = 0;
+
+		/*
+		 * Reserve the existing mappings left by the first kernel.
+		 */
+		for (index = 0; index < tbl->it_size; index++) {
+			tceval = ppc_md.tce_get(tbl, index + tbl->it_offset);
+			/*
+			 * Freed TCE entry contains 0x7fffffffffffffff on JS20
+			 */
+			if (tceval && (tceval != 0x7fffffffffffffffUL)) {
+				__set_bit(index, tbl->it_map);
+				tcecount++;
+			}
+		}
+		if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) {
+			printk(KERN_WARNING "TCE table is full; ");
+			printk(KERN_WARNING "freeing %d entries for the kdump boot\n",
+				KDUMP_MIN_TCE_ENTRIES);
+			for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES;
+				index < tbl->it_size; index++)
+				__clear_bit(index, tbl->it_map);
+		}
+	}
+#else
 	/* Clear the hardware table in case firmware left allocations in it */
 	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+#endif
 
 	if (!welcomed) {
 		printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",

+ 11 - 0
arch/powerpc/kernel/legacy_serial.c

@@ -302,6 +302,17 @@ void __init find_legacy_serial_ports(void)
 		of_node_put(isa);
 	}
 
+	/* First fill our array with tsi-bridge ports */
+	for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) {
+		struct device_node *tsi = of_get_parent(np);
+		if (tsi && !strcmp(tsi->type, "tsi-bridge")) {
+			index = add_legacy_soc_port(np, np);
+			if (index >= 0 && np == stdout)
+				legacy_serial_console = index;
+		}
+		of_node_put(tsi);
+	}
+
 #ifdef CONFIG_PCI
 	/* Next, try to locate PCI ports */
 	for (np = NULL; (np = of_find_all_nodes(np));) {

+ 76 - 71
arch/powerpc/kernel/lparcfg.c

@@ -45,11 +45,9 @@
 static struct proc_dir_entry *proc_ppc64_lparcfg;
 #define LPARCFG_BUFF_SIZE 4096
 
-#ifdef CONFIG_PPC_ISERIES
-
 /*
- * For iSeries legacy systems, the PPA purr function is available from the
- * emulated_time_base field in the paca.
+ * Track sum of all purrs across all processors. This is used to further
+ * calculate usage values by different applications
  */
 static unsigned long get_purr(void)
 {
@@ -57,48 +55,31 @@ static unsigned long get_purr(void)
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		sum_purr += lppaca[cpu].emulated_time_base;
+		if (firmware_has_feature(FW_FEATURE_ISERIES))
+			sum_purr += lppaca[cpu].emulated_time_base;
+		else {
+			struct cpu_usage *cu;
 
-#ifdef PURR_DEBUG
-		printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
-			cpu, lppaca[cpu].emulated_time_base);
-#endif
+			cu = &per_cpu(cpu_usage_array, cpu);
+			sum_purr += cu->current_tb;
+		}
 	}
 	return sum_purr;
 }
 
-#define lparcfg_write NULL
+#ifdef CONFIG_PPC_ISERIES
 
 /*
  * Methods used to fetch LPAR data when running on an iSeries platform.
  */
-static int lparcfg_data(struct seq_file *m, void *v)
+static int iseries_lparcfg_data(struct seq_file *m, void *v)
 {
-	unsigned long pool_id, lp_index;
+	unsigned long pool_id;
 	int shared, entitled_capacity, max_entitled_capacity;
 	int processors, max_processors;
 	unsigned long purr = get_purr();
 
-	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
-
 	shared = (int)(get_lppaca()->shared_proc);
-	seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
-		   e2a(xItExtVpdPanel.mfgID[2]),
-		   e2a(xItExtVpdPanel.mfgID[3]),
-		   e2a(xItExtVpdPanel.systemSerial[1]),
-		   e2a(xItExtVpdPanel.systemSerial[2]),
-		   e2a(xItExtVpdPanel.systemSerial[3]),
-		   e2a(xItExtVpdPanel.systemSerial[4]),
-		   e2a(xItExtVpdPanel.systemSerial[5]));
-
-	seq_printf(m, "system_type=%c%c%c%c\n",
-		   e2a(xItExtVpdPanel.machineType[0]),
-		   e2a(xItExtVpdPanel.machineType[1]),
-		   e2a(xItExtVpdPanel.machineType[2]),
-		   e2a(xItExtVpdPanel.machineType[3]));
-
-	lp_index = HvLpConfig_getLpIndex();
-	seq_printf(m, "partition_id=%d\n", (int)lp_index);
 
 	seq_printf(m, "system_active_processors=%d\n",
 		   (int)HvLpConfig_getSystemPhysicalProcessors());
@@ -137,6 +118,14 @@ static int lparcfg_data(struct seq_file *m, void *v)
 
 	return 0;
 }
+
+#else				/* CONFIG_PPC_ISERIES */
+
+static int iseries_lparcfg_data(struct seq_file *m, void *v)
+{
+	return 0;
+}
+
 #endif				/* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_PSERIES
@@ -213,22 +202,6 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
 		log_plpar_hcall_return(rc, "H_PIC");
 }
 
-/* Track sum of all purrs across all processors. This is used to further */
-/* calculate usage values by different applications                       */
-
-static unsigned long get_purr(void)
-{
-	unsigned long sum_purr = 0;
-	int cpu;
-	struct cpu_usage *cu;
-
-	for_each_possible_cpu(cpu) {
-		cu = &per_cpu(cpu_usage_array, cpu);
-		sum_purr += cu->current_tb;
-	}
-	return sum_purr;
-}
-
 #define SPLPAR_CHARACTERISTICS_TOKEN 20
 #define SPLPAR_MAXLENGTH 1026*(sizeof(char))
 
@@ -333,35 +306,13 @@ static int lparcfg_count_active_processors(void)
 	return count;
 }
 
-static int lparcfg_data(struct seq_file *m, void *v)
+static int pseries_lparcfg_data(struct seq_file *m, void *v)
 {
 	int partition_potential_processors;
 	int partition_active_processors;
-	struct device_node *rootdn;
-	const char *model = "";
-	const char *system_id = "";
-	unsigned int *lp_index_ptr, lp_index = 0;
 	struct device_node *rtas_node;
 	int *lrdrp = NULL;
 
-	rootdn = find_path_device("/");
-	if (rootdn) {
-		model = get_property(rootdn, "model", NULL);
-		system_id = get_property(rootdn, "system-id", NULL);
-		lp_index_ptr = (unsigned int *)
-		    get_property(rootdn, "ibm,partition-no", NULL);
-		if (lp_index_ptr)
-			lp_index = *lp_index_ptr;
-	}
-
-	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
-
-	seq_printf(m, "serial_number=%s\n", system_id);
-
-	seq_printf(m, "system_type=%s\n", model);
-
-	seq_printf(m, "partition_id=%d\n", (int)lp_index);
-
 	rtas_node = find_path_device("/rtas");
 	if (rtas_node)
 		lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity",
@@ -549,8 +500,61 @@ out:
 	return retval;
 }
 
+#else				/* CONFIG_PPC_PSERIES */
+
+static int pseries_lparcfg_data(struct seq_file *m, void *v)
+{
+	return 0;
+}
+
+static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+			     size_t count, loff_t * off)
+{
+	return count;
+}
+
 #endif				/* CONFIG_PPC_PSERIES */
 
+static int lparcfg_data(struct seq_file *m, void *v)
+{
+	struct device_node *rootdn;
+	const char *model = "";
+	const char *system_id = "";
+	const char *tmp;
+	unsigned int *lp_index_ptr, lp_index = 0;
+
+	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
+
+	rootdn = find_path_device("/");
+	if (rootdn) {
+		tmp = get_property(rootdn, "model", NULL);
+		if (tmp) {
+			model = tmp;
+			/* Skip "IBM," - see platforms/iseries/dt.c */
+			if (firmware_has_feature(FW_FEATURE_ISERIES))
+				model += 4;
+		}
+		tmp = get_property(rootdn, "system-id", NULL);
+		if (tmp) {
+			system_id = tmp;
+			/* Skip "IBM," - see platforms/iseries/dt.c */
+			if (firmware_has_feature(FW_FEATURE_ISERIES))
+				system_id += 4;
+		}
+		lp_index_ptr = (unsigned int *)
+			get_property(rootdn, "ibm,partition-no", NULL);
+		if (lp_index_ptr)
+			lp_index = *lp_index_ptr;
+	}
+	seq_printf(m, "serial_number=%s\n", system_id);
+	seq_printf(m, "system_type=%s\n", model);
+	seq_printf(m, "partition_id=%d\n", (int)lp_index);
+
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return iseries_lparcfg_data(m, v);
+	return pseries_lparcfg_data(m, v);
+}
+
 static int lparcfg_open(struct inode *inode, struct file *file)
 {
 	return single_open(file, lparcfg_data, NULL);
@@ -569,7 +573,8 @@ int __init lparcfg_init(void)
 	mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
 
 	/* Allow writing if we have FW_FEATURE_SPLPAR */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+	if (firmware_has_feature(FW_FEATURE_SPLPAR) &&
+			!firmware_has_feature(FW_FEATURE_ISERIES)) {
 		lparcfg_fops.write = lparcfg_write;
 		mode |= S_IWUSR;
 	}

+ 3 - 1
arch/powerpc/kernel/machine_kexec_64.c

@@ -378,11 +378,13 @@ static void __init export_crashk_values(void)
 	of_node_put(node);
 }
 
-void __init kexec_setup(void)
+static int __init kexec_setup(void)
 {
 	export_htab_values();
 	export_crashk_values();
+	return 0;
 }
+__initcall(kexec_setup);
 
 static int __init early_parse_crashk(char *p)
 {

+ 203 - 0
arch/powerpc/kernel/misc.S

@@ -0,0 +1,203 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
+ * PPC64 updates by Dave Engebretsen (engebret@us.ibm.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 Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <asm/ppc_asm.h>
+
+	.text
+
+#ifdef CONFIG_PPC64
+#define IN_SYNC		twi	0,r5,0; isync
+#define EIEIO_32
+#define SYNC_64		sync
+#else /* CONFIG_PPC32 */
+#define IN_SYNC
+#define EIEIO_32	eieio
+#define SYNC_64
+#endif
+/*
+ * Returns (address we are running at) - (address we were linked at)
+ * for use before the text and data are mapped to KERNELBASE.
+ */
+
+_GLOBAL(reloc_offset)
+	mflr	r0
+	bl	1f
+1:	mflr	r3
+	LOAD_REG_IMMEDIATE(r4,1b)
+	subf	r3,r4,r3
+	mtlr	r0
+	blr
+
+/*
+ * add_reloc_offset(x) returns x + reloc_offset().
+ */
+_GLOBAL(add_reloc_offset)
+	mflr	r0
+	bl	1f
+1:	mflr	r5
+	LOAD_REG_IMMEDIATE(r4,1b)
+	subf	r5,r4,r5
+	add	r3,r3,r5
+	mtlr	r0
+	blr
+
+/*
+ * I/O string operations
+ *
+ * insb(port, buf, len)
+ * outsb(port, buf, len)
+ * insw(port, buf, len)
+ * outsw(port, buf, len)
+ * insl(port, buf, len)
+ * outsl(port, buf, len)
+ * insw_ns(port, buf, len)
+ * outsw_ns(port, buf, len)
+ * insl_ns(port, buf, len)
+ * outsl_ns(port, buf, len)
+ *
+ * The *_ns versions don't do byte-swapping.
+ */
+_GLOBAL(_insb)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,1
+	blelr-
+00:	lbz	r5,0(r3)
+	eieio
+	stbu	r5,1(r4)
+	bdnz	00b
+	IN_SYNC
+	blr
+
+_GLOBAL(_outsb)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,1
+	blelr-
+00:	lbzu	r5,1(r4)
+	stb	r5,0(r3)
+	EIEIO_32
+	bdnz	00b
+	SYNC_64
+	blr
+
+_GLOBAL(_insw)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,2
+	blelr-
+00:	lhbrx	r5,0,r3
+	eieio
+	sthu	r5,2(r4)
+	bdnz	00b
+	IN_SYNC
+	blr
+
+_GLOBAL(_outsw)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,2
+	blelr-
+00:	lhzu	r5,2(r4)
+	EIEIO_32
+	sthbrx	r5,0,r3
+	bdnz	00b
+	SYNC_64
+	blr
+
+_GLOBAL(_insl)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,4
+	blelr-
+00:	lwbrx	r5,0,r3
+	eieio
+	stwu	r5,4(r4)
+	bdnz	00b
+	IN_SYNC
+	blr
+
+_GLOBAL(_outsl)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,4
+	blelr-
+00:	lwzu	r5,4(r4)
+	stwbrx	r5,0,r3
+	EIEIO_32
+	bdnz	00b
+	SYNC_64
+	blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_insw)
+#endif
+_GLOBAL(_insw_ns)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,2
+	blelr-
+00:	lhz	r5,0(r3)
+	eieio
+	sthu	r5,2(r4)
+	bdnz	00b
+	IN_SYNC
+	blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_outsw)
+#endif
+_GLOBAL(_outsw_ns)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,2
+	blelr-
+00:	lhzu	r5,2(r4)
+	sth	r5,0(r3)
+	EIEIO_32
+	bdnz	00b
+	SYNC_64
+	blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_insl)
+#endif
+_GLOBAL(_insl_ns)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,4
+	blelr-
+00:	lwz	r5,0(r3)
+	eieio
+	stwu	r5,4(r4)
+	bdnz	00b
+	IN_SYNC
+	blr
+
+#ifdef CONFIG_PPC32
+_GLOBAL(__ide_mm_outsl)
+#endif
+_GLOBAL(_outsl_ns)
+	cmpwi	0,r5,0
+	mtctr	r5
+	subi	r4,r4,4
+	blelr-
+00:	lwzu	r5,4(r4)
+	stw	r5,0(r3)
+	EIEIO_32
+	bdnz	00b
+	SYNC_64
+	blr
+

+ 0 - 156
arch/powerpc/kernel/misc_32.S

@@ -60,32 +60,6 @@ _GLOBAL(mulhdu)
 	addze	r3,r3
 	blr
 
-/*
- * Returns (address we're running at) - (address we were linked at)
- * for use before the text and data are mapped to KERNELBASE.
- */
-_GLOBAL(reloc_offset)
-	mflr	r0
-	bl	1f
-1:	mflr	r3
-	LOAD_REG_IMMEDIATE(r4,1b)
-	subf	r3,r4,r3
-	mtlr	r0
-	blr
-
-/*
- * add_reloc_offset(x) returns x + reloc_offset().
- */
-_GLOBAL(add_reloc_offset)
-	mflr	r0
-	bl	1f
-1:	mflr	r5
-	LOAD_REG_IMMEDIATE(r4,1b)
-	subf	r5,r4,r5
-	add	r3,r3,r5
-	mtlr	r0
-	blr
-
 /*
  * sub_reloc_offset(x) returns x - reloc_offset().
  */
@@ -780,136 +754,6 @@ _GLOBAL(atomic_set_mask)
 	bne-	10b
 	blr
 
-/*
- * I/O string operations
- *
- * insb(port, buf, len)
- * outsb(port, buf, len)
- * insw(port, buf, len)
- * outsw(port, buf, len)
- * insl(port, buf, len)
- * outsl(port, buf, len)
- * insw_ns(port, buf, len)
- * outsw_ns(port, buf, len)
- * insl_ns(port, buf, len)
- * outsl_ns(port, buf, len)
- *
- * The *_ns versions don't do byte-swapping.
- */
-_GLOBAL(_insb)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,1
-	blelr-
-00:	lbz	r5,0(r3)
-	eieio
-	stbu	r5,1(r4)
-	bdnz	00b
-	blr
-
-_GLOBAL(_outsb)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,1
-	blelr-
-00:	lbzu	r5,1(r4)
-	stb	r5,0(r3)
-	eieio
-	bdnz	00b
-	blr
-
-_GLOBAL(_insw)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhbrx	r5,0,r3
-	eieio
-	sthu	r5,2(r4)
-	bdnz	00b
-	blr
-
-_GLOBAL(_outsw)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhzu	r5,2(r4)
-	eieio
-	sthbrx	r5,0,r3
-	bdnz	00b
-	blr
-
-_GLOBAL(_insl)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwbrx	r5,0,r3
-	eieio
-	stwu	r5,4(r4)
-	bdnz	00b
-	blr
-
-_GLOBAL(_outsl)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwzu	r5,4(r4)
-	stwbrx	r5,0,r3
-	eieio
-	bdnz	00b
-	blr
-
-_GLOBAL(__ide_mm_insw)
-_GLOBAL(_insw_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhz	r5,0(r3)
-	eieio
-	sthu	r5,2(r4)
-	bdnz	00b
-	blr
-
-_GLOBAL(__ide_mm_outsw)
-_GLOBAL(_outsw_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhzu	r5,2(r4)
-	sth	r5,0(r3)
-	eieio
-	bdnz	00b
-	blr
-
-_GLOBAL(__ide_mm_insl)
-_GLOBAL(_insl_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwz	r5,0(r3)
-	eieio
-	stwu	r5,4(r4)
-	bdnz	00b
-	blr
-
-_GLOBAL(__ide_mm_outsl)
-_GLOBAL(_outsl_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwzu	r5,4(r4)
-	stw	r5,0(r3)
-	eieio
-	bdnz	00b
-	blr
-
 /*
  * Extended precision shifts.
  *

+ 4 - 219
arch/powerpc/kernel/misc_64.S

@@ -1,14 +1,12 @@
 /*
- *  arch/powerpc/kernel/misc64.S
- *
  * This file contains miscellaneous low-level functions.
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
  * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
  * and Paul Mackerras.
  * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
- * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) 
- * 
+ * PPC64 updates by Dave Engebretsen (engebret@us.ibm.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 Free Software Foundation; either version
@@ -30,41 +28,10 @@
 
 	.text
 
-/*
- * Returns (address we are running at) - (address we were linked at)
- * for use before the text and data are mapped to KERNELBASE.
- */
-
-_GLOBAL(reloc_offset)
-	mflr	r0
-	bl	1f
-1:	mflr	r3
-	LOAD_REG_IMMEDIATE(r4,1b)
-	subf	r3,r4,r3
-	mtlr	r0
-	blr
-
-/*
- * add_reloc_offset(x) returns x + reloc_offset().
- */
-_GLOBAL(add_reloc_offset)
-	mflr	r0
-	bl	1f
-1:	mflr	r5
-	LOAD_REG_IMMEDIATE(r4,1b)
-	subf	r5,r4,r5
-	add	r3,r3,r5
-	mtlr	r0
-	blr
-
 _GLOBAL(get_msr)
 	mfmsr	r3
 	blr
 
-_GLOBAL(get_dar)
-	mfdar	r3
-	blr
-
 _GLOBAL(get_srr0)
 	mfsrr0  r3
 	blr
@@ -72,10 +39,6 @@ _GLOBAL(get_srr0)
 _GLOBAL(get_srr1)
 	mfsrr1  r3
 	blr
-	
-_GLOBAL(get_sp)
-	mr	r3,r1
-	blr
 
 #ifdef CONFIG_IRQSTACKS
 _GLOBAL(call_do_softirq)
@@ -101,48 +64,6 @@ _GLOBAL(call___do_IRQ)
 	blr
 #endif /* CONFIG_IRQSTACKS */
 
-	/*
- * To be called by C code which needs to do some operations with MMU
- * disabled. Note that interrupts have to be disabled by the caller
- * prior to calling us. The code called _MUST_ be in the RMO of course
- * and part of the linear mapping as we don't attempt to translate the
- * stack pointer at all. The function is called with the stack switched
- * to this CPU emergency stack
- *
- * prototype is void *call_with_mmu_off(void *func, void *data);
- *
- * the called function is expected to be of the form
- *
- * void *called(void *data); 
- */
-_GLOBAL(call_with_mmu_off)
-	mflr	r0			/* get link, save it on stackframe */
-	std	r0,16(r1)
-	mr	r1,r5			/* save old stack ptr */
-	ld	r1,PACAEMERGSP(r13)	/* get emerg. stack */
-	subi	r1,r1,STACK_FRAME_OVERHEAD
-	std	r0,16(r1)		/* save link on emerg. stack */
-	std	r5,0(r1)		/* save old stack ptr in backchain */
-	ld	r3,0(r3)		/* get to real function ptr (assume same TOC) */
-	bl	2f			/* we need LR to return, continue at label 2 */
-
-	ld	r0,16(r1)		/* we return here from the call, get LR and */
-	ld	r1,0(r1)		/* .. old stack ptr */
-	mtspr	SPRN_SRR0,r0		/* and get back to virtual mode with these */
-	mfmsr	r4
-	ori	r4,r4,MSR_IR|MSR_DR
-	mtspr	SPRN_SRR1,r4
-	rfid
-
-2:	mtspr	SPRN_SRR0,r3		/* coming from above, enter real mode */
-	mr	r3,r4			/* get parameter */
-	mfmsr	r0
-	ori	r0,r0,MSR_IR|MSR_DR
-	xori	r0,r0,MSR_IR|MSR_DR
-	mtspr	SPRN_SRR1,r0
-	rfid
-
-
 	.section	".toc","aw"
 PPC64_CACHES:
 	.tc		ppc64_caches[TC],ppc64_caches
@@ -323,144 +244,6 @@ _GLOBAL(__flush_dcache_icache)
 	bdnz	1b
 	isync
 	blr
-	
-/*
- * I/O string operations
- *
- * insb(port, buf, len)
- * outsb(port, buf, len)
- * insw(port, buf, len)
- * outsw(port, buf, len)
- * insl(port, buf, len)
- * outsl(port, buf, len)
- * insw_ns(port, buf, len)
- * outsw_ns(port, buf, len)
- * insl_ns(port, buf, len)
- * outsl_ns(port, buf, len)
- *
- * The *_ns versions don't do byte-swapping.
- */
-_GLOBAL(_insb)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,1
-	blelr-
-00:	lbz	r5,0(r3)
-	eieio
-	stbu	r5,1(r4)
-	bdnz	00b
-	twi	0,r5,0
-	isync
-	blr
-
-_GLOBAL(_outsb)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,1
-	blelr-
-00:	lbzu	r5,1(r4)
-	stb	r5,0(r3)
-	bdnz	00b
-	sync
-	blr	
-
-_GLOBAL(_insw)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhbrx	r5,0,r3
-	eieio
-	sthu	r5,2(r4)
-	bdnz	00b
-	twi	0,r5,0
-	isync
-	blr
-
-_GLOBAL(_outsw)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhzu	r5,2(r4)
-	sthbrx	r5,0,r3	
-	bdnz	00b
-	sync
-	blr	
-
-_GLOBAL(_insl)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwbrx	r5,0,r3
-	eieio
-	stwu	r5,4(r4)
-	bdnz	00b
-	twi	0,r5,0
-	isync
-	blr
-
-_GLOBAL(_outsl)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwzu	r5,4(r4)
-	stwbrx	r5,0,r3
-	bdnz	00b
-	sync
-	blr	
-
-/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */
-_GLOBAL(_insw_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhz	r5,0(r3)
-	eieio
-	sthu	r5,2(r4)
-	bdnz	00b
-	twi	0,r5,0
-	isync
-	blr
-
-/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */
-_GLOBAL(_outsw_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,2
-	blelr-
-00:	lhzu	r5,2(r4)
-	sth	r5,0(r3)
-	bdnz	00b
-	sync
-	blr	
-
-_GLOBAL(_insl_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwz	r5,0(r3)
-	eieio
-	stwu	r5,4(r4)
-	bdnz	00b
-	twi	0,r5,0
-	isync
-	blr
-
-_GLOBAL(_outsl_ns)
-	cmpwi	0,r5,0
-	mtctr	r5
-	subi	r4,r4,4
-	blelr-
-00:	lwzu	r5,4(r4)
-	stw	r5,0(r3)
-	bdnz	00b
-	sync
-	blr	
 
 /*
  * identify_cpu and calls setup_cpu
@@ -605,6 +388,7 @@ _GLOBAL(real_writeb)
 	blr
 #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
 
+#ifdef CONFIG_CPU_FREQ_PMAC64
 /*
  * SCOM access functions for 970 (FX only for now)
  *
@@ -673,6 +457,7 @@ _GLOBAL(scom970_write)
 	/* restore interrupts */
 	mtmsrd	r5,1
 	blr
+#endif /* CONFIG_CPU_FREQ_PMAC64 */
 
 
 /*

+ 0 - 1
arch/powerpc/kernel/paca.c

@@ -16,7 +16,6 @@
 #include <asm/ptrace.h>
 #include <asm/page.h>
 #include <asm/lppaca.h>
-#include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/it_lp_reg_save.h>
 #include <asm/paca.h>
 

+ 31 - 18
arch/powerpc/kernel/prom.c

@@ -30,6 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/debugfs.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -952,6 +953,7 @@ static struct ibm_pa_feature {
 	/* put this back once we know how to test if firmware does 64k IO */
 	{CPU_FTR_CI_LARGE_PAGE, 0,	1, 2, 0},
 #endif
+	{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
 };
 
 static void __init check_cpu_pa_features(unsigned long node)
@@ -1124,24 +1126,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
  		tce_alloc_end = *lprop;
 #endif
 
-#ifdef CONFIG_PPC_RTAS
-	/* To help early debugging via the front panel, we retrieve a minimal
-	 * set of RTAS infos now if available
-	 */
-	{
-		u64 *basep, *entryp, *sizep;
-
-		basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
-		entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
-		sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
-		if (basep && entryp && sizep) {
-			rtas.base = *basep;
-			rtas.entry = *entryp;
-			rtas.size = *sizep;
-		}
-	}
-#endif /* CONFIG_PPC_RTAS */
-
 #ifdef CONFIG_KEXEC
        lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
        if (lprop)
@@ -1326,6 +1310,11 @@ void __init early_init_devtree(void *params)
 	/* Setup flat device-tree pointer */
 	initial_boot_params = params;
 
+#ifdef CONFIG_PPC_RTAS
+	/* Some machines might need RTAS info for debugging, grab it now. */
+	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
+#endif
+
 	/* Retrieve various informations from the /chosen node of the
 	 * device-tree, including the platform type, initrd location and
 	 * size, TCE reserve, and more ...
@@ -2148,3 +2137,27 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 	}
 	return NULL;
 }
+
+#ifdef DEBUG
+static struct debugfs_blob_wrapper flat_dt_blob;
+
+static int __init export_flat_device_tree(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_dir("powerpc", NULL);
+	if (!d)
+		return 1;
+
+	flat_dt_blob.data = initial_boot_params;
+	flat_dt_blob.size = initial_boot_params->totalsize;
+
+	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
+				d, &flat_dt_blob);
+	if (!d)
+		return 1;
+
+	return 0;
+}
+__initcall(export_flat_device_tree);
+#endif

+ 105 - 14
arch/powerpc/kernel/rtas.c

@@ -38,16 +38,19 @@
 struct rtas_t rtas = {
 	.lock = SPIN_LOCK_UNLOCKED
 };
+EXPORT_SYMBOL(rtas);
 
 struct rtas_suspend_me_data {
 	long waiting;
 	struct rtas_args *args;
 };
 
-EXPORT_SYMBOL(rtas);
-
 DEFINE_SPINLOCK(rtas_data_buf_lock);
+EXPORT_SYMBOL(rtas_data_buf_lock);
+
 char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
+EXPORT_SYMBOL(rtas_data_buf);
+
 unsigned long rtas_rmo_buf;
 
 /*
@@ -106,11 +109,71 @@ static void call_rtas_display_status_delay(char c)
 	}
 }
 
-void __init udbg_init_rtas(void)
+void __init udbg_init_rtas_panel(void)
 {
 	udbg_putc = call_rtas_display_status_delay;
 }
 
+#ifdef CONFIG_UDBG_RTAS_CONSOLE
+
+/* If you think you're dying before early_init_dt_scan_rtas() does its
+ * work, you can hard code the token values for your firmware here and
+ * hardcode rtas.base/entry etc.
+ */
+static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE;
+static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE;
+
+static void udbg_rtascon_putc(char c)
+{
+	int tries;
+
+	if (!rtas.base)
+		return;
+
+	/* Add CRs before LFs */
+	if (c == '\n')
+		udbg_rtascon_putc('\r');
+
+	/* if there is more than one character to be displayed, wait a bit */
+	for (tries = 0; tries < 16; tries++) {
+		if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0)
+			break;
+		udelay(1000);
+	}
+}
+
+static int udbg_rtascon_getc_poll(void)
+{
+	int c;
+
+	if (!rtas.base)
+		return -1;
+
+	if (rtas_call(rtas_getchar_token, 0, 2, &c))
+		return -1;
+
+	return c;
+}
+
+static int udbg_rtascon_getc(void)
+{
+	int c;
+
+	while ((c = udbg_rtascon_getc_poll()) == -1)
+		;
+
+	return c;
+}
+
+
+void __init udbg_init_rtas_console(void)
+{
+	udbg_putc = udbg_rtascon_putc;
+	udbg_getc = udbg_rtascon_getc;
+	udbg_getc_poll = udbg_rtascon_getc_poll;
+}
+#endif /* CONFIG_UDBG_RTAS_CONSOLE */
+
 void rtas_progress(char *s, unsigned short hex)
 {
 	struct device_node *root;
@@ -236,6 +299,7 @@ int rtas_token(const char *service)
 	tokp = (int *) get_property(rtas.dev, service, NULL);
 	return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
 }
+EXPORT_SYMBOL(rtas_token);
 
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 /*
@@ -328,7 +392,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
 	char *buff_copy = NULL;
 	int ret;
 
-	if (token == RTAS_UNKNOWN_SERVICE)
+	if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
 		return -1;
 
 	/* Gotta do something different here, use global lock for now... */
@@ -369,6 +433,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
 	}
 	return ret;
 }
+EXPORT_SYMBOL(rtas_call);
 
 /* 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.
@@ -388,6 +453,7 @@ unsigned int rtas_busy_delay_time(int status)
 
 	return ms;
 }
+EXPORT_SYMBOL(rtas_busy_delay_time);
 
 /* For an RTAS busy status code, perform the hinted delay. */
 unsigned int rtas_busy_delay(int status)
@@ -401,6 +467,7 @@ unsigned int rtas_busy_delay(int status)
 
 	return ms;
 }
+EXPORT_SYMBOL(rtas_busy_delay);
 
 int rtas_error_rc(int rtas_rc)
 {
@@ -446,6 +513,7 @@ int rtas_get_power_level(int powerdomain, int *level)
 		return rtas_error_rc(rc);
 	return rc;
 }
+EXPORT_SYMBOL(rtas_get_power_level);
 
 int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
@@ -463,6 +531,7 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 		return rtas_error_rc(rc);
 	return rc;
 }
+EXPORT_SYMBOL(rtas_set_power_level);
 
 int rtas_get_sensor(int sensor, int index, int *state)
 {
@@ -480,6 +549,7 @@ int rtas_get_sensor(int sensor, int index, int *state)
 		return rtas_error_rc(rc);
 	return rc;
 }
+EXPORT_SYMBOL(rtas_get_sensor);
 
 int rtas_set_indicator(int indicator, int index, int new_value)
 {
@@ -497,6 +567,7 @@ int rtas_set_indicator(int indicator, int index, int new_value)
 		return rtas_error_rc(rc);
 	return rc;
 }
+EXPORT_SYMBOL(rtas_set_indicator);
 
 void rtas_restart(char *cmd)
 {
@@ -791,14 +862,34 @@ void __init rtas_initialize(void)
 #endif
 }
 
+int __init early_init_dt_scan_rtas(unsigned long node,
+		const char *uname, int depth, void *data)
+{
+	u32 *basep, *entryp, *sizep;
 
-EXPORT_SYMBOL(rtas_token);
-EXPORT_SYMBOL(rtas_call);
-EXPORT_SYMBOL(rtas_data_buf);
-EXPORT_SYMBOL(rtas_data_buf_lock);
-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);
-EXPORT_SYMBOL(rtas_set_indicator);
+	if (depth != 1 || strcmp(uname, "rtas") != 0)
+		return 0;
+
+	basep  = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
+	entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+	sizep  = of_get_flat_dt_prop(node, "rtas-size", NULL);
+
+	if (basep && entryp && sizep) {
+		rtas.base = *basep;
+		rtas.entry = *entryp;
+		rtas.size = *sizep;
+	}
+
+#ifdef CONFIG_UDBG_RTAS_CONSOLE
+	basep = of_get_flat_dt_prop(node, "put-term-char", NULL);
+	if (basep)
+		rtas_putchar_token = *basep;
+
+	basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
+	if (basep)
+		rtas_getchar_token = *basep;
+#endif
+
+	/* break now */
+	return 1;
+}

+ 12 - 10
arch/powerpc/kernel/setup_64.c

@@ -149,6 +149,13 @@ early_param("smt-enabled", early_smt_enabled);
 #define check_smt_enabled()
 #endif /* CONFIG_SMP */
 
+/* Put the paca pointer into r13 and SPRG3 */
+void __init setup_paca(int cpu)
+{
+	local_paca = &paca[cpu];
+	mtspr(SPRN_SPRG3, local_paca);
+}
+
 /*
  * Early initialization entry point. This is called by head.S
  * with MMU translation disabled. We rely on the "feature" of
@@ -170,6 +177,9 @@ early_param("smt-enabled", early_smt_enabled);
 
 void __init early_setup(unsigned long dt_ptr)
 {
+	/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
+	setup_paca(0);
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
@@ -183,7 +193,7 @@ void __init early_setup(unsigned long dt_ptr)
 	early_init_devtree(__va(dt_ptr));
 
 	/* Now we know the logical id of our boot cpu, setup the paca. */
-	setup_boot_paca();
+	setup_paca(boot_cpuid);
 
 	/* Fix up paca fields required for the boot cpu */
 	get_paca()->cpu_start = 1;
@@ -350,19 +360,11 @@ void __init setup_system(void)
 	 */
 	unflatten_device_tree();
 
-#ifdef CONFIG_KEXEC
-	kexec_setup();	/* requires unflattened device tree. */
-#endif
-
 	/*
 	 * Fill the ppc64_caches & systemcfg structures with informations
 	 * retrieved from the device-tree. Need to be called before
 	 * finish_device_tree() since the later requires some of the
-	 * informations filled up here to properly parse the interrupt
-	 * tree.
-	 * It also sets up the cache line sizes which allows to call
-	 * routines like flush_icache_range (used by the hash init
-	 * later on).
+	 * informations filled up here to properly parse the interrupt tree.
 	 */
 	initialize_cache_info();
 

+ 13 - 14
arch/powerpc/kernel/traps.c

@@ -52,9 +52,13 @@
 #include <asm/firmware.h>
 #include <asm/processor.h>
 #endif
+#include <asm/kexec.h>
 
 #ifdef CONFIG_PPC64	/* XXX */
 #define _IO_BASE	pci_io_base
+#ifdef CONFIG_KEXEC
+cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#endif
 #endif
 
 #ifdef CONFIG_DEBUGGER
@@ -97,7 +101,7 @@ static DEFINE_SPINLOCK(die_lock);
 
 int die(const char *str, struct pt_regs *regs, long err)
 {
-	static int die_counter, crash_dump_start = 0;
+	static int die_counter;
 
 	if (debugger(regs))
 		return 1;
@@ -137,21 +141,12 @@ int die(const char *str, struct pt_regs *regs, long err)
 	print_modules();
 	show_regs(regs);
 	bust_spinlocks(0);
+	spin_unlock_irq(&die_lock);
 
-	if (!crash_dump_start && kexec_should_crash(current)) {
-		crash_dump_start = 1;
-		spin_unlock_irq(&die_lock);
+	if (kexec_should_crash(current) ||
+		kexec_sr_activated(smp_processor_id()))
 		crash_kexec(regs);
-		/* NOTREACHED */
-	}
-	spin_unlock_irq(&die_lock);
-	if (crash_dump_start)
-		/*
-		 * Only for soft-reset: Other CPUs will be responded to an IPI
-		 * sent by first kexec CPU.
-		 */
-		for(;;)
-			;
+	crash_kexec_secondary(regs);
 
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
@@ -215,6 +210,10 @@ void system_reset_exception(struct pt_regs *regs)
 			return;
 	}
 
+#ifdef CONFIG_KEXEC
+	cpu_set(smp_processor_id(), cpus_in_sr);
+#endif
+
 	die("System Reset", regs, SIGABRT);
 
 	/* Must die if the interrupt is not recoverable */

+ 5 - 2
arch/powerpc/kernel/udbg.c

@@ -34,9 +34,12 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
 	/* For use on Apple G5 machines */
 	udbg_init_pmac_realmode();
-#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS)
+#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL)
 	/* RTAS panel debug */
-	udbg_init_rtas();
+	udbg_init_rtas_panel();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE)
+	/* RTAS console debug */
+	udbg_init_rtas_console();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
 	/* Maple real mode debug */
 	udbg_init_maple_realmode();

+ 1 - 2
arch/powerpc/mm/hash_native_64.c

@@ -520,7 +520,7 @@ static inline int tlb_batching_enabled(void)
 }
 #endif
 
-void hpte_init_native(void)
+void __init hpte_init_native(void)
 {
 	ppc_md.hpte_invalidate	= native_hpte_invalidate;
 	ppc_md.hpte_updatepp	= native_hpte_updatepp;
@@ -530,5 +530,4 @@ void hpte_init_native(void)
 	ppc_md.hpte_clear_all	= native_hpte_clear;
 	if (tlb_batching_enabled())
 		ppc_md.flush_hash_range = native_flush_hash_range;
-	htab_finish_init();
 }

+ 43 - 63
arch/powerpc/mm/hash_utils_64.c

@@ -167,34 +167,12 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 		hash = hpt_hash(va, shift);
 		hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-		/* The crap below can be cleaned once ppd_md.probe() can
-		 * set up the hash callbacks, thus we can just used the
-		 * normal insert callback here.
-		 */
-#ifdef CONFIG_PPC_ISERIES
-		if (machine_is(iseries))
-			ret = iSeries_hpte_insert(hpteg, va,
-						  paddr,
-						  tmp_mode,
-						  HPTE_V_BOLTED,
-						  psize);
-		else
-#endif
-#ifdef CONFIG_PPC_PSERIES
-		if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR))
-			ret = pSeries_lpar_hpte_insert(hpteg, va,
-						       paddr,
-						       tmp_mode,
-						       HPTE_V_BOLTED,
-						       psize);
-		else
-#endif
-#ifdef CONFIG_PPC_MULTIPLATFORM
-			ret = native_hpte_insert(hpteg, va,
-						 paddr,
-						 tmp_mode, HPTE_V_BOLTED,
-						 psize);
-#endif
+		DBG("htab_bolt_mapping: calling %p\n", ppc_md.hpte_insert);
+
+		BUG_ON(!ppc_md.hpte_insert);
+		ret = ppc_md.hpte_insert(hpteg, va, paddr,
+				tmp_mode, HPTE_V_BOLTED, psize);
+
 		if (ret < 0)
 			break;
 	}
@@ -413,6 +391,41 @@ void create_section_mapping(unsigned long start, unsigned long end)
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+static inline void make_bl(unsigned int *insn_addr, void *func)
+{
+	unsigned long funcp = *((unsigned long *)func);
+	int offset = funcp - (unsigned long)insn_addr;
+
+	*insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
+	flush_icache_range((unsigned long)insn_addr, 4+
+			   (unsigned long)insn_addr);
+}
+
+static void __init htab_finish_init(void)
+{
+	extern unsigned int *htab_call_hpte_insert1;
+	extern unsigned int *htab_call_hpte_insert2;
+	extern unsigned int *htab_call_hpte_remove;
+	extern unsigned int *htab_call_hpte_updatepp;
+
+#ifdef CONFIG_PPC_64K_PAGES
+	extern unsigned int *ht64_call_hpte_insert1;
+	extern unsigned int *ht64_call_hpte_insert2;
+	extern unsigned int *ht64_call_hpte_remove;
+	extern unsigned int *ht64_call_hpte_updatepp;
+
+	make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
+	make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
+	make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
+	make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
+#endif /* CONFIG_PPC_64K_PAGES */
+
+	make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
+	make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
+	make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
+	make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
+}
+
 void __init htab_initialize(void)
 {
 	unsigned long table;
@@ -525,6 +538,8 @@ void __init htab_initialize(void)
 					 mmu_linear_psize));
 	}
 
+	htab_finish_init();
+
 	DBG(" <- htab_initialize()\n");
 }
 #undef KB
@@ -787,16 +802,6 @@ void flush_hash_range(unsigned long number, int local)
 	}
 }
 
-static inline void make_bl(unsigned int *insn_addr, void *func)
-{
-	unsigned long funcp = *((unsigned long *)func);
-	int offset = funcp - (unsigned long)insn_addr;
-
-	*insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
-	flush_icache_range((unsigned long)insn_addr, 4+
-			   (unsigned long)insn_addr);
-}
-
 /*
  * low_hash_fault is called when we the low level hash code failed
  * to instert a PTE due to an hypervisor error
@@ -815,28 +820,3 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address)
 	}
 	bad_page_fault(regs, address, SIGBUS);
 }
-
-void __init htab_finish_init(void)
-{
-	extern unsigned int *htab_call_hpte_insert1;
-	extern unsigned int *htab_call_hpte_insert2;
-	extern unsigned int *htab_call_hpte_remove;
-	extern unsigned int *htab_call_hpte_updatepp;
-
-#ifdef CONFIG_PPC_64K_PAGES
-	extern unsigned int *ht64_call_hpte_insert1;
-	extern unsigned int *ht64_call_hpte_insert2;
-	extern unsigned int *ht64_call_hpte_remove;
-	extern unsigned int *ht64_call_hpte_updatepp;
-
-	make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
-	make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
-	make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
-	make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
-#endif /* CONFIG_PPC_64K_PAGES */
-
-	make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
-	make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
-	make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
-	make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
-}

+ 2 - 0
arch/powerpc/mm/mmu_context_64.c

@@ -44,7 +44,9 @@ again:
 		return err;
 
 	if (index > MAX_CONTEXT) {
+		spin_lock(&mmu_context_lock);
 		idr_remove(&mmu_context_idr, index);
+		spin_unlock(&mmu_context_lock);
 		return -ENOMEM;
 	}
 

+ 1 - 5
arch/powerpc/platforms/86xx/Kconfig

@@ -7,6 +7,7 @@ choice
 
 config MPC8641_HPCN
 	bool "Freescale MPC8641 HPCN"
+	select PPC_I8259
 	help
 	  This option enables support for the MPC8641 HPCN board.
 
@@ -28,9 +29,4 @@ config PPC_INDIRECT_PCI_BE
 	depends on PPC_86xx
 	default y
 
-config PPC_STD_MMU
-	bool
-	depends on PPC_86xx
-	default y
-
 endmenu

+ 0 - 3
arch/powerpc/platforms/86xx/Makefile

@@ -2,9 +2,6 @@
 # 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

+ 0 - 1
arch/powerpc/platforms/86xx/mpc8641_hpcn.h

@@ -14,7 +14,6 @@
 #ifndef __MPC8641_HPCN_H__
 #define __MPC8641_HPCN_H__
 
-#include <linux/config.h>
 #include <linux/init.h>
 
 /* PCI interrupt controller */

+ 5 - 3
arch/powerpc/platforms/86xx/mpc86xx.h

@@ -15,11 +15,13 @@
  * mpc86xx_* files. Mostly for use by mpc86xx_setup().
  */
 
-extern int __init add_bridge(struct device_node *dev);
+extern int add_bridge(struct device_node *dev);
 
-extern void __init setup_indirect_pcie(struct pci_controller *hose,
+extern int mpc86xx_exclude_device(u_char bus, u_char devfn);
+
+extern void setup_indirect_pcie(struct pci_controller *hose,
 				       u32 cfg_addr, u32 cfg_data);
-extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose,
+extern void setup_indirect_pcie_nomap(struct pci_controller *hose,
 					     void __iomem *cfg_addr,
 					     void __iomem *cfg_data);
 

+ 121 - 8
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c

@@ -12,7 +12,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -36,6 +35,7 @@
 #include <sysdev/fsl_soc.h>
 
 #include "mpc86xx.h"
+#include "mpc8641_hpcn.h"
 
 #ifndef CONFIG_PCI
 unsigned long isa_io_base = 0;
@@ -186,17 +186,130 @@ mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
 }
 
+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);
+}
 
-int
-mpc86xx_exclude_device(u_char bus, u_char devfn)
+static void __devinit quirk_uli5288(struct pci_dev *dev)
 {
-#if !defined(CONFIG_PCI)
-	if (bus == 0 && PCI_SLOT(devfn) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
+	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);
 
-	return PCIBIOS_SUCCESSFUL;
+	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);
 #endif /* CONFIG_PCI */
 
 

+ 4 - 6
arch/powerpc/platforms/86xx/mpc86xx_smp.c

@@ -10,7 +10,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -34,8 +33,8 @@ extern unsigned long __secondary_hold_acknowledge;
 static void __init
 smp_86xx_release_core(int nr)
 {
-	void *mcm_vaddr;
-	unsigned long vaddr, pcr;
+	__be32 __iomem *mcm_vaddr;
+	unsigned long pcr;
 
 	if (nr < 0 || nr >= NR_CPUS)
 		return;
@@ -45,10 +44,9 @@ smp_86xx_release_core(int 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 = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2));
 	pcr |= 1 << (nr + 24);
-	out_be32((volatile unsigned *)vaddr, pcr);
+	out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr);
 }
 
 

+ 8 - 129
arch/powerpc/platforms/86xx/pci.c

@@ -12,7 +12,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -122,15 +121,12 @@ static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource
 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;
@@ -144,6 +140,14 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
 	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
 }
 
+int mpc86xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
 int __init add_bridge(struct device_node *dev)
 {
 	int len;
@@ -198,128 +202,3 @@ int __init add_bridge(struct device_node *dev)
 
 	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);

+ 1 - 0
arch/powerpc/platforms/Makefile

@@ -14,3 +14,4 @@ obj-$(CONFIG_PPC_PSERIES)	+= pseries/
 obj-$(CONFIG_PPC_ISERIES)	+= iseries/
 obj-$(CONFIG_PPC_MAPLE)		+= maple/
 obj-$(CONFIG_PPC_CELL)		+= cell/
+obj-$(CONFIG_EMBEDDED6xx)	+= embedded6xx/

+ 1 - 1
arch/powerpc/platforms/cell/Kconfig

@@ -6,6 +6,7 @@ config SPU_FS
 	default m
 	depends on PPC_CELL
 	select SPU_BASE
+	select MEMORY_HOTPLUG
 	help
 	  The SPU file system is used to access Synergistic Processing
 	  Units on machines implementing the Broadband Processor
@@ -18,7 +19,6 @@ config SPU_BASE
 config SPUFS_MMAP
 	bool
 	depends on SPU_FS && SPARSEMEM
-	select MEMORY_HOTPLUG
 	default y
 
 config CBE_RAS

+ 10 - 6
arch/powerpc/platforms/cell/setup.c

@@ -125,8 +125,6 @@ static void __init cell_init_early(void)
 {
 	DBG(" -> cell_init_early()\n");
 
-	hpte_init_native();
-
 	cell_init_iommu();
 
 	ppc64_interrupt_controller = IC_CELL_PIC;
@@ -139,11 +137,17 @@ static int __init cell_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
-	    of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
-		return 1;
+	if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&
+	    !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+		return 0;
+
+#ifdef CONFIG_UDBG_RTAS_CONSOLE
+	udbg_init_rtas_console();
+#endif
+
+	hpte_init_native();
 
-	return 0;
+	return 1;
 }
 
 /*

+ 4 - 4
arch/powerpc/platforms/cell/spu_base.c

@@ -168,12 +168,12 @@ spu_irq_class_0_bottom(struct spu *spu)
 
 	stat &= mask;
 
-	if (stat & 1) /* invalid MFC DMA */
-		__spu_trap_invalid_dma(spu);
-
-	if (stat & 2) /* invalid DMA alignment */
+	if (stat & 1) /* invalid DMA alignment */
 		__spu_trap_dma_align(spu);
 
+	if (stat & 2) /* invalid MFC DMA */
+		__spu_trap_invalid_dma(spu);
+
 	if (stat & 4) /* error on SPU */
 		__spu_trap_error(spu);
 

+ 5 - 5
arch/powerpc/platforms/cell/spufs/file.c

@@ -204,7 +204,7 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-				     | _PAGE_NO_CACHE);
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
 	vma->vm_ops = &spufs_cntl_mmap_vmops;
 	return 0;
@@ -675,7 +675,7 @@ static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-				     | _PAGE_NO_CACHE);
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
 	vma->vm_ops = &spufs_signal1_mmap_vmops;
 	return 0;
@@ -762,7 +762,7 @@ static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma)
 	/* FIXME: */
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-				     | _PAGE_NO_CACHE);
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
 	vma->vm_ops = &spufs_signal2_mmap_vmops;
 	return 0;
@@ -850,7 +850,7 @@ static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-				     | _PAGE_NO_CACHE);
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
 	vma->vm_ops = &spufs_mss_mmap_vmops;
 	return 0;
@@ -899,7 +899,7 @@ static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_flags |= VM_RESERVED;
 	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
-				     | _PAGE_NO_CACHE);
+				     | _PAGE_NO_CACHE | _PAGE_GUARDED);
 
 	vma->vm_ops = &spufs_mfc_mmap_vmops;
 	return 0;

+ 4 - 2
arch/powerpc/platforms/cell/spufs/switch.c

@@ -464,7 +464,8 @@ static inline void wait_purge_complete(struct spu_state *csa, struct spu *spu)
 	 *     Poll MFC_CNTL[Ps] until value '11' is read
 	 *     (purge complete).
 	 */
-	POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
+	POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+			 MFC_CNTL_PURGE_DMA_STATUS_MASK) ==
 			 MFC_CNTL_PURGE_DMA_COMPLETE);
 }
 
@@ -1028,7 +1029,8 @@ static inline void wait_suspend_mfc_complete(struct spu_state *csa,
 	 * Restore, Step 47.
 	 *     Poll MFC_CNTL[Ss] until 11 is returned.
 	 */
-	POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
+	POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+			 MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
 			 MFC_CNTL_SUSPEND_COMPLETE);
 }
 

+ 15 - 0
arch/powerpc/platforms/embedded6xx/Kconfig

@@ -74,6 +74,16 @@ config SANDPOINT
 	  Select SANDPOINT if configuring for a Motorola Sandpoint X3
 	  (any flavor).
 
+config MPC7448HPC2
+	bool "Freescale MPC7448HPC2(Taiga)"
+	select TSI108_BRIDGE
+	select DEFAULT_UIMAGE
+	select PPC_UDBG_16550
+	select MPIC
+	help
+	  Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
+	  platform
+
 config RADSTONE_PPC7D
 	bool "Radstone Technology PPC7D board"
 	select PPC_I8259
@@ -221,6 +231,11 @@ config MV64X60
 	select PPC_INDIRECT_PCI
 	default y
 
+config TSI108_BRIDGE
+	bool
+	depends on MPC7448HPC2
+	default y
+
 menu "Set bridge options"
 	depends on MV64X60
 

+ 4 - 0
arch/powerpc/platforms/embedded6xx/Makefile

@@ -0,0 +1,4 @@
+#
+# Makefile for the 6xx/7xx/7xxxx linux kernel.
+#
+obj-$(CONFIG_MPC7448HPC2)	+= mpc7448_hpc2.o

+ 335 - 0
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c

@@ -0,0 +1,335 @@
+/*
+ * mpc7448_hpc2.c
+ *
+ * Board setup routines for the Freescale Taiga platform
+ *
+ * Author: Jacob Pan
+ *	 jacob.pan@freescale.com
+ * Author: Xianghua Xiao
+ *       x.xiao@freescale.com
+ * Maintainer: Roy Zang <tie-fei.zang@freescale.com>
+ * 	Add Flat Device Tree support fot mpc7448hpc2 board
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/tsi108.h>
+#include <asm/pci-bridge.h>
+#include <asm/reg.h>
+#include <mm/mmu_decl.h>
+#include "mpc7448_hpc2.h"
+#include <asm/tsi108_irq.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+#ifndef CONFIG_PCI
+isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
+isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
+pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
+#endif
+
+extern int tsi108_setup_pci(struct device_node *dev);
+extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+extern void tsi108_pci_int_init(void);
+extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
+
+/*
+ * Define all of the IRQ senses and polarities.  Taken from the
+ * mpc7448hpc  manual.
+ * Note:  Likely, this table and the following function should be
+ *        obtained and derived from the OF Device Tree.
+ */
+
+static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
+	/* External on-board sources */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[0] XINT0 from FPGA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[1] XINT1 from FPGA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[2] PHY_INT from both GIGE */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[3] RESERVED */
+	/* Internal Tsi108/109 interrupt sources */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA0 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA2 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA3 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART0 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* I2C */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* GPIO */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE1 */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* HLP */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* SDC */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Processor IF */
+	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* PCI/X block */
+};
+
+int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * find pci slot by devfn in interrupt map of OF tree
+ */
+u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn)
+{
+	int i;
+	unsigned int tmp;
+	for (i = 0; i < 4; i++){
+		tmp = interrupt_map[i*4*7];
+		if ((tmp >> 11) == (devfn >> 3))
+			return i;
+	}
+	return i;
+}
+
+/*
+ * Scans the interrupt map for pci device
+ */
+void mpc7448_hpc2_fixup_irq(struct pci_dev *dev)
+{
+	struct pci_controller *hose;
+	struct device_node *node;
+	unsigned int *interrupt;
+	int busnr;
+	int len;
+	u8 slot;
+	u8 pin;
+
+	/* Lookup the hose */
+	busnr = dev->bus->number;
+	hose = pci_bus_to_hose(busnr);
+	if (!hose)
+		printk(KERN_ERR "No pci hose found\n");
+
+	/* Check it has an OF node associated */
+	node = (struct device_node *) hose->arch_data;
+	if (!node)
+		printk(KERN_ERR "No pci node found\n");
+
+	interrupt = (unsigned int *) get_property(node, "interrupt-map", &len);
+	slot = find_slot_by_devfn(interrupt, dev->devfn);
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (pin == 0 || pin > 4)
+		pin = 1;
+	pin--;
+	dev->irq  = interrupt[slot*4*7 + pin*7 + 5];
+	DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq);
+}
+/* temporary pci irq map fixup*/
+
+void __init mpc7448_hpc2_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+	for_each_pci_dev(dev) {
+		mpc7448_hpc2_fixup_irq(dev);
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+static void __init mpc7448_hpc2_setup_arch(void)
+{
+	struct device_node *cpu;
+	struct device_node *np;
+	if (ppc_md.progress)
+		ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 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 = 50000000 / HZ;
+		of_node_put(cpu);
+	}
+	tsi108_csr_vir_base = get_vir_csrbase();
+
+#ifdef	CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	ROOT_DEV = Root_RAM0;
+#endif
+
+	/* setup PCI host bridge */
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		tsi108_setup_pci(np);
+
+	ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
+	if (ppc_md.progress)
+		ppc_md.progress("tsi108: resources set", 0x100);
+#endif
+
+	printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
+	printk(KERN_INFO
+	       "Jointly ported by Freescale and Tundra Semiconductor\n");
+	printk(KERN_INFO
+	       "Enabling L2 cache then enabling the HID0 prefetch engine.\n");
+}
+
+/*
+ * Interrupt setup and service.  Interrrupts on the mpc7448_hpc2 come
+ * from the four external INT pins, PCI interrupts are routed via
+ * PCI interrupt control registers, it generates internal IRQ23
+ *
+ * Interrupt routing on the Taiga Board:
+ * TSI108:PB_INT[0] -> CPU0:INT#
+ * TSI108:PB_INT[1] -> CPU0:MCP#
+ * TSI108:PB_INT[2] -> N/C
+ * TSI108:PB_INT[3] -> N/C
+ */
+static void __init mpc7448_hpc2_init_IRQ(void)
+{
+	struct mpic *mpic;
+	phys_addr_t mpic_paddr = 0;
+	struct device_node *tsi_pic;
+
+	tsi_pic = of_find_node_by_type(NULL, "open-pic");
+	if (tsi_pic) {
+		unsigned int size;
+		void *prop = get_property(tsi_pic, "reg", &size);
+		mpic_paddr = of_translate_address(tsi_pic, prop);
+	}
+
+	if (mpic_paddr == 0) {
+		printk("%s: No tsi108 PIC found !\n", __FUNCTION__);
+		return;
+	}
+
+	DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
+	    (u32) mpic_paddr);
+
+	mpic = mpic_alloc(mpic_paddr,
+			MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
+			MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
+			0, /* num_sources used */
+			TSI108_IRQ_BASE,
+			0, /* num_sources used */
+			NR_IRQS - 4 /* XXXX */,
+			mpc7448_hpc2_pic_initsenses,
+			sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
+
+	BUG_ON(mpic == NULL); /* XXXX */
+
+	mpic_init(mpic);
+	mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
+	tsi108_pci_int_init();
+
+	/* Configure MPIC outputs to CPU0 */
+	tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
+}
+
+void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
+{
+	seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "machine\t\t: MPC7448hpc2\n");
+}
+
+void mpc7448_hpc2_restart(char *cmd)
+{
+	local_irq_disable();
+
+	/* Set exception prefix high - to the firmware */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	for (;;) ;		/* Spin until reset happens */
+}
+
+void mpc7448_hpc2_power_off(void)
+{
+	local_irq_disable();
+	for (;;) ;		/* No way to shut power off with software */
+}
+
+void mpc7448_hpc2_halt(void)
+{
+	mpc7448_hpc2_power_off();
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc7448_hpc2_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (!of_flat_dt_is_compatible(root, "mpc74xx"))
+		return 0;
+	return 1;
+}
+
+static int mpc7448_machine_check_exception(struct pt_regs *regs)
+{
+	extern void tsi108_clear_pci_cfg_error(void);
+	const struct exception_table_entry *entry;
+
+	/* Are we prepared to handle this fault */
+	if ((entry = search_exception_tables(regs->nip)) != NULL) {
+		tsi108_clear_pci_cfg_error();
+		regs->msr |= MSR_RI;
+		regs->nip = entry->fixup;
+		return 1;
+	}
+	return 0;
+
+}
+define_machine(mpc7448_hpc2){
+	.name 			= "MPC7448 HPC2",
+	.probe 			= mpc7448_hpc2_probe,
+	.setup_arch 		= mpc7448_hpc2_setup_arch,
+	.init_IRQ 		= mpc7448_hpc2_init_IRQ,
+	.show_cpuinfo 		= mpc7448_hpc2_show_cpuinfo,
+	.get_irq 		= mpic_get_irq,
+	.pcibios_fixup 		= mpc7448_hpc2_pcibios_fixup,
+	.restart 		= mpc7448_hpc2_restart,
+	.calibrate_decr 	= generic_calibrate_decr,
+	.machine_check_exception= mpc7448_machine_check_exception,
+	.progress 		= udbg_progress,
+};

+ 26 - 0
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h

@@ -0,0 +1,26 @@
+/*
+ * mpc7448_hpc2.h
+ *
+ * Definitions for Freescale MPC7448_HPC2 platform
+ *
+ * Author: Jacob Pan
+ *         jacob.pan@freescale.com
+ * Maintainer: Roy Zang <roy.zang@freescale.com>
+ *
+ * 2006 (c) Freescale Semiconductor, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H
+#define __PPC_PLATFORMS_MPC7448_HPC2_H
+
+#include <asm/ppcboot.h>
+
+/* Base Addresses for the PCI bus
+ */
+#define MPC7448_HPC2_PCI_MEM_OFFSET	(0x00000000)
+#define MPC7448_HPC2_ISA_IO_BASE	(0x00000000)
+#define MPC7448_HPC2_ISA_MEM_BASE	(0x00000000)
+#endif				/* __PPC_PLATFORMS_MPC7448_HPC2_H */

+ 2 - 0
arch/powerpc/platforms/iseries/dt.c

@@ -252,6 +252,7 @@ static void __init dt_model(struct iseries_flat_dt *dt)
 {
 	char buf[16] = "IBM,";
 
+	/* N.B. lparcfg.c knows about the "IBM," prefixes ... */
 	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
 	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
 	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
@@ -264,6 +265,7 @@ static void __init dt_model(struct iseries_flat_dt *dt)
 	dt_prop_str(dt, "model", buf);
 
 	dt_prop_str(dt, "compatible", "IBM,iSeries");
+	dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex());
 }
 
 static void __init dt_do_vdevice(struct iseries_flat_dt *dt,

+ 1 - 3
arch/powerpc/platforms/iseries/htab.c

@@ -242,13 +242,11 @@ static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va,
 	local_irq_restore(flags);
 }
 
-void hpte_init_iSeries(void)
+void __init hpte_init_iSeries(void)
 {
 	ppc_md.hpte_invalidate	= iSeries_hpte_invalidate;
 	ppc_md.hpte_updatepp	= iSeries_hpte_updatepp;
 	ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
 	ppc_md.hpte_insert	= iSeries_hpte_insert;
 	ppc_md.hpte_remove	= iSeries_hpte_remove;
-
-	htab_finish_init();
 }

+ 28 - 27
arch/powerpc/platforms/iseries/lpevents.c

@@ -51,20 +51,21 @@ static unsigned lpEventHandlerPaths[HvLpEvent_Type_NumTypes];
 static struct HvLpEvent * get_next_hvlpevent(void)
 {
 	struct HvLpEvent * event;
-	event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+	event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
 
 	if (hvlpevent_is_valid(event)) {
 		/* rmb() needed only for weakly consistent machines (regatta) */
 		rmb();
 		/* Set pointer to next potential event */
-		hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +
-				LpEventAlign) / LpEventAlign) * LpEventAlign;
+		hvlpevent_queue.hq_current_event += ((event->xSizeMinus1 +
+				IT_LP_EVENT_ALIGN) / IT_LP_EVENT_ALIGN) *
+					IT_LP_EVENT_ALIGN;
 
 		/* Wrap to beginning if no room at end */
-		if (hvlpevent_queue.xSlicCurEventPtr >
-				hvlpevent_queue.xSlicLastValidEventPtr) {
-			hvlpevent_queue.xSlicCurEventPtr =
-				hvlpevent_queue.xSlicEventStackPtr;
+		if (hvlpevent_queue.hq_current_event >
+				hvlpevent_queue.hq_last_event) {
+			hvlpevent_queue.hq_current_event =
+				hvlpevent_queue.hq_event_stack;
 		}
 	} else {
 		event = NULL;
@@ -82,10 +83,10 @@ int hvlpevent_is_pending(void)
 	if (smp_processor_id() >= spread_lpevents)
 		return 0;
 
-	next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
+	next_event = (struct HvLpEvent *)hvlpevent_queue.hq_current_event;
 
 	return hvlpevent_is_valid(next_event) ||
-		hvlpevent_queue.xPlicOverflowIntPending;
+		hvlpevent_queue.hq_overflow_pending;
 }
 
 static void hvlpevent_clear_valid(struct HvLpEvent * event)
@@ -95,18 +96,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event)
 	 * ie. on 64-byte boundaries.
 	 */
 	struct HvLpEvent *tmp;
-	unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /
-						 LpEventAlign) - 1;
+	unsigned extra = ((event->xSizeMinus1 + IT_LP_EVENT_ALIGN) /
+				IT_LP_EVENT_ALIGN) - 1;
 
 	switch (extra) {
 	case 3:
-		tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
+		tmp = (struct HvLpEvent*)((char*)event + 3 * IT_LP_EVENT_ALIGN);
 		hvlpevent_invalidate(tmp);
 	case 2:
-		tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
+		tmp = (struct HvLpEvent*)((char*)event + 2 * IT_LP_EVENT_ALIGN);
 		hvlpevent_invalidate(tmp);
 	case 1:
-		tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
+		tmp = (struct HvLpEvent*)((char*)event + 1 * IT_LP_EVENT_ALIGN);
 		hvlpevent_invalidate(tmp);
 	}
 
@@ -120,7 +121,7 @@ void process_hvlpevents(struct pt_regs *regs)
 	struct HvLpEvent * event;
 
 	/* If we have recursed, just return */
-	if (!spin_trylock(&hvlpevent_queue.lock))
+	if (!spin_trylock(&hvlpevent_queue.hq_lock))
 		return;
 
 	for (;;) {
@@ -148,17 +149,17 @@ void process_hvlpevents(struct pt_regs *regs)
 				printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
 
 			hvlpevent_clear_valid(event);
-		} else if (hvlpevent_queue.xPlicOverflowIntPending)
+		} else if (hvlpevent_queue.hq_overflow_pending)
 			/*
 			 * No more valid events. If overflow events are
 			 * pending process them
 			 */
-			HvCallEvent_getOverflowLpEvents(hvlpevent_queue.xIndex);
+			HvCallEvent_getOverflowLpEvents(hvlpevent_queue.hq_index);
 		else
 			break;
 	}
 
-	spin_unlock(&hvlpevent_queue.lock);
+	spin_unlock(&hvlpevent_queue.hq_lock);
 }
 
 static int set_spread_lpevents(char *str)
@@ -184,20 +185,20 @@ void setup_hvlpevent_queue(void)
 {
 	void *eventStack;
 
-	spin_lock_init(&hvlpevent_queue.lock);
+	spin_lock_init(&hvlpevent_queue.hq_lock);
 
 	/* Allocate a page for the Event Stack. */
-	eventStack = alloc_bootmem_pages(LpEventStackSize);
-	memset(eventStack, 0, LpEventStackSize);
+	eventStack = alloc_bootmem_pages(IT_LP_EVENT_STACK_SIZE);
+	memset(eventStack, 0, IT_LP_EVENT_STACK_SIZE);
 
 	/* Invoke the hypervisor to initialize the event stack */
-	HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
+	HvCallEvent_setLpEventStack(0, eventStack, IT_LP_EVENT_STACK_SIZE);
 
-	hvlpevent_queue.xSlicEventStackPtr = (char *)eventStack;
-	hvlpevent_queue.xSlicCurEventPtr = (char *)eventStack;
-	hvlpevent_queue.xSlicLastValidEventPtr = (char *)eventStack +
-					(LpEventStackSize - LpEventMaxSize);
-	hvlpevent_queue.xIndex = 0;
+	hvlpevent_queue.hq_event_stack = eventStack;
+	hvlpevent_queue.hq_current_event = eventStack;
+	hvlpevent_queue.hq_last_event = (char *)eventStack +
+		(IT_LP_EVENT_STACK_SIZE - IT_LP_EVENT_MAX_SIZE);
+	hvlpevent_queue.hq_index = 0;
 }
 
 /* Register a handler for an LpEvent type */

+ 0 - 1
arch/powerpc/platforms/iseries/proc.c

@@ -24,7 +24,6 @@
 #include <asm/processor.h>
 #include <asm/time.h>
 #include <asm/lppaca.h>
-#include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/hv_call_xm.h>
 
 #include "processor_vpd.h"

+ 2 - 17
arch/powerpc/platforms/iseries/setup.c

@@ -81,8 +81,6 @@ static void iSeries_pci_final_fixup(void) { }
 #endif
 
 extern int rd_size;		/* Defined in drivers/block/rd.c */
-extern unsigned long embedded_sysmap_start;
-extern unsigned long embedded_sysmap_end;
 
 extern unsigned long iSeries_recal_tb;
 extern unsigned long iSeries_recal_titan;
@@ -320,11 +318,6 @@ static void __init iSeries_init_early(void)
 	iSeries_recal_tb = get_tb();
 	iSeries_recal_titan = HvCallXm_loadTod();
 
-	/*
-	 * Initialize the hash table management pointers
-	 */
-	hpte_init_iSeries();
-
 	/*
 	 * Initialize the DMA/TCE management
 	 */
@@ -563,16 +556,6 @@ static void __init iSeries_fixup_klimit(void)
 	if (naca.xRamDisk)
 		klimit = KERNELBASE + (u64)naca.xRamDisk +
 			(naca.xRamDiskSize * HW_PAGE_SIZE);
-	else {
-		/*
-		 * No ram disk was included - check and see if there
-		 * was an embedded system map.  Change klimit to take
-		 * into account any embedded system map
-		 */
-		if (embedded_sysmap_end)
-			klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
-					0xfffffffffffff000);
-	}
 }
 
 static int __init iSeries_src_init(void)
@@ -683,6 +666,8 @@ static int __init iseries_probe(void)
 	 */
 	virt_irq_max = 255;
 
+	hpte_init_iSeries();
+
 	return 1;
 }
 

+ 2 - 5
arch/powerpc/platforms/maple/setup.c

@@ -199,11 +199,6 @@ static void __init maple_init_early(void)
 {
 	DBG(" -> maple_init_early\n");
 
-	/* Initialize hash table, from now on, we can take hash faults
-	 * and call ioremap
-	 */
-	hpte_init_native();
-
 	/* Setup interrupt mapping options */
 	ppc64_interrupt_controller = IC_OPEN_PIC;
 
@@ -272,6 +267,8 @@ static int __init maple_probe(void)
 	 */
 	alloc_dart_table();
 
+	hpte_init_native();
+
 	return 1;
 }
 

+ 2 - 7
arch/powerpc/platforms/powermac/setup.c

@@ -600,13 +600,6 @@ pmac_halt(void)
  */
 static void __init pmac_init_early(void)
 {
-#ifdef CONFIG_PPC64
-	/* Initialize hash table, from now on, we can take hash faults
-	 * and call ioremap
-	 */
-	hpte_init_native();
-#endif
-
 	/* Enable early btext debug if requested */
 	if (strstr(cmd_line, "btextdbg")) {
 		udbg_adb_init_early();
@@ -683,6 +676,8 @@ static int __init pmac_probe(void)
 	 * part of the cacheable linar mapping
 	 */
 	alloc_dart_table();
+
+	hpte_init_native();
 #endif
 
 #ifdef CONFIG_PPC32

+ 33 - 0
arch/powerpc/platforms/pseries/iommu.c

@@ -92,6 +92,15 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 		*(tcep++) = 0;
 }
 
+static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
+{
+	u64 *tcep;
+
+	index <<= TCE_PAGE_FACTOR;
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	return *tcep;
+}
 
 static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				long npages, unsigned long uaddr,
@@ -235,6 +244,25 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
 	}
 }
 
+static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
+{
+	u64 rc;
+	unsigned long tce_ret;
+
+	tcenum <<= TCE_PAGE_FACTOR;
+	rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
+
+	if (rc && printk_ratelimit()) {
+		printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%ld\n",
+			rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+
+	return tce_ret;
+}
+
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
 				 struct iommu_table *tbl)
@@ -254,7 +282,10 @@ static void iommu_table_setparms(struct pci_controller *phb,
 	}
 
 	tbl->it_base = (unsigned long)__va(*basep);
+
+#ifndef CONFIG_CRASH_DUMP
 	memset((void *)tbl->it_base, 0, *sizep);
+#endif
 
 	tbl->it_busno = phb->bus->number;
 
@@ -560,11 +591,13 @@ void iommu_init_early_pSeries(void)
 			ppc_md.tce_build = tce_build_pSeriesLP;
 			ppc_md.tce_free	 = tce_free_pSeriesLP;
 		}
+		ppc_md.tce_get   = tce_get_pSeriesLP;
 		ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
 		ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
+		ppc_md.tce_get   = tce_get_pseries;
 		ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
 		ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
 	}

+ 1 - 3
arch/powerpc/platforms/pseries/lpar.c

@@ -513,7 +513,7 @@ void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-void hpte_init_lpar(void)
+void __init hpte_init_lpar(void)
 {
 	ppc_md.hpte_invalidate	= pSeries_lpar_hpte_invalidate;
 	ppc_md.hpte_updatepp	= pSeries_lpar_hpte_updatepp;
@@ -522,6 +522,4 @@ void hpte_init_lpar(void)
 	ppc_md.hpte_remove	= pSeries_lpar_hpte_remove;
 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
 	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
-
-	htab_finish_init();
 }

+ 5 - 5
arch/powerpc/platforms/pseries/setup.c

@@ -322,11 +322,6 @@ static void __init pSeries_init_early(void)
 	DBG(" -> pSeries_init_early()\n");
 
 	fw_feature_init();
-	
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		hpte_init_lpar();
-	else
-		hpte_init_native();
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		find_udbg_vterm();
@@ -384,6 +379,11 @@ static int __init pSeries_probe_hypertas(unsigned long node,
 	if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
  		powerpc_firmware_features |= FW_FEATURE_LPAR;
 
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		hpte_init_lpar();
+	else
+		hpte_init_native();
+
  	return 1;
 }
 

+ 2 - 0
arch/powerpc/sysdev/Makefile

@@ -12,3 +12,5 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
+obj-$(CONFIG_PPC_TODC)		+= todc.o
+obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o

+ 5 - 1
arch/powerpc/sysdev/dart.h

@@ -47,8 +47,12 @@
 /* U4 registers */
 #define DART_BASE_U4_BASE_MASK	0xffffff
 #define DART_BASE_U4_BASE_SHIFT	0
-#define DART_CNTL_U4_FLUSHTLB	0x20000000
 #define DART_CNTL_U4_ENABLE	0x80000000
+#define DART_CNTL_U4_IONE	0x40000000
+#define DART_CNTL_U4_FLUSHTLB	0x20000000
+#define DART_CNTL_U4_IDLE	0x10000000
+#define DART_CNTL_U4_PAR_EN	0x08000000
+#define DART_CNTL_U4_IONE_MASK	0x07ffffff
 #define DART_SIZE_U4_SIZE_MASK	0x1fff
 #define DART_SIZE_U4_SIZE_SHIFT	0
 

+ 43 - 6
arch/powerpc/sysdev/dart_iommu.c

@@ -101,8 +101,8 @@ retry:
 	if (l == (1L << limit)) {
 		if (limit < 4) {
 			limit++;
-		        reg = DART_IN(DART_CNTL);
-		        reg &= ~inv_bit;
+			reg = DART_IN(DART_CNTL);
+			reg &= ~inv_bit;
 			DART_OUT(DART_CNTL, reg);
 			goto retry;
 		} else
@@ -111,11 +111,39 @@ retry:
 	}
 }
 
+static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
+{
+	unsigned int reg;
+	unsigned int l, limit;
+
+	reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE |
+		(bus_rpn & DART_CNTL_U4_IONE_MASK);
+	DART_OUT(DART_CNTL, reg);
+
+	limit = 0;
+wait_more:
+	l = 0;
+	while ((DART_IN(DART_CNTL) & DART_CNTL_U4_IONE) && l < (1L << limit)) {
+		rmb();
+		l++;
+	}
+
+	if (l == (1L << limit)) {
+		if (limit < 4) {
+			limit++;
+			goto wait_more;
+		} else
+			panic("DART: TLB did not flush after waiting a long "
+			      "time. Buggy U4 ?");
+	}
+}
+
 static void dart_flush(struct iommu_table *tbl)
 {
-	if (dart_dirty)
+	if (dart_dirty) {
 		dart_tlb_invalidate_all();
-	dart_dirty = 0;
+		dart_dirty = 0;
+	}
 }
 
 static void dart_build(struct iommu_table *tbl, long index,
@@ -124,6 +152,7 @@ static void dart_build(struct iommu_table *tbl, long index,
 {
 	unsigned int *dp;
 	unsigned int rpn;
+	long l;
 
 	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
 
@@ -135,7 +164,8 @@ static void dart_build(struct iommu_table *tbl, long index,
 	/* On U3, all memory is contigous, so we can move this
 	 * out of the loop.
 	 */
-	while (npages--) {
+	l = npages;
+	while (l--) {
 		rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
 
 		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
@@ -143,7 +173,14 @@ static void dart_build(struct iommu_table *tbl, long index,
 		uaddr += DART_PAGE_SIZE;
 	}
 
-	dart_dirty = 1;
+	if (dart_is_u4) {
+		rpn = index;
+		mb(); /* make sure all updates have reached memory */
+		while (npages--)
+			dart_tlb_invalidate_one(rpn++);
+	} else {
+		dart_dirty = 1;
+	}
 }
 
 

+ 392 - 0
arch/powerpc/sysdev/todc.c

@@ -0,0 +1,392 @@
+/*
+ * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818
+ * Real Time Clocks/Timekeepers.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001-2004 (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/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/bcd.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+
+/*
+ * Depending on the hardware on your board and your board design, the
+ * RTC/NVRAM may be accessed either directly (like normal memory) or via
+ * address/data registers.  If your board uses the direct method, set
+ * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
+ * 'nvram_as1' NULL.  If your board uses address/data regs to access nvram,
+ * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
+ * address of the upper byte (leave NULL if using mc146818), and set
+ * 'nvram_data' to the address of the 8-bit data register.
+ *
+ * Note: Even though the documentation for the various RTC chips say that it
+ * 	 take up to a second before it starts updating once the 'R' bit is
+ * 	 cleared, they always seem to update even though we bang on it many
+ * 	 times a second.  This is true, except for the Dallas Semi 1746/1747
+ * 	 (possibly others).  Those chips seem to have a real problem whenever
+ * 	 we set the 'R' bit before reading them, they basically stop counting.
+ * 	 					--MAG
+ */
+
+/*
+ * 'todc_info' should be initialized in your *_setup.c file to
+ * point to a fully initialized 'todc_info_t' structure.
+ * This structure holds all the register offsets for your particular
+ * TODC/RTC chip.
+ * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you.
+ */
+
+#ifdef	RTC_FREQ_SELECT
+#undef	RTC_FREQ_SELECT
+#define	RTC_FREQ_SELECT		control_b	/* Register A */
+#endif
+
+#ifdef	RTC_CONTROL
+#undef	RTC_CONTROL
+#define	RTC_CONTROL		control_a	/* Register B */
+#endif
+
+#ifdef	RTC_INTR_FLAGS
+#undef	RTC_INTR_FLAGS
+#define	RTC_INTR_FLAGS		watchdog	/* Register C */
+#endif
+
+#ifdef	RTC_VALID
+#undef	RTC_VALID
+#define	RTC_VALID		interrupts	/* Register D */
+#endif
+
+/* Access routines when RTC accessed directly (like normal memory) */
+u_char
+todc_direct_read_val(int addr)
+{
+	return readb((void __iomem *)(todc_info->nvram_data + addr));
+}
+
+void
+todc_direct_write_val(int addr, unsigned char val)
+{
+	writeb(val, (void __iomem *)(todc_info->nvram_data + addr));
+	return;
+}
+
+/* Access routines for accessing m48txx type chips via addr/data regs */
+u_char
+todc_m48txx_read_val(int addr)
+{
+	outb(addr, todc_info->nvram_as0);
+	outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+	return inb(todc_info->nvram_data);
+}
+
+void
+todc_m48txx_write_val(int addr, unsigned char val)
+{
+	outb(addr, todc_info->nvram_as0);
+	outb(addr>>todc_info->as0_bits, todc_info->nvram_as1);
+	outb(val, todc_info->nvram_data);
+	return;
+}
+
+/* Access routines for accessing mc146818 type chips via addr/data regs */
+u_char
+todc_mc146818_read_val(int addr)
+{
+	outb_p(addr, todc_info->nvram_as0);
+	return inb_p(todc_info->nvram_data);
+}
+
+void
+todc_mc146818_write_val(int addr, unsigned char val)
+{
+	outb_p(addr, todc_info->nvram_as0);
+	outb_p(val, todc_info->nvram_data);
+}
+
+
+/*
+ * Routines to make RTC chips with NVRAM buried behind an addr/data pair
+ * have the NVRAM and clock regs appear at the same level.
+ * The NVRAM will appear to start at addr 0 and the clock regs will appear
+ * to start immediately after the NVRAM (actually, start at offset
+ * todc_info->nvram_size).
+ */
+static inline u_char
+todc_read_val(int addr)
+{
+	u_char	val;
+
+	if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+		if (addr < todc_info->nvram_size) { /* NVRAM */
+			ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+			val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
+		} else { /* Clock Reg */
+			addr -= todc_info->nvram_size;
+			val = ppc_md.rtc_read_val(addr);
+		}
+	} else
+		val = ppc_md.rtc_read_val(addr);
+
+	return val;
+}
+
+static inline void
+todc_write_val(int addr, u_char val)
+{
+	if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
+		if (addr < todc_info->nvram_size) { /* NVRAM */
+			ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
+			ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
+		} else { /* Clock Reg */
+			addr -= todc_info->nvram_size;
+			ppc_md.rtc_write_val(addr, val);
+		}
+	} else
+		ppc_md.rtc_write_val(addr, val);
+}
+
+/*
+ * TODC routines
+ *
+ * There is some ugly stuff in that there are assumptions for the mc146818.
+ *
+ * Assumptions:
+ *	- todc_info->control_a has the offset as mc146818 Register B reg
+ *	- todc_info->control_b has the offset as mc146818 Register A reg
+ *	- m48txx control reg's write enable or 'W' bit is same as
+ *	  mc146818 Register B 'SET' bit (i.e., 0x80)
+ *
+ * These assumptions were made to make the code simpler.
+ */
+long __init
+todc_time_init(void)
+{
+	u_char	cntl_b;
+
+	if (!ppc_md.rtc_read_val)
+		ppc_md.rtc_read_val = ppc_md.nvram_read_val;
+	if (!ppc_md.rtc_write_val)
+		ppc_md.rtc_write_val = ppc_md.nvram_write_val;
+
+	cntl_b = todc_read_val(todc_info->control_b);
+
+	if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+		if ((cntl_b & 0x70) != 0x20) {
+			printk(KERN_INFO "TODC real-time-clock was stopped."
+				"  Now starting...");
+			cntl_b &= ~0x70;
+			cntl_b |= 0x20;
+		}
+
+		todc_write_val(todc_info->control_b, cntl_b);
+	} else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
+		u_char mode;
+
+		mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
+		/* Make sure countdown clear is not set */
+		mode &= ~0x40;
+		/* Enable oscillator, extended register set */
+		mode |= 0x30;
+		todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
+
+	} else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
+		u_char	month;
+
+		todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
+		todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
+
+		month = todc_read_val(todc_info->month);
+
+		if ((month & 0x80) == 0x80) {
+			printk(KERN_INFO "TODC %s %s\n",
+				"real-time-clock was stopped.",
+				"Now starting...");
+			month &= ~0x80;
+			todc_write_val(todc_info->month, month);
+		}
+
+		cntl_b &= ~TODC_DS1501_CNTL_B_TE;
+		todc_write_val(todc_info->control_b, cntl_b);
+	} else { /* must be a m48txx type */
+		u_char	cntl_a;
+
+		todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
+		todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
+
+		cntl_a = todc_read_val(todc_info->control_a);
+
+		/* Check & clear STOP bit in control B register */
+		if (cntl_b & TODC_MK48TXX_DAY_CB) {
+			printk(KERN_INFO "TODC %s %s\n",
+				"real-time-clock was stopped.",
+				"Now starting...");
+
+			cntl_a |= todc_info->enable_write;
+			cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
+
+			todc_write_val(todc_info->control_a, cntl_a);
+			todc_write_val(todc_info->control_b, cntl_b);
+		}
+
+		/* Make sure READ & WRITE bits are cleared. */
+		cntl_a &= ~(todc_info->enable_write | todc_info->enable_read);
+		todc_write_val(todc_info->control_a, cntl_a);
+	}
+
+	return 0;
+}
+
+/*
+ * There is some ugly stuff in that there are assumptions that for a mc146818,
+ * the todc_info->control_a has the offset of the mc146818 Register B reg and
+ * that the register'ss 'SET' bit is the same as the m48txx's write enable
+ * bit in the control register of the m48txx (i.e., 0x80).
+ *
+ * It was done to make the code look simpler.
+ */
+void
+todc_get_rtc_time(struct rtc_time *tm)
+{
+	uint	year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0;
+	uint	limit, i;
+	u_char	save_control, uip = 0;
+	extern void GregorianDay(struct rtc_time *);
+
+	spin_lock(&rtc_lock);
+	save_control = todc_read_val(todc_info->control_a);
+
+	if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+		limit = 1;
+
+		switch (todc_info->rtc_type) {
+		case TODC_TYPE_DS1553:
+		case TODC_TYPE_DS1557:
+		case TODC_TYPE_DS1743:
+		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
+		case TODC_TYPE_DS1747:
+		case TODC_TYPE_DS17285:
+			break;
+		default:
+			todc_write_val(todc_info->control_a,
+				(save_control | todc_info->enable_read));
+		}
+	} else
+		limit = 100000000;
+
+	for (i=0; i<limit; i++) {
+		if (todc_info->rtc_type == TODC_TYPE_MC146818)
+			uip = todc_read_val(todc_info->RTC_FREQ_SELECT);
+
+		sec = todc_read_val(todc_info->seconds) & 0x7f;
+		min = todc_read_val(todc_info->minutes) & 0x7f;
+		hour = todc_read_val(todc_info->hours) & 0x3f;
+		mday = todc_read_val(todc_info->day_of_month) & 0x3f;
+		mon = todc_read_val(todc_info->month) & 0x1f;
+		year = todc_read_val(todc_info->year) & 0xff;
+
+		if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+			uip |= todc_read_val(todc_info->RTC_FREQ_SELECT);
+			if ((uip & RTC_UIP) == 0)
+				break;
+		}
+	}
+
+	if (todc_info->rtc_type != TODC_TYPE_MC146818) {
+		switch (todc_info->rtc_type) {
+		case TODC_TYPE_DS1553:
+		case TODC_TYPE_DS1557:
+		case TODC_TYPE_DS1743:
+		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
+		case TODC_TYPE_DS1747:
+		case TODC_TYPE_DS17285:
+			break;
+		default:
+			save_control &= ~(todc_info->enable_read);
+			todc_write_val(todc_info->control_a, save_control);
+		}
+	}
+	spin_unlock(&rtc_lock);
+
+	if ((todc_info->rtc_type != TODC_TYPE_MC146818)
+			|| ((save_control & RTC_DM_BINARY) == 0)
+			|| RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(mday);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+
+	if ((year + 1900) < 1970) {
+		year += 100;
+	}
+
+	tm->tm_sec = sec;
+	tm->tm_min = min;
+	tm->tm_hour = hour;
+	tm->tm_mday = mday;
+	tm->tm_mon = mon;
+	tm->tm_year = year;
+
+	GregorianDay(tm);
+}
+
+int
+todc_set_rtc_time(struct rtc_time *tm)
+{
+	u_char save_control, save_freq_select = 0;
+
+	spin_lock(&rtc_lock);
+	save_control = todc_read_val(todc_info->control_a);
+
+	/* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */
+	todc_write_val(todc_info->control_a,
+		(save_control | todc_info->enable_write));
+	save_control &= ~(todc_info->enable_write); /* in case it was set */
+
+	if (todc_info->rtc_type == TODC_TYPE_MC146818) {
+		save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT);
+		todc_write_val(todc_info->RTC_FREQ_SELECT,
+			save_freq_select | RTC_DIV_RESET2);
+	}
+
+	if ((todc_info->rtc_type != TODC_TYPE_MC146818)
+			|| ((save_control & RTC_DM_BINARY) == 0)
+			|| RTC_ALWAYS_BCD) {
+		BIN_TO_BCD(tm->tm_sec);
+		BIN_TO_BCD(tm->tm_min);
+		BIN_TO_BCD(tm->tm_hour);
+		BIN_TO_BCD(tm->tm_mon);
+		BIN_TO_BCD(tm->tm_mday);
+		BIN_TO_BCD(tm->tm_year);
+	}
+
+	todc_write_val(todc_info->seconds, tm->tm_sec);
+	todc_write_val(todc_info->minutes, tm->tm_min);
+	todc_write_val(todc_info->hours, tm->tm_hour);
+	todc_write_val(todc_info->month, tm->tm_mon);
+	todc_write_val(todc_info->day_of_month, tm->tm_mday);
+	todc_write_val(todc_info->year, tm->tm_year);
+
+	todc_write_val(todc_info->control_a, save_control);
+
+	if (todc_info->rtc_type == TODC_TYPE_MC146818)
+		todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select);
+
+	spin_unlock(&rtc_lock);
+	return 0;
+}

+ 145 - 0
arch/powerpc/sysdev/tsi108_dev.c

@@ -0,0 +1,145 @@
+/*
+ * tsi108/109 device setup code
+ *
+ * Maintained by Roy Zang < tie-fei.zang@freescale.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
+ * 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/major.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/tsi108.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+static phys_addr_t tsi108_csr_base = -1;
+
+phys_addr_t get_csrbase(void)
+{
+	struct device_node *tsi;
+
+	if (tsi108_csr_base != -1)
+		return tsi108_csr_base;
+
+	tsi = of_find_node_by_type(NULL, "tsi-bridge");
+	if (tsi) {
+		unsigned int size;
+		void *prop = get_property(tsi, "reg", &size);
+		tsi108_csr_base = of_translate_address(tsi, prop);
+		of_node_put(tsi);
+	};
+	return tsi108_csr_base;
+}
+
+u32 get_vir_csrbase(void)
+{
+	return (u32) (ioremap(get_csrbase(), 0x10000));
+}
+
+EXPORT_SYMBOL(get_csrbase);
+EXPORT_SYMBOL(get_vir_csrbase);
+
+static int __init tsi108_eth_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *tsi_eth_dev;
+	struct resource res;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL;
+	     i++) {
+		struct resource r[2];
+		struct device_node *phy;
+		hw_info tsi_eth_data;
+		unsigned int *id;
+		unsigned int *phy_id;
+		void *mac_addr;
+		phandle *ph;
+
+		memset(r, 0, sizeof(r));
+		memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+			__FUNCTION__,r[0].name, r[0].start, r[0].end);
+		if (ret)
+			goto err;
+
+		r[1].name = "tx";
+		r[1].start = np->intrs[0].line;
+		r[1].end = np->intrs[0].line;
+		r[1].flags = IORESOURCE_IRQ;
+
+		tsi_eth_dev =
+		    platform_device_register_simple("tsi-ethernet", i, &r[0],
+						    np->n_intrs + 1);
+
+		if (IS_ERR(tsi_eth_dev)) {
+			ret = PTR_ERR(tsi_eth_dev);
+			goto err;
+		}
+
+		mac_addr = get_property(np, "address", NULL);
+		memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
+
+		ph = (phandle *) get_property(np, "phy-handle", NULL);
+		phy = of_find_node_by_phandle(*ph);
+
+		if (phy == NULL) {
+			ret = -ENODEV;
+			goto unreg;
+		}
+
+		id = (u32 *) get_property(phy, "reg", NULL);
+		phy_id = (u32 *) get_property(phy, "phy-id", NULL);
+		ret = of_address_to_resource(phy, 0, &res);
+		if (ret) {
+			of_node_put(phy);
+			goto unreg;
+		}
+		tsi_eth_data.regs = r[0].start;
+		tsi_eth_data.phyregs = res.start;
+		tsi_eth_data.phy = *phy_id;
+		tsi_eth_data.irq_num = np->intrs[0].line;
+		of_node_put(phy);
+		ret =
+		    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
+					     sizeof(hw_info));
+		if (ret)
+			goto unreg;
+	}
+	return 0;
+unreg:
+	platform_device_unregister(tsi_eth_dev);
+err:
+	return ret;
+}
+
+arch_initcall(tsi108_eth_of_init);

+ 412 - 0
arch/powerpc/sysdev/tsi108_pci.c

@@ -0,0 +1,412 @@
+/*
+ * Common routines for Tundra Semiconductor TSI108 host bridge.
+ *
+ * 2004-2005 (c) Tundra Semiconductor Corp.
+ * Author: Alex Bounine (alexandreb@tundra.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 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/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/tsi108.h>
+#include <asm/tsi108_irq.h>
+#include <asm/prom.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#define tsi_mk_config_addr(bus, devfunc, offset) \
+	((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base)
+
+u32 tsi108_pci_cfg_base;
+u32 tsi108_csr_vir_base;
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_read_reg(u32 reg_offset);
+extern void tsi108_write_reg(u32 reg_offset, u32 val);
+
+int
+tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
+			   int offset, int len, u32 val)
+{
+	volatile unsigned char *cfg_addr;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfunc))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
+							devfunc, offset) |
+							(offset & 0x03));
+
+#ifdef DEBUG
+	printk("PCI CFG write : ");
+	printk("%d:0x%x:0x%x ", bus->number, devfunc, offset);
+	printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
+	printk("data = 0x%08x\n", val);
+#endif
+
+	switch (len) {
+	case 1:
+		out_8((u8 *) cfg_addr, val);
+		break;
+	case 2:
+		out_le16((u16 *) cfg_addr, val);
+		break;
+	default:
+		out_le32((u32 *) cfg_addr, val);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+void tsi108_clear_pci_error(u32 pci_cfg_base)
+{
+	u32 err_stat, err_addr, pci_stat;
+
+	/*
+	 * Quietly clear PB and PCI error flags set as result
+	 * of PCI/X configuration read requests.
+	 */
+
+	/* Read PB Error Log Registers */
+
+	err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS);
+	err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR);
+
+	if (err_stat & TSI108_PB_ERRCS_ES) {
+		/* Clear error flag */
+		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS,
+				 TSI108_PB_ERRCS_ES);
+
+		/* Clear read error reported in PB_ISR */
+		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR,
+				 TSI108_PB_ISR_PBS_RD_ERR);
+
+		/* Clear PCI/X bus cfg errors if applicable */
+		if ((err_addr & 0xFF000000) == pci_cfg_base) {
+			pci_stat =
+			    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR);
+			tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR,
+					 pci_stat);
+		}
+	}
+
+	return;
+}
+
+#define __tsi108_read_pci_config(x, addr, op)		\
+	__asm__ __volatile__(				\
+		"	"op" %0,0,%1\n"		\
+		"1:	eieio\n"			\
+		"2:\n"					\
+		".section .fixup,\"ax\"\n"		\
+		"3:	li %0,-1\n"			\
+		"	b 2b\n"				\
+		".section __ex_table,\"a\"\n"		\
+		"	.align 2\n"			\
+		"	.long 1b,3b\n"			\
+		".text"					\
+		: "=r"(x) : "r"(addr))
+
+int
+tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+			  int len, u32 * val)
+{
+	volatile unsigned char *cfg_addr;
+	u32 temp;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
+							devfn,
+							offset) | (offset &
+								   0x03));
+
+	switch (len) {
+	case 1:
+		__tsi108_read_pci_config(temp, cfg_addr, "lbzx");
+		break;
+	case 2:
+		__tsi108_read_pci_config(temp, cfg_addr, "lhbrx");
+		break;
+	default:
+		__tsi108_read_pci_config(temp, cfg_addr, "lwbrx");
+		break;
+	}
+
+	*val = temp;
+
+#ifdef DEBUG
+	if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) {
+		printk("PCI CFG read : ");
+		printk("%d:0x%x:0x%x ", bus->number, devfn, offset);
+		printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
+		printk("data = 0x%x\n", *val);
+	}
+#endif
+	return PCIBIOS_SUCCESSFUL;
+}
+
+void tsi108_clear_pci_cfg_error(void)
+{
+	tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS);
+}
+
+static struct pci_ops tsi108_direct_pci_ops = {
+	tsi108_direct_read_config,
+	tsi108_direct_write_config
+};
+
+int __init tsi108_setup_pci(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct resource rsrc;
+	int *bus_range;
+	int primary = 0, has_address = 0;
+
+	/* PCI Config mapping */
+	tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS,
+			TSI108_PCI_CFG_SIZE);
+	DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
+	    tsi108_pci_cfg_base);
+
+	/* 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) {
+		printk("PCI Host bridge init failed\n");
+		return -ENOMEM;
+	}
+	hose->arch_data = dev;
+	hose->set_cfg_type = 1;
+
+	hose->first_busno = bus_range ? bus_range[0] : 0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+	(hose)->ops = &tsi108_direct_pci_ops;
+
+	printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. "
+	       "Firmware bus number: %d->%d\n",
+	       rsrc.start, hose->first_busno, hose->last_busno);
+
+	/* 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);
+	return 0;
+}
+
+/*
+ * Low level utility functions
+ */
+
+static void tsi108_pci_int_mask(u_int irq)
+{
+	u_int irp_cfg;
+	int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+	mb();
+	irp_cfg |= (1 << int_line);	/* INTx_DIR = output */
+	irp_cfg &= ~(3 << (8 + (int_line * 2)));	/* INTx_TYPE = unused */
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+	mb();
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+}
+
+static void tsi108_pci_int_unmask(u_int irq)
+{
+	u_int irp_cfg;
+	int int_line = (irq - IRQ_PCI_INTAD_BASE);
+
+	irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+	mb();
+	irp_cfg &= ~(1 << int_line);
+	irp_cfg |= (3 << (8 + (int_line * 2)));
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg);
+	mb();
+}
+
+static void init_pci_source(void)
+{
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL,
+			0x0000ff00);
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+			TSI108_PCI_IRP_ENABLE_P_INT);
+	mb();
+}
+
+static inline int get_pci_source(void)
+{
+	u_int temp = 0;
+	int irq = -1;
+	int i;
+	u_int pci_irp_stat;
+	static int mask = 0;
+
+	/* Read PCI/X block interrupt status register */
+	pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+	mb();
+
+	if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) {
+		/* Process Interrupt from PCI bus INTA# - INTD# lines */
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET +
+				    TSI108_PCI_IRP_INTAD) & 0xf;
+		mb();
+		for (i = 0; i < 4; i++, mask++) {
+			if (temp & (1 << mask % 4)) {
+				irq = IRQ_PCI_INTA + mask % 4;
+				mask++;
+				break;
+			}
+		}
+
+		/* Disable interrupts from PCI block */
+		temp = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+				temp & ~TSI108_PCI_IRP_ENABLE_P_INT);
+		mb();
+		(void)tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		mb();
+	}
+#ifdef DEBUG
+	else {
+		printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n");
+		pci_irp_stat =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD);
+		mb();
+		printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL);
+		mb();
+		printk("cfg_ctl=0x%08x ", temp);
+		temp =
+		    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE);
+		mb();
+		printk("irp_enable=0x%08x\n", temp);
+	}
+#endif	/* end of DEBUG */
+
+	return irq;
+}
+
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+static void tsi108_pci_irq_enable(u_int irq)
+{
+	tsi108_pci_int_unmask(irq);
+}
+
+static void tsi108_pci_irq_disable(u_int irq)
+{
+	tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_ack(u_int irq)
+{
+	tsi108_pci_int_mask(irq);
+}
+
+static void tsi108_pci_irq_end(u_int irq)
+{
+	tsi108_pci_int_unmask(irq);
+
+	/* Enable interrupts from PCI block */
+	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
+			 tsi108_read_reg(TSI108_PCI_OFFSET +
+					 TSI108_PCI_IRP_ENABLE) |
+			 TSI108_PCI_IRP_ENABLE_P_INT);
+	mb();
+}
+
+/*
+ * Interrupt controller descriptor for cascaded PCI interrupt controller.
+ */
+
+struct hw_interrupt_type tsi108_pci_irq = {
+	.typename = "tsi108_PCI_int",
+	.enable = tsi108_pci_irq_enable,
+	.disable = tsi108_pci_irq_disable,
+	.ack = tsi108_pci_irq_ack,
+	.end = tsi108_pci_irq_end,
+};
+
+/*
+ * Exported functions
+ */
+
+/*
+ * The Tsi108 PCI interrupts initialization routine.
+ *
+ * The INTA# - INTD# interrupts on the PCI bus are reported by the PCI block
+ * to the MPIC using single interrupt source (IRQ_TSI108_PCI). Therefore the
+ * PCI block has to be treated as a cascaded interrupt controller connected
+ * to the MPIC.
+ */
+
+void __init tsi108_pci_int_init(void)
+{
+	u_int i;
+
+	DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
+
+	for (i = 0; i < NUM_PCI_IRQS; i++) {
+		irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
+		irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
+	}
+
+	init_pci_source();
+}
+
+int tsi108_irq_cascade(struct pt_regs *regs, void *unused)
+{
+	return get_pci_source();
+}

+ 8 - 1
drivers/ide/Kconfig

@@ -774,11 +774,18 @@ config BLK_DEV_IDEDMA_PMAC
 	  performance.
 
 config BLK_DEV_IDE_PMAC_BLINK
-	bool "Blink laptop LED on drive activity"
+	bool "Blink laptop LED on drive activity (DEPRECATED)"
 	depends on BLK_DEV_IDE_PMAC && ADB_PMU
+	select ADB_PMU_LED
+	select LEDS_TRIGGERS
+	select LEDS_TRIGGER_IDE_DISK
 	help
 	  This option enables the use of the sleep LED as a hard drive
 	  activity LED.
+	  This option is deprecated, it only selects ADB_PMU_LED and
+	  LEDS_TRIGGER_IDE_DISK and changes the code in the new led class
+	  device to default to the ide-disk trigger (which should be set
+	  from userspace via sysfs).
 
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"

+ 0 - 125
drivers/ide/ppc/pmac.c

@@ -420,107 +420,6 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
 
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
-/*
- * Below is the code for blinking the laptop LED along with hard
- * disk activity.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-
-/* Set to 50ms minimum led-on time (also used to limit frequency
- * of requests sent to the PMU
- */
-#define PMU_HD_BLINK_TIME	(HZ/50)
-
-static struct adb_request pmu_blink_on, pmu_blink_off;
-static spinlock_t pmu_blink_lock;
-static unsigned long pmu_blink_stoptime;
-static int pmu_blink_ledstate;
-static struct timer_list pmu_blink_timer;
-static int pmu_ide_blink_enabled;
-
-
-static void
-pmu_hd_blink_timeout(unsigned long data)
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-
-	/* We may have been triggered again in a racy way, check
-	 * that we really want to switch it off
-	 */
-	if (time_after(pmu_blink_stoptime, jiffies))
-		goto done;
-
-	/* Previous req. not complete, try 100ms more */
-	if (pmu_blink_off.complete == 0)
-		mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME);
-	else if (pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0);
-		pmu_blink_ledstate = 0;
-	}
-done:
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static void
-pmu_hd_kick_blink(void *data, int rw)
-{
-	unsigned long flags;
-	
-	pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME;
-	wmb();
-	mod_timer(&pmu_blink_timer, pmu_blink_stoptime);
-	/* Fast path when LED is already ON */
-	if (pmu_blink_ledstate == 1)
-		return;
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-	if (pmu_blink_on.complete && !pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1);
-		pmu_blink_ledstate = 1;
-	}
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static int
-pmu_hd_blink_init(void)
-{
-	struct device_node *dt;
-	const char *model;
-
-	/* Currently, I only enable this feature on KeyLargo based laptops,
-	 * older laptops may support it (at least heathrow/paddington) but
-	 * I don't feel like loading those venerable old machines with so
-	 * much additional interrupt & PMU activity...
-	 */
-	if (pmu_get_model() != PMU_KEYLARGO_BASED)
-		return 0;
-	
-	dt = of_find_node_by_path("/");
-	if (dt == NULL)
-		return 0;
-	model = (const char *)get_property(dt, "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
-	    strncmp(model, "iBook", strlen("iBook")) != 0) {
-		of_node_put(dt);
-	    	return 0;
-	}
-	of_node_put(dt);
-
-	pmu_blink_on.complete = 1;
-	pmu_blink_off.complete = 1;
-	spin_lock_init(&pmu_blink_lock);
-	init_timer(&pmu_blink_timer);
-	pmu_blink_timer.function = pmu_hd_blink_timeout;
-
-	return 1;
-}
-
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 /*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
@@ -1192,23 +1091,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
 	pmif->timings[0] = 0;
 	pmif->timings[1] = 0;
 	
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	/* Note: This code will be called for every hwif, thus we'll
-	 * try several time to stop the LED blinker timer,  but that
-	 * should be harmless
-	 */
-	if (pmu_ide_blink_enabled) {
-		unsigned long flags;
-
-		/* Make sure we don't hit the PMU blink */
-		spin_lock_irqsave(&pmu_blink_lock, flags);
-		if (pmu_blink_ledstate)
-			del_timer(&pmu_blink_timer);
-		pmu_blink_ledstate = 0;
-		spin_unlock_irqrestore(&pmu_blink_lock, flags);
-	}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 	disable_irq(pmif->irq);
 
 	/* The media bay will handle itself just fine */
@@ -1376,13 +1258,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 		hwif->selectproc = pmac_ide_selectproc;
 	hwif->speedproc = pmac_ide_tune_chipset;
 
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	pmu_ide_blink_enabled = pmu_hd_blink_init();
-
-	if (pmu_ide_blink_enabled)
-		hwif->led_act = pmu_hd_kick_blink;
-#endif
-
 	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
 	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
 	       pmif->mediabay ? " (mediabay)" : "", hwif->irq);

+ 12 - 0
drivers/macintosh/Kconfig

@@ -78,6 +78,18 @@ config ADB_PMU
 	  this device; you should do so if your machine is one of those
 	  mentioned above.
 
+config ADB_PMU_LED
+	bool "Support for the Power/iBook front LED"
+	depends on ADB_PMU
+	select NEW_LEDS
+	select LEDS_CLASS
+	help
+	  Support the front LED on Power/iBooks as a generic LED that can
+	  be triggered by any of the supported triggers. To get the
+	  behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this
+	  and the ide-disk LED trigger and configure appropriately through
+	  sysfs.
+
 config PMAC_SMU
 	bool "Support for SMU  based PowerMacs"
 	depends on PPC_PMAC64

+ 1 - 0
drivers/macintosh/Makefile

@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
 obj-$(CONFIG_ADB_PMU)		+= via-pmu.o via-pmu-event.o
+obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= via-pmu-backlight.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o

+ 144 - 0
drivers/macintosh/via-pmu-led.c

@@ -0,0 +1,144 @@
+/*
+ * via-pmu LED class device
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.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.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+
+static spinlock_t pmu_blink_lock;
+static struct adb_request pmu_blink_req;
+/* -1: no change, 0: request off, 1: request on */
+static int requested_change;
+static int sleeping;
+
+static void pmu_req_done(struct adb_request * req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	/* if someone requested a change in the meantime
+	 * (we only see the last one which is fine)
+	 * then apply it now */
+	if (requested_change != -1 && !sleeping)
+		pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+	/* reset requested change */
+	requested_change = -1;
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_set(struct led_classdev *led_cdev,
+			enum led_brightness brightness)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	switch (brightness) {
+	case LED_OFF:
+		requested_change = 0;
+		break;
+	case LED_FULL:
+		requested_change = 1;
+		break;
+	default:
+		goto out;
+		break;
+	}
+	/* if request isn't done, then don't do anything */
+	if (pmu_blink_req.complete && !sleeping)
+		pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change);
+ out:
+ 	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static struct led_classdev pmu_led = {
+	.name = "pmu-front-led",
+#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
+	.default_trigger = "ide-disk",
+#endif
+	.brightness_set = pmu_led_set,
+};
+
+#ifdef CONFIG_PM
+static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+
+	switch (when) {
+	case PBOOK_SLEEP_REQUEST:
+		sleeping = 1;
+		break;
+	case PBOOK_WAKE:
+		sleeping = 0;
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+
+	return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier via_pmu_led_sleep_notif = {
+	.notifier_call = pmu_led_sleep_call,
+};
+#endif
+
+static int __init via_pmu_led_init(void)
+{
+	struct device_node *dt;
+	const char *model;
+
+	/* only do this on keylargo based models */
+	if (pmu_get_model() != PMU_KEYLARGO_BASED)
+		return -ENODEV;
+
+	dt = of_find_node_by_path("/");
+	if (dt == NULL)
+		return -ENODEV;
+	model = (const char *)get_property(dt, "model", NULL);
+	if (model == NULL)
+		return -ENODEV;
+	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
+	    strncmp(model, "iBook", strlen("iBook")) != 0) {
+		of_node_put(dt);
+		/* ignore */
+		return -ENODEV;
+	}
+	of_node_put(dt);
+
+	spin_lock_init(&pmu_blink_lock);
+	/* no outstanding req */
+	pmu_blink_req.complete = 1;
+	pmu_blink_req.done = pmu_req_done;
+#ifdef CONFIG_PM
+	pmu_register_sleep_notifier(&via_pmu_led_sleep_notif);
+#endif
+	return led_classdev_register(NULL, &pmu_led);
+}
+
+late_initcall(via_pmu_led_init);

+ 20 - 28
include/asm-powerpc/cputable.h

@@ -117,38 +117,30 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
 #define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
 
+/*
+ * Add the 64-bit processor unique features in the top half of the word;
+ * on 32-bit, make the names available but defined to be 0.
+ */
 #ifdef __powerpc64__
-/* Add the 64b processor unique features in the top half of the word */
-#define CPU_FTR_SLB			ASM_CONST(0x0000000100000000)
-#define CPU_FTR_16M_PAGE		ASM_CONST(0x0000000200000000)
-#define CPU_FTR_TLBIEL			ASM_CONST(0x0000000400000000)
-#define CPU_FTR_NOEXECUTE		ASM_CONST(0x0000000800000000)
-#define CPU_FTR_IABR			ASM_CONST(0x0000002000000000)
-#define CPU_FTR_MMCRA			ASM_CONST(0x0000004000000000)
-#define CPU_FTR_CTRL			ASM_CONST(0x0000008000000000)
-#define CPU_FTR_SMT			ASM_CONST(0x0000010000000000)
-#define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0000020000000000)
-#define CPU_FTR_LOCKLESS_TLBIE		ASM_CONST(0x0000040000000000)
-#define CPU_FTR_CI_LARGE_PAGE		ASM_CONST(0x0000100000000000)
-#define CPU_FTR_PAUSE_ZERO		ASM_CONST(0x0000200000000000)
-#define CPU_FTR_PURR			ASM_CONST(0x0000400000000000)
+#define LONG_ASM_CONST(x)		ASM_CONST(x)
 #else
-/* ensure on 32b processors the flags are available for compiling but
- * don't do anything */
-#define CPU_FTR_SLB			ASM_CONST(0x0)
-#define CPU_FTR_16M_PAGE		ASM_CONST(0x0)
-#define CPU_FTR_TLBIEL			ASM_CONST(0x0)
-#define CPU_FTR_NOEXECUTE		ASM_CONST(0x0)
-#define CPU_FTR_IABR			ASM_CONST(0x0)
-#define CPU_FTR_MMCRA			ASM_CONST(0x0)
-#define CPU_FTR_CTRL			ASM_CONST(0x0)
-#define CPU_FTR_SMT			ASM_CONST(0x0)
-#define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0)
-#define CPU_FTR_LOCKLESS_TLBIE		ASM_CONST(0x0)
-#define CPU_FTR_CI_LARGE_PAGE		ASM_CONST(0x0)
-#define CPU_FTR_PURR			ASM_CONST(0x0)
+#define LONG_ASM_CONST(x)		0
 #endif
 
+#define CPU_FTR_SLB			LONG_ASM_CONST(0x0000000100000000)
+#define CPU_FTR_16M_PAGE		LONG_ASM_CONST(0x0000000200000000)
+#define CPU_FTR_TLBIEL			LONG_ASM_CONST(0x0000000400000000)
+#define CPU_FTR_NOEXECUTE		LONG_ASM_CONST(0x0000000800000000)
+#define CPU_FTR_IABR			LONG_ASM_CONST(0x0000002000000000)
+#define CPU_FTR_MMCRA			LONG_ASM_CONST(0x0000004000000000)
+#define CPU_FTR_CTRL			LONG_ASM_CONST(0x0000008000000000)
+#define CPU_FTR_SMT			LONG_ASM_CONST(0x0000010000000000)
+#define CPU_FTR_COHERENT_ICACHE		LONG_ASM_CONST(0x0000020000000000)
+#define CPU_FTR_LOCKLESS_TLBIE		LONG_ASM_CONST(0x0000040000000000)
+#define CPU_FTR_CI_LARGE_PAGE		LONG_ASM_CONST(0x0000100000000000)
+#define CPU_FTR_PAUSE_ZERO		LONG_ASM_CONST(0x0000200000000000)
+#define CPU_FTR_PURR			LONG_ASM_CONST(0x0000400000000000)
+
 #ifndef __ASSEMBLY__
 
 #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \

+ 20 - 20
include/asm-powerpc/iseries/it_lp_queue.h

@@ -29,20 +29,20 @@
 
 struct HvLpEvent;
 
-#define ITMaxLpQueues	8
+#define IT_LP_MAX_QUEUES	8
 
-#define NotUsed		0	// Queue will not be used by PLIC
-#define DedicatedIo	1	// Queue dedicated to IO processor specified
-#define DedicatedLp	2	// Queue dedicated to LP specified
-#define Shared		3	// Queue shared for both IO and LP
+#define IT_LP_NOT_USED		0	/* Queue will not be used by PLIC */
+#define IT_LP_DEDICATED_IO	1	/* Queue dedicated to IO processor specified */
+#define IT_LP_DEDICATED_LP	2	/* Queue dedicated to LP specified */
+#define IT_LP_SHARED		3	/* Queue shared for both IO and LP */
 
-#define LpEventStackSize	4096
-#define LpEventMaxSize		256
-#define LpEventAlign		64
+#define IT_LP_EVENT_STACK_SIZE	4096
+#define IT_LP_EVENT_MAX_SIZE	256
+#define IT_LP_EVENT_ALIGN	64
 
 struct hvlpevent_queue {
 /*
- * The xSlicCurEventPtr is the pointer to the next event stack entry
+ * The hq_current_event is the pointer to the next event stack entry
  * that will become valid.  The OS must peek at this entry to determine
  * if it is valid.  PLIC will set the valid indicator as the very last
  * store into that entry.
@@ -52,23 +52,23 @@ struct hvlpevent_queue {
  * location again.
  *
  * If the event stack fills and there are overflow events, then PLIC
- * will set the xPlicOverflowIntPending flag in which case the OS will
+ * will set the hq_overflow_pending flag in which case the OS will
  * have to fetch the additional LP events once they have drained the
  * event stack.
  *
  * The first 16-bytes are known by both the OS and PLIC.  The remainder
  * of the cache line is for use by the OS.
  */
-	u8	xPlicOverflowIntPending;// 0x00 Overflow events are pending
-	u8	xPlicStatus;		// 0x01 DedicatedIo or DedicatedLp or NotUsed
-	u16	xSlicLogicalProcIndex;	// 0x02 Logical Proc Index for correlation
-	u8	xPlicRsvd[12];		// 0x04
-	char	*xSlicCurEventPtr;	// 0x10
-	char	*xSlicLastValidEventPtr; // 0x18
-	char	*xSlicEventStackPtr;	// 0x20
-	u8	xIndex;			// 0x28 unique sequential index.
-	u8	xSlicRsvd[3];		// 0x29-2b
-	spinlock_t	lock;
+	u8		hq_overflow_pending;	/* 0x00 Overflow events are pending */
+	u8		hq_status;		/* 0x01 DedicatedIo or DedicatedLp or NotUsed */
+	u16		hq_proc_index;		/* 0x02 Logical Proc Index for correlation */
+	u8		hq_reserved1[12];	/* 0x04 */
+	char		*hq_current_event;	/* 0x10 */
+	char		*hq_last_event;		/* 0x18 */
+	char		*hq_event_stack;	/* 0x20 */
+	u8		hq_index;		/* 0x28 unique sequential index. */
+	u8		hq_reserved2[3];	/* 0x29-2b */
+	spinlock_t	hq_lock;
 };
 
 extern struct hvlpevent_queue hvlpevent_queue;

+ 2 - 0
include/asm-powerpc/kdump.h

@@ -15,6 +15,8 @@
 #define KDUMP_TRAMPOLINE_START	0x0100
 #define KDUMP_TRAMPOLINE_END	0x3000
 
+#define KDUMP_MIN_TCE_ENTRIES	2048
+
 #else /* !CONFIG_CRASH_DUMP */
 
 #define PHYSICAL_START	0x0

+ 8 - 1
include/asm-powerpc/kexec.h

@@ -112,9 +112,13 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 #ifdef __powerpc64__
 extern void kexec_smp_wait(void);	/* get and clear naca physid, wait for
 					  master to copy new code to 0 */
-extern void __init kexec_setup(void);
 extern int crashing_cpu;
 extern void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *));
+extern cpumask_t cpus_in_sr;
+static inline int kexec_sr_activated(int cpu)
+{
+	return cpu_isset(cpu,cpus_in_sr);
+}
 #endif /* __powerpc64 __ */
 
 struct kimage;
@@ -124,10 +128,13 @@ extern int default_machine_kexec_prepare(struct kimage *image);
 extern void default_machine_crash_shutdown(struct pt_regs *regs);
 
 extern void machine_kexec_simple(struct kimage *image);
+extern void crash_kexec_secondary(struct pt_regs *regs);
 extern int overlaps_crashkernel(unsigned long start, unsigned long size);
 extern void reserve_crashkernel(void);
 
 #else /* !CONFIG_KEXEC */
+static inline int kexec_sr_activated(int cpu) { return 0; }
+static inline void crash_kexec_secondary(struct pt_regs *regs) { }
 
 static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
 {

+ 2 - 0
include/asm-powerpc/machdep.h

@@ -81,6 +81,8 @@ struct machdep_calls {
 	void		(*tce_free)(struct iommu_table *tbl,
 				    long index,
 				    long npages);
+	unsigned long	(*tce_get)(struct iommu_table *tbl,
+				    long index);
 	void		(*tce_flush)(struct iommu_table *tbl);
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);

+ 0 - 1
include/asm-powerpc/mmu.h

@@ -238,7 +238,6 @@ extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
 			  unsigned long ea, unsigned long vsid, int local,
 			  unsigned long trap);
 
-extern void htab_finish_init(void);
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 			     unsigned long pstart, unsigned long mode,
 			     int psize);

+ 6 - 1
include/asm-powerpc/mmu_context.h

@@ -25,8 +25,13 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
 {
 }
 
+/*
+ * The proto-VSID space has 2^35 - 1 segments available for user mappings.
+ * Each segment contains 2^28 bytes.  Each context maps 2^44 bytes,
+ * so we can support 2^19-1 contexts (19 == 35 + 28 - 44).
+ */
 #define NO_CONTEXT	0
-#define MAX_CONTEXT	(0x100000-1)
+#define MAX_CONTEXT	((1UL << 19) - 1)
 
 extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 extern void destroy_context(struct mm_struct *mm);

+ 0 - 5
include/asm-powerpc/mpc86xx.h

@@ -15,15 +15,10 @@
 #ifndef __ASM_POWERPC_MPC86xx_H__
 #define __ASM_POWERPC_MPC86xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_PPC_86xx
 
-#ifdef CONFIG_MPC8641_HPCN
-#include <platforms/86xx/mpc8641_hpcn.h>
-#endif
-
 #define _IO_BASE        isa_io_base
 #define _ISA_MEM_BASE   isa_mem_base
 #ifdef CONFIG_PCI

+ 3 - 0
include/asm-powerpc/rtas.h

@@ -181,6 +181,9 @@ extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
 extern unsigned int rtas_busy_delay_time(int status);
 extern unsigned int rtas_busy_delay(int status);
 
+extern int early_init_dt_scan_rtas(unsigned long node,
+		const char *uname, int depth, void *data);
+
 extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 
 /* Error types logged.  */

+ 4 - 2
include/asm-powerpc/time.h

@@ -18,8 +18,9 @@
 #include <linux/percpu.h>
 
 #include <asm/processor.h>
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_ISERIES
 #include <asm/paca.h>
+#include <asm/firmware.h>
 #include <asm/iseries/hv_call.h>
 #endif
 
@@ -177,7 +178,8 @@ static inline void set_dec(int val)
 #ifdef CONFIG_PPC_ISERIES
 	int cur_dec;
 
-	if (get_lppaca()->shared_proc) {
+	if (firmware_has_feature(FW_FEATURE_ISERIES) &&
+			get_lppaca()->shared_proc) {
 		get_lppaca()->virtual_decr = val;
 		cur_dec = get_dec();
 		if (cur_dec > val)

+ 487 - 0
include/asm-powerpc/todc.h

@@ -0,0 +1,487 @@
+/*
+ * Definitions for the M48Txx and mc146818 series of Time of day/Real Time
+ * Clock chips.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (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.
+ */
+
+/*
+ * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips.
+ * Purpose is to make one generic file that handles all of these chips instead
+ * of every platform implementing the same code over & over again.
+ */
+
+#ifndef __PPC_KERNEL_TODC_H
+#define __PPC_KERNEL_TODC_H
+
+typedef struct {
+	uint rtc_type;		/* your particular chip */
+
+	/*
+	 * Following are the addresses of the AS0, AS1, and DATA registers
+	 * of these chips.  Note that these are board-specific.
+	 */
+	unsigned int nvram_as0;
+	unsigned int nvram_as1;
+	unsigned int nvram_data;
+
+	/*
+	 * Define bits to stop external set of regs from changing so
+	 * the chip can be read/written reliably.
+	 */
+	unsigned char enable_read;
+	unsigned char enable_write;
+
+	/*
+	 * Following is the number of AS0 address bits.  This is normally
+	 * 8 but some bad hardware routes address lines incorrectly.
+	 */
+	int as0_bits;
+
+	int nvram_size;	/* Size of NVRAM on chip */
+	int sw_flags;	/* Software control flags */
+
+	/* Following are the register offsets for the particular chip */
+	int year;
+	int month;
+	int day_of_month;
+	int day_of_week;
+	int hours;
+	int minutes;
+	int seconds;
+	int control_b;
+	int control_a;
+	int watchdog;
+	int interrupts;
+	int alarm_date;
+	int alarm_hour;
+	int alarm_minutes;
+	int alarm_seconds;
+	int century;
+	int flags;
+
+	/*
+	 * Some RTC chips have their NVRAM buried behind a addr/data pair of
+	 * regs on the first level/clock registers.  The following fields
+	 * are the addresses for those addr/data regs.
+	 */
+	int nvram_addr_reg;
+	int nvram_data_reg;
+} todc_info_t;
+
+/*
+ * Define the types of TODC/RTC variants that are supported in
+ * arch/ppc/kernel/todc_time.c
+ * Make a new one of these for any chip somehow differs from what's already
+ * defined.  That way, if you ever need to put in code to touch those
+ * bits/registers in todc_time.c, you can put it inside an
+ * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break
+ * anyone else.
+ */
+#define TODC_TYPE_MK48T35		1
+#define TODC_TYPE_MK48T37		2
+#define TODC_TYPE_MK48T59		3
+#define TODC_TYPE_DS1693		4	/* Dallas DS1693 RTC */
+#define TODC_TYPE_DS1743		5	/* Dallas DS1743 RTC */
+#define TODC_TYPE_DS1746		6	/* Dallas DS1746 RTC */
+#define TODC_TYPE_DS1747		7	/* Dallas DS1747 RTC */
+#define TODC_TYPE_DS1501		8	/* Dallas DS1501 RTC */
+#define TODC_TYPE_DS1643		9	/* Dallas DS1643 RTC */
+#define TODC_TYPE_PC97307		10	/* PC97307 internal RTC */
+#define TODC_TYPE_DS1557		11	/* Dallas DS1557 RTC */
+#define TODC_TYPE_DS17285		12	/* Dallas DS17285 RTC */
+#define TODC_TYPE_DS1553		13	/* Dallas DS1553 RTC */
+#define TODC_TYPE_MC146818		100	/* Leave room for m48txx's */
+
+/*
+ * Bit to clear/set to enable reads/writes to the chip
+ */
+#define TODC_MK48TXX_CNTL_A_R		0x40
+#define TODC_MK48TXX_CNTL_A_W		0x80
+#define TODC_MK48TXX_DAY_CB		0x80
+
+#define TODC_DS1501_CNTL_B_TE		0x80
+
+/*
+ * Define flag bits used by todc routines.
+ */
+#define TODC_FLAG_2_LEVEL_NVRAM		0x00000001
+
+/*
+ * Define the values for the various RTC's that should to into the todc_info
+ * table.
+ * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only
+ * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set.
+ */
+#define TODC_TYPE_MK48T35_NVRAM_SIZE		0x7ff8
+#define TODC_TYPE_MK48T35_SW_FLAGS		0
+#define TODC_TYPE_MK48T35_YEAR			0x7fff
+#define TODC_TYPE_MK48T35_MONTH			0x7ffe
+#define TODC_TYPE_MK48T35_DOM			0x7ffd	/* Day of Month */
+#define TODC_TYPE_MK48T35_DOW			0x7ffc	/* Day of Week */
+#define TODC_TYPE_MK48T35_HOURS			0x7ffb
+#define TODC_TYPE_MK48T35_MINUTES		0x7ffa
+#define TODC_TYPE_MK48T35_SECONDS		0x7ff9
+#define TODC_TYPE_MK48T35_CNTL_B		0x7ff9
+#define TODC_TYPE_MK48T35_CNTL_A		0x7ff8
+#define TODC_TYPE_MK48T35_WATCHDOG		0x0000
+#define TODC_TYPE_MK48T35_INTERRUPTS		0x0000
+#define TODC_TYPE_MK48T35_ALARM_DATE		0x0000
+#define TODC_TYPE_MK48T35_ALARM_HOUR		0x0000
+#define TODC_TYPE_MK48T35_ALARM_MINUTES		0x0000
+#define TODC_TYPE_MK48T35_ALARM_SECONDS		0x0000
+#define TODC_TYPE_MK48T35_CENTURY		0x0000
+#define TODC_TYPE_MK48T35_FLAGS			0x0000
+#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG	0
+#define TODC_TYPE_MK48T35_NVRAM_DATA_REG	0
+
+#define TODC_TYPE_MK48T37_NVRAM_SIZE		0x7ff0
+#define TODC_TYPE_MK48T37_SW_FLAGS		0
+#define TODC_TYPE_MK48T37_YEAR			0x7fff
+#define TODC_TYPE_MK48T37_MONTH			0x7ffe
+#define TODC_TYPE_MK48T37_DOM			0x7ffd	/* Day of Month */
+#define TODC_TYPE_MK48T37_DOW			0x7ffc	/* Day of Week */
+#define TODC_TYPE_MK48T37_HOURS			0x7ffb
+#define TODC_TYPE_MK48T37_MINUTES		0x7ffa
+#define TODC_TYPE_MK48T37_SECONDS		0x7ff9
+#define TODC_TYPE_MK48T37_CNTL_B		0x7ff9
+#define TODC_TYPE_MK48T37_CNTL_A		0x7ff8
+#define TODC_TYPE_MK48T37_WATCHDOG		0x7ff7
+#define TODC_TYPE_MK48T37_INTERRUPTS		0x7ff6
+#define TODC_TYPE_MK48T37_ALARM_DATE		0x7ff5
+#define TODC_TYPE_MK48T37_ALARM_HOUR		0x7ff4
+#define TODC_TYPE_MK48T37_ALARM_MINUTES		0x7ff3
+#define TODC_TYPE_MK48T37_ALARM_SECONDS		0x7ff2
+#define TODC_TYPE_MK48T37_CENTURY		0x7ff1
+#define TODC_TYPE_MK48T37_FLAGS			0x7ff0
+#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG	0
+#define TODC_TYPE_MK48T37_NVRAM_DATA_REG	0
+
+#define TODC_TYPE_MK48T59_NVRAM_SIZE		0x1ff0
+#define TODC_TYPE_MK48T59_SW_FLAGS		0
+#define TODC_TYPE_MK48T59_YEAR			0x1fff
+#define TODC_TYPE_MK48T59_MONTH			0x1ffe
+#define TODC_TYPE_MK48T59_DOM			0x1ffd	/* Day of Month */
+#define TODC_TYPE_MK48T59_DOW			0x1ffc	/* Day of Week */
+#define TODC_TYPE_MK48T59_HOURS			0x1ffb
+#define TODC_TYPE_MK48T59_MINUTES		0x1ffa
+#define TODC_TYPE_MK48T59_SECONDS		0x1ff9
+#define TODC_TYPE_MK48T59_CNTL_B		0x1ff9
+#define TODC_TYPE_MK48T59_CNTL_A		0x1ff8
+#define TODC_TYPE_MK48T59_WATCHDOG		0x1fff
+#define TODC_TYPE_MK48T59_INTERRUPTS		0x1fff
+#define TODC_TYPE_MK48T59_ALARM_DATE		0x1fff
+#define TODC_TYPE_MK48T59_ALARM_HOUR		0x1fff
+#define TODC_TYPE_MK48T59_ALARM_MINUTES		0x1fff
+#define TODC_TYPE_MK48T59_ALARM_SECONDS		0x1fff
+#define TODC_TYPE_MK48T59_CENTURY		0x1fff
+#define TODC_TYPE_MK48T59_FLAGS			0x1fff
+#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG	0
+#define TODC_TYPE_MK48T59_NVRAM_DATA_REG	0
+
+#define TODC_TYPE_DS1501_NVRAM_SIZE	0x100
+#define TODC_TYPE_DS1501_SW_FLAGS	TODC_FLAG_2_LEVEL_NVRAM
+#define TODC_TYPE_DS1501_YEAR		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x06)
+#define TODC_TYPE_DS1501_MONTH		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x05)
+#define TODC_TYPE_DS1501_DOM		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x04)
+#define TODC_TYPE_DS1501_DOW		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x03)
+#define TODC_TYPE_DS1501_HOURS		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x02)
+#define TODC_TYPE_DS1501_MINUTES	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x01)
+#define TODC_TYPE_DS1501_SECONDS	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x00)
+#define TODC_TYPE_DS1501_CNTL_B		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
+#define TODC_TYPE_DS1501_CNTL_A		(TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f)
+#define TODC_TYPE_DS1501_WATCHDOG	(TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_INTERRUPTS	(TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_ALARM_DATE	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b)
+#define TODC_TYPE_DS1501_ALARM_HOUR	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a)
+#define TODC_TYPE_DS1501_ALARM_MINUTES	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x09)
+#define TODC_TYPE_DS1501_ALARM_SECONDS	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x08)
+#define TODC_TYPE_DS1501_CENTURY	(TODC_TYPE_DS1501_NVRAM_SIZE + 0x07)
+#define TODC_TYPE_DS1501_FLAGS		(TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
+#define TODC_TYPE_DS1501_NVRAM_ADDR_REG	0x10
+#define TODC_TYPE_DS1501_NVRAM_DATA_REG	0x13
+
+#define TODC_TYPE_DS1553_NVRAM_SIZE		0x1ff0
+#define TODC_TYPE_DS1553_SW_FLAGS		0
+#define TODC_TYPE_DS1553_YEAR			0x1fff
+#define TODC_TYPE_DS1553_MONTH			0x1ffe
+#define TODC_TYPE_DS1553_DOM			0x1ffd	/* Day of Month */
+#define TODC_TYPE_DS1553_DOW			0x1ffc	/* Day of Week */
+#define TODC_TYPE_DS1553_HOURS			0x1ffb
+#define TODC_TYPE_DS1553_MINUTES		0x1ffa
+#define TODC_TYPE_DS1553_SECONDS		0x1ff9
+#define TODC_TYPE_DS1553_CNTL_B			0x1ff9
+#define TODC_TYPE_DS1553_CNTL_A			0x1ff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1553_WATCHDOG		0x1ff7
+#define TODC_TYPE_DS1553_INTERRUPTS		0x1ff6
+#define TODC_TYPE_DS1553_ALARM_DATE		0x1ff5
+#define TODC_TYPE_DS1553_ALARM_HOUR		0x1ff4
+#define TODC_TYPE_DS1553_ALARM_MINUTES		0x1ff3
+#define TODC_TYPE_DS1553_ALARM_SECONDS		0x1ff2
+#define TODC_TYPE_DS1553_CENTURY		0x1ff8
+#define TODC_TYPE_DS1553_FLAGS			0x1ff0
+#define TODC_TYPE_DS1553_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1553_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1557_NVRAM_SIZE		0x7fff0
+#define TODC_TYPE_DS1557_SW_FLAGS		0
+#define TODC_TYPE_DS1557_YEAR			0x7ffff
+#define TODC_TYPE_DS1557_MONTH			0x7fffe
+#define TODC_TYPE_DS1557_DOM			0x7fffd	/* Day of Month */
+#define TODC_TYPE_DS1557_DOW			0x7fffc	/* Day of Week */
+#define TODC_TYPE_DS1557_HOURS			0x7fffb
+#define TODC_TYPE_DS1557_MINUTES		0x7fffa
+#define TODC_TYPE_DS1557_SECONDS		0x7fff9
+#define TODC_TYPE_DS1557_CNTL_B			0x7fff9
+#define TODC_TYPE_DS1557_CNTL_A			0x7fff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1557_WATCHDOG		0x7fff7
+#define TODC_TYPE_DS1557_INTERRUPTS		0x7fff6
+#define TODC_TYPE_DS1557_ALARM_DATE		0x7fff5
+#define TODC_TYPE_DS1557_ALARM_HOUR		0x7fff4
+#define TODC_TYPE_DS1557_ALARM_MINUTES		0x7fff3
+#define TODC_TYPE_DS1557_ALARM_SECONDS		0x7fff2
+#define TODC_TYPE_DS1557_CENTURY		0x7fff8
+#define TODC_TYPE_DS1557_FLAGS			0x7fff0
+#define TODC_TYPE_DS1557_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1557_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1643_NVRAM_SIZE		0x1ff8
+#define TODC_TYPE_DS1643_SW_FLAGS		0
+#define TODC_TYPE_DS1643_YEAR			0x1fff
+#define TODC_TYPE_DS1643_MONTH			0x1ffe
+#define TODC_TYPE_DS1643_DOM			0x1ffd	/* Day of Month */
+#define TODC_TYPE_DS1643_DOW			0x1ffc	/* Day of Week */
+#define TODC_TYPE_DS1643_HOURS			0x1ffb
+#define TODC_TYPE_DS1643_MINUTES		0x1ffa
+#define TODC_TYPE_DS1643_SECONDS		0x1ff9
+#define TODC_TYPE_DS1643_CNTL_B			0x1ff9
+#define TODC_TYPE_DS1643_CNTL_A			0x1ff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1643_WATCHDOG		0x1fff
+#define TODC_TYPE_DS1643_INTERRUPTS		0x1fff
+#define TODC_TYPE_DS1643_ALARM_DATE		0x1fff
+#define TODC_TYPE_DS1643_ALARM_HOUR		0x1fff
+#define TODC_TYPE_DS1643_ALARM_MINUTES		0x1fff
+#define TODC_TYPE_DS1643_ALARM_SECONDS		0x1fff
+#define TODC_TYPE_DS1643_CENTURY		0x1ff8
+#define TODC_TYPE_DS1643_FLAGS			0x1fff
+#define TODC_TYPE_DS1643_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1643_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1693_NVRAM_SIZE		0 /* Not handled yet */
+#define TODC_TYPE_DS1693_SW_FLAGS		0
+#define TODC_TYPE_DS1693_YEAR			0x09
+#define TODC_TYPE_DS1693_MONTH			0x08
+#define TODC_TYPE_DS1693_DOM			0x07	/* Day of Month */
+#define TODC_TYPE_DS1693_DOW			0x06	/* Day of Week */
+#define TODC_TYPE_DS1693_HOURS			0x04
+#define TODC_TYPE_DS1693_MINUTES		0x02
+#define TODC_TYPE_DS1693_SECONDS		0x00
+#define TODC_TYPE_DS1693_CNTL_B			0x0b
+#define TODC_TYPE_DS1693_CNTL_A			0x0a
+#define TODC_TYPE_DS1693_WATCHDOG		0xff
+#define TODC_TYPE_DS1693_INTERRUPTS		0xff
+#define TODC_TYPE_DS1693_ALARM_DATE		0x49
+#define TODC_TYPE_DS1693_ALARM_HOUR		0x05
+#define TODC_TYPE_DS1693_ALARM_MINUTES		0x03
+#define TODC_TYPE_DS1693_ALARM_SECONDS		0x01
+#define TODC_TYPE_DS1693_CENTURY		0x48
+#define TODC_TYPE_DS1693_FLAGS			0xff
+#define TODC_TYPE_DS1693_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1693_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1743_NVRAM_SIZE		0x1ff8
+#define TODC_TYPE_DS1743_SW_FLAGS		0
+#define TODC_TYPE_DS1743_YEAR			0x1fff
+#define TODC_TYPE_DS1743_MONTH			0x1ffe
+#define TODC_TYPE_DS1743_DOM			0x1ffd	/* Day of Month */
+#define TODC_TYPE_DS1743_DOW			0x1ffc	/* Day of Week */
+#define TODC_TYPE_DS1743_HOURS			0x1ffb
+#define TODC_TYPE_DS1743_MINUTES		0x1ffa
+#define TODC_TYPE_DS1743_SECONDS		0x1ff9
+#define TODC_TYPE_DS1743_CNTL_B			0x1ff9
+#define TODC_TYPE_DS1743_CNTL_A			0x1ff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1743_WATCHDOG		0x1fff
+#define TODC_TYPE_DS1743_INTERRUPTS		0x1fff
+#define TODC_TYPE_DS1743_ALARM_DATE		0x1fff
+#define TODC_TYPE_DS1743_ALARM_HOUR		0x1fff
+#define TODC_TYPE_DS1743_ALARM_MINUTES		0x1fff
+#define TODC_TYPE_DS1743_ALARM_SECONDS		0x1fff
+#define TODC_TYPE_DS1743_CENTURY		0x1ff8
+#define TODC_TYPE_DS1743_FLAGS			0x1fff
+#define TODC_TYPE_DS1743_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1743_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1746_NVRAM_SIZE		0x1fff8
+#define TODC_TYPE_DS1746_SW_FLAGS		0
+#define TODC_TYPE_DS1746_YEAR			0x1ffff
+#define TODC_TYPE_DS1746_MONTH			0x1fffe
+#define TODC_TYPE_DS1746_DOM			0x1fffd	/* Day of Month */
+#define TODC_TYPE_DS1746_DOW			0x1fffc	/* Day of Week */
+#define TODC_TYPE_DS1746_HOURS			0x1fffb
+#define TODC_TYPE_DS1746_MINUTES		0x1fffa
+#define TODC_TYPE_DS1746_SECONDS		0x1fff9
+#define TODC_TYPE_DS1746_CNTL_B			0x1fff9
+#define TODC_TYPE_DS1746_CNTL_A			0x1fff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1746_WATCHDOG		0x00000
+#define TODC_TYPE_DS1746_INTERRUPTS		0x00000
+#define TODC_TYPE_DS1746_ALARM_DATE		0x00000
+#define TODC_TYPE_DS1746_ALARM_HOUR		0x00000
+#define TODC_TYPE_DS1746_ALARM_MINUTES		0x00000
+#define TODC_TYPE_DS1746_ALARM_SECONDS		0x00000
+#define TODC_TYPE_DS1746_CENTURY		0x00000
+#define TODC_TYPE_DS1746_FLAGS			0x00000
+#define TODC_TYPE_DS1746_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1746_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS1747_NVRAM_SIZE		0x7fff8
+#define TODC_TYPE_DS1747_SW_FLAGS		0
+#define TODC_TYPE_DS1747_YEAR			0x7ffff
+#define TODC_TYPE_DS1747_MONTH			0x7fffe
+#define TODC_TYPE_DS1747_DOM			0x7fffd	/* Day of Month */
+#define TODC_TYPE_DS1747_DOW			0x7fffc	/* Day of Week */
+#define TODC_TYPE_DS1747_HOURS			0x7fffb
+#define TODC_TYPE_DS1747_MINUTES		0x7fffa
+#define TODC_TYPE_DS1747_SECONDS		0x7fff9
+#define TODC_TYPE_DS1747_CNTL_B			0x7fff9
+#define TODC_TYPE_DS1747_CNTL_A			0x7fff8	/* control_a R/W regs */
+#define TODC_TYPE_DS1747_WATCHDOG		0x00000
+#define TODC_TYPE_DS1747_INTERRUPTS		0x00000
+#define TODC_TYPE_DS1747_ALARM_DATE		0x00000
+#define TODC_TYPE_DS1747_ALARM_HOUR		0x00000
+#define TODC_TYPE_DS1747_ALARM_MINUTES		0x00000
+#define TODC_TYPE_DS1747_ALARM_SECONDS		0x00000
+#define TODC_TYPE_DS1747_CENTURY		0x00000
+#define TODC_TYPE_DS1747_FLAGS			0x00000
+#define TODC_TYPE_DS1747_NVRAM_ADDR_REG		0
+#define TODC_TYPE_DS1747_NVRAM_DATA_REG		0
+
+#define TODC_TYPE_DS17285_NVRAM_SIZE		(0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */
+#define TODC_TYPE_DS17285_SW_FLAGS		TODC_FLAG_2_LEVEL_NVRAM
+#define TODC_TYPE_DS17285_SECONDS		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x00)
+#define TODC_TYPE_DS17285_ALARM_SECONDS		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x01)
+#define TODC_TYPE_DS17285_MINUTES		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x02)
+#define TODC_TYPE_DS17285_ALARM_MINUTES		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x03)
+#define TODC_TYPE_DS17285_HOURS			(TODC_TYPE_DS17285_NVRAM_SIZE + 0x04)
+#define TODC_TYPE_DS17285_ALARM_HOUR		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x05)
+#define TODC_TYPE_DS17285_DOW			(TODC_TYPE_DS17285_NVRAM_SIZE + 0x06)
+#define TODC_TYPE_DS17285_DOM			(TODC_TYPE_DS17285_NVRAM_SIZE + 0x07)
+#define TODC_TYPE_DS17285_MONTH			(TODC_TYPE_DS17285_NVRAM_SIZE + 0x08)
+#define TODC_TYPE_DS17285_YEAR			(TODC_TYPE_DS17285_NVRAM_SIZE + 0x09)
+#define TODC_TYPE_DS17285_CNTL_A		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A)
+#define TODC_TYPE_DS17285_CNTL_B		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B)
+#define TODC_TYPE_DS17285_CNTL_C		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C)
+#define TODC_TYPE_DS17285_CNTL_D		(TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D)
+#define TODC_TYPE_DS17285_WATCHDOG		0
+#define TODC_TYPE_DS17285_INTERRUPTS		0
+#define TODC_TYPE_DS17285_ALARM_DATE		0
+#define TODC_TYPE_DS17285_CENTURY		0
+#define TODC_TYPE_DS17285_FLAGS			0
+#define TODC_TYPE_DS17285_NVRAM_ADDR_REG	0x50
+#define TODC_TYPE_DS17285_NVRAM_DATA_REG	0x53
+
+#define TODC_TYPE_MC146818_NVRAM_SIZE		0	/* XXXX */
+#define TODC_TYPE_MC146818_SW_FLAGS		0
+#define TODC_TYPE_MC146818_YEAR			0x09
+#define TODC_TYPE_MC146818_MONTH		0x08
+#define TODC_TYPE_MC146818_DOM			0x07	/* Day of Month */
+#define TODC_TYPE_MC146818_DOW			0x06	/* Day of Week */
+#define TODC_TYPE_MC146818_HOURS		0x04
+#define TODC_TYPE_MC146818_MINUTES		0x02
+#define TODC_TYPE_MC146818_SECONDS		0x00
+#define TODC_TYPE_MC146818_CNTL_B		0x0a
+#define TODC_TYPE_MC146818_CNTL_A		0x0b	/* control_a R/W regs */
+#define TODC_TYPE_MC146818_WATCHDOG		0
+#define TODC_TYPE_MC146818_INTERRUPTS		0x0c
+#define TODC_TYPE_MC146818_ALARM_DATE		0xff
+#define TODC_TYPE_MC146818_ALARM_HOUR		0x05
+#define TODC_TYPE_MC146818_ALARM_MINUTES	0x03
+#define TODC_TYPE_MC146818_ALARM_SECONDS	0x01
+#define TODC_TYPE_MC146818_CENTURY		0xff
+#define TODC_TYPE_MC146818_FLAGS		0xff
+#define TODC_TYPE_MC146818_NVRAM_ADDR_REG	0
+#define TODC_TYPE_MC146818_NVRAM_DATA_REG	0
+
+#define TODC_TYPE_PC97307_NVRAM_SIZE		0	/* No NVRAM? */
+#define TODC_TYPE_PC97307_SW_FLAGS		0
+#define TODC_TYPE_PC97307_YEAR			0x09
+#define TODC_TYPE_PC97307_MONTH			0x08
+#define TODC_TYPE_PC97307_DOM			0x07	/* Day of Month */
+#define TODC_TYPE_PC97307_DOW			0x06	/* Day of Week */
+#define TODC_TYPE_PC97307_HOURS			0x04
+#define TODC_TYPE_PC97307_MINUTES		0x02
+#define TODC_TYPE_PC97307_SECONDS		0x00
+#define TODC_TYPE_PC97307_CNTL_B		0x0a
+#define TODC_TYPE_PC97307_CNTL_A		0x0b	/* control_a R/W regs */
+#define TODC_TYPE_PC97307_WATCHDOG		0x0c
+#define TODC_TYPE_PC97307_INTERRUPTS		0x0d
+#define TODC_TYPE_PC97307_ALARM_DATE		0xff
+#define TODC_TYPE_PC97307_ALARM_HOUR		0x05
+#define TODC_TYPE_PC97307_ALARM_MINUTES		0x03
+#define TODC_TYPE_PC97307_ALARM_SECONDS		0x01
+#define TODC_TYPE_PC97307_CENTURY		0xff
+#define TODC_TYPE_PC97307_FLAGS			0xff
+#define TODC_TYPE_PC97307_NVRAM_ADDR_REG	0
+#define TODC_TYPE_PC97307_NVRAM_DATA_REG	0
+
+/*
+ * Define macros to allocate and init the todc_info_t table that will
+ * be used by the todc_time.c routines.
+ */
+#define TODC_ALLOC()							\
+	static todc_info_t todc_info_alloc;				\
+	todc_info_t *todc_info = &todc_info_alloc;
+
+#define TODC_INIT(clock_type, as0, as1, data, bits) {			\
+	todc_info->rtc_type = clock_type;				\
+									\
+	todc_info->nvram_as0 = (unsigned int)(as0);			\
+	todc_info->nvram_as1 = (unsigned int)(as1);			\
+	todc_info->nvram_data = (unsigned int)(data);			\
+									\
+	todc_info->as0_bits = (bits);					\
+									\
+	todc_info->nvram_size = clock_type ##_NVRAM_SIZE;		\
+	todc_info->sw_flags = clock_type ##_SW_FLAGS;			\
+									\
+	todc_info->year = clock_type ##_YEAR;				\
+	todc_info->month = clock_type ##_MONTH;				\
+	todc_info->day_of_month = clock_type ##_DOM;			\
+	todc_info->day_of_week = clock_type ##_DOW;			\
+	todc_info->hours = clock_type ##_HOURS;				\
+	todc_info->minutes = clock_type ##_MINUTES;			\
+	todc_info->seconds = clock_type ##_SECONDS;			\
+	todc_info->control_b = clock_type ##_CNTL_B;			\
+	todc_info->control_a = clock_type ##_CNTL_A;			\
+	todc_info->watchdog = clock_type ##_WATCHDOG;			\
+	todc_info->interrupts = clock_type ##_INTERRUPTS;		\
+	todc_info->alarm_date = clock_type ##_ALARM_DATE;		\
+	todc_info->alarm_hour = clock_type ##_ALARM_HOUR;		\
+	todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES;		\
+	todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS;		\
+	todc_info->century = clock_type ##_CENTURY;			\
+	todc_info->flags = clock_type ##_FLAGS;				\
+									\
+	todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG;	\
+	todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG;	\
+}
+
+extern todc_info_t *todc_info;
+
+unsigned char todc_direct_read_val(int addr);
+void todc_direct_write_val(int addr, unsigned char val);
+unsigned char todc_m48txx_read_val(int addr);
+void todc_m48txx_write_val(int addr, unsigned char val);
+unsigned char todc_mc146818_read_val(int addr);
+void todc_mc146818_write_val(int addr, unsigned char val);
+
+long todc_time_init(void);
+void todc_get_rtc_time(struct rtc_time *);
+int todc_set_rtc_time(struct rtc_time *);
+void todc_calibrate_decr(void);
+
+#endif				/* __PPC_KERNEL_TODC_H */

+ 109 - 0
include/asm-powerpc/tsi108.h

@@ -0,0 +1,109 @@
+/*
+ * include/asm-ppc/tsi108.h
+ *
+ * common routine and memory layout for Tundra TSI108(Grendel) host bridge
+ * memory controller.
+ *
+ * Author: Jacob Pan (jacob.pan@freescale.com)
+ *	   Alex Bounine (alexandreb@tundra.com)
+ * 2004 (c) Freescale Semiconductor Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PPC_KERNEL_TSI108_H
+#define __PPC_KERNEL_TSI108_H
+
+#include <asm/pci-bridge.h>
+
+/* Size of entire register space */
+#define TSI108_REG_SIZE		(0x10000)
+
+/* Sizes of register spaces for individual blocks */
+#define TSI108_HLP_SIZE		0x1000
+#define TSI108_PCI_SIZE		0x1000
+#define TSI108_CLK_SIZE		0x1000
+#define TSI108_PB_SIZE		0x1000
+#define TSI108_SD_SIZE		0x1000
+#define TSI108_DMA_SIZE		0x1000
+#define TSI108_ETH_SIZE		0x1000
+#define TSI108_I2C_SIZE		0x400
+#define TSI108_MPIC_SIZE	0x400
+#define TSI108_UART0_SIZE	0x200
+#define TSI108_GPIO_SIZE	0x200
+#define TSI108_UART1_SIZE	0x200
+
+/* Offsets within Tsi108(A) CSR space for individual blocks */
+#define TSI108_HLP_OFFSET	0x0000
+#define TSI108_PCI_OFFSET	0x1000
+#define TSI108_CLK_OFFSET	0x2000
+#define TSI108_PB_OFFSET	0x3000
+#define TSI108_SD_OFFSET	0x4000
+#define TSI108_DMA_OFFSET	0x5000
+#define TSI108_ETH_OFFSET	0x6000
+#define TSI108_I2C_OFFSET	0x7000
+#define TSI108_MPIC_OFFSET	0x7400
+#define TSI108_UART0_OFFSET	0x7800
+#define TSI108_GPIO_OFFSET	0x7A00
+#define TSI108_UART1_OFFSET	0x7C00
+
+/* Tsi108 registers used by common code components */
+#define TSI108_PCI_CSR		(0x004)
+#define TSI108_PCI_IRP_CFG_CTL	(0x180)
+#define TSI108_PCI_IRP_STAT	(0x184)
+#define TSI108_PCI_IRP_ENABLE	(0x188)
+#define TSI108_PCI_IRP_INTAD	(0x18C)
+
+#define TSI108_PCI_IRP_STAT_P_INT	(0x00400000)
+#define TSI108_PCI_IRP_ENABLE_P_INT	(0x00400000)
+
+#define TSI108_CG_PWRUP_STATUS	(0x234)
+
+#define TSI108_PB_ISR		(0x00C)
+#define TSI108_PB_ERRCS		(0x404)
+#define TSI108_PB_AERR		(0x408)
+
+#define TSI108_PB_ERRCS_ES		(1 << 1)
+#define TSI108_PB_ISR_PBS_RD_ERR	(1 << 8)
+
+#define TSI108_PCI_CFG_BASE_PHYS	(0xfb000000)
+#define TSI108_PCI_CFG_SIZE		(0x01000000)
+/* Global variables */
+
+extern u32 tsi108_pci_cfg_base;
+/* Exported functions */
+
+extern int tsi108_bridge_init(struct pci_controller *hose, uint phys_csr_base);
+extern unsigned long tsi108_get_mem_size(void);
+extern unsigned long tsi108_get_cpu_clk(void);
+extern unsigned long tsi108_get_sdc_clk(void);
+extern int tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfn,
+				      int offset, int len, u32 val);
+extern int tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn,
+				     int offset, int len, u32 * val);
+extern void tsi108_clear_pci_error(u32 pci_cfg_base);
+
+extern phys_addr_t get_csrbase(void);
+
+typedef struct {
+	u32 regs;		/* hw registers base address */
+	u32 phyregs;		/* phy registers base address */
+	u16 phy;		/* phy address */
+	u16 irq_num;		/* irq number */
+	u8 mac_addr[6];		/* phy mac address */
+} hw_info;
+
+extern u32 get_vir_csrbase(void);
+extern u32 tsi108_csr_vir_base;
+
+extern inline u32 tsi108_read_reg(u32 reg_offset)
+{
+	return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset));
+}
+
+extern inline void tsi108_write_reg(u32 reg_offset, u32 val)
+{
+	out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val);
+}
+
+#endif				/* __PPC_KERNEL_TSI108_H */

+ 2 - 1
include/asm-powerpc/udbg.h

@@ -42,7 +42,8 @@ extern void __init udbg_init_debug_lpar(void);
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_iseries(void);
-extern void __init udbg_init_rtas(void);
+extern void __init udbg_init_rtas_panel(void);
+extern void __init udbg_init_rtas_console(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */

+ 2 - 4
kernel/kexec.c

@@ -1042,7 +1042,6 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry,
 
 void crash_kexec(struct pt_regs *regs)
 {
-	struct kimage *image;
 	int locked;
 
 
@@ -1056,12 +1055,11 @@ void crash_kexec(struct pt_regs *regs)
 	 */
 	locked = xchg(&kexec_lock, 1);
 	if (!locked) {
-		image = xchg(&kexec_crash_image, NULL);
-		if (image) {
+		if (kexec_crash_image) {
 			struct pt_regs fixed_regs;
 			crash_setup_regs(&fixed_regs, regs);
 			machine_crash_shutdown(&fixed_regs);
-			machine_kexec(image);
+			machine_kexec(kexec_crash_image);
 		}
 		xchg(&kexec_lock, 0);
 	}