diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
commit | 95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch) | |
tree | 27a92a942821cde1edda9a1b088718d436b3efe4 /arch/ppc | |
parent | 45b27b0a0652331d104c953a5b192d843fff88f8 (diff) |
Merge with Linux 2.3.40.
Diffstat (limited to 'arch/ppc')
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 |