summaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
commit95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch)
tree27a92a942821cde1edda9a1b088718d436b3efe4 /arch/ppc
parent45b27b0a0652331d104c953a5b192d843fff88f8 (diff)
Merge with Linux 2.3.40.
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/Makefile3
-rw-r--r--arch/ppc/coffboot/Makefile4
-rw-r--r--arch/ppc/coffboot/chrpmain.c1
-rw-r--r--arch/ppc/coffboot/coffmain.c1
-rw-r--r--arch/ppc/config.in17
-rw-r--r--arch/ppc/configs/common_defconfig6
-rw-r--r--arch/ppc/configs/gemini_defconfig45
-rw-r--r--arch/ppc/configs/oak_defconfig79
-rw-r--r--arch/ppc/configs/pmac_defconfig1
-rw-r--r--arch/ppc/configs/walnut_defconfig77
-rw-r--r--arch/ppc/defconfig8
-rw-r--r--arch/ppc/kernel/Makefile7
-rw-r--r--arch/ppc/kernel/entry.S50
-rw-r--r--arch/ppc/kernel/gemini_pci.c6
-rw-r--r--arch/ppc/kernel/gemini_setup.c4
-rw-r--r--arch/ppc/kernel/head.S8
-rw-r--r--arch/ppc/kernel/head_4xx.S183
-rw-r--r--arch/ppc/kernel/head_8xx.S36
-rw-r--r--arch/ppc/kernel/irq.c6
-rw-r--r--arch/ppc/kernel/oak_setup.c237
-rw-r--r--arch/ppc/kernel/oak_setup.h26
-rw-r--r--arch/ppc/kernel/open_pic.c11
-rw-r--r--arch/ppc/kernel/open_pic.h1
-rw-r--r--arch/ppc/kernel/pci.c80
-rw-r--r--arch/ppc/kernel/pmac_nvram.c1
-rw-r--r--arch/ppc/kernel/pmac_time.c1
-rw-r--r--arch/ppc/kernel/ppc4xx_pic.c204
-rw-r--r--arch/ppc/kernel/ppc4xx_pic.h36
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c3
-rw-r--r--arch/ppc/kernel/process.c8
-rw-r--r--arch/ppc/kernel/setup.c139
-rw-r--r--arch/ppc/kernel/smp.c2
-rw-r--r--arch/ppc/kernel/time.c3
-rw-r--r--arch/ppc/kernel/time.h18
-rw-r--r--arch/ppc/kernel/traps.c1
-rw-r--r--arch/ppc/mm/4xx_tlb.c397
-rw-r--r--arch/ppc/mm/4xx_tlb.h35
-rw-r--r--arch/ppc/mm/init.c98
-rw-r--r--arch/ppc/mm/mem_pieces.c2
-rw-r--r--arch/ppc/treeboot/Makefile4
-rw-r--r--arch/ppc/treeboot/crt0.S2
-rw-r--r--arch/ppc/treeboot/main.c45
-rw-r--r--arch/ppc/treeboot/misc.S30
-rw-r--r--arch/ppc/xmon/start.c4
-rw-r--r--arch/ppc/xmon/xmon.c4
45 files changed, 1548 insertions, 386 deletions
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 6552a7140..d62c07669 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -155,9 +155,6 @@ oak_config: clean_config
walnut_config: clean_config
ln -s configs/walnut_defconfig arch/ppc/defconfig
-tags:
- etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h}
-
archclean:
rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks}
@$(MAKECOFFBOOT) clean
diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile
index b9868e6ac..12032930d 100644
--- a/arch/ppc/coffboot/Makefile
+++ b/arch/ppc/coffboot/Makefile
@@ -39,11 +39,13 @@ ifeq ($(CONFIG_PMAC),y)
hack-coff: hack-coff.c
$(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
-znetboot: vmlinux.coff zImage
+znetboot: vmlinux.coff vmlinux.elf zImage
cp vmlinux.coff $(TFTPIMAGE)
+ cp vmlinux.elf $(TFTPIMAGE).elf
znetboot.initrd: vmlinux.coff.initrd
cp vmlinux.coff.initrd $(TFTPIMAGE)
+ cp vmlinux.elf.initrd $(TFTPIMAGE).elf
floppy: zImage
# mount -t hfs /dev/fd0 /mnt
diff --git a/arch/ppc/coffboot/chrpmain.c b/arch/ppc/coffboot/chrpmain.c
index fc5648944..bffb9d9ee 100644
--- a/arch/ppc/coffboot/chrpmain.c
+++ b/arch/ppc/coffboot/chrpmain.c
@@ -10,7 +10,6 @@
#include "zlib.h"
#include <asm/bootinfo.h>
#include <asm/processor.h>
-#define __KERNEL__
#include <asm/page.h>
extern void *finddevice(const char *);
diff --git a/arch/ppc/coffboot/coffmain.c b/arch/ppc/coffboot/coffmain.c
index 2bb4ea31d..b76ba5976 100644
--- a/arch/ppc/coffboot/coffmain.c
+++ b/arch/ppc/coffboot/coffmain.c
@@ -10,7 +10,6 @@
#include "zlib.h"
#include <asm/bootinfo.h>
#include <asm/processor.h>
-#define __KERNEL__
#include <asm/page.h>
extern void *finddevice(const char *);
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index fa98b5fcf..43a678c6d 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -2,6 +2,8 @@
# For a description of the syntax of this configuration file,
# see the Configure script.
#
+define_bool CONFIG_UID16 n
+
mainmenu_name "Linux/PowerPC Kernel Configuration"
mainmenu_option next_comment
@@ -91,10 +93,9 @@ if [ "$CONFIG_OAK" = "y" ]; then
fi
if [ "$CONFIG_8xx" = "y" ]; then
bool 'QSpan PCI' CONFIG_PCI
-else
- if [ "$CONFIG_APUS" != "y" ]; then
+fi
+if [ "$CONFIG_6xx" = "y" -a "$CONFIG_APUS" != "y" ]; then
define_bool CONFIG_PCI y
- fi
fi
bool 'Networking support' CONFIG_NET
@@ -112,11 +113,15 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
source drivers/pci/Config.in
-source drivers/pcmcia/Config.in
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+if [ "$CONFIG_HOTPLUG" = "y" ]; then
+ source drivers/pcmcia/Config.in
+fi
source drivers/parport/Config.in
-if [ "$CONFIG_8xx" != "y" ]; then
+if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
bool 'Support for frame buffer devices' CONFIG_FB
if [ "$CONFIG_FB" = "y" ]; then
@@ -188,6 +193,8 @@ if [ "$CONFIG_SCSI" != "n" ]; then
fi
endmenu
+source drivers/ieee1394/Config.in
+
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
comment 'Network device support'
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index 977626274..795aa5b83 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -45,11 +45,7 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
# CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
# CONFIG_PARPORT is not set
CONFIG_VGA_CONSOLE=y
CONFIG_FB=y
diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
index b3129c7a5..9850f61d8 100644
--- a/arch/ppc/configs/gemini_defconfig
+++ b/arch/ppc/configs/gemini_defconfig
@@ -46,11 +46,8 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
# CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_PCI_NAMES is not set
+# CONFIG_HOTPLUG is not set
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_FB is not set
@@ -161,6 +158,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
@@ -243,7 +241,6 @@ CONFIG_NCR885E=y
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_YELLOWFIN is not set
# CONFIG_RTL8139 is not set
# CONFIG_DM9102 is not set
# CONFIG_AT1700 is not set
@@ -251,6 +248,13 @@ CONFIG_NCR885E=y
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
@@ -310,10 +314,20 @@ CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256
#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
# Mice
#
# CONFIG_BUSMOUSE is not set
# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
# CONFIG_QIC02_TAPE is not set
#
@@ -327,11 +341,6 @@ CONFIG_UNIX98_PTY_COUNT=256
# Video For Linux
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -341,9 +350,10 @@ CONFIG_UNIX98_PTY_COUNT=256
#
# CONFIG_FTAPE is not set
# CONFIG_DRM is not set
+# CONFIG_AGP is not set
#
-# Support for USB
+# USB support
#
# CONFIG_USB is not set
@@ -358,9 +368,9 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -370,16 +380,17 @@ CONFIG_DEVPTS_FS=y
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
-# CONFIG_NFS_FS is not set
+CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
@@ -403,4 +414,4 @@ CONFIG_MSDOS_PARTITION=y
#
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
diff --git a/arch/ppc/configs/oak_defconfig b/arch/ppc/configs/oak_defconfig
index 1c2daf125..5fe9be376 100644
--- a/arch/ppc/configs/oak_defconfig
+++ b/arch/ppc/configs/oak_defconfig
@@ -3,41 +3,44 @@
#
#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
# Platform support
#
CONFIG_PPC=y
-CONFIG_4xx=y
# CONFIG_6xx is not set
+CONFIG_4xx=y
# CONFIG_PPC64 is not set
# CONFIG_82xx is not set
# CONFIG_8xx is not set
-CONFIG_403=y
-# CONFIG_405 is not set
CONFIG_OAK=y
+# CONFIG_WALNUT is not set
+# CONFIG_PCI is not set
# CONFIG_SMP is not set
CONFIG_MACH_SPECIFIC=y
# CONFIG_MATH_EMULATION is not set
#
-# General setup
+# Loadable module support
#
-# CONFIG_EXPERIMENTAL is not set
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
-# CONFIG_PCI is not set
+
+#
+# General setup
+#
CONFIG_NET=y
CONFIG_SYSCTL=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_FB is not set
@@ -66,7 +69,6 @@ CONFIG_BINFMT_MISC=y
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -77,7 +79,6 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_PARIDE_PARPORT=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
@@ -108,12 +109,29 @@ CONFIG_SYN_COOKIES=y
# (it is safe to leave these untouched)
#
# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
#
#
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
#
# SCSI support
@@ -140,15 +158,27 @@ CONFIG_NET_ETHERNET=y
# CONFIG_MACE is not set
# CONFIG_BMAC is not set
# CONFIG_NCR885E is not set
+CONFIG_OAKNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -162,6 +192,8 @@ CONFIG_NET_ETHERNET=y
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
#
# Wan interfaces
@@ -208,6 +240,10 @@ CONFIG_SERIAL_CONSOLE=y
# CONFIG_BUSMOUSE is not set
# CONFIG_MOUSE is not set
# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -229,9 +265,10 @@ CONFIG_SERIAL_CONSOLE=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
#
-# USB drivers - not for the faint of heart
+# Support for USB
#
# CONFIG_USB is not set
@@ -239,13 +276,16 @@ CONFIG_SERIAL_CONSOLE=y
# Filesystems
#
# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_UDF_FS is not set
@@ -253,7 +293,8 @@ CONFIG_AUTOFS_FS=y
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
-CONFIG_ROMFS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
@@ -274,8 +315,8 @@ CONFIG_LOCKD=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
index 514843d00..e2b7c31bd 100644
--- a/arch/ppc/configs/pmac_defconfig
+++ b/arch/ppc/configs/pmac_defconfig
@@ -35,6 +35,7 @@ CONFIG_SYSVIPC=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_MISC=m
+CONFIG_HOTPLUG=y
#
# PCMCIA/Cardbus support
diff --git a/arch/ppc/configs/walnut_defconfig b/arch/ppc/configs/walnut_defconfig
index 66edd11b6..931e1a7a9 100644
--- a/arch/ppc/configs/walnut_defconfig
+++ b/arch/ppc/configs/walnut_defconfig
@@ -3,41 +3,44 @@
#
#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
# Platform support
#
CONFIG_PPC=y
-CONFIG_4xx=y
# CONFIG_6xx is not set
+CONFIG_4xx=y
# CONFIG_PPC64 is not set
# CONFIG_82xx is not set
# CONFIG_8xx is not set
-CONFIG_403=y
-# CONFIG_405 is not set
-CONFIG_OAK=y
+# CONFIG_OAK is not set
+CONFIG_WALNUT=y
+CONFIG_PCI=y
# CONFIG_SMP is not set
CONFIG_MACH_SPECIFIC=y
# CONFIG_MATH_EMULATION is not set
#
-# General setup
+# Loadable module support
#
-# CONFIG_EXPERIMENTAL is not set
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y
-CONFIG_PCI=y
+
+#
+# General setup
+#
CONFIG_NET=y
CONFIG_SYSCTL=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_HOTPLUG is not set
# CONFIG_PARPORT is not set
# CONFIG_VGA_CONSOLE is not set
# CONFIG_FB is not set
@@ -66,7 +69,6 @@ CONFIG_BINFMT_MISC=y
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
#
# Additional Block Devices
@@ -77,7 +79,6 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_PARIDE_PARPORT=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
@@ -108,12 +109,29 @@ CONFIG_SYN_COOKIES=y
# (it is safe to leave these untouched)
#
# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
#
#
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
#
# SCSI support
@@ -140,15 +158,27 @@ CONFIG_NET_ETHERNET=y
# CONFIG_MACE is not set
# CONFIG_BMAC is not set
# CONFIG_NCR885E is not set
+# CONFIG_OAKNET is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
# CONFIG_NET_EISA is not set
# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -162,6 +192,8 @@ CONFIG_NET_ETHERNET=y
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
#
# Wan interfaces
@@ -208,6 +240,10 @@ CONFIG_SERIAL_CONSOLE=y
# CONFIG_BUSMOUSE is not set
# CONFIG_MOUSE is not set
# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
@@ -229,9 +265,10 @@ CONFIG_SERIAL_CONSOLE=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
#
-# USB drivers - not for the faint of heart
+# Support for USB
#
# CONFIG_USB is not set
@@ -239,13 +276,16 @@ CONFIG_SERIAL_CONSOLE=y
# Filesystems
#
# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_MSDOS_FS is not set
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_UDF_FS is not set
@@ -253,7 +293,8 @@ CONFIG_AUTOFS_FS=y
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
-CONFIG_ROMFS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index 2a3aac0f7..795aa5b83 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -35,8 +35,8 @@ CONFIG_KMOD=y
#
# General setup
#
+# CONFIG_PCI is not set
CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
CONFIG_NET=y
CONFIG_SYSCTL=y
CONFIG_SYSVIPC=y
@@ -45,11 +45,7 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
# CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
# CONFIG_PARPORT is not set
CONFIG_VGA_CONSOLE=y
CONFIG_FB=y
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index a41473fa5..7aaacfadb 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -57,8 +57,11 @@ ifdef CONFIG_SMP
O_OBJS += smp.o
endif
-ifeq ($(CONFIG_OAK),y)
- O_OBJS += oak_setup.o
+ifeq ($(CONFIG_4xx),y)
+ O_OBJS += ppc4xx_pic.o
+ ifeq ($(CONFIG_OAK),y)
+ O_OBJS += oak_setup.o
+ endif
endif
ifeq ($(CONFIG_8xx),y)
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5ed04344e..cb92163d6 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -265,37 +265,29 @@ _GLOBAL(_switch)
SYNC
rfi
-/*
- * ret_from_int():
- *
- * Return from an interrupt (external interrupt and
- * decrementer). This checks the first argument so
- * we know if rtl_intercept wants us to check for
- * a bottom half, signals and so on (normal return) or
- * we're returning from a real-time interrupt or have
- * interrupts soft disabled so we cannot enter Linux.
- * -- Cort
- */
- .globl ret_from_int
-ret_from_int:
- cmpi 0,r3,0
- beq 10f
- /* we're allowed to do signal/bh checks */
- b ret_from_syscall
#ifdef __SMP__
.globl ret_from_smpfork
ret_from_smpfork:
bl schedule_tail
+ b ret_from_except
#endif
- .globl ret_from_syscall
-ret_from_syscall:
+ .globl ret_from_intercept
+ret_from_intercept:
+ /*
+ * We may be returning from RTL and cannot do the normal checks
+ * -- Cort
+ */
+ cmpi 0,r3,0
+ beq 10f
.globl ret_from_except
ret_from_except:
-0: mfmsr r30 /* Disable interrupts */
- rlwinm r30,r30,0,17,15 /* clear MSR_EE */
- SYNC /* Some chip revs need this... */
- mtmsr r30
- SYNC
+0: /* disable interrupts */
+ lis r30,int_control@h
+ ori r30,r30,int_control@l
+ lwz r30,0(r30)
+ mtlr r30
+ blrl
+
lwz r5,_MSR(r1)
andi. r5,r5,MSR_EE
beq 2f
@@ -317,9 +309,13 @@ lost_irq_ret:
bl do_bottom_half
.globl do_bottom_half_ret
do_bottom_half_ret:
-2: SYNC
- mtmsr r30 /* disable interrupts again */
- SYNC
+2: /* disable interrupts */
+ lis r30,int_control@h
+ ori r30,r30,int_control@l
+ lwz r30,0(r30)
+ mtlr r30
+ blrl
+
lwz r3,_MSR(r1) /* Returning to user mode? */
andi. r3,r3,MSR_PR
beq+ 10f /* if so, check need_resched and signals */
diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c
index 3d6feed13..fb80dc493 100644
--- a/arch/ppc/kernel/gemini_pci.c
+++ b/arch/ppc/kernel/gemini_pci.c
@@ -229,13 +229,11 @@ __init void layout_bus( struct pci_bus *bus )
{
struct pci_dev *dev;
- if (!bus->devices && !bus->children)
- return;
-
io_base = ALIGN(io_base, 4*KB);
mem_base = ALIGN(mem_base, 4*KB);
- for( dev = bus->devices; dev; dev = dev->sibling ) {
+ pci_for_each_dev(dev)
+ {
if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
layout_dev( dev );
diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c
index fadddda8b..d7ca91780 100644
--- a/arch/ppc/kernel/gemini_setup.c
+++ b/arch/ppc/kernel/gemini_setup.c
@@ -330,7 +330,7 @@ void __init gemini_init_IRQ(void)
int i;
/* gemini has no 8259 */
- open_pic.irq_offset = 0;
+ open_pic_irq_offset = 0;
for( i=0; i < NR_IRQS; i++ )
irq_desc[i].handler = &open_pic;
openpic_init(1);
@@ -515,7 +515,7 @@ void gemini_post_irq(int irq)
* We do it this way since our irq_desc[irq].handler can change
* with RTL and no longer be open_pic -- Cort
*/
- if ( irq >= open_pic.irq_offset)
+ if ( irq >= open_pic_irq_offset)
openpic_eoi( smp_processor_id() );
}
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 451a1cad4..a70ba8bfd 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -287,7 +287,8 @@ turn_on_mmu:
stw r2,GPR2(r21); \
stw r1,0(r21); \
tovirt(r1,r21); /* set new kernel sp */ \
- SAVE_4GPRS(3, r21);
+ SAVE_4GPRS(3, r21); \
+ SAVE_GPR(7, r21);
/*
* Note: code which follows this uses cr0.eq (set if from kernel),
* r21, r22 (SRR0), and r23 (SRR1).
@@ -374,7 +375,7 @@ HardwareInterrupt:
.globl do_IRQ_intercept
do_IRQ_intercept:
.long do_IRQ;
- .long ret_from_except
+ .long ret_from_intercept
#else
bl apus_interrupt_entry
#endif /* CONFIG_APUS */
@@ -424,7 +425,7 @@ Decrementer:
.globl timer_interrupt_intercept
timer_interrupt_intercept:
.long timer_interrupt
- .long ret_from_except
+ .long ret_from_intercept
STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
@@ -674,7 +675,6 @@ DataStoreTLBMiss:
transfer_to_handler:
stw r22,_NIP(r21)
stw r23,_MSR(r21)
- SAVE_GPR(7, r21)
SAVE_4GPRS(8, r21)
SAVE_8GPRS(12, r21)
SAVE_8GPRS(24, r21)
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index abc651218..ba3284ad8 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -27,10 +27,8 @@
#include <linux/config.h>
#include <asm/processor.h>
-#include <asm/4xx.h>
-#include <asm/403gcx.h>
-#include <asm/405gp.h>
#include <asm/page.h>
+#include <asm/pgtable.h>
#include <asm/mmu.h>
#include "ppc_asm.h"
@@ -58,7 +56,7 @@
### execution begins here, the following registers contain valid, yet
### optional, information:
###
-### r3 - ???
+### r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
### r4 - Starting address of the init RAM disk
### r5 - Ending address of the init RAM disk
### r6 - Start of kernel command line string (e.g. "mem=96m")
@@ -80,17 +78,55 @@ _GLOBAL(_start)
li r24,0
- ## Establish exception vector base
+ ## We should still be executing code at physical address 0x0000xxxx
+ ## at this point. However, start_here is at virtual address
+ ## 0xC000xxxx. So, set up a TLB mapping to cover this once
+ ## translation is enabled.
+
+ lis r3,KERNELBASE@h # Load the kernel virtual address
+ addis r3,r3,KERNELBASE@l
+ tophys(r4,r3) # Load the kernel physical address
+
+ ## Save the existing PID and load the kernel PID.
+
+ mfspr r7,SPRN_PID # Save the old PID
+ li r0,0
+ mtspr SPRN_PID,r0 # Load the kernel PID
+
+ ## Configure and load entry into TLB slot 0.
- lis r0,KERNELBASE@h
- mtspr SPRN_EVPR,r0
+ clrrwi r4,r4,10 # Mask off the real page number
- ## Jump to the main PowerPC kernel start-up code
+ ## XXX - Temporarily set the TLB_I bit because of cache issues that
+ ## seem to foul-up the exception handling code.
+
+ ori r4,r4,(TLB_WR | TLB_EX | TLB_I) # Set the write and execute bits
-1: lis r7,start_here@ha
- addi r7,r7,start_here@l
- mtlr r7
- blr
+ clrrwi r3,r3,10 # Mask off the effective page number
+ ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
+
+ tlbwe r4,r0,TLB_DATA # Load the data portion of the entry
+ tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry
+ isync
+
+ mtspr SPRN_PID,r7 # Restore the existing PID
+
+ ## Establish the exception vector base
+
+ lis r4,KERNELBASE@h # EVPR only uses the high 16-bits
+ tophys(r0,r4) # Use the physical address
+ mtspr SPRN_EVPR,r0
+
+ ## Enable the MMU and jump to the main PowerPC kernel start-up code
+
+ mfmsr r0 # Get the machine state register
+ ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation
+ mtspr SPRN_SRR1,r0 # Set up the new machine state register
+ lis r0,start_here@h
+ ori r0,r0,start_here@l
+ mtspr SPRN_SRR0,r0 # Set up the new instruction pointer
+ rfi # Jump to start_here w/ translation on
+
###
### Exception vector entry code. This code runs with address translation
@@ -129,7 +165,8 @@ _GLOBAL(_start)
stw r2,GPR2(r21); /* Save r2 on the stack */\
stw r1,0(r21); \
tovirt(r1,r21); /* Set-up new kernel stack pointer */\
- SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */
+ SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */\
+ SAVE_GPR(7, r21); /* Save r7 on the stack */
## Common exception code for standard (non-critical) exceptions.
@@ -166,7 +203,7 @@ label:
START_EXCEPTION(n, label); \
STND_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
- li r0,STND_EXC; \
+ li r7,STND_EXC; \
li r20,MSR_KERNEL; \
FINISH_EXCEPTION(func)
@@ -175,23 +212,10 @@ label:
START_EXCEPTION(n, label); \
CRIT_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
- li r0,CRIT_EXC; \
+ li r7,CRIT_EXC; \
li r20,MSR_KERNEL; \
FINISH_EXCEPTION(func)
-
-#define INTR_EXCEPTION(n, label, func) \
- START_EXCEPTION(n, label); \
- STND_EXCEPTION_PROLOG; \
- addi r3,r1,STACK_FRAME_OVERHEAD; \
- li r0,STND_EXC; \
- li r20,MSR_KERNEL; \
- li r4,0; \
- bl transfer_to_handler; \
-_GLOBAL(do_IRQ_intercept); \
- .long func; \
- .long ret_from_except
-
###
### Exception vectors.
@@ -214,7 +238,7 @@ _GLOBAL(do_IRQ_intercept); \
mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2
stw r4,_DEAR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC # This is a standard exception
+ li r7,STND_EXC # This is a standard exception
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR)
@@ -226,15 +250,24 @@ _GLOBAL(do_IRQ_intercept); \
mr r4,r22 # Pass SRR0 as arg2
mr r5,r23 # Pass SRR1 as arg3
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC # This is a standard exception
+ li r7,STND_EXC # This is a standard exception
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1)
### 0x0500 - External Interrupt Exception
- INTR_EXCEPTION(0x0500, HardwareInterrupt, do_IRQ)
-
+ START_EXCEPTION(0x0500, HardwareInterrupt)
+ STND_EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r7,STND_EXC
+ li r20,MSR_KERNEL
+ li r4,0
+ bl transfer_to_handler
+_GLOBAL(do_IRQ_intercept)
+ .long do_IRQ
+ .long ret_from_intercept
+
### 0x0600 - Alignment Exception
START_EXCEPTION(0x0600, Alignment)
@@ -242,7 +275,7 @@ _GLOBAL(do_IRQ_intercept); \
mfspr r4,SPRN_DEAR # Grab the DEAR and save it
stw r4,_DEAR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC # This is a standard exception
+ li r7,STND_EXC # This is a standard exception
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
FINISH_EXCEPTION(AlignmentException)
@@ -252,7 +285,7 @@ _GLOBAL(do_IRQ_intercept); \
START_EXCEPTION(0x0700, ProgramCheck)
STND_EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC # This is a standard exception
+ li r7,STND_EXC # This is a standard exception
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
FINISH_EXCEPTION(ProgramCheckException)
@@ -266,7 +299,7 @@ _GLOBAL(do_IRQ_intercept); \
START_EXCEPTION(0x0C00, SystemCall)
STND_EXCEPTION_PROLOG
stw r3,ORIG_GPR3(r21)
- li r0,STND_EXC # This is a standard exception
+ li r7,STND_EXC # This is a standard exception
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR
FINISH_EXCEPTION(DoSyscall)
@@ -275,11 +308,21 @@ _GLOBAL(do_IRQ_intercept); \
STND_EXCEPTION(0x0E00, Trap_0E, UnknownException)
STND_EXCEPTION(0x0F00, Trap_0F, UnknownException)
-#if 0
### 0x1000 - Programmable Interval Timer (PIT) Exception
- STND_EXCEPTION(0x1000, PITException, UnknownException)
+ START_EXCEPTION(0x1000, Decrementer)
+ STND_EXCEPTION_PROLOG
+ lis r0,TSR_PIS@h # Set-up the PIT exception mask
+ mtspr SPRN_TSR,r0 # Clear the PIT exception
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r7,STND_EXC # This is a standard exception
+ li r20,MSR_KERNEL
+ bl transfer_to_handler
+_GLOBAL(timer_interrupt_intercept)
+ .long timer_interrupt
+ .long ret_from_intercept
+#if 0
### 0x1010 - Fixed Interval Timer (FIT) Exception
STND_EXCEPTION(0x1010, FITException, UnknownException)
@@ -294,7 +337,7 @@ _GLOBAL(do_IRQ_intercept); \
START_EXCEPTION(0x1100, DTLBMiss)
STND_EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC
+ li r7,STND_EXC
li r20,MSR_KERNEL
FINISH_EXCEPTION(UnknownException)
@@ -303,7 +346,7 @@ _GLOBAL(do_IRQ_intercept); \
START_EXCEPTION(0x1200, ITLBMiss)
STND_EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
- li r0,STND_EXC
+ li r7,STND_EXC
li r20,MSR_KERNEL
FINISH_EXCEPTION(UnknownException)
@@ -341,7 +384,6 @@ _GLOBAL(do_IRQ_intercept); \
_GLOBAL(transfer_to_handler)
stw r22,_NIP(r21) # Save the faulting IP on the stack
stw r23,_MSR(r21) # Save the exception MSR on the stack
- SAVE_GPR(7, r21) # Save r7 on the stack
SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack
SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack
SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack
@@ -367,7 +409,7 @@ _GLOBAL(transfer_to_handler)
bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE
lwz r24,0(r23) # Virtual address of the handler
lwz r23,4(r23) # Handler return pointer
- cmpwi cr0,r0,STND_EXC # What type of exception is this?
+ cmpwi cr0,r7,STND_EXC # What type of exception is this?
bne 3f # It is a critical exception...
## Standard exception jump path
@@ -432,67 +474,10 @@ _GLOBAL(giveup_fpu)
_GLOBAL(abort)
mfspr r13,SPRN_DBCR
- ori r13,r13,DBCR_RST(SYSTEM)@h
+ oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
mtspr SPRN_DBCR,r13
-
-###
-### This code is jumped-to from the startup code. It copies the kernel
-### image from wherever it happens to be currently running at in physical
-### address space to physical address 0.
-###
-### In general, for a running Linux/PPC system:
-### Kernel Physical Address (KPA) = 0x00000000
-### Kernel Virtual Address (KVA) = 0xC0000000
-###
-
-#if 0
-relocate_kernel:
- lis r9,0x426f /* if booted from BootX, don't */
- addi r9,r9,0x6f58 /* translate source addr */
- cmpw r31,r9 /* (we have to on chrp) */
- beq 7f
- rlwinm r4,r4,0,8,31 /* translate source address */
- add r4,r4,r3 /* to region mapped with BATs */
-7: addis r9,r26,klimit@ha /* fetch klimit */
- lwz r25,klimit@l(r9)
- addis r25,r25,-KERNELBASE@h
- li r6,0 /* Destination offset */
- li r5,0x4000 /* # bytes of memory to copy */
- bl copy_and_flush /* copy the first 0x4000 bytes */
- addi r0,r3,4f@l /* jump to the address of 4f */
- mtctr r0 /* in copy and do the rest. */
- bctr /* jump to the copy */
-4: mr r5,r25
- bl copy_and_flush /* copy the rest */
- b turn_on_mmu
-/*
- * Copy routine used to copy the kernel to start at physical address 0
- * and flush and invalidate the caches as needed.
- * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
- * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
- */
-copy_and_flush:
- addi r5,r5,-4
- addi r6,r6,-4
-4: li r0,8
- mtctr r0
-3: addi r6,r6,4 /* copy a cache line */
- lwzx r0,r6,r4
- stwx r0,r6,r3
- bdnz 3b
- dcbst r6,r3 /* write it to memory */
- sync
- icbi r6,r3 /* flush the icache line */
- cmplw 0,r6,r5
- blt 4b
- isync
- addi r5,r5,4
- addi r6,r6,4
- blr
-#endif
-
###
### This is where the main kernel code starts.
###
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index c5a55c6a2..94cd67d3b 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -197,7 +197,8 @@ turn_on_mmu:
stw r2,GPR2(r21); \
stw r1,0(r21); \
tovirt(r1,r21); /* set new kernel sp */ \
- SAVE_4GPRS(3, r21);
+ SAVE_4GPRS(3, r21); \
+ SAVE_GPR(7, r21);
/*
* Note: code which follows this uses cr0.eq (set if from kernel),
* r21, r22 (SRR0), and r23 (SRR1).
@@ -265,34 +266,6 @@ InstructionAccess:
. = 0x500;
HardwareInterrupt:
EXCEPTION_PROLOG;
-#ifdef CONFIG_APUS
- /* This is horrible, but there's no way around it. Enable the
- data cache so the IRQ hardware register can be accessed
- without cache intervention. Then disable interrupts and get
- the current emulated m68k IPL value. */
-
- mfmsr 20
- xori r20,r20,MSR_DR
- sync
- mtmsr r20
- sync
-
- lis r3,APUS_IPL_EMU@h
-
- li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
- stb r20,APUS_IPL_EMU@l(r3)
- eieio
-
- lbz r3,APUS_IPL_EMU@l(r3)
-
- mfmsr r20
- xori r20,r20,MSR_DR
- sync
- mtmsr r20
- sync
-
- stw r3,(_CCR+4)(r21);
-#endif
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
li r4,0
@@ -300,7 +273,7 @@ HardwareInterrupt:
.globl do_IRQ_intercept
do_IRQ_intercept:
.long do_IRQ;
- .long ret_from_except
+ .long ret_from_intercept
/* Alignment exception */
@@ -342,7 +315,7 @@ Decrementer:
.globl timer_interrupt_intercept
timer_interrupt_intercept:
.long timer_interrupt
- .long ret_from_except
+ .long ret_from_intercept
STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
@@ -591,7 +564,6 @@ transfer_to_handler:
lis r22,MSR_POW@h
andc r23,r23,r22
stw r23,_MSR(r21)
- SAVE_GPR(7, r21)
SAVE_4GPRS(8, r21)
SAVE_8GPRS(12, r21)
SAVE_8GPRS(24, r21)
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index a09d6ad98..c2f2d1c11 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -294,11 +294,10 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
}
}
-asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
+asmlinkage int do_IRQ(struct pt_regs *regs, int isfake)
{
int cpu = smp_processor_id();
int irq;
-
hardirq_enter( cpu );
/* every arch is required to have a get_irq -- Cort */
@@ -320,10 +319,9 @@ asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
out:
hardirq_exit( cpu );
+ return 1; /* lets ret_from_int know we can do checks */
}
-
-
unsigned long probe_irq_on (void)
{
return 0;
diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c
index a9c9137a0..ad2c224bb 100644
--- a/arch/ppc/kernel/oak_setup.c
+++ b/arch/ppc/kernel/oak_setup.c
@@ -7,26 +7,74 @@
* Description:
* Architecture- / platform-specific boot-time initialization code for
* the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dmalek@jlc.net>.
+ * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ * <dan@net4x.com>.
*
*/
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/param.h>
#include <linux/string.h>
+#include <asm/processor.h>
+#include <asm/board.h>
#include <asm/machdep.h>
#include <asm/page.h>
+#include "local_irq.h"
+#include "ppc4xx_pic.h"
+#include "time.h"
#include "oak_setup.h"
+/* Function Prototypes */
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init oak_init()
+ *
+ * Description:
+ * This routine...
+ *
+ * Input(s):
+ * r3 - Optional pointer to a board information structure.
+ * r4 - Optional pointer to the physical starting address of the init RAM
+ * disk.
+ * r5 - Optional pointer to the physical ending address of the init RAM
+ * disk.
+ * r6 - Optional pointer to the physical starting address of any kernel
+ * command-line parameters.
+ * r7 - Optional pointer to the physical ending address of any kernel
+ * command-line parameters.
+ *
+ * Output(s):
+ * N/A
+ *
+ * Returns:
+ * N/A
+ *
+ */
void __init
oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
-#if 0
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3) {
+ memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+ }
+
#if defined(CONFIG_BLK_DEV_INITRD)
/*
* If the init RAM disk has been configured in, and there's a valid
@@ -44,24 +92,25 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
*(char *)(r7 + KERNELBASE) = 0;
strcpy(cmd_line, (char *)(r6 + KERNELBASE));
}
-#endif /* 0 */
+
+ /* Initialize machine-dependency vectors */
ppc_md.setup_arch = oak_setup_arch;
- ppc_md.setup_residual = NULL;
+ ppc_md.setup_residual = oak_setup_residual;
ppc_md.get_cpuinfo = NULL;
ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = NULL;
- ppc_md.get_irq = NULL;
+ ppc_md.init_IRQ = oak_init_IRQ;
+ ppc_md.get_irq = oak_get_irq;
ppc_md.init = NULL;
- ppc_md.restart = NULL;
- ppc_md.power_off = NULL;
- ppc_md.halt = NULL;
+ ppc_md.restart = oak_restart;
+ ppc_md.power_off = oak_power_off;
+ ppc_md.halt = oak_halt;
- ppc_md.time_init = NULL;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = NULL;
+ ppc_md.time_init = oak_time_init;
+ ppc_md.set_rtc_time = oak_set_rtc_time;
+ ppc_md.get_rtc_time = oak_get_rtc_time;
+ ppc_md.calibrate_decr = oak_calibrate_decr;
ppc_md.kbd_setkeycode = NULL;
ppc_md.kbd_getkeycode = NULL;
@@ -77,8 +126,168 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
return;
}
+/*
+ * Document me.
+ */
void __init
oak_setup_arch(void)
{
+ /* XXX - Implement me */
+}
+
+/*
+ * int oak_setup_residual()
+ *
+ * Description:
+ * This routine pretty-prints the platform's internal CPU and bus clock
+ * frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ * *buffer - Buffer into which CPU and bus clock frequencies are to be
+ * printed.
+ *
+ * Output(s):
+ * *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ * The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ * on error.
+ */
+int
+oak_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp = (bd_t *)__res;
+
+ len += sprintf(len + buffer,
+ "clock\t\t: %dMHz\n"
+ "bus clock\t\t: %dMHz\n",
+ bp->bi_intfreq / 1000000,
+ bp->bi_busfreq / 1000000);
+
+ return (len);
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_init_IRQ(void)
+{
+ int i;
+
+ ppc4xx_pic_init();
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].handler = ppc4xx_pic;
+ }
+
+ return;
+}
+
+/*
+ * Document me.
+ */
+int
+oak_get_irq(struct pt_regs *regs)
+{
+ return (ppc4xx_pic_get_irq(regs));
+}
+
+/*
+ * Document me.
+ */
+void
+oak_restart(char *cmd)
+{
+ abort();
+}
+
+/*
+ * Document me.
+ */
+void
+oak_power_off(void)
+{
+ oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+oak_halt(void)
+{
+ oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_time_init(void)
+{
+ /* XXX - Implement me */
+}
+
+/*
+ * Document me.
+ */
+int __init
+oak_set_rtc_time(unsigned long time)
+{
+ /* XXX - Implement me */
+
+ return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+oak_get_rtc_time(void)
+{
+ /* XXX - Implement me */
+
+ return (0);
+}
+
+/*
+ * void __init oak_calibrate_decr()
+ *
+ * Description:
+ * This routine retrieves the internal processor frequency from the board
+ * information structure, sets up the kernel timer decrementer based on
+ * that value, enables the 403 programmable interval timer (PIT) and sets
+ * it up for auto-reload.
+ *
+ * Input(s):
+ * N/A
+ *
+ * Output(s):
+ * N/A
+ *
+ * Returns:
+ * N/A
+ *
+ */
+void __init
+oak_calibrate_decr(void)
+{
+ unsigned int freq;
+ bd_t *bip = (bd_t *)__res;
+
+ freq = bip->bi_intfreq;
+
+ decrementer_count = freq / HZ;
+ count_period_num = 1;
+ count_period_den = freq;
+
+ /* Enable the PIT and set auto-reload of its value */
+
+ mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+ /* Clear any pending timer interrupts */
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
}
diff --git a/arch/ppc/kernel/oak_setup.h b/arch/ppc/kernel/oak_setup.h
index 10f7d7354..62cfac906 100644
--- a/arch/ppc/kernel/oak_setup.h
+++ b/arch/ppc/kernel/oak_setup.h
@@ -15,14 +15,32 @@
#ifndef __OAK_SETUP_H__
#define __OAK_SETUP_H__
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
#ifdef __cplusplus
extern "C" {
#endif
-extern void oak_init(unsigned long r3,
- unsigned long ird_start, unsigned long ird_end,
- unsigned long cline_start, unsigned long cline_end);
-extern void oak_setup_arch(void);
+extern unsigned char __res[sizeof(bd_t)];
+
+extern void oak_init(unsigned long r3,
+ unsigned long ird_start,
+ unsigned long ird_end,
+ unsigned long cline_start,
+ unsigned long cline_end);
+extern void oak_setup_arch(void);
+extern int oak_setup_residual(char *buffer);
+extern void oak_init_IRQ(void);
+extern int oak_get_irq(struct pt_regs *regs);
+extern void oak_restart(char *cmd);
+extern void oak_power_off(void);
+extern void oak_halt(void);
+extern void oak_time_init(void);
+extern int oak_set_rtc_time(unsigned long now);
+extern unsigned long oak_get_rtc_time(void);
+extern void oak_calibrate_decr(void);
#ifdef __cplusplus
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index 02e276729..6857aa36f 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -38,6 +38,7 @@ struct hw_interrupt_type open_pic = {
0,
0
};
+int open_pic_irq_offset;
/*
* Accesses to the current processor's registers
@@ -69,7 +70,7 @@ struct hw_interrupt_type open_pic = {
* -- Cort
*/
#define check_arg_irq(irq) \
- /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \
+ /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \
printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/
#define check_arg_cpu(cpu) \
if (cpu < 0 || cpu >= NumProcessors) \
@@ -212,11 +213,11 @@ void __init openpic_init(int main_pic)
/* Initialize external interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
/* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
+ openpic_initirq(0, 8, open_pic_irq_offset, 1, 1);
openpic_mapirq(0, 1<<0);
for (i = 1; i < NumSources; i++) {
/* Enabled, Priority 8 */
- openpic_initirq(i, 8, open_pic.irq_offset+i, 0,
+ openpic_initirq(i, 8, open_pic_irq_offset+i, 0,
i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
/* Processor 0 */
openpic_mapirq(i, 1<<0);
@@ -416,13 +417,13 @@ void openpic_maptimer(u_int timer, u_int cpumask)
void openpic_enable_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
+ openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
}
void openpic_disable_irq(u_int irq)
{
check_arg_irq(irq);
- openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
+ openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK);
}
/*
diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h
index 2673263cf..3e51ffba3 100644
--- a/arch/ppc/kernel/open_pic.h
+++ b/arch/ppc/kernel/open_pic.h
@@ -7,4 +7,5 @@ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
void openpic_enable_IPI(u_int ipi);
void do_openpic_setup_cpu(void);
+extern int open_pic_irq_offset;
#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index ec1ff3565..6c98bbf2c 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -9,6 +9,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/openpic.h>
+#include <linux/errno.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -21,7 +22,7 @@
#include "pci.h"
-static void __init pcibios_claim_resources(struct pci_bus *);
+static void __init pcibios_claim_resources(struct list_head *);
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
@@ -69,10 +70,9 @@ struct pci_ops generic_pci_ops =
void __init pcibios_init(void)
{
printk("PCI: Probing PCI hardware\n");
- ioport_resource.end = ~0L;
pci_scan_bus(0, &generic_pci_ops, NULL);
- pcibios_claim_resources(pci_root);
- if ( ppc_md.pcibios_fixup )
+ pcibios_claim_resources(&pci_root_buses);
+ if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
}
@@ -162,3 +162,75 @@ void __init
pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+/*
+ * Assign new address to PCI resource. We hope our resource information
+ * is complete. We don't re-assign resources unless we are
+ * forced to do so.
+ *
+ * Expects start=0, end=size-1, flags=resource type.
+ */
+
+int pci_assign_resource(struct pci_dev *dev, int i)
+{
+ struct resource *r = &dev->resource[i];
+ struct resource *pr = pci_find_parent_resource(dev, r);
+ unsigned long size = r->end + 1;
+ u32 new, check;
+
+ if (!pr) {
+ printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO) {
+ if (allocate_resource(pr, r, size, 0x100, ~0, size, NULL, NULL)) {
+ printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
+ return -EBUSY;
+ }
+ } else {
+ if (allocate_resource(pr, r, size, 0x10000, ~0, size, NULL, NULL)) {
+ printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
+ return -EBUSY;
+ }
+ }
+ if (i < 6) {
+ int reg = PCI_BASE_ADDRESS_0 + 4*i;
+ new = r->start | (r->flags & PCI_REGION_FLAG_MASK);
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ if (new != check)
+ printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check);
+ } else if (i == PCI_ROM_RESOURCE) {
+ r->flags |= PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK));
+ }
+ printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i);
+ return 0;
+}
diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c
index 99bfa4f8b..ea3338aef 100644
--- a/arch/ppc/kernel/pmac_nvram.c
+++ b/arch/ppc/kernel/pmac_nvram.c
@@ -10,6 +10,7 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/prom.h>
+#include <asm/machdep.h>
#include <linux/adb.h>
#include <linux/pmu.h>
diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c
index 60b497cd6..3b7dd283f 100644
--- a/arch/ppc/kernel/pmac_time.c
+++ b/arch/ppc/kernel/pmac_time.c
@@ -24,6 +24,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/pgtable.h>
+#include <asm/machdep.h>
#include "time.h"
diff --git a/arch/ppc/kernel/ppc4xx_pic.c b/arch/ppc/kernel/ppc4xx_pic.c
new file mode 100644
index 000000000..8b40080b4
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_pic.c
@@ -0,0 +1,204 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: ppc4xx_pic.c
+ *
+ * Description:
+ * Interrupt controller driver for PowerPC 4xx-based processors.
+ */
+
+/*
+ * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
+ * 32 possible interrupts, a majority of which are not implemented on
+ * all cores. There are six configurable, external interrupt pins and
+ * there are eight internal interrupts for the on-chip serial port
+ * (SPU), DMA controller, and JTAG controller.
+ *
+ * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32
+ * possible interrupts as well. There are seven, configurable external
+ * interrupt pins and there are 17 internal interrupts for the on-chip
+ * serial port, DMA controller, on-chip Ethernet controller, PCI, etc.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include "local_irq.h"
+#include "ppc4xx_pic.h"
+
+
+/* Global Variables */
+
+struct hw_interrupt_type *ppc4xx_pic;
+
+
+/* Function Prototypes */
+
+static void ppc403_aic_enable(unsigned int irq);
+static void ppc403_aic_disable(unsigned int irq);
+static void ppc403_aic_disable_and_ack(unsigned int irq);
+
+static void ppc405_uic_enable(unsigned int irq);
+static void ppc405_uic_disable(unsigned int irq);
+static void ppc405_uic_disable_and_ack(unsigned int irq);
+
+static struct hw_interrupt_type ppc403_aic = {
+ "403GC AIC",
+ NULL,
+ NULL,
+ ppc403_aic_enable,
+ ppc403_aic_disable,
+ ppc403_aic_disable_and_ack,
+ 0
+};
+
+static struct hw_interrupt_type ppc405_uic = {
+ "405GP UIC",
+ NULL,
+ NULL,
+ ppc405_uic_enable,
+ ppc405_uic_disable,
+ ppc405_uic_disable_and_ack,
+ 0
+};
+
+/*
+ * Document me.
+ */
+void __init
+ppc4xx_pic_init(void)
+{
+ unsigned long ver = PVR_VER(mfspr(SPRN_PVR));
+
+ switch (ver) {
+
+ case PVR_VER(PVR_403GC):
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ ppc_cached_irq_mask[0] = 0;
+ mtdcr(DCRN_EXIER, 0);
+
+ ppc4xx_pic = &ppc403_aic;
+ break;
+
+ case PVR_VER(PVR_405GP):
+ ppc4xx_pic = &ppc405_uic;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * XXX - Currently 403-specific!
+ *
+ * Document me.
+ */
+int
+ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits, mask = (1 << 31);
+
+ /*
+ * Only report the status of those interrupts that are actually
+ * enabled.
+ */
+
+ bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER);
+
+ /*
+ * Walk through the interrupts from highest priority to lowest, and
+ * report the first pending interrupt found.
+ */
+
+ for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) {
+ if (bits & mask)
+ break;
+ }
+
+ return (irq);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_enable(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_disable(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_disable_and_ack(unsigned int irq)
+{
+ int bit, word;
+
+ bit = irq & 0x1f;
+ word = irq >> 5;
+
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+ mtdcr(DCRN_EXISR, (1 << (31 - bit)));
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_enable(unsigned int irq)
+{
+ /* XXX - Implement me. */
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_disable(unsigned int irq)
+{
+ /* XXX - Implement me. */
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_disable_and_ack(unsigned int irq)
+{
+ /* XXX - Implement me. */
+}
diff --git a/arch/ppc/kernel/ppc4xx_pic.h b/arch/ppc/kernel/ppc4xx_pic.h
new file mode 100644
index 000000000..6de862a46
--- /dev/null
+++ b/arch/ppc/kernel/ppc4xx_pic.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: ppc4xx_pic.h
+ *
+ * Description:
+ * Interrupt controller driver for PowerPC 4xx-based processors.
+ */
+
+#ifndef __PPC4XX_PIC_H__
+#define __PPC4XX_PIC_H__
+
+#include <asm/ptrace.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* External Global Variables */
+
+extern struct hw_interrupt_type *ppc4xx_pic;
+
+
+/* Function Prototypes */
+
+extern void ppc4xx_pic_init(void);
+extern int ppc4xx_pic_get_irq(struct pt_regs *regs);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PPC4XX_PIC_H__ */
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 397685d43..65e925034 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -260,10 +260,8 @@ EXPORT_SYMBOL(screen_info);
#endif
EXPORT_SYMBOL(int_control);
-#if !defined(CONFIG_4xx)
EXPORT_SYMBOL(timer_interrupt_intercept);
EXPORT_SYMBOL(timer_interrupt);
-#endif
extern unsigned long do_IRQ_intercept;
EXPORT_SYMBOL(do_IRQ_intercept);
EXPORT_SYMBOL(irq_desc);
@@ -272,3 +270,4 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler);
EXPORT_SYMBOL(decrementer_count);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
+EXPORT_SYMBOL(do_bottom_half);
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index 64b171042..241b7c33c 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -287,11 +287,12 @@ int
copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
+ unsigned long msr;
struct pt_regs * childregs, *kregs;
#ifdef __SMP__
extern void ret_from_smpfork(void);
#else
- extern void ret_from_syscall(void);
+ extern void ret_from_except(void);
#endif
/* Copy registers */
childregs = ((struct pt_regs *)
@@ -308,9 +309,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
#ifdef __SMP__
kregs->nip = (unsigned long)ret_from_smpfork;
#else
- kregs->nip = (unsigned long)ret_from_syscall;
+ kregs->nip = (unsigned long)ret_from_except;
#endif
- kregs->msr = MSR_KERNEL;
+ asm volatile("mfmsr %0" : "=r" (msr):);
+ kregs->msr = msr;
kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
kregs->gpr[2] = (unsigned long)p;
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index caffdcf99..dccb066ff 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -29,8 +29,9 @@
#endif
#include <asm/bootx.h>
#include <asm/machdep.h>
-
+#ifdef CONFIG_OAK
#include "oak_setup.h"
+#endif /* CONFIG_OAK */
extern void pmac_init(unsigned long r3,
unsigned long r4,
@@ -71,7 +72,13 @@ extern void gemini_init(unsigned long r3,
extern boot_infos_t *boot_infos;
char saved_command_line[256];
unsigned char aux_device_present;
-struct int_control_struct int_control;
+struct int_control_struct int_control =
+{
+ __no_use_cli,
+ __no_use_sti,
+ __no_use_restore_flags,
+ __no_use_save_flags
+};
struct ide_machdep_calls ppc_ide_md;
int parse_bootinfo(void);
@@ -89,20 +96,13 @@ unsigned long SYSRQ_KEY;
struct machdep_calls ppc_md;
-/* copy of the residual data */
-#ifndef CONFIG_8xx
-extern unsigned char __res[sizeof(RESIDUAL)];
-#else
-extern unsigned char __res[sizeof(bd_t)];
-#endif
-
/*
* Perhaps we can put the pmac screen_info[] here
* on pmac as well so we don't need the ifdef's.
* Until we get multiple-console support in here
* that is. -- Cort
*/
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
struct screen_info screen_info = {
0, 25, /* orig-x, orig-y */
0, /* unused */
@@ -126,7 +126,7 @@ void __init pmac_find_display(void)
{
}
-#else /* CONFIG_8xx */
+#else /* CONFIG_4xx || CONFIG_8xx */
/* We need this to satisfy some external references until we can
* strip the kernel down.
@@ -142,7 +142,7 @@ struct screen_info screen_info = {
0, /* orig-video-isVGA */
16 /* orig-video-points */
};
-#endif /* CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
void machine_restart(char *cmd)
{
@@ -193,6 +193,7 @@ int get_cpuinfo(char *buffer)
unsigned long len = 0;
unsigned long bogosum = 0;
unsigned long i;
+ unsigned int pvr;
unsigned short maj, min;
#ifdef __SMP__
@@ -215,45 +216,75 @@ int get_cpuinfo(char *buffer)
len += sprintf(len+buffer,"processor\t: %lu\n",i);
len += sprintf(len+buffer,"cpu\t\t: ");
- switch (GET_PVR >> 16)
+ pvr = GET_PVR;
+
+ switch (PVR_VER(pvr))
{
- case 1:
+ case 0x0001:
len += sprintf(len+buffer, "601\n");
break;
- case 3:
+ case 0x0003:
len += sprintf(len+buffer, "603\n");
break;
- case 4:
+ case 0x0004:
len += sprintf(len+buffer, "604\n");
break;
- case 6:
+ case 0x0006:
len += sprintf(len+buffer, "603e\n");
break;
- case 7:
- len += sprintf(len+buffer, "603ev\n");
+ case 0x0007:
+ len += sprintf(len+buffer, "603");
+ if (((pvr >> 12) & 0xF) == 1) {
+ pvr ^= 0x00001000; /* revision fix-up */
+ len += sprintf(len+buffer, "r\n");
+ } else {
+ len += sprintf(len+buffer, "ev\n");
+ }
break;
- case 8:
- len += sprintf(len+buffer, "750\n");
+ case 0x0008: /* 740/750(P) */
+ case 0x1008:
+ len += sprintf(len+buffer, "750%s\n",
+ PVR_VER(pvr) == 0x1008 ? "P" : "");
len += sprintf(len+buffer, "temperature \t: %lu C\n",
cpu_temp());
break;
- case 9:
- len += sprintf(len+buffer, "604e\n");
+ case 0x0009: /* 604e/604r */
+ case 0x000A:
+ len += sprintf(len+buffer, "604");
+
+ if (PVR_VER(pvr) == 0x000A ||
+ ((pvr >> 12) & 0xF) != 0) {
+ pvr &= ~0x00003000; /* revision fix-up */
+ len += sprintf(len+buffer, "r\n");
+ } else {
+ len += sprintf(len+buffer, "e\n");
+ }
break;
- case 10:
- len += sprintf(len+buffer, "604ev5 (MachV)\n");
+ case 0x000C:
+ len += sprintf(len+buffer, "7400\n");
break;
- case 12:
- len += sprintf(len+buffer, "7400 (G4)\n");
+ case 0x0020:
+ len += sprintf(len+buffer, "403G");
+ switch ((pvr >> 8) & 0xFF) {
+ case 0x02:
+ len += sprintf(len+buffer, "C\n");
+ break;
+ case 0x14:
+ len += sprintf(len+buffer, "CX\n");
+ break;
+ }
break;
- case 50:
+ case 0x0050:
len += sprintf(len+buffer, "821\n");
- case 80:
- len += sprintf(len+buffer, "860\n");
+ break;
+ case 0x0081:
+ len += sprintf(len+buffer, "8240\n");
+ break;
+ case 0x4011:
+ len += sprintf(len+buffer, "405GP\n");
break;
default:
- len += sprintf(len+buffer, "unknown (%lx)\n",
- GET_PVR>>16);
+ len += sprintf(len+buffer, "unknown (%08x)\n", pvr);
break;
}
@@ -292,6 +323,22 @@ int get_cpuinfo(char *buffer)
len += ppc_md.setup_residual(buffer + len);
}
+ switch (PVR_VER(pvr))
+ {
+ case 0x0020:
+ maj = PVR_MAJ(pvr) + 1;
+ min = PVR_MIN(pvr);
+ break;
+ case 0x1008:
+ maj = ((pvr >> 8) & 0xFF) - 1;
+ min = pvr & 0xFF;
+ break;
+ default:
+ maj = (pvr >> 8) & 0xFF;
+ min = pvr & 0xFF;
+ break;
+ }
+
len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
@@ -362,11 +409,6 @@ unsigned long __init
identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
- int_control.int_sti = __no_use_sti;
- int_control.int_cli = __no_use_cli;
- int_control.int_save_flags = __no_use_save_flags;
- int_control.int_restore_flags = __no_use_restore_flags;
-
parse_bootinfo();
if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
@@ -674,25 +716,25 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->word72 = __le16_to_cpu(id->word72);
id->word73 = __le16_to_cpu(id->word73);
id->word74 = __le16_to_cpu(id->word74);
- id->word75 = __le16_to_cpu(id->word75);
+ id->queue_depth = __le16_to_cpu(id->queue_depth);
id->word76 = __le16_to_cpu(id->word76);
id->word77 = __le16_to_cpu(id->word77);
id->word78 = __le16_to_cpu(id->word78);
id->word79 = __le16_to_cpu(id->word79);
- id->word80 = __le16_to_cpu(id->word80);
- id->word81 = __le16_to_cpu(id->word81);
- id->command_sets = __le16_to_cpu(id->command_sets);
- id->word83 = __le16_to_cpu(id->word83);
- id->word84 = __le16_to_cpu(id->word84);
- id->word85 = __le16_to_cpu(id->word85);
- id->word86 = __le16_to_cpu(id->word86);
- id->word87 = __le16_to_cpu(id->word87);
+ id->major_rev_num = __le16_to_cpu(id->major_rev_num);
+ id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
+ id->command_set_1 = __le16_to_cpu(id->command_set_1);
+ id->command_set_2 = __le16_to_cpu(id->command_set_2);
+ id->cfsse = __le16_to_cpu(id->cfsse);
+ id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
+ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
+ id->csf_default = __le16_to_cpu(id->csf_default);
id->dma_ultra = __le16_to_cpu(id->dma_ultra);
id->word89 = __le16_to_cpu(id->word89);
id->word90 = __le16_to_cpu(id->word90);
- id->word91 = __le16_to_cpu(id->word91);
+ id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->word92 = __le16_to_cpu(id->word92);
- id->word93 = __le16_to_cpu(id->word93);
+ id->hw_config = __le16_to_cpu(id->hw_config);
id->word94 = __le16_to_cpu(id->word94);
id->word95 = __le16_to_cpu(id->word95);
id->word96 = __le16_to_cpu(id->word96);
@@ -727,7 +769,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
id->word125 = __le16_to_cpu(id->word125);
id->word126 = __le16_to_cpu(id->word126);
id->word127 = __le16_to_cpu(id->word127);
- id->security = __le16_to_cpu(id->security);
for (i=0; i<127; i++)
id->reserved[i] = __le16_to_cpu(id->reserved[i]);
}
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index c2891e21f..386764ddd 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -446,6 +446,8 @@ void __init smp_callin(void)
*/
if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
do_openpic_setup_cpu();
+ if ( _machine == _MACH_gemini )
+ gemini_init_l2();
while(!smp_commenced)
barrier();
__sti();
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index e21c30e14..b695da797 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -68,7 +68,7 @@ unsigned count_period_den; /* count_period_num / count_period_den us */
* with interrupts disabled.
* We set it up to overflow again in 1/HZ seconds.
*/
-void timer_interrupt(struct pt_regs * regs)
+int timer_interrupt(struct pt_regs * regs)
{
int dval, d;
unsigned long cpu = smp_processor_id();
@@ -141,6 +141,7 @@ void timer_interrupt(struct pt_regs * regs)
ppc_md.heartbeat();
hardirq_exit(cpu);
+ return 1; /* lets ret_from_int know we can do checks */
}
/*
diff --git a/arch/ppc/kernel/time.h b/arch/ppc/kernel/time.h
index a0a5c62d2..05d791546 100644
--- a/arch/ppc/kernel/time.h
+++ b/arch/ppc/kernel/time.h
@@ -6,8 +6,11 @@
* Paul Mackerras' version and mine for PReP and Pmac.
*/
+#include <linux/config.h>
#include <linux/mc146818rtc.h>
+#include <asm/processor.h>
+
/* time.c */
extern unsigned decrementer_count;
extern unsigned count_period_num;
@@ -22,13 +25,18 @@ int via_calibrate_decr(void);
/* Accessor functions for the decrementer register. */
static __inline__ unsigned int get_dec(void)
{
- unsigned int ret;
-
- asm volatile("mfspr %0,22" : "=r" (ret) :);
- return ret;
+#if defined(CONFIG_4xx)
+ return (mfspr(SPRN_PIT));
+#else
+ return (mfspr(SPRN_DEC));
+#endif
}
static __inline__ void set_dec(unsigned int val)
{
- asm volatile("mtspr 22,%0" : : "r" (val));
+#if defined(CONFIG_4xx)
+ mtspr(SPRN_PIT, val);
+#else
+ mtspr(SPRN_DEC, val);
+#endif
}
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 47fef50d4..04b4e2d36 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -194,7 +194,6 @@ void
ProgramCheckException(struct pt_regs *regs)
{
#if defined(CONFIG_4xx)
- unsigned int instr;
unsigned int esr = mfspr(SPRN_ESR);
if (esr & ESR_PTR) {
diff --git a/arch/ppc/mm/4xx_tlb.c b/arch/ppc/mm/4xx_tlb.c
new file mode 100644
index 000000000..b9d9d2119
--- /dev/null
+++ b/arch/ppc/mm/4xx_tlb.c
@@ -0,0 +1,397 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: 4xx_tlb.c
+ *
+ * Description:
+ * Routines for manipulating the TLB on PowerPC 400-class processors.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+
+/* Preprocessor Defines */
+
+#if !defined(TRUE) || TRUE != 1
+#define TRUE 1
+#endif
+
+#if !defined(FALSE) || FALSE != 0
+#define FALSE 0
+#endif
+
+
+/* Function Macros */
+
+
+/* Type Definitios */
+
+typedef struct pin_entry_s {
+ unsigned int e_pinned: 1, /* This TLB entry is pinned down. */
+ e_used: 23; /* Number of users for this mapping. */
+} pin_entry_t;
+
+
+/* Global Variables */
+
+static pin_entry_t pin_table[PPC4XX_TLB_SIZE];
+
+
+/* Function Prototypes */
+
+
+void
+PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache)
+{
+ int i, found = FALSE;
+ unsigned long tag, data;
+ unsigned long opid;
+
+ opid = mfspr(SPRN_PID);
+ mtspr(SPRN_PID, 0);
+
+ data = (pa & TLB_RPN_MASK) | TLB_WR;
+
+ if (cache)
+ data |= (TLB_EX | TLB_I);
+ else
+ data |= (TLB_G | TLB_I);
+
+ tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz;
+
+ for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
+ if (pin_table[i].e_pinned == FALSE) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found) {
+ /* printk("Pinning %#x -> %#x in entry %d...\n", va, pa, i); */
+ asm("tlbwe %0,%1,1" : : "r" (data), "r" (i));
+ asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
+ asm("isync");
+ pin_table[i].e_pinned = found;
+ }
+
+ mtspr(SPRN_PID, opid);
+ return;
+}
+
+void
+PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size)
+{
+ /* XXX - To beimplemented. */
+}
+
+void
+PPC4xx_tlb_flush_all(void)
+{
+ int i;
+ unsigned long flags, opid;
+
+ save_flags(flags);
+ cli();
+
+ opid = mfspr(SPRN_PID);
+ mtspr(SPRN_PID, 0);
+
+ for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
+ unsigned long ov = 0;
+
+ if (pin_table[i].e_pinned)
+ continue;
+
+ asm("tlbwe %0,%1,0" : : "r" (ov), "r" (i));
+ asm("tlbwe %0,%1,1" : : "r" (ov), "r" (i));
+ }
+
+ asm("sync;isync");
+
+ mtspr(SPRN_PID, opid);
+ restore_flags(flags);
+}
+
+void
+PPC4xx_tlb_flush(unsigned long va, int pid)
+{
+ unsigned long i, tag, flags, found = 1, opid;
+
+ save_flags(flags);
+ cli();
+
+ opid = mfspr(SPRN_PID);
+ mtspr(SPRN_PID, pid);
+
+ asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (i), "=r" (found) : "r" (va));
+
+ if (found && pin_table[i].e_pinned == 0) {
+ asm("tlbre %0,%1,0" : "=r" (tag) : "r" (i));
+ tag &= ~ TLB_VALID;
+ asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
+ }
+
+ mtspr(SPRN_PID, opid);
+
+ restore_flags(flags);
+}
+
+#if 0
+/*
+ * TLB miss handling code.
+ */
+
+/*
+ * Handle TLB faults. We should push this back to assembly code eventually.
+ * Caller is responsible for turning off interrupts ...
+ */
+static inline void
+tlbDropin(unsigned long tlbhi, unsigned long tlblo) {
+ /*
+ * Avoid the divide at the slight cost of a little too
+ * much emphasis on the last few entries.
+ */
+ unsigned long rand = mfspr(SPRN_TBLO);
+ rand &= 0x3f;
+ rand += NTLB_WIRED;
+ if (rand >= NTLB)
+ rand -= NTLB_WIRED;
+
+ asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (rand));
+ asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (rand));
+ asm("isync;sync");
+}
+
+static inline void
+mkTlbEntry(unsigned long addr, pte_t *pte) {
+ unsigned long tlbhi;
+ unsigned long tlblo;
+ int found = 1;
+ int idx;
+
+ /*
+ * Construct the TLB entry.
+ */
+ tlbhi = addr & ~(PAGE_SIZE-1);
+ tlblo = virt_to_phys(pte_page(*pte)) & TLBLO_RPN;
+ if (pte_val(*pte) & _PAGE_HWWRITE)
+ tlblo |= TLBLO_WR;
+ if (pte_val(*pte) & _PAGE_NO_CACHE)
+ tlblo |= TLBLO_I;
+ tlblo |= TLBLO_EX;
+ if (addr < KERNELBASE)
+ tlblo |= TLBLO_Z_USER;
+ tlbhi |= TLBHI_PGSZ_4K;
+ tlbhi |= TLBHI_VALID;
+
+ /*
+ * See if a match already exists in the TLB.
+ */
+ asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (idx), "=r" (found) : "r" (tlbhi));
+ if (found) {
+ /*
+ * Found an existing entry. Just reuse the index.
+ */
+ asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (idx));
+ asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (idx));
+ }
+ else {
+ /*
+ * Do the more expensive operation
+ */
+ tlbDropin(tlbhi, tlblo);
+ }
+}
+
+/*
+ * Mainline of the TLB miss handler. The above inline routines should fold into
+ * this one, eliminating most function call overhead.
+ */
+#ifdef TLBMISS_DEBUG
+volatile unsigned long miss_start;
+volatile unsigned long miss_end;
+#endif
+
+static inline int tlbMiss(struct pt_regs *regs, unsigned long badaddr, int wasWrite)
+{
+ int spid, ospid;
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (!user_mode(regs) && (badaddr >= KERNELBASE)) {
+ mm = task[0]->mm;
+ spid = 0;
+#ifdef TLBMISS_DEBUG
+ miss_start = 0;
+#endif
+ }
+ else {
+ mm = current->mm;
+ spid = mfspr(SPRN_PID);
+#ifdef TLBMISS_DEBUG
+ miss_start = 1;
+#endif
+ }
+#ifdef TLBMISS_DEBUG
+ store_cache_range((unsigned long)&miss_start, sizeof(miss_start));
+#endif
+
+ pgd = pgd_offset(mm, badaddr);
+ if (pgd_none(*pgd))
+ goto NOGOOD;
+
+ pmd = pmd_offset(pgd, badaddr);
+ if (pmd_none(*pmd))
+ goto NOGOOD;
+
+ pte = pte_offset(pmd, badaddr);
+ if (pte_none(*pte))
+ goto NOGOOD;
+ if (!pte_present(*pte))
+ goto NOGOOD;
+#if 1
+ prohibit_if_guarded(badaddr, sizeof(int));
+#endif
+ if (wasWrite) {
+ if (!pte_write(*pte)) {
+ goto NOGOOD;
+ }
+ set_pte(pte, pte_mkdirty(*pte));
+ }
+ set_pte(pte, pte_mkyoung(*pte));
+
+ ospid = mfspr(SPRN_PID);
+ mtspr(SPRN_PID, spid);
+ mkTlbEntry(badaddr, pte);
+ mtspr(SPRN_PID, ospid);
+
+#ifdef TLBMISS_DEBUG
+ miss_end = 0;
+ store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
+#endif
+ return 0;
+
+NOGOOD:
+#ifdef TLBMISS_DEBUG
+ miss_end = 1;
+ store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
+#endif
+ return 1;
+}
+
+/*
+ * End TLB miss handling code.
+ */
+/* ---------- */
+
+/*
+ * Used to flush the TLB if the page fault handler decides to change
+ * something.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) {
+ int spid;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (addr >= KERNELBASE)
+ spid = 0;
+ else
+ spid = vma->vm_mm->context;
+ tlbFlush1(addr, spid);
+
+ restore_flags(flags);
+}
+
+/*
+ * Given a virtual address in the current address space, make
+ * sure the associated physical page is present in memory,
+ * and if the data is to be modified, that any copy-on-write
+ * actions have taken place.
+ */
+unsigned long make_page_present(unsigned long p, int rw) {
+ pte_t *pte;
+ char c;
+
+ get_user(c, (char *) p);
+
+ pte = findPTE(current->mm, p);
+ if (pte_none(*pte) || !pte_present(*pte))
+ debug("make_page_present didn't load page", 0);
+
+ if (rw) {
+ /*
+ * You have to write-touch the page, so that
+ * zero-filled pages are forced to be copied
+ * rather than still pointing at the zero
+ * page.
+ */
+ extern void tlbFlush1(unsigned long, int);
+ tlbFlush1(p, get_context());
+ put_user(c, (char *) p);
+ if (!pte_write(*pte))
+ debug("make_page_present didn't make page writable", 0);
+
+ tlbFlush1(p, get_context());
+ }
+ return pte_page(*pte);
+}
+
+void DataTLBMissException(struct pt_regs *regs)
+{
+ unsigned long badaddr = mfspr(SPRN_DEAR);
+ int wasWrite = mfspr(SPRN_ESR) & 0x800000;
+ if (tlbMiss(regs, badaddr, wasWrite)) {
+ sti();
+ do_page_fault(regs, badaddr, wasWrite);
+ cli();
+ }
+}
+
+void InstructionTLBMissException(struct pt_regs *regs)
+{
+ if (!current) {
+ debug("ITLB Miss with no current task", regs);
+ sti();
+ bad_page_fault(regs, regs->nip);
+ cli();
+ return;
+ }
+ if (tlbMiss(regs, regs->nip, 0)) {
+ sti();
+ do_page_fault(regs, regs->nip, 0);
+ cli();
+ }
+}
+
+void DataPageFault(struct pt_regs *regs)
+{
+ unsigned long badaddr = mfspr(SPRN_DEAR);
+ int wasWrite = mfspr(SPRN_ESR) & 0x800000;
+ sti();
+ do_page_fault(regs, badaddr, wasWrite);
+ cli();
+}
+
+void InstructionPageFault(struct pt_regs *regs)
+{
+ if (!current) {
+ debug("ITLB fault with no current task", regs);
+ sti();
+ bad_page_fault(regs, regs->nip);
+ cli();
+ return;
+ }
+ sti();
+ do_page_fault(regs, regs->nip, 0);
+ cli();
+}
+#endif
diff --git a/arch/ppc/mm/4xx_tlb.h b/arch/ppc/mm/4xx_tlb.h
new file mode 100644
index 000000000..03fef109f
--- /dev/null
+++ b/arch/ppc/mm/4xx_tlb.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ * Module name: 4xx_tlb.h
+ *
+ * Description:
+ * Routines for manipulating the TLB on PowerPC 400-class processors.
+ *
+ */
+
+#ifndef __4XX_TLB_H__
+#define __4XX_TLB_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Function Prototypes */
+
+extern void PPC4xx_tlb_pin(unsigned long va, unsigned long pa,
+ int pagesz, int cache);
+extern void PPC4xx_tlb_unpin(unsigned long va, unsigned long pa,
+ int size);
+extern void PPC4xx_tlb_flush_all(void);
+extern void PPC4xx_tlb_flush(unsigned long va, int pid);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __4XX_TLB_H__ */
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 34117098e..c558ef051 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -59,6 +59,10 @@
#include "mem_pieces.h"
+#if defined(CONFIG_4xx)
+#include "4xx_tlb.h"
+#endif
+
#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10)
int prom_trashed;
@@ -97,6 +101,9 @@ extern unsigned long *find_end_of_memory(void);
#ifdef CONFIG_8xx
unsigned long *m8xx_find_end_of_memory(void);
#endif /* CONFIG_8xx */
+#ifdef CONFIG_4xx
+unsigned long *oak_find_end_of_memory(void);
+#endif
static void mapin_ram(void);
void map_page(unsigned long va, unsigned long pa, int flags);
extern void die_if_kernel(char *,struct pt_regs *,long);
@@ -339,9 +346,7 @@ void si_meminfo(struct sysinfo *val)
continue;
val->sharedram += atomic_read(&mem_map[i].count) - 1;
}
- val->totalram <<= PAGE_SHIFT;
- val->sharedram <<= PAGE_SHIFT;
- return;
+ val->mem_unit = PAGE_SIZE;
}
void *
@@ -682,7 +687,7 @@ static void __init mapin_ram(void)
int i;
unsigned long v, p, s, f;
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
if (!__map_without_bats) {
unsigned long tot, mem_base, bl, done;
unsigned long max_size = (256<<20);
@@ -717,7 +722,7 @@ static void __init mapin_ram(void)
RAM_PAGE);
}
}
-#endif /* CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
for (i = 0; i < phys_mem.n_regions; ++i) {
v = (ulong)__va(phys_mem.regions[i].address);
@@ -846,6 +851,31 @@ void free_initrd_mem(unsigned long start, unsigned long end)
* still be merged.
* -- Cort
*/
+#if defined(CONFIG_4xx)
+void __init
+MMU_init(void)
+{
+ PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1);
+ PPC4xx_tlb_pin(OAKNET_IO_BASE, OAKNET_IO_BASE, TLB_PAGESZ(PAGESZ_4K), 0);
+ end_of_DRAM = oak_find_end_of_memory();
+
+ /* Map in all of RAM starting at KERNELBASE */
+
+ mapin_ram();
+
+ /* Zone 0 - kernel (above 0x80000000), zone 1 - user */
+
+ mtspr(SPRN_ZPR, 0x2aaaaaaa);
+ mtspr(SPRN_DCWR, 0x00000000); /* all caching is write-back */
+
+ /* Cache 128MB of space starting at KERNELBASE. */
+
+ mtspr(SPRN_DCCR, 0x00000000);
+ /* flush_instruction_cache(); XXX */
+ mtspr(SPRN_ICCR, 0x00000000);
+
+}
+#else
void __init MMU_init(void)
{
if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
@@ -947,6 +977,7 @@ void __init MMU_init(void)
#endif /* CONFIG_8xx */
if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
}
+#endif /* CONFIG_4xx */
/*
* Initialize the bootmem system and give it all the memory we
@@ -1037,29 +1068,21 @@ unsigned long __init find_available_memory(void)
*/
void __init paging_init(void)
{
+ unsigned int zones_size[MAX_NR_ZONES], i;
+
/*
* Grab some memory for bad_page and bad_pagetable to use.
*/
empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
- {
- unsigned int zones_size[MAX_NR_ZONES], i;
- /*
- * All pages are DMA-able so this is wrong - the zone code is
- * assuming both regions have a value so this is necessary for
- * now.
- * -- Cort
- */
-#if 1
- for ( i = 1; i < MAX_NR_ZONES; i++ )
- zones_size[i] = 1<<MAX_ORDER;
- zones_size[0] = (virt_to_phys(end_of_DRAM) >> PAGE_SHIFT) -
- ((MAX_NR_ZONES-1)*(1<<MAX_ORDER));
-#else
- zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT;
-#endif
- free_area_init(zones_size);
- }
+
+ /*
+ * All pages are DMA-able so we put them all in the DMA zone.
+ */
+ zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT;
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+ free_area_init(zones_size);
}
void __init mem_init(void)
@@ -1404,7 +1427,7 @@ static void __init hash_init(void)
}
if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
}
-#else /* CONFIG_8xx */
+#elif defined(CONFIG_8xx)
/*
* This is a big hack right now, but it may turn into something real
* someday.
@@ -1432,4 +1455,29 @@ unsigned long __init *m8xx_find_end_of_memory(void)
set_phys_avail(&phys_mem);
return ret;
}
-#endif /* ndef CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
+
+#ifdef CONFIG_OAK
+/*
+ * Return the virtual address representing the top of physical RAM
+ * on the Oak board.
+ */
+unsigned long __init *
+oak_find_end_of_memory(void)
+{
+ extern unsigned char __res[];
+
+ unsigned long *ret;
+ bd_t *bip = (bd_t *)__res;
+
+ phys_mem.regions[0].address = 0;
+ phys_mem.regions[0].size = bip->bi_memsize;
+ phys_mem.n_regions = 1;
+
+ ret = __va(phys_mem.regions[0].address +
+ phys_mem.regions[0].size);
+
+ set_phys_avail(&phys_mem);
+ return (ret);
+}
+#endif
diff --git a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c
index 138b2a40f..e695d5a0a 100644
--- a/arch/ppc/mm/mem_pieces.c
+++ b/arch/ppc/mm/mem_pieces.c
@@ -209,8 +209,6 @@ set_phys_avail(struct mem_pieces *mp)
kstart = __pa(_stext); /* should be 0 */
ksize = PAGE_ALIGN(klimit - _stext);
- printk("kstart = 0x%08lx, ksize = 0x%08lx\n", kstart, ksize);
-
mem_pieces_remove(&phys_avail, kstart, ksize, 0);
mem_pieces_remove(&phys_avail, 0, 0x4000, 0);
diff --git a/arch/ppc/treeboot/Makefile b/arch/ppc/treeboot/Makefile
index 405634214..f84810e1e 100644
--- a/arch/ppc/treeboot/Makefile
+++ b/arch/ppc/treeboot/Makefile
@@ -21,9 +21,9 @@ MKEVIMG = mkevimg -l
MKIRIMG = mkirimg
CFLAGS = -O -fno-builtin -I$(TOPDIR)/include
-LD_ARGS = -e _start -T ld.script -Ttext 80200000 -Bstatic
+LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic
-OBJS = crt0.o main.o misc.o string.o zlib.o irSect.o
+OBJS = crt0.o main.o misc.o irSect.o ../coffboot/string.o ../coffboot/zlib.o
LIBS =
treeboot: $(OBJS) ld.script
diff --git a/arch/ppc/treeboot/crt0.S b/arch/ppc/treeboot/crt0.S
index 1f2c1c094..e54ac2331 100644
--- a/arch/ppc/treeboot/crt0.S
+++ b/arch/ppc/treeboot/crt0.S
@@ -20,7 +20,7 @@
*
*/
-#include "../kernel/ppc_asm.h"
+#include "../kernel/ppc_asm.tmpl"
.text
diff --git a/arch/ppc/treeboot/main.c b/arch/ppc/treeboot/main.c
index 1b5ef3805..277b77047 100644
--- a/arch/ppc/treeboot/main.c
+++ b/arch/ppc/treeboot/main.c
@@ -24,13 +24,22 @@
*
*/
-#include "nonstdio.h"
-#include "zlib.h"
+#include <asm/board.h>
+
+#include "../coffboot/nonstdio.h"
+#include "../coffboot/zlib.h"
#include "irSect.h"
/* Preprocessor Defines */
+/*
+ * Location of the IBM boot ROM function pointer address for retrieving
+ * the board information structure.
+ */
+
+#define BOARD_INFO_VECTOR 0xFFFE0B50
+
#define RAM_SIZE (4 * 1024 * 1024)
#define RAM_PBASE 0x00000000
@@ -58,6 +67,17 @@
char *avail_ram; /* Indicates start of RAM available for heap */
char *end_avail; /* Indicates end of RAM available for heap */
+bd_t board_info;
+
+/*
+ * XXX - Until either the IBM boot ROM provides a way of passing arguments to
+ * the program it launches or until I/O is working in the boot loader,
+ * this is a good spot to pass in command line arguments to the kernel
+ * (e.g. console=tty0).
+ */
+
+static char *cmdline = "";
+
/* Function Prototypes */
@@ -75,10 +95,16 @@ void start(void)
{
void *options;
int ns, oh, i;
- unsigned sa, len;
+ unsigned long sa, len;
void *dst;
unsigned char *im;
- unsigned initrd_start, initrd_size;
+ unsigned long initrd_start, initrd_size;
+ bd_t *(*get_board_info)(void) =
+ (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+ bd_t *bip = NULL;
+
+ if ((bip = get_board_info()) != NULL)
+ memcpy(&board_info, bip, sizeof(bd_t));
/* setup_bats(RAM_START); */
@@ -96,6 +122,7 @@ void start(void)
end_avail = (char *)initrd_start;
} else {
+ initrd_start = initrd_size = 0;
end_avail = (char *)RAM_END;
}
@@ -117,16 +144,20 @@ void start(void)
/* I'm not sure what the 0x200000 parameter is for, but it works. */
- gunzip(dst, 0x200000, cp, &len);
+ gunzip(dst, 0x200000, cp, (int *)&len);
} else {
memmove(dst, im, len);
}
- /* flush_cache(dst, len); */
+ flush_cache(dst, len);
sa = (unsigned long)dst;
- (*(void (*)())sa)();
+ (*(void (*)())sa)(&board_info,
+ initrd_start,
+ initrd_start + initrd_size,
+ cmdline,
+ cmdline + strlen(cmdline));
pause();
}
diff --git a/arch/ppc/treeboot/misc.S b/arch/ppc/treeboot/misc.S
index 27417563f..c51844329 100644
--- a/arch/ppc/treeboot/misc.S
+++ b/arch/ppc/treeboot/misc.S
@@ -6,6 +6,9 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+
+#include "../kernel/ppc_asm.tmpl"
+
.text
/*
@@ -15,14 +18,23 @@
*/
.global flush_cache
flush_cache:
- addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */
- rlwinm. 4,4,27,5,31
- mtctr 4
- beqlr
-1: dcbf 0,3
- icbi 0,3
- addi 3,3,0x20
- bdnz 1b
+ mfpvr r5 # Get processor version register
+ extrwi r5,r5,16,0 # Get the version bits
+ cmpwi cr0,r5,0x0020 # Is this a 403-based processor?
+ beq 1f # Yes, it is
+ li r5,32 # It is not a 403, set to 32 bytes
+ addi r4,r4,32-1 # len += line_size - 1
+ srwi. r4,r4,5 # Convert from bytes to lines
+ b 2f
+1: li r5,16 # It is a 403, set to 16 bytes
+ addi r4,r4,16-1 # len += line_size - 1
+ srwi. r4,r4,4 # Convert from bytes to lines
+2: mtctr r4 # Set-up the counter register
+ beqlr # If it is 0, we are done
+3: dcbf r0,r3 # Flush and invalidate the data line
+ icbi r0,r3 # Invalidate the instruction line
+ add r3,r3,r5 # Move to the next line
+ bdnz 3b # Are we done yet?
sync
isync
- blr
+ blr # Return to the caller
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index 9fc97b5a9..426f80ff3 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -102,9 +102,11 @@ xmon_write(void *handle, void *ptr, int nb)
if (!scc_initialized)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
+#ifdef CONFIG_ADB
while ((*sccc & TXRDY) == 0)
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
+#endif /* CONFIG_ADB */
buf_access();
if ( console && (*p != '\r'))
printk("%c", *p);
@@ -195,9 +197,11 @@ xmon_read(void *handle, void *ptr, int nb)
if (!scc_initialized)
xmon_init_scc();
for (i = 0; i < nb; ++i) {
+#ifdef CONFIG_ADB
while ((*sccc & RXRDY) == 0)
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
+#endif /* CONFIG_ADB */
buf_access();
#if 0
if ( 0/*console*/ )
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index f5a42cc29..1c6a812d2 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -469,7 +469,7 @@ backtrace(struct pt_regs *excp)
unsigned sp;
unsigned stack[2];
struct pt_regs regs;
- extern char ret_from_int, ret_from_syscall_1, ret_from_syscall_2;
+ extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
extern char ret_from_except;
@@ -483,7 +483,7 @@ backtrace(struct pt_regs *excp)
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
break;
printf("%x ", stack[1]);
- if (stack[1] == (unsigned) &ret_from_int
+ if (stack[1] == (unsigned) &ret_from_intercept
|| stack[1] == (unsigned) &ret_from_except
|| stack[1] == (unsigned) &ret_from_syscall_1
|| stack[1] == (unsigned) &ret_from_syscall_2