diff options
52 files changed, 2367 insertions, 10487 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 513f3b6c35b9..ce3c8f52c919 100644 --- a/MAINTAINERS +++ b/MAINTAINERS  | |||
| @@ -2965,6 +2965,12 @@ M: dm@sangoma.com | |||
| 2965 | W: http://www.sangoma.com | 2965 | W: http://www.sangoma.com | 
| 2966 | S: Supported | 2966 | S: Supported | 
| 2967 | 2967 | ||
| 2968 | WATCHDOG DEVICE DRIVERS | ||
| 2969 | P: Wim Van Sebroeck | ||
| 2970 | M: wim@iguana.be | ||
| 2971 | T: git kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git | ||
| 2972 | S: Maintained | ||
| 2973 | |||
| 2968 | WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS | 2974 | WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS | 
| 2969 | P: Jean Tourrilhes | 2975 | P: Jean Tourrilhes | 
| 2970 | M: jt@hpl.hp.com | 2976 | M: jt@hpl.hp.com | 
| @@ -151,7 +151,7 @@ export srctree objtree VPATH TOPDIR | |||
| 151 | SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | 151 | SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | 
| 152 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 152 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 
| 153 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 153 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 
| 154 | -e s/ppc64/powerpc/ ) | 154 | -e s/ppc.*/powerpc/ ) | 
| 155 | 155 | ||
| 156 | # Cross compiling and selecting different set of gcc/bin-utils | 156 | # Cross compiling and selecting different set of gcc/bin-utils | 
| 157 | # --------------------------------------------------------------------------- | 157 | # --------------------------------------------------------------------------- | 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 01feed0e2a15..df338c5cc910 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig  | |||
| @@ -78,17 +78,6 @@ config PPC_UDBG_16550 | |||
| 78 | bool | 78 | bool | 
| 79 | default n | 79 | default n | 
| 80 | 80 | ||
| 81 | config CRASH_DUMP | ||
| 82 | bool "kernel crash dumps (EXPERIMENTAL)" | ||
| 83 | depends on PPC_MULTIPLATFORM | ||
| 84 | depends on EXPERIMENTAL | ||
| 85 | help | ||
| 86 | Build a kernel suitable for use as a kdump capture kernel. | ||
| 87 | The kernel will be linked at a different address than normal, and | ||
| 88 | so can only be used for Kdump. | ||
| 89 | |||
| 90 | Don't change this unless you know what you are doing. | ||
| 91 | |||
| 92 | config GENERIC_TBSYNC | 81 | config GENERIC_TBSYNC | 
| 93 | bool | 82 | bool | 
| 94 | default y if PPC32 && SMP | 83 | default y if PPC32 && SMP | 
| @@ -584,6 +573,16 @@ config KEXEC | |||
| 584 | support. As of this writing the exact hardware interface is | 573 | support. As of this writing the exact hardware interface is | 
| 585 | strongly in flux, so no good recommendation can be made. | 574 | strongly in flux, so no good recommendation can be made. | 
| 586 | 575 | ||
| 576 | config CRASH_DUMP | ||
| 577 | bool "kernel crash dumps (EXPERIMENTAL)" | ||
| 578 | depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL | ||
| 579 | help | ||
| 580 | Build a kernel suitable for use as a kdump capture kernel. | ||
| 581 | The kernel will be linked at a different address than normal, and | ||
| 582 | so can only be used for Kdump. | ||
| 583 | |||
| 584 | Don't change this unless you know what you are doing. | ||
| 585 | |||
| 587 | config EMBEDDEDBOOT | 586 | config EMBEDDEDBOOT | 
| 588 | bool | 587 | bool | 
| 589 | depends on 8xx || 8260 | 588 | depends on 8xx || 8260 | 
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 788dec4c7ef3..840ae595a617 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile  | |||
| @@ -27,6 +27,7 @@ BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \ | |||
| 27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 
| 28 | OBJCOPYFLAGS := contents,alloc,load,readonly,data | 28 | OBJCOPYFLAGS := contents,alloc,load,readonly,data | 
| 29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 | 29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 | 
| 30 | OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment | ||
| 30 | 31 | ||
| 31 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 32 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 
| 32 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h | 33 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h | 
| @@ -90,11 +91,11 @@ gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) | |||
| 90 | hostprogs-y := addnote addRamDisk hack-coff | 91 | hostprogs-y := addnote addRamDisk hack-coff | 
| 91 | 92 | ||
| 92 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ | 93 | targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \ | 
| 93 | zImage.coff zImage.initrd.coff \ | 94 | zImage.coff zImage.initrd.coff miboot.image miboot.initrd.image \ | 
| 94 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ | 95 | $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ | 
| 95 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ | 96 | $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ | 
| 96 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | 97 | $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ | 
| 97 | vmlinux.initrd | 98 | vmlinux.initrd dummy.o | 
| 98 | extra-y := initrd.o | 99 | extra-y := initrd.o | 
| 99 | 100 | ||
| 100 | quiet_cmd_ramdisk = RAMDISK $@ | 101 | quiet_cmd_ramdisk = RAMDISK $@ | 
| @@ -116,6 +117,10 @@ quiet_cmd_addsection = ADDSEC $@ | |||
| 116 | quiet_cmd_addnote = ADDNOTE $@ | 117 | quiet_cmd_addnote = ADDNOTE $@ | 
| 117 | cmd_addnote = $(obj)/addnote $@ | 118 | cmd_addnote = $(obj)/addnote $@ | 
| 118 | 119 | ||
| 120 | quiet_cmd_gen-miboot = GEN $@ | ||
| 121 | cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_MIB_ARGS) \ | ||
| 122 | --add-section=$1=$(word 2, $^) $< $@ | ||
| 123 | |||
| 119 | quiet_cmd_gencoff = COFF $@ | 124 | quiet_cmd_gencoff = COFF $@ | 
| 120 | cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ | 125 | cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \ | 
| 121 | $(obj)/hack-coff $@ | 126 | $(obj)/hack-coff $@ | 
| @@ -141,19 +146,25 @@ $(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec | |||
| 141 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 146 | $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds | 
| 142 | $(call cmd,bootld,$(obj-boot),zImage.lds) | 147 | $(call cmd,bootld,$(obj-boot),zImage.lds) | 
| 143 | 148 | ||
| 144 | # For 32-bit powermacs, build the COFF images as well as the ELF images. | 149 | # For 32-bit powermacs, build the COFF and miboot images | 
| 150 | # as well as the ELF images. | ||
| 145 | coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff | 151 | coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff | 
| 146 | coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff | 152 | coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff | 
| 153 | mibootimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.image | ||
| 154 | mibrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.initrd.image | ||
| 147 | 155 | ||
| 148 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) | 156 | $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) \ | 
| 157 | $(mibootimg-y-y) | ||
| 149 | @cp -f $< $@ | 158 | @cp -f $< $@ | 
| 150 | $(call if_changed,addnote) | 159 | $(call if_changed,addnote) | 
| 151 | 160 | ||
| 152 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y) | 161 | $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote \ | 
| 162 | $(coffrdimg-y-y) $(mibrdimg-y-y) | ||
| 153 | @cp -f $< $@ | 163 | @cp -f $< $@ | 
| 154 | $(call if_changed,addnote) | 164 | $(call if_changed,addnote) | 
| 155 | 165 | ||
| 156 | $(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | 166 | $(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) \ | 
| 167 | $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff | ||
| 157 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | 168 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | 
| 158 | $(call cmd,gencoff) | 169 | $(call cmd,gencoff) | 
| 159 | 170 | ||
| @@ -162,6 +173,12 @@ $(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \ | |||
| 162 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | 173 | $(call cmd,bootld,$(obj-boot),zImage.coff.lds) | 
| 163 | $(call cmd,gencoff) | 174 | $(call cmd,gencoff) | 
| 164 | 175 | ||
| 176 | $(obj)/miboot.image: $(obj)/dummy.o $(obj)/vmlinux.gz | ||
| 177 | $(call cmd,gen-miboot,image) | ||
| 178 | |||
| 179 | $(obj)/miboot.initrd.image: $(obj)/miboot.image $(images)/ramdisk.image.gz | ||
| 180 | $(call cmd,gen-miboot,initrd) | ||
| 181 | |||
| 165 | #----------------------------------------------------------- | 182 | #----------------------------------------------------------- | 
| 166 | # build u-boot images | 183 | # build u-boot images | 
| 167 | #----------------------------------------------------------- | 184 | #----------------------------------------------------------- | 
diff --git a/arch/powerpc/boot/dummy.c b/arch/powerpc/boot/dummy.c new file mode 100644 index 000000000000..31dbf45bf99c --- /dev/null +++ b/arch/powerpc/boot/dummy.c  | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | int main(void) | ||
| 2 | { | ||
| 3 | return 0; | ||
| 4 | } | ||
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 398203bd98eb..2ace57d1e333 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig  | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | # | 1 | # | 
| 2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit | 
| 3 | # Linux kernel version: 2.6.15-rc5 | 3 | # Linux kernel version: 2.6.15 | 
| 4 | # Tue Dec 13 17:24:05 2005 | 4 | # Sat Jan 14 16:26:08 2006 | 
| 5 | # | 5 | # | 
| 6 | # CONFIG_PPC64 is not set | 6 | # CONFIG_PPC64 is not set | 
| 7 | CONFIG_PPC32=y | 7 | CONFIG_PPC32=y | 
| @@ -15,11 +15,15 @@ CONFIG_EARLY_PRINTK=y | |||
| 15 | CONFIG_GENERIC_NVRAM=y | 15 | CONFIG_GENERIC_NVRAM=y | 
| 16 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 16 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 
| 17 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 17 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 
| 18 | CONFIG_PPC_OF=y | ||
| 19 | # CONFIG_PPC_UDBG_16550 is not set | ||
| 20 | # CONFIG_CRASH_DUMP is not set | ||
| 21 | # CONFIG_GENERIC_TBSYNC is not set | ||
| 18 | 22 | ||
| 19 | # | 23 | # | 
| 20 | # Processor support | 24 | # Processor support | 
| 21 | # | 25 | # | 
| 22 | CONFIG_6xx=y | 26 | CONFIG_CLASSIC32=y | 
| 23 | # CONFIG_PPC_52xx is not set | 27 | # CONFIG_PPC_52xx is not set | 
| 24 | # CONFIG_PPC_82xx is not set | 28 | # CONFIG_PPC_82xx is not set | 
| 25 | # CONFIG_PPC_83xx is not set | 29 | # CONFIG_PPC_83xx is not set | 
| @@ -28,6 +32,7 @@ CONFIG_6xx=y | |||
| 28 | # CONFIG_8xx is not set | 32 | # CONFIG_8xx is not set | 
| 29 | # CONFIG_E200 is not set | 33 | # CONFIG_E200 is not set | 
| 30 | # CONFIG_E500 is not set | 34 | # CONFIG_E500 is not set | 
| 35 | CONFIG_6xx=y | ||
| 31 | CONFIG_PPC_FPU=y | 36 | CONFIG_PPC_FPU=y | 
| 32 | CONFIG_ALTIVEC=y | 37 | CONFIG_ALTIVEC=y | 
| 33 | CONFIG_PPC_STD_MMU=y | 38 | CONFIG_PPC_STD_MMU=y | 
| @@ -53,17 +58,18 @@ CONFIG_POSIX_MQUEUE=y | |||
| 53 | # CONFIG_BSD_PROCESS_ACCT is not set | 58 | # CONFIG_BSD_PROCESS_ACCT is not set | 
| 54 | CONFIG_SYSCTL=y | 59 | CONFIG_SYSCTL=y | 
| 55 | # CONFIG_AUDIT is not set | 60 | # CONFIG_AUDIT is not set | 
| 56 | CONFIG_HOTPLUG=y | ||
| 57 | CONFIG_KOBJECT_UEVENT=y | ||
| 58 | CONFIG_IKCONFIG=y | 61 | CONFIG_IKCONFIG=y | 
| 59 | CONFIG_IKCONFIG_PROC=y | 62 | CONFIG_IKCONFIG_PROC=y | 
| 60 | CONFIG_INITRAMFS_SOURCE="" | 63 | CONFIG_INITRAMFS_SOURCE="" | 
| 64 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
| 61 | # CONFIG_EMBEDDED is not set | 65 | # CONFIG_EMBEDDED is not set | 
| 62 | CONFIG_KALLSYMS=y | 66 | CONFIG_KALLSYMS=y | 
| 63 | # CONFIG_KALLSYMS_ALL is not set | 67 | # CONFIG_KALLSYMS_ALL is not set | 
| 64 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 68 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 
| 69 | CONFIG_HOTPLUG=y | ||
| 65 | CONFIG_PRINTK=y | 70 | CONFIG_PRINTK=y | 
| 66 | CONFIG_BUG=y | 71 | CONFIG_BUG=y | 
| 72 | CONFIG_ELF_CORE=y | ||
| 67 | CONFIG_BASE_FULL=y | 73 | CONFIG_BASE_FULL=y | 
| 68 | CONFIG_FUTEX=y | 74 | CONFIG_FUTEX=y | 
| 69 | CONFIG_EPOLL=y | 75 | CONFIG_EPOLL=y | 
| @@ -72,8 +78,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 | |||
| 72 | CONFIG_CC_ALIGN_LABELS=0 | 78 | CONFIG_CC_ALIGN_LABELS=0 | 
| 73 | CONFIG_CC_ALIGN_LOOPS=0 | 79 | CONFIG_CC_ALIGN_LOOPS=0 | 
| 74 | CONFIG_CC_ALIGN_JUMPS=0 | 80 | CONFIG_CC_ALIGN_JUMPS=0 | 
| 81 | CONFIG_SLAB=y | ||
| 75 | # CONFIG_TINY_SHMEM is not set | 82 | # CONFIG_TINY_SHMEM is not set | 
| 76 | CONFIG_BASE_SMALL=0 | 83 | CONFIG_BASE_SMALL=0 | 
| 84 | # CONFIG_SLOB is not set | ||
| 77 | 85 | ||
| 78 | # | 86 | # | 
| 79 | # Loadable module support | 87 | # Loadable module support | 
| @@ -113,13 +121,10 @@ CONFIG_PPC_MULTIPLATFORM=y | |||
| 113 | # CONFIG_APUS is not set | 121 | # CONFIG_APUS is not set | 
| 114 | # CONFIG_PPC_CHRP is not set | 122 | # CONFIG_PPC_CHRP is not set | 
| 115 | CONFIG_PPC_PMAC=y | 123 | CONFIG_PPC_PMAC=y | 
| 116 | CONFIG_PPC_OF=y | ||
| 117 | CONFIG_MPIC=y | 124 | CONFIG_MPIC=y | 
| 118 | # CONFIG_PPC_RTAS is not set | 125 | # CONFIG_PPC_RTAS is not set | 
| 119 | # CONFIG_MMIO_NVRAM is not set | 126 | # CONFIG_MMIO_NVRAM is not set | 
| 120 | # CONFIG_CRASH_DUMP is not set | ||
| 121 | CONFIG_PPC_MPC106=y | 127 | CONFIG_PPC_MPC106=y | 
| 122 | # CONFIG_GENERIC_TBSYNC is not set | ||
| 123 | CONFIG_CPU_FREQ=y | 128 | CONFIG_CPU_FREQ=y | 
| 124 | CONFIG_CPU_FREQ_TABLE=y | 129 | CONFIG_CPU_FREQ_TABLE=y | 
| 125 | # CONFIG_CPU_FREQ_DEBUG is not set | 130 | # CONFIG_CPU_FREQ_DEBUG is not set | 
| @@ -195,6 +200,11 @@ CONFIG_CARDBUS=y | |||
| 195 | # PC-card bridges | 200 | # PC-card bridges | 
| 196 | # | 201 | # | 
| 197 | CONFIG_YENTA=m | 202 | CONFIG_YENTA=m | 
| 203 | CONFIG_YENTA_O2=y | ||
| 204 | CONFIG_YENTA_RICOH=y | ||
| 205 | CONFIG_YENTA_TI=y | ||
| 206 | CONFIG_YENTA_ENE_TUNE=y | ||
| 207 | CONFIG_YENTA_TOSHIBA=y | ||
| 198 | # CONFIG_PD6729 is not set | 208 | # CONFIG_PD6729 is not set | 
| 199 | # CONFIG_I82092 is not set | 209 | # CONFIG_I82092 is not set | 
| 200 | CONFIG_PCCARD_NONSTATIC=m | 210 | CONFIG_PCCARD_NONSTATIC=m | 
| @@ -464,7 +474,7 @@ CONFIG_IEEE80211_CRYPT_TKIP=m | |||
| 464 | # | 474 | # | 
| 465 | # CONFIG_STANDALONE is not set | 475 | # CONFIG_STANDALONE is not set | 
| 466 | CONFIG_PREVENT_FIRMWARE_BUILD=y | 476 | CONFIG_PREVENT_FIRMWARE_BUILD=y | 
| 467 | CONFIG_FW_LOADER=m | 477 | CONFIG_FW_LOADER=y | 
| 468 | # CONFIG_DEBUG_DRIVER is not set | 478 | # CONFIG_DEBUG_DRIVER is not set | 
| 469 | 479 | ||
| 470 | # | 480 | # | 
| @@ -491,7 +501,7 @@ CONFIG_PROC_EVENTS=y | |||
| 491 | # Block devices | 501 | # Block devices | 
| 492 | # | 502 | # | 
| 493 | # CONFIG_BLK_DEV_FD is not set | 503 | # CONFIG_BLK_DEV_FD is not set | 
| 494 | CONFIG_MAC_FLOPPY=y | 504 | CONFIG_MAC_FLOPPY=m | 
| 495 | # CONFIG_BLK_CPQ_DA is not set | 505 | # CONFIG_BLK_CPQ_DA is not set | 
| 496 | # CONFIG_BLK_CPQ_CISS_DA is not set | 506 | # CONFIG_BLK_CPQ_CISS_DA is not set | 
| 497 | # CONFIG_BLK_DEV_DAC960 is not set | 507 | # CONFIG_BLK_DEV_DAC960 is not set | 
| @@ -603,7 +613,7 @@ CONFIG_SCSI_CONSTANTS=y | |||
| 603 | # SCSI Transport Attributes | 613 | # SCSI Transport Attributes | 
| 604 | # | 614 | # | 
| 605 | CONFIG_SCSI_SPI_ATTRS=y | 615 | CONFIG_SCSI_SPI_ATTRS=y | 
| 606 | # CONFIG_SCSI_FC_ATTRS is not set | 616 | CONFIG_SCSI_FC_ATTRS=y | 
| 607 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 617 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 
| 608 | # CONFIG_SCSI_SAS_ATTRS is not set | 618 | # CONFIG_SCSI_SAS_ATTRS is not set | 
| 609 | 619 | ||
| @@ -645,12 +655,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 | |||
| 645 | # CONFIG_SCSI_QLOGIC_FC is not set | 655 | # CONFIG_SCSI_QLOGIC_FC is not set | 
| 646 | # CONFIG_SCSI_QLOGIC_1280 is not set | 656 | # CONFIG_SCSI_QLOGIC_1280 is not set | 
| 647 | CONFIG_SCSI_QLA2XXX=y | 657 | CONFIG_SCSI_QLA2XXX=y | 
| 648 | # CONFIG_SCSI_QLA21XX is not set | 658 | # CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set | 
| 649 | # CONFIG_SCSI_QLA22XX is not set | ||
| 650 | # CONFIG_SCSI_QLA2300 is not set | ||
| 651 | # CONFIG_SCSI_QLA2322 is not set | ||
| 652 | # CONFIG_SCSI_QLA6312 is not set | ||
| 653 | # CONFIG_SCSI_QLA24XX is not set | ||
| 654 | # CONFIG_SCSI_LPFC is not set | 659 | # CONFIG_SCSI_LPFC is not set | 
| 655 | # CONFIG_SCSI_DC395x is not set | 660 | # CONFIG_SCSI_DC395x is not set | 
| 656 | # CONFIG_SCSI_DC390T is not set | 661 | # CONFIG_SCSI_DC390T is not set | 
| @@ -658,7 +663,7 @@ CONFIG_SCSI_QLA2XXX=y | |||
| 658 | # CONFIG_SCSI_DEBUG is not set | 663 | # CONFIG_SCSI_DEBUG is not set | 
| 659 | CONFIG_SCSI_MESH=y | 664 | CONFIG_SCSI_MESH=y | 
| 660 | CONFIG_SCSI_MESH_SYNC_RATE=5 | 665 | CONFIG_SCSI_MESH_SYNC_RATE=5 | 
| 661 | CONFIG_SCSI_MESH_RESET_DELAY_MS=1000 | 666 | CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 | 
| 662 | CONFIG_SCSI_MAC53C94=y | 667 | CONFIG_SCSI_MAC53C94=y | 
| 663 | 668 | ||
| 664 | # | 669 | # | 
| @@ -727,7 +732,6 @@ CONFIG_IEEE1394_SBP2=m | |||
| 727 | CONFIG_IEEE1394_ETH1394=m | 732 | CONFIG_IEEE1394_ETH1394=m | 
| 728 | CONFIG_IEEE1394_DV1394=m | 733 | CONFIG_IEEE1394_DV1394=m | 
| 729 | CONFIG_IEEE1394_RAWIO=m | 734 | CONFIG_IEEE1394_RAWIO=m | 
| 730 | # CONFIG_IEEE1394_CMP is not set | ||
| 731 | 735 | ||
| 732 | # | 736 | # | 
| 733 | # I2O device support | 737 | # I2O device support | 
| @@ -740,7 +744,7 @@ CONFIG_IEEE1394_RAWIO=m | |||
| 740 | CONFIG_ADB=y | 744 | CONFIG_ADB=y | 
| 741 | CONFIG_ADB_CUDA=y | 745 | CONFIG_ADB_CUDA=y | 
| 742 | CONFIG_ADB_PMU=y | 746 | CONFIG_ADB_PMU=y | 
| 743 | CONFIG_PMAC_APM_EMU=y | 747 | CONFIG_PMAC_APM_EMU=m | 
| 744 | CONFIG_PMAC_MEDIABAY=y | 748 | CONFIG_PMAC_MEDIABAY=y | 
| 745 | CONFIG_PMAC_BACKLIGHT=y | 749 | CONFIG_PMAC_BACKLIGHT=y | 
| 746 | CONFIG_INPUT_ADBHID=y | 750 | CONFIG_INPUT_ADBHID=y | 
| @@ -819,6 +823,7 @@ CONFIG_PCNET32=y | |||
| 819 | # CONFIG_R8169 is not set | 823 | # CONFIG_R8169 is not set | 
| 820 | # CONFIG_SIS190 is not set | 824 | # CONFIG_SIS190 is not set | 
| 821 | # CONFIG_SKGE is not set | 825 | # CONFIG_SKGE is not set | 
| 826 | # CONFIG_SKY2 is not set | ||
| 822 | # CONFIG_SK98LIN is not set | 827 | # CONFIG_SK98LIN is not set | 
| 823 | # CONFIG_VIA_VELOCITY is not set | 828 | # CONFIG_VIA_VELOCITY is not set | 
| 824 | # CONFIG_TIGON3 is not set | 829 | # CONFIG_TIGON3 is not set | 
| @@ -978,14 +983,14 @@ CONFIG_HW_CONSOLE=y | |||
| 978 | CONFIG_SERIAL_8250=m | 983 | CONFIG_SERIAL_8250=m | 
| 979 | # CONFIG_SERIAL_8250_CS is not set | 984 | # CONFIG_SERIAL_8250_CS is not set | 
| 980 | CONFIG_SERIAL_8250_NR_UARTS=4 | 985 | CONFIG_SERIAL_8250_NR_UARTS=4 | 
| 986 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
| 981 | # CONFIG_SERIAL_8250_EXTENDED is not set | 987 | # CONFIG_SERIAL_8250_EXTENDED is not set | 
| 982 | 988 | ||
| 983 | # | 989 | # | 
| 984 | # Non-8250 serial port support | 990 | # Non-8250 serial port support | 
| 985 | # | 991 | # | 
| 986 | CONFIG_SERIAL_CORE=m | 992 | CONFIG_SERIAL_CORE=m | 
| 987 | # CONFIG_SERIAL_PMACZILOG is not set | 993 | CONFIG_SERIAL_PMACZILOG=m | 
| 988 | # CONFIG_SERIAL_JSM is not set | ||
| 989 | CONFIG_UNIX98_PTYS=y | 994 | CONFIG_UNIX98_PTYS=y | 
| 990 | CONFIG_LEGACY_PTYS=y | 995 | CONFIG_LEGACY_PTYS=y | 
| 991 | CONFIG_LEGACY_PTY_COUNT=256 | 996 | CONFIG_LEGACY_PTY_COUNT=256 | 
| @@ -1058,7 +1063,7 @@ CONFIG_I2C_ALGOBIT=y | |||
| 1058 | # CONFIG_I2C_I801 is not set | 1063 | # CONFIG_I2C_I801 is not set | 
| 1059 | # CONFIG_I2C_I810 is not set | 1064 | # CONFIG_I2C_I810 is not set | 
| 1060 | # CONFIG_I2C_PIIX4 is not set | 1065 | # CONFIG_I2C_PIIX4 is not set | 
| 1061 | CONFIG_I2C_KEYWEST=m | 1066 | CONFIG_I2C_POWERMAC=y | 
| 1062 | # CONFIG_I2C_MPC is not set | 1067 | # CONFIG_I2C_MPC is not set | 
| 1063 | # CONFIG_I2C_NFORCE2 is not set | 1068 | # CONFIG_I2C_NFORCE2 is not set | 
| 1064 | # CONFIG_I2C_PARPORT_LIGHT is not set | 1069 | # CONFIG_I2C_PARPORT_LIGHT is not set | 
| @@ -1160,7 +1165,6 @@ CONFIG_FB_ATY128=y | |||
| 1160 | CONFIG_FB_ATY=y | 1165 | CONFIG_FB_ATY=y | 
| 1161 | CONFIG_FB_ATY_CT=y | 1166 | CONFIG_FB_ATY_CT=y | 
| 1162 | # CONFIG_FB_ATY_GENERIC_LCD is not set | 1167 | # CONFIG_FB_ATY_GENERIC_LCD is not set | 
| 1163 | # CONFIG_FB_ATY_XL_INIT is not set | ||
| 1164 | CONFIG_FB_ATY_GX=y | 1168 | CONFIG_FB_ATY_GX=y | 
| 1165 | # CONFIG_FB_SAVAGE is not set | 1169 | # CONFIG_FB_SAVAGE is not set | 
| 1166 | # CONFIG_FB_SIS is not set | 1170 | # CONFIG_FB_SIS is not set | 
| @@ -1169,7 +1173,6 @@ CONFIG_FB_ATY_GX=y | |||
| 1169 | CONFIG_FB_3DFX=y | 1173 | CONFIG_FB_3DFX=y | 
| 1170 | # CONFIG_FB_3DFX_ACCEL is not set | 1174 | # CONFIG_FB_3DFX_ACCEL is not set | 
| 1171 | # CONFIG_FB_VOODOO1 is not set | 1175 | # CONFIG_FB_VOODOO1 is not set | 
| 1172 | # CONFIG_FB_CYBLA is not set | ||
| 1173 | # CONFIG_FB_TRIDENT is not set | 1176 | # CONFIG_FB_TRIDENT is not set | 
| 1174 | # CONFIG_FB_VIRTUAL is not set | 1177 | # CONFIG_FB_VIRTUAL is not set | 
| 1175 | 1178 | ||
| @@ -1214,9 +1217,10 @@ CONFIG_SND_OSSEMUL=y | |||
| 1214 | CONFIG_SND_MIXER_OSS=m | 1217 | CONFIG_SND_MIXER_OSS=m | 
| 1215 | CONFIG_SND_PCM_OSS=m | 1218 | CONFIG_SND_PCM_OSS=m | 
| 1216 | CONFIG_SND_SEQUENCER_OSS=y | 1219 | CONFIG_SND_SEQUENCER_OSS=y | 
| 1220 | # CONFIG_SND_DYNAMIC_MINORS is not set | ||
| 1221 | CONFIG_SND_SUPPORT_OLD_API=y | ||
| 1217 | # CONFIG_SND_VERBOSE_PRINTK is not set | 1222 | # CONFIG_SND_VERBOSE_PRINTK is not set | 
| 1218 | # CONFIG_SND_DEBUG is not set | 1223 | # CONFIG_SND_DEBUG is not set | 
| 1219 | CONFIG_SND_GENERIC_DRIVER=y | ||
| 1220 | 1224 | ||
| 1221 | # | 1225 | # | 
| 1222 | # Generic devices | 1226 | # Generic devices | 
| @@ -1230,6 +1234,8 @@ CONFIG_SND_DUMMY=m | |||
| 1230 | # | 1234 | # | 
| 1231 | # PCI devices | 1235 | # PCI devices | 
| 1232 | # | 1236 | # | 
| 1237 | # CONFIG_SND_AD1889 is not set | ||
| 1238 | # CONFIG_SND_ALS4000 is not set | ||
| 1233 | # CONFIG_SND_ALI5451 is not set | 1239 | # CONFIG_SND_ALI5451 is not set | 
| 1234 | # CONFIG_SND_ATIIXP is not set | 1240 | # CONFIG_SND_ATIIXP is not set | 
| 1235 | # CONFIG_SND_ATIIXP_MODEM is not set | 1241 | # CONFIG_SND_ATIIXP_MODEM is not set | 
| @@ -1238,45 +1244,44 @@ CONFIG_SND_DUMMY=m | |||
| 1238 | # CONFIG_SND_AU8830 is not set | 1244 | # CONFIG_SND_AU8830 is not set | 
| 1239 | # CONFIG_SND_AZT3328 is not set | 1245 | # CONFIG_SND_AZT3328 is not set | 
| 1240 | # CONFIG_SND_BT87X is not set | 1246 | # CONFIG_SND_BT87X is not set | 
| 1241 | # CONFIG_SND_CS46XX is not set | 1247 | # CONFIG_SND_CA0106 is not set | 
| 1248 | # CONFIG_SND_CMIPCI is not set | ||
| 1242 | # CONFIG_SND_CS4281 is not set | 1249 | # CONFIG_SND_CS4281 is not set | 
| 1250 | # CONFIG_SND_CS46XX is not set | ||
| 1243 | # CONFIG_SND_EMU10K1 is not set | 1251 | # CONFIG_SND_EMU10K1 is not set | 
| 1244 | # CONFIG_SND_EMU10K1X is not set | 1252 | # CONFIG_SND_EMU10K1X is not set | 
| 1245 | # CONFIG_SND_CA0106 is not set | ||
| 1246 | # CONFIG_SND_KORG1212 is not set | ||
| 1247 | # CONFIG_SND_MIXART is not set | ||
| 1248 | # CONFIG_SND_NM256 is not set | ||
| 1249 | # CONFIG_SND_RME32 is not set | ||
| 1250 | # CONFIG_SND_RME96 is not set | ||
| 1251 | # CONFIG_SND_RME9652 is not set | ||
| 1252 | # CONFIG_SND_HDSP is not set | ||
| 1253 | # CONFIG_SND_HDSPM is not set | ||
| 1254 | # CONFIG_SND_TRIDENT is not set | ||
| 1255 | # CONFIG_SND_YMFPCI is not set | ||
| 1256 | # CONFIG_SND_AD1889 is not set | ||
| 1257 | # CONFIG_SND_ALS4000 is not set | ||
| 1258 | # CONFIG_SND_CMIPCI is not set | ||
| 1259 | # CONFIG_SND_ENS1370 is not set | 1253 | # CONFIG_SND_ENS1370 is not set | 
| 1260 | # CONFIG_SND_ENS1371 is not set | 1254 | # CONFIG_SND_ENS1371 is not set | 
| 1261 | # CONFIG_SND_ES1938 is not set | 1255 | # CONFIG_SND_ES1938 is not set | 
| 1262 | # CONFIG_SND_ES1968 is not set | 1256 | # CONFIG_SND_ES1968 is not set | 
| 1263 | # CONFIG_SND_MAESTRO3 is not set | ||
| 1264 | # CONFIG_SND_FM801 is not set | 1257 | # CONFIG_SND_FM801 is not set | 
| 1258 | # CONFIG_SND_HDA_INTEL is not set | ||
| 1259 | # CONFIG_SND_HDSP is not set | ||
| 1260 | # CONFIG_SND_HDSPM is not set | ||
| 1265 | # CONFIG_SND_ICE1712 is not set | 1261 | # CONFIG_SND_ICE1712 is not set | 
| 1266 | # CONFIG_SND_ICE1724 is not set | 1262 | # CONFIG_SND_ICE1724 is not set | 
| 1267 | # CONFIG_SND_INTEL8X0 is not set | 1263 | # CONFIG_SND_INTEL8X0 is not set | 
| 1268 | # CONFIG_SND_INTEL8X0M is not set | 1264 | # CONFIG_SND_INTEL8X0M is not set | 
| 1265 | # CONFIG_SND_KORG1212 is not set | ||
| 1266 | # CONFIG_SND_MAESTRO3 is not set | ||
| 1267 | # CONFIG_SND_MIXART is not set | ||
| 1268 | # CONFIG_SND_NM256 is not set | ||
| 1269 | # CONFIG_SND_PCXHR is not set | ||
| 1270 | # CONFIG_SND_RME32 is not set | ||
| 1271 | # CONFIG_SND_RME96 is not set | ||
| 1272 | # CONFIG_SND_RME9652 is not set | ||
| 1269 | # CONFIG_SND_SONICVIBES is not set | 1273 | # CONFIG_SND_SONICVIBES is not set | 
| 1274 | # CONFIG_SND_TRIDENT is not set | ||
| 1270 | # CONFIG_SND_VIA82XX is not set | 1275 | # CONFIG_SND_VIA82XX is not set | 
| 1271 | # CONFIG_SND_VIA82XX_MODEM is not set | 1276 | # CONFIG_SND_VIA82XX_MODEM is not set | 
| 1272 | # CONFIG_SND_VX222 is not set | 1277 | # CONFIG_SND_VX222 is not set | 
| 1273 | # CONFIG_SND_HDA_INTEL is not set | 1278 | # CONFIG_SND_YMFPCI is not set | 
| 1274 | 1279 | ||
| 1275 | # | 1280 | # | 
| 1276 | # ALSA PowerMac devices | 1281 | # ALSA PowerMac devices | 
| 1277 | # | 1282 | # | 
| 1278 | CONFIG_SND_POWERMAC=m | 1283 | CONFIG_SND_POWERMAC=m | 
| 1279 | # CONFIG_SND_POWERMAC_AUTO_DRC is not set | 1284 | CONFIG_SND_POWERMAC_AUTO_DRC=y | 
| 1280 | 1285 | ||
| 1281 | # | 1286 | # | 
| 1282 | # USB devices | 1287 | # USB devices | 
| @@ -1336,6 +1341,7 @@ CONFIG_USB_PRINTER=m | |||
| 1336 | # may also be needed; see USB_STORAGE Help for more information | 1341 | # may also be needed; see USB_STORAGE Help for more information | 
| 1337 | # | 1342 | # | 
| 1338 | # CONFIG_USB_STORAGE is not set | 1343 | # CONFIG_USB_STORAGE is not set | 
| 1344 | # CONFIG_USB_LIBUSUAL is not set | ||
| 1339 | 1345 | ||
| 1340 | # | 1346 | # | 
| 1341 | # USB Input Devices | 1347 | # USB Input Devices | 
| @@ -1355,6 +1361,7 @@ CONFIG_USB_HIDINPUT=y | |||
| 1355 | # CONFIG_USB_YEALINK is not set | 1361 | # CONFIG_USB_YEALINK is not set | 
| 1356 | # CONFIG_USB_XPAD is not set | 1362 | # CONFIG_USB_XPAD is not set | 
| 1357 | # CONFIG_USB_ATI_REMOTE is not set | 1363 | # CONFIG_USB_ATI_REMOTE is not set | 
| 1364 | # CONFIG_USB_ATI_REMOTE2 is not set | ||
| 1358 | # CONFIG_USB_KEYSPAN_REMOTE is not set | 1365 | # CONFIG_USB_KEYSPAN_REMOTE is not set | 
| 1359 | CONFIG_USB_APPLETOUCH=y | 1366 | CONFIG_USB_APPLETOUCH=y | 
| 1360 | 1367 | ||
| @@ -1501,6 +1508,7 @@ CONFIG_FS_MBCACHE=y | |||
| 1501 | # CONFIG_JFS_FS is not set | 1508 | # CONFIG_JFS_FS is not set | 
| 1502 | # CONFIG_FS_POSIX_ACL is not set | 1509 | # CONFIG_FS_POSIX_ACL is not set | 
| 1503 | # CONFIG_XFS_FS is not set | 1510 | # CONFIG_XFS_FS is not set | 
| 1511 | # CONFIG_OCFS2_FS is not set | ||
| 1504 | # CONFIG_MINIX_FS is not set | 1512 | # CONFIG_MINIX_FS is not set | 
| 1505 | # CONFIG_ROMFS_FS is not set | 1513 | # CONFIG_ROMFS_FS is not set | 
| 1506 | CONFIG_INOTIFY=y | 1514 | CONFIG_INOTIFY=y | 
| @@ -1540,6 +1548,7 @@ CONFIG_TMPFS=y | |||
| 1540 | # CONFIG_HUGETLB_PAGE is not set | 1548 | # CONFIG_HUGETLB_PAGE is not set | 
| 1541 | CONFIG_RAMFS=y | 1549 | CONFIG_RAMFS=y | 
| 1542 | CONFIG_RELAYFS_FS=m | 1550 | CONFIG_RELAYFS_FS=m | 
| 1551 | # CONFIG_CONFIGFS_FS is not set | ||
| 1543 | 1552 | ||
| 1544 | # | 1553 | # | 
| 1545 | # Miscellaneous filesystems | 1554 | # Miscellaneous filesystems | 
| @@ -1670,12 +1679,13 @@ CONFIG_OPROFILE=y | |||
| 1670 | # Kernel hacking | 1679 | # Kernel hacking | 
| 1671 | # | 1680 | # | 
| 1672 | # CONFIG_PRINTK_TIME is not set | 1681 | # CONFIG_PRINTK_TIME is not set | 
| 1673 | CONFIG_DEBUG_KERNEL=y | ||
| 1674 | # CONFIG_MAGIC_SYSRQ is not set | 1682 | # CONFIG_MAGIC_SYSRQ is not set | 
| 1683 | CONFIG_DEBUG_KERNEL=y | ||
| 1675 | CONFIG_LOG_BUF_SHIFT=14 | 1684 | CONFIG_LOG_BUF_SHIFT=14 | 
| 1676 | CONFIG_DETECT_SOFTLOCKUP=y | 1685 | CONFIG_DETECT_SOFTLOCKUP=y | 
| 1677 | # CONFIG_SCHEDSTATS is not set | 1686 | # CONFIG_SCHEDSTATS is not set | 
| 1678 | # CONFIG_DEBUG_SLAB is not set | 1687 | # CONFIG_DEBUG_SLAB is not set | 
| 1688 | # CONFIG_DEBUG_MUTEXES is not set | ||
| 1679 | # CONFIG_DEBUG_SPINLOCK is not set | 1689 | # CONFIG_DEBUG_SPINLOCK is not set | 
| 1680 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | 1690 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | 
| 1681 | # CONFIG_DEBUG_KOBJECT is not set | 1691 | # CONFIG_DEBUG_KOBJECT is not set | 
| @@ -1688,6 +1698,11 @@ CONFIG_XMON=y | |||
| 1688 | CONFIG_XMON_DEFAULT=y | 1698 | CONFIG_XMON_DEFAULT=y | 
| 1689 | # CONFIG_BDI_SWITCH is not set | 1699 | # CONFIG_BDI_SWITCH is not set | 
| 1690 | CONFIG_BOOTX_TEXT=y | 1700 | CONFIG_BOOTX_TEXT=y | 
| 1701 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
| 1702 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
| 1703 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
| 1704 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
| 1705 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
| 1691 | 1706 | ||
| 1692 | # | 1707 | # | 
| 1693 | # Security options | 1708 | # Security options | 
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index a94699d8dc52..c287980b7e65 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile  | |||
| @@ -60,7 +60,8 @@ obj-$(CONFIG_MODULES) += $(module-y) | |||
| 60 | 60 | ||
| 61 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | 61 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | 
| 62 | pci_direct_iommu.o iomap.o | 62 | pci_direct_iommu.o iomap.o | 
| 63 | obj-$(CONFIG_PCI) += $(pci64-y) | 63 | pci32-$(CONFIG_PPC32) := pci_32.o | 
| 64 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | ||
| 64 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o | 65 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o | 
| 65 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 66 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 
| 66 | obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) | 67 | obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y) | 
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 5f248e3fdf82..8c21d378f5d2 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c  | |||
| @@ -84,7 +84,10 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) | |||
| 84 | * squirrelled away. ELF notes happen to provide | 84 | * squirrelled away. ELF notes happen to provide | 
| 85 | * all of that that no need to invent something new. | 85 | * all of that that no need to invent something new. | 
| 86 | */ | 86 | */ | 
| 87 | buf = &crash_notes[cpu][0]; | 87 | buf = (u32*)per_cpu_ptr(crash_notes, cpu); | 
| 88 | if (!buf) | ||
| 89 | return; | ||
| 90 | |||
| 88 | memset(&prstatus, 0, sizeof(prstatus)); | 91 | memset(&prstatus, 0, sizeof(prstatus)); | 
| 89 | prstatus.pr_pid = current->pid; | 92 | prstatus.pr_pid = current->pid; | 
| 90 | elf_core_copy_regs(&prstatus.pr_reg, regs); | 93 | elf_core_copy_regs(&prstatus.pr_reg, regs); | 
| @@ -93,76 +96,6 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu) | |||
| 93 | final_note(buf); | 96 | final_note(buf); | 
| 94 | } | 97 | } | 
| 95 | 98 | ||
| 96 | /* FIXME Merge this with xmon_save_regs ?? */ | ||
| 97 | static inline void crash_get_current_regs(struct pt_regs *regs) | ||
| 98 | { | ||
| 99 | unsigned long tmp1, tmp2; | ||
| 100 | |||
| 101 | __asm__ __volatile__ ( | ||
| 102 | "std 0,0(%2)\n" | ||
| 103 | "std 1,8(%2)\n" | ||
| 104 | "std 2,16(%2)\n" | ||
| 105 | "std 3,24(%2)\n" | ||
| 106 | "std 4,32(%2)\n" | ||
| 107 | "std 5,40(%2)\n" | ||
| 108 | "std 6,48(%2)\n" | ||
| 109 | "std 7,56(%2)\n" | ||
| 110 | "std 8,64(%2)\n" | ||
| 111 | "std 9,72(%2)\n" | ||
| 112 | "std 10,80(%2)\n" | ||
| 113 | "std 11,88(%2)\n" | ||
| 114 | "std 12,96(%2)\n" | ||
| 115 | "std 13,104(%2)\n" | ||
| 116 | "std 14,112(%2)\n" | ||
| 117 | "std 15,120(%2)\n" | ||
| 118 | "std 16,128(%2)\n" | ||
| 119 | "std 17,136(%2)\n" | ||
| 120 | "std 18,144(%2)\n" | ||
| 121 | "std 19,152(%2)\n" | ||
| 122 | "std 20,160(%2)\n" | ||
| 123 | "std 21,168(%2)\n" | ||
| 124 | "std 22,176(%2)\n" | ||
| 125 | "std 23,184(%2)\n" | ||
| 126 | "std 24,192(%2)\n" | ||
| 127 | "std 25,200(%2)\n" | ||
| 128 | "std 26,208(%2)\n" | ||
| 129 | "std 27,216(%2)\n" | ||
| 130 | "std 28,224(%2)\n" | ||
| 131 | "std 29,232(%2)\n" | ||
| 132 | "std 30,240(%2)\n" | ||
| 133 | "std 31,248(%2)\n" | ||
| 134 | "mfmsr %0\n" | ||
| 135 | "std %0, 264(%2)\n" | ||
| 136 | "mfctr %0\n" | ||
| 137 | "std %0, 280(%2)\n" | ||
| 138 | "mflr %0\n" | ||
| 139 | "std %0, 288(%2)\n" | ||
| 140 | "bl 1f\n" | ||
| 141 | "1: mflr %1\n" | ||
| 142 | "std %1, 256(%2)\n" | ||
| 143 | "mtlr %0\n" | ||
| 144 | "mfxer %0\n" | ||
| 145 | "std %0, 296(%2)\n" | ||
| 146 | : "=&r" (tmp1), "=&r" (tmp2) | ||
| 147 | : "b" (regs)); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* We may have saved_regs from where the error came from | ||
| 151 | * or it is NULL if via a direct panic(). | ||
| 152 | */ | ||
| 153 | static void crash_save_self(struct pt_regs *saved_regs) | ||
| 154 | { | ||
| 155 | struct pt_regs regs; | ||
| 156 | int cpu; | ||
| 157 | |||
| 158 | cpu = smp_processor_id(); | ||
| 159 | if (saved_regs) | ||
| 160 | memcpy(®s, saved_regs, sizeof(regs)); | ||
| 161 | else | ||
| 162 | crash_get_current_regs(®s); | ||
| 163 | crash_save_this_cpu(®s, cpu); | ||
| 164 | } | ||
| 165 | |||
| 166 | #ifdef CONFIG_SMP | 99 | #ifdef CONFIG_SMP | 
| 167 | static atomic_t waiting_for_crash_ipi; | 100 | static atomic_t waiting_for_crash_ipi; | 
| 168 | 101 | ||
| @@ -260,5 +193,5 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
| 260 | */ | 193 | */ | 
| 261 | crashing_cpu = smp_processor_id(); | 194 | crashing_cpu = smp_processor_id(); | 
| 262 | crash_kexec_prepare_cpus(); | 195 | crash_kexec_prepare_cpus(); | 
| 263 | crash_save_self(regs); | 196 | crash_save_this_cpu(regs, crashing_cpu); | 
| 264 | } | 197 | } | 
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c new file mode 100644 index 000000000000..704c846b2b0f --- /dev/null +++ b/arch/powerpc/kernel/pci_32.c  | |||
| @@ -0,0 +1,1897 @@ | |||
| 1 | /* | ||
| 2 | * Common pmac/prep/chrp pci routines. -- Cort | ||
| 3 | */ | ||
| 4 | |||
| 5 | #include <linux/config.h> | ||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/pci.h> | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/string.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/capability.h> | ||
| 12 | #include <linux/sched.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/bootmem.h> | ||
| 15 | |||
| 16 | #include <asm/processor.h> | ||
| 17 | #include <asm/io.h> | ||
| 18 | #include <asm/prom.h> | ||
| 19 | #include <asm/sections.h> | ||
| 20 | #include <asm/pci-bridge.h> | ||
| 21 | #include <asm/byteorder.h> | ||
| 22 | #include <asm/irq.h> | ||
| 23 | #include <asm/uaccess.h> | ||
| 24 | #include <asm/machdep.h> | ||
| 25 | |||
| 26 | #undef DEBUG | ||
| 27 | |||
| 28 | #ifdef DEBUG | ||
| 29 | #define DBG(x...) printk(x) | ||
| 30 | #else | ||
| 31 | #define DBG(x...) | ||
| 32 | #endif | ||
| 33 | |||
| 34 | unsigned long isa_io_base = 0; | ||
| 35 | unsigned long isa_mem_base = 0; | ||
| 36 | unsigned long pci_dram_offset = 0; | ||
| 37 | int pcibios_assign_bus_offset = 1; | ||
| 38 | |||
| 39 | void pcibios_make_OF_bus_map(void); | ||
| 40 | |||
| 41 | static int pci_relocate_bridge_resource(struct pci_bus *bus, int i); | ||
| 42 | static int probe_resource(struct pci_bus *parent, struct resource *pr, | ||
| 43 | struct resource *res, struct resource **conflict); | ||
| 44 | static void update_bridge_base(struct pci_bus *bus, int i); | ||
| 45 | static void pcibios_fixup_resources(struct pci_dev* dev); | ||
| 46 | static void fixup_broken_pcnet32(struct pci_dev* dev); | ||
| 47 | static int reparent_resources(struct resource *parent, struct resource *res); | ||
| 48 | static void fixup_cpc710_pci64(struct pci_dev* dev); | ||
| 49 | #ifdef CONFIG_PPC_OF | ||
| 50 | static u8* pci_to_OF_bus_map; | ||
| 51 | #endif | ||
| 52 | |||
| 53 | /* By default, we don't re-assign bus numbers. We do this only on | ||
| 54 | * some pmacs | ||
| 55 | */ | ||
| 56 | int pci_assign_all_buses; | ||
| 57 | |||
| 58 | struct pci_controller* hose_head; | ||
| 59 | struct pci_controller** hose_tail = &hose_head; | ||
| 60 | |||
| 61 | static int pci_bus_count; | ||
| 62 | |||
| 63 | static void | ||
| 64 | fixup_broken_pcnet32(struct pci_dev* dev) | ||
| 65 | { | ||
| 66 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { | ||
| 67 | dev->vendor = PCI_VENDOR_ID_AMD; | ||
| 68 | pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); | ||
| 72 | |||
| 73 | static void | ||
| 74 | fixup_cpc710_pci64(struct pci_dev* dev) | ||
| 75 | { | ||
| 76 | /* Hide the PCI64 BARs from the kernel as their content doesn't | ||
| 77 | * fit well in the resource management | ||
| 78 | */ | ||
| 79 | dev->resource[0].start = dev->resource[0].end = 0; | ||
| 80 | dev->resource[0].flags = 0; | ||
| 81 | dev->resource[1].start = dev->resource[1].end = 0; | ||
| 82 | dev->resource[1].flags = 0; | ||
| 83 | } | ||
| 84 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); | ||
| 85 | |||
| 86 | static void | ||
| 87 | pcibios_fixup_resources(struct pci_dev *dev) | ||
| 88 | { | ||
| 89 | struct pci_controller* hose = (struct pci_controller *)dev->sysdata; | ||
| 90 | int i; | ||
| 91 | unsigned long offset; | ||
| 92 | |||
| 93 | if (!hose) { | ||
| 94 | printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev)); | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
| 98 | struct resource *res = dev->resource + i; | ||
| 99 | if (!res->flags) | ||
| 100 | continue; | ||
| 101 | if (res->end == 0xffffffff) { | ||
| 102 | DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n", | ||
| 103 | pci_name(dev), i, res->start, res->end); | ||
| 104 | res->end -= res->start; | ||
| 105 | res->start = 0; | ||
| 106 | res->flags |= IORESOURCE_UNSET; | ||
| 107 | continue; | ||
| 108 | } | ||
| 109 | offset = 0; | ||
| 110 | if (res->flags & IORESOURCE_MEM) { | ||
| 111 | offset = hose->pci_mem_offset; | ||
| 112 | } else if (res->flags & IORESOURCE_IO) { | ||
| 113 | offset = (unsigned long) hose->io_base_virt | ||
| 114 | - isa_io_base; | ||
| 115 | } | ||
| 116 | if (offset != 0) { | ||
| 117 | res->start += offset; | ||
| 118 | res->end += offset; | ||
| 119 | #ifdef DEBUG | ||
| 120 | printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n", | ||
| 121 | i, res->flags, pci_name(dev), | ||
| 122 | res->start - offset, res->start); | ||
| 123 | #endif | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | /* Call machine specific resource fixup */ | ||
| 128 | if (ppc_md.pcibios_fixup_resources) | ||
| 129 | ppc_md.pcibios_fixup_resources(dev); | ||
| 130 | } | ||
| 131 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); | ||
| 132 | |||
| 133 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
| 134 | struct resource *res) | ||
| 135 | { | ||
| 136 | unsigned long offset = 0; | ||
| 137 | struct pci_controller *hose = dev->sysdata; | ||
| 138 | |||
| 139 | if (hose && res->flags & IORESOURCE_IO) | ||
| 140 | offset = (unsigned long)hose->io_base_virt - isa_io_base; | ||
| 141 | else if (hose && res->flags & IORESOURCE_MEM) | ||
| 142 | offset = hose->pci_mem_offset; | ||
| 143 | region->start = res->start - offset; | ||
| 144 | region->end = res->end - offset; | ||
| 145 | } | ||
| 146 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
| 147 | |||
| 148 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
| 149 | struct pci_bus_region *region) | ||
| 150 | { | ||
| 151 | unsigned long offset = 0; | ||
| 152 | struct pci_controller *hose = dev->sysdata; | ||
| 153 | |||
| 154 | if (hose && res->flags & IORESOURCE_IO) | ||
| 155 | offset = (unsigned long)hose->io_base_virt - isa_io_base; | ||
| 156 | else if (hose && res->flags & IORESOURCE_MEM) | ||
| 157 | offset = hose->pci_mem_offset; | ||
| 158 | res->start = region->start + offset; | ||
| 159 | res->end = region->end + offset; | ||
| 160 | } | ||
| 161 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
| 162 | |||
| 163 | /* | ||
| 164 | * We need to avoid collisions with `mirrored' VGA ports | ||
| 165 | * and other strange ISA hardware, so we always want the | ||
| 166 | * addresses to be allocated in the 0x000-0x0ff region | ||
| 167 | * modulo 0x400. | ||
| 168 | * | ||
| 169 | * Why? Because some silly external IO cards only decode | ||
| 170 | * the low 10 bits of the IO address. The 0x00-0xff region | ||
| 171 | * is reserved for motherboard devices that decode all 16 | ||
| 172 | * bits, so it's ok to allocate at, say, 0x2800-0x28ff, | ||
| 173 | * but we want to try to avoid allocating at 0x2900-0x2bff | ||
| 174 | * which might have be mirrored at 0x0100-0x03ff.. | ||
| 175 | */ | ||
| 176 | void pcibios_align_resource(void *data, struct resource *res, unsigned long size, | ||
| 177 | unsigned long align) | ||
| 178 | { | ||
| 179 | struct pci_dev *dev = data; | ||
| 180 | |||
| 181 | if (res->flags & IORESOURCE_IO) { | ||
| 182 | unsigned long start = res->start; | ||
| 183 | |||
| 184 | if (size > 0x100) { | ||
| 185 | printk(KERN_ERR "PCI: I/O Region %s/%d too large" | ||
| 186 | " (%ld bytes)\n", pci_name(dev), | ||
| 187 | dev->resource - res, size); | ||
| 188 | } | ||
| 189 | |||
| 190 | if (start & 0x300) { | ||
| 191 | start = (start + 0x3ff) & ~0x3ff; | ||
| 192 | res->start = start; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | EXPORT_SYMBOL(pcibios_align_resource); | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Handle resources of PCI devices. If the world were perfect, we could | ||
| 200 | * just allocate all the resource regions and do nothing more. It isn't. | ||
| 201 | * On the other hand, we cannot just re-allocate all devices, as it would | ||
| 202 | * require us to know lots of host bridge internals. So we attempt to | ||
| 203 | * keep as much of the original configuration as possible, but tweak it | ||
| 204 | * when it's found to be wrong. | ||
| 205 | * | ||
| 206 | * Known BIOS problems we have to work around: | ||
| 207 | * - I/O or memory regions not configured | ||
| 208 | * - regions configured, but not enabled in the command register | ||
| 209 | * - bogus I/O addresses above 64K used | ||
| 210 | * - expansion ROMs left enabled (this may sound harmless, but given | ||
| 211 | * the fact the PCI specs explicitly allow address decoders to be | ||
| 212 | * shared between expansion ROMs and other resource regions, it's | ||
| 213 | * at least dangerous) | ||
| 214 | * | ||
| 215 | * Our solution: | ||
| 216 | * (1) Allocate resources for all buses behind PCI-to-PCI bridges. | ||
| 217 | * This gives us fixed barriers on where we can allocate. | ||
| 218 | * (2) Allocate resources for all enabled devices. If there is | ||
| 219 | * a collision, just mark the resource as unallocated. Also | ||
| 220 | * disable expansion ROMs during this step. | ||
| 221 | * (3) Try to allocate resources for disabled devices. If the | ||
| 222 | * resources were assigned correctly, everything goes well, | ||
| 223 | * if they weren't, they won't disturb allocation of other | ||
| 224 | * resources. | ||
| 225 | * (4) Assign new addresses to resources which were either | ||
| 226 | * not configured at all or misconfigured. If explicitly | ||
| 227 | * requested by the user, configure expansion ROM address | ||
| 228 | * as well. | ||
| 229 | */ | ||
| 230 | |||
| 231 | static void __init | ||
| 232 | pcibios_allocate_bus_resources(struct list_head *bus_list) | ||
| 233 | { | ||
| 234 | struct pci_bus *bus; | ||
| 235 | int i; | ||
| 236 | struct resource *res, *pr; | ||
| 237 | |||
| 238 | /* Depth-First Search on bus tree */ | ||
| 239 | list_for_each_entry(bus, bus_list, node) { | ||
| 240 | for (i = 0; i < 4; ++i) { | ||
| 241 | if ((res = bus->resource[i]) == NULL || !res->flags | ||
| 242 | || res->start > res->end) | ||
| 243 | continue; | ||
| 244 | if (bus->parent == NULL) | ||
| 245 | pr = (res->flags & IORESOURCE_IO)? | ||
| 246 | &ioport_resource: &iomem_resource; | ||
| 247 | else { | ||
| 248 | pr = pci_find_parent_resource(bus->self, res); | ||
| 249 | if (pr == res) { | ||
| 250 | /* this happens when the generic PCI | ||
| 251 | * code (wrongly) decides that this | ||
| 252 | * bridge is transparent -- paulus | ||
| 253 | */ | ||
| 254 | continue; | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n", | ||
| 259 | res->start, res->end, res->flags, pr); | ||
| 260 | if (pr) { | ||
| 261 | if (request_resource(pr, res) == 0) | ||
| 262 | continue; | ||
| 263 | /* | ||
| 264 | * Must be a conflict with an existing entry. | ||
| 265 | * Move that entry (or entries) under the | ||
| 266 | * bridge resource and try again. | ||
| 267 | */ | ||
| 268 | if (reparent_resources(pr, res) == 0) | ||
| 269 | continue; | ||
| 270 | } | ||
| 271 | printk(KERN_ERR "PCI: Cannot allocate resource region " | ||
| 272 | "%d of PCI bridge %d\n", i, bus->number); | ||
| 273 | if (pci_relocate_bridge_resource(bus, i)) | ||
| 274 | bus->resource[i] = NULL; | ||
| 275 | } | ||
| 276 | pcibios_allocate_bus_resources(&bus->children); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Reparent resource children of pr that conflict with res | ||
| 282 | * under res, and make res replace those children. | ||
| 283 | */ | ||
| 284 | static int __init | ||
| 285 | reparent_resources(struct resource *parent, struct resource *res) | ||
| 286 | { | ||
| 287 | struct resource *p, **pp; | ||
| 288 | struct resource **firstpp = NULL; | ||
| 289 | |||
| 290 | for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) { | ||
| 291 | if (p->end < res->start) | ||
| 292 | continue; | ||
| 293 | if (res->end < p->start) | ||
| 294 | break; | ||
| 295 | if (p->start < res->start || p->end > res->end) | ||
| 296 | return -1; /* not completely contained */ | ||
| 297 | if (firstpp == NULL) | ||
| 298 | firstpp = pp; | ||
| 299 | } | ||
| 300 | if (firstpp == NULL) | ||
| 301 | return -1; /* didn't find any conflicting entries? */ | ||
| 302 | res->parent = parent; | ||
| 303 | res->child = *firstpp; | ||
| 304 | res->sibling = *pp; | ||
| 305 | *firstpp = res; | ||
| 306 | *pp = NULL; | ||
| 307 | for (p = res->child; p != NULL; p = p->sibling) { | ||
| 308 | p->parent = res; | ||
| 309 | DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n", | ||
| 310 | p->name, p->start, p->end, res->name); | ||
| 311 | } | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | /* | ||
| 316 | * A bridge has been allocated a range which is outside the range | ||
| 317 | * of its parent bridge, so it needs to be moved. | ||
| 318 | */ | ||
| 319 | static int __init | ||
| 320 | pci_relocate_bridge_resource(struct pci_bus *bus, int i) | ||
| 321 | { | ||
| 322 | struct resource *res, *pr, *conflict; | ||
| 323 | unsigned long try, size; | ||
| 324 | int j; | ||
| 325 | struct pci_bus *parent = bus->parent; | ||
| 326 | |||
| 327 | if (parent == NULL) { | ||
| 328 | /* shouldn't ever happen */ | ||
| 329 | printk(KERN_ERR "PCI: can't move host bridge resource\n"); | ||
| 330 | return -1; | ||
| 331 | } | ||
| 332 | res = bus->resource[i]; | ||
| 333 | if (res == NULL) | ||
| 334 | return -1; | ||
| 335 | pr = NULL; | ||
| 336 | for (j = 0; j < 4; j++) { | ||
| 337 | struct resource *r = parent->resource[j]; | ||
| 338 | if (!r) | ||
| 339 | continue; | ||
| 340 | if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM)) | ||
| 341 | continue; | ||
| 342 | if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) { | ||
| 343 | pr = r; | ||
| 344 | break; | ||
| 345 | } | ||
| 346 | if (res->flags & IORESOURCE_PREFETCH) | ||
| 347 | pr = r; | ||
| 348 | } | ||
| 349 | if (pr == NULL) | ||
| 350 | return -1; | ||
| 351 | size = res->end - res->start; | ||
| 352 | if (pr->start > pr->end || size > pr->end - pr->start) | ||
| 353 | return -1; | ||
| 354 | try = pr->end; | ||
| 355 | for (;;) { | ||
| 356 | res->start = try - size; | ||
| 357 | res->end = try; | ||
| 358 | if (probe_resource(bus->parent, pr, res, &conflict) == 0) | ||
| 359 | break; | ||
| 360 | if (conflict->start <= pr->start + size) | ||
| 361 | return -1; | ||
| 362 | try = conflict->start - 1; | ||
| 363 | } | ||
| 364 | if (request_resource(pr, res)) { | ||
| 365 | DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n", | ||
| 366 | res->start, res->end); | ||
| 367 | return -1; /* "can't happen" */ | ||
| 368 | } | ||
| 369 | update_bridge_base(bus, i); | ||
| 370 | printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n", | ||
| 371 | bus->number, i, res->start, res->end); | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | static int __init | ||
| 376 | probe_resource(struct pci_bus *parent, struct resource *pr, | ||
| 377 | struct resource *res, struct resource **conflict) | ||
| 378 | { | ||
| 379 | struct pci_bus *bus; | ||
| 380 | struct pci_dev *dev; | ||
| 381 | struct resource *r; | ||
| 382 | int i; | ||
| 383 | |||
| 384 | for (r = pr->child; r != NULL; r = r->sibling) { | ||
| 385 | if (r->end >= res->start && res->end >= r->start) { | ||
| 386 | *conflict = r; | ||
| 387 | return 1; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | list_for_each_entry(bus, &parent->children, node) { | ||
| 391 | for (i = 0; i < 4; ++i) { | ||
| 392 | if ((r = bus->resource[i]) == NULL) | ||
| 393 | continue; | ||
| 394 | if (!r->flags || r->start > r->end || r == res) | ||
| 395 | continue; | ||
| 396 | if (pci_find_parent_resource(bus->self, r) != pr) | ||
| 397 | continue; | ||
| 398 | if (r->end >= res->start && res->end >= r->start) { | ||
| 399 | *conflict = r; | ||
| 400 | return 1; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | } | ||
| 404 | list_for_each_entry(dev, &parent->devices, bus_list) { | ||
| 405 | for (i = 0; i < 6; ++i) { | ||
| 406 | r = &dev->resource[i]; | ||
| 407 | if (!r->flags || (r->flags & IORESOURCE_UNSET)) | ||
| 408 | continue; | ||
| 409 | if (pci_find_parent_resource(dev, r) != pr) | ||
| 410 | continue; | ||
| 411 | if (r->end >= res->start && res->end >= r->start) { | ||
| 412 | *conflict = r; | ||
| 413 | return 1; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | static void __init | ||
| 421 | update_bridge_base(struct pci_bus *bus, int i) | ||
| 422 | { | ||
| 423 | struct resource *res = bus->resource[i]; | ||
| 424 | u8 io_base_lo, io_limit_lo; | ||
| 425 | u16 mem_base, mem_limit; | ||
| 426 | u16 cmd; | ||
| 427 | unsigned long start, end, off; | ||
| 428 | struct pci_dev *dev = bus->self; | ||
| 429 | struct pci_controller *hose = dev->sysdata; | ||
| 430 | |||
| 431 | if (!hose) { | ||
| 432 | printk("update_bridge_base: no hose?\n"); | ||
| 433 | return; | ||
| 434 | } | ||
| 435 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 436 | pci_write_config_word(dev, PCI_COMMAND, | ||
| 437 | cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); | ||
| 438 | if (res->flags & IORESOURCE_IO) { | ||
| 439 | off = (unsigned long) hose->io_base_virt - isa_io_base; | ||
| 440 | start = res->start - off; | ||
| 441 | end = res->end - off; | ||
| 442 | io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK; | ||
| 443 | io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK; | ||
| 444 | if (end > 0xffff) { | ||
| 445 | pci_write_config_word(dev, PCI_IO_BASE_UPPER16, | ||
| 446 | start >> 16); | ||
| 447 | pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16, | ||
| 448 | end >> 16); | ||
| 449 | io_base_lo |= PCI_IO_RANGE_TYPE_32; | ||
| 450 | } else | ||
| 451 | io_base_lo |= PCI_IO_RANGE_TYPE_16; | ||
| 452 | pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo); | ||
| 453 | pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo); | ||
| 454 | |||
| 455 | } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) | ||
| 456 | == IORESOURCE_MEM) { | ||
| 457 | off = hose->pci_mem_offset; | ||
| 458 | mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK; | ||
| 459 | mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK; | ||
| 460 | pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base); | ||
| 461 | pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit); | ||
| 462 | |||
| 463 | } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH)) | ||
| 464 | == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) { | ||
| 465 | off = hose->pci_mem_offset; | ||
| 466 | mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK; | ||
| 467 | mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK; | ||
| 468 | pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base); | ||
| 469 | pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit); | ||
| 470 | |||
| 471 | } else { | ||
| 472 | DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n", | ||
| 473 | pci_name(dev), i, res->flags); | ||
| 474 | } | ||
| 475 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 476 | } | ||
| 477 | |||
| 478 | static inline void alloc_resource(struct pci_dev *dev, int idx) | ||
| 479 | { | ||
| 480 | struct resource *pr, *r = &dev->resource[idx]; | ||
| 481 | |||
| 482 | DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n", | ||
| 483 | pci_name(dev), idx, r->start, r->end, r->flags); | ||
| 484 | pr = pci_find_parent_resource(dev, r); | ||
| 485 | if (!pr || request_resource(pr, r) < 0) { | ||
| 486 | printk(KERN_ERR "PCI: Cannot allocate resource region %d" | ||
| 487 | " of device %s\n", idx, pci_name(dev)); | ||
| 488 | if (pr) | ||
| 489 | DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n", | ||
| 490 | pr, pr->start, pr->end, pr->flags); | ||
| 491 | /* We'll assign a new address later */ | ||
| 492 | r->flags |= IORESOURCE_UNSET; | ||
| 493 | r->end -= r->start; | ||
| 494 | r->start = 0; | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | static void __init | ||
| 499 | pcibios_allocate_resources(int pass) | ||
| 500 | { | ||
| 501 | struct pci_dev *dev = NULL; | ||
| 502 | int idx, disabled; | ||
| 503 | u16 command; | ||
| 504 | struct resource *r; | ||
| 505 | |||
| 506 | for_each_pci_dev(dev) { | ||
| 507 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
| 508 | for (idx = 0; idx < 6; idx++) { | ||
| 509 | r = &dev->resource[idx]; | ||
| 510 | if (r->parent) /* Already allocated */ | ||
| 511 | continue; | ||
| 512 | if (!r->flags || (r->flags & IORESOURCE_UNSET)) | ||
| 513 | continue; /* Not assigned at all */ | ||
| 514 | if (r->flags & IORESOURCE_IO) | ||
| 515 | disabled = !(command & PCI_COMMAND_IO); | ||
| 516 | else | ||
| 517 | disabled = !(command & PCI_COMMAND_MEMORY); | ||
| 518 | if (pass == disabled) | ||
| 519 | alloc_resource(dev, idx); | ||
| 520 | } | ||
| 521 | if (pass) | ||
| 522 | continue; | ||
| 523 | r = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 524 | if (r->flags & IORESOURCE_ROM_ENABLE) { | ||
| 525 | /* Turn the ROM off, leave the resource region, but keep it unregistered. */ | ||
| 526 | u32 reg; | ||
| 527 | DBG("PCI: Switching off ROM of %s\n", pci_name(dev)); | ||
| 528 | r->flags &= ~IORESOURCE_ROM_ENABLE; | ||
| 529 | pci_read_config_dword(dev, dev->rom_base_reg, ®); | ||
| 530 | pci_write_config_dword(dev, dev->rom_base_reg, | ||
| 531 | reg & ~PCI_ROM_ADDRESS_ENABLE); | ||
| 532 | } | ||
| 533 | } | ||
| 534 | } | ||
| 535 | |||
| 536 | static void __init | ||
| 537 | pcibios_assign_resources(void) | ||
| 538 | { | ||
| 539 | struct pci_dev *dev = NULL; | ||
| 540 | int idx; | ||
| 541 | struct resource *r; | ||
| 542 | |||
| 543 | for_each_pci_dev(dev) { | ||
| 544 | int class = dev->class >> 8; | ||
| 545 | |||
| 546 | /* Don't touch classless devices and host bridges */ | ||
| 547 | if (!class || class == PCI_CLASS_BRIDGE_HOST) | ||
| 548 | continue; | ||
| 549 | |||
| 550 | for (idx = 0; idx < 6; idx++) { | ||
| 551 | r = &dev->resource[idx]; | ||
| 552 | |||
| 553 | /* | ||
| 554 | * We shall assign a new address to this resource, | ||
| 555 | * either because the BIOS (sic) forgot to do so | ||
| 556 | * or because we have decided the old address was | ||
| 557 | * unusable for some reason. | ||
| 558 | */ | ||
| 559 | if ((r->flags & IORESOURCE_UNSET) && r->end && | ||
| 560 | (!ppc_md.pcibios_enable_device_hook || | ||
| 561 | !ppc_md.pcibios_enable_device_hook(dev, 1))) { | ||
| 562 | r->flags &= ~IORESOURCE_UNSET; | ||
| 563 | pci_assign_resource(dev, idx); | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 567 | #if 0 /* don't assign ROMs */ | ||
| 568 | r = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 569 | r->end -= r->start; | ||
| 570 | r->start = 0; | ||
| 571 | if (r->end) | ||
| 572 | pci_assign_resource(dev, PCI_ROM_RESOURCE); | ||
| 573 | #endif | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | |||
| 578 | int | ||
| 579 | pcibios_enable_resources(struct pci_dev *dev, int mask) | ||
| 580 | { | ||
| 581 | u16 cmd, old_cmd; | ||
| 582 | int idx; | ||
| 583 | struct resource *r; | ||
| 584 | |||
| 585 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 586 | old_cmd = cmd; | ||
| 587 | for (idx=0; idx<6; idx++) { | ||
| 588 | /* Only set up the requested stuff */ | ||
| 589 | if (!(mask & (1<<idx))) | ||
| 590 | continue; | ||
| 591 | |||
| 592 | r = &dev->resource[idx]; | ||
| 593 | if (r->flags & IORESOURCE_UNSET) { | ||
| 594 | printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||
| 595 | return -EINVAL; | ||
| 596 | } | ||
| 597 | if (r->flags & IORESOURCE_IO) | ||
| 598 | cmd |= PCI_COMMAND_IO; | ||
| 599 | if (r->flags & IORESOURCE_MEM) | ||
| 600 | cmd |= PCI_COMMAND_MEMORY; | ||
| 601 | } | ||
| 602 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
| 603 | cmd |= PCI_COMMAND_MEMORY; | ||
| 604 | if (cmd != old_cmd) { | ||
| 605 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | ||
| 606 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 607 | } | ||
| 608 | return 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | static int next_controller_index; | ||
| 612 | |||
| 613 | struct pci_controller * __init | ||
| 614 | pcibios_alloc_controller(void) | ||
| 615 | { | ||
| 616 | struct pci_controller *hose; | ||
| 617 | |||
| 618 | hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); | ||
| 619 | memset(hose, 0, sizeof(struct pci_controller)); | ||
| 620 | |||
| 621 | *hose_tail = hose; | ||
| 622 | hose_tail = &hose->next; | ||
| 623 | |||
| 624 | hose->index = next_controller_index++; | ||
| 625 | |||
| 626 | return hose; | ||
| 627 | } | ||
| 628 | |||
| 629 | #ifdef CONFIG_PPC_OF | ||
| 630 | /* | ||
| 631 | * Functions below are used on OpenFirmware machines. | ||
| 632 | */ | ||
| 633 | static void | ||
| 634 | make_one_node_map(struct device_node* node, u8 pci_bus) | ||
| 635 | { | ||
| 636 | int *bus_range; | ||
| 637 | int len; | ||
| 638 | |||
| 639 | if (pci_bus >= pci_bus_count) | ||
| 640 | return; | ||
| 641 | bus_range = (int *) get_property(node, "bus-range", &len); | ||
| 642 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
| 643 | printk(KERN_WARNING "Can't get bus-range for %s, " | ||
| 644 | "assuming it starts at 0\n", node->full_name); | ||
| 645 | pci_to_OF_bus_map[pci_bus] = 0; | ||
| 646 | } else | ||
| 647 | pci_to_OF_bus_map[pci_bus] = bus_range[0]; | ||
| 648 | |||
| 649 | for (node=node->child; node != 0;node = node->sibling) { | ||
| 650 | struct pci_dev* dev; | ||
| 651 | unsigned int *class_code, *reg; | ||
| 652 | |||
| 653 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
| 654 | if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
| 655 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) | ||
| 656 | continue; | ||
| 657 | reg = (unsigned int *)get_property(node, "reg", NULL); | ||
| 658 | if (!reg) | ||
| 659 | continue; | ||
| 660 | dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff)); | ||
| 661 | if (!dev || !dev->subordinate) | ||
| 662 | continue; | ||
| 663 | make_one_node_map(node, dev->subordinate->number); | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | void | ||
| 668 | pcibios_make_OF_bus_map(void) | ||
| 669 | { | ||
| 670 | int i; | ||
| 671 | struct pci_controller* hose; | ||
| 672 | u8* of_prop_map; | ||
| 673 | |||
| 674 | pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL); | ||
| 675 | if (!pci_to_OF_bus_map) { | ||
| 676 | printk(KERN_ERR "Can't allocate OF bus map !\n"); | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* We fill the bus map with invalid values, that helps | ||
| 681 | * debugging. | ||
| 682 | */ | ||
| 683 | for (i=0; i<pci_bus_count; i++) | ||
| 684 | pci_to_OF_bus_map[i] = 0xff; | ||
| 685 | |||
| 686 | /* For each hose, we begin searching bridges */ | ||
| 687 | for(hose=hose_head; hose; hose=hose->next) { | ||
| 688 | struct device_node* node; | ||
| 689 | node = (struct device_node *)hose->arch_data; | ||
| 690 | if (!node) | ||
| 691 | continue; | ||
| 692 | make_one_node_map(node, hose->first_busno); | ||
| 693 | } | ||
| 694 | of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL); | ||
| 695 | if (of_prop_map) | ||
| 696 | memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count); | ||
| 697 | #ifdef DEBUG | ||
| 698 | printk("PCI->OF bus map:\n"); | ||
| 699 | for (i=0; i<pci_bus_count; i++) { | ||
| 700 | if (pci_to_OF_bus_map[i] == 0xff) | ||
| 701 | continue; | ||
| 702 | printk("%d -> %d\n", i, pci_to_OF_bus_map[i]); | ||
| 703 | } | ||
| 704 | #endif | ||
| 705 | } | ||
| 706 | |||
| 707 | typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data); | ||
| 708 | |||
| 709 | static struct device_node* | ||
| 710 | scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data) | ||
| 711 | { | ||
| 712 | struct device_node* sub_node; | ||
| 713 | |||
| 714 | for (; node != 0;node = node->sibling) { | ||
| 715 | unsigned int *class_code; | ||
| 716 | |||
| 717 | if (filter(node, data)) | ||
| 718 | return node; | ||
| 719 | |||
| 720 | /* For PCI<->PCI bridges or CardBus bridges, we go down | ||
| 721 | * Note: some OFs create a parent node "multifunc-device" as | ||
| 722 | * a fake root for all functions of a multi-function device, | ||
| 723 | * we go down them as well. | ||
| 724 | */ | ||
| 725 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
| 726 | if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
| 727 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) && | ||
| 728 | strcmp(node->name, "multifunc-device")) | ||
| 729 | continue; | ||
| 730 | sub_node = scan_OF_pci_childs(node->child, filter, data); | ||
| 731 | if (sub_node) | ||
| 732 | return sub_node; | ||
| 733 | } | ||
| 734 | return NULL; | ||
| 735 | } | ||
| 736 | |||
| 737 | static int | ||
| 738 | scan_OF_pci_childs_iterator(struct device_node* node, void* data) | ||
| 739 | { | ||
| 740 | unsigned int *reg; | ||
| 741 | u8* fdata = (u8*)data; | ||
| 742 | |||
| 743 | reg = (unsigned int *) get_property(node, "reg", NULL); | ||
| 744 | if (reg && ((reg[0] >> 8) & 0xff) == fdata[1] | ||
| 745 | && ((reg[0] >> 16) & 0xff) == fdata[0]) | ||
| 746 | return 1; | ||
| 747 | return 0; | ||
| 748 | } | ||
| 749 | |||
| 750 | static struct device_node* | ||
| 751 | scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn) | ||
| 752 | { | ||
| 753 | u8 filter_data[2] = {bus, dev_fn}; | ||
| 754 | |||
| 755 | return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data); | ||
| 756 | } | ||
| 757 | |||
| 758 | /* | ||
| 759 | * Scans the OF tree for a device node matching a PCI device | ||
| 760 | */ | ||
| 761 | struct device_node * | ||
| 762 | pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) | ||
| 763 | { | ||
| 764 | struct pci_controller *hose; | ||
| 765 | struct device_node *node; | ||
| 766 | int busnr; | ||
| 767 | |||
| 768 | if (!have_of) | ||
| 769 | return NULL; | ||
| 770 | |||
| 771 | /* Lookup the hose */ | ||
| 772 | busnr = bus->number; | ||
| 773 | hose = pci_bus_to_hose(busnr); | ||
| 774 | if (!hose) | ||
| 775 | return NULL; | ||
| 776 | |||
| 777 | /* Check it has an OF node associated */ | ||
| 778 | node = (struct device_node *) hose->arch_data; | ||
| 779 | if (!node) | ||
| 780 | return NULL; | ||
| 781 | |||
| 782 | /* Fixup bus number according to what OF think it is. */ | ||
| 783 | #ifdef CONFIG_PPC_PMAC | ||
| 784 | /* The G5 need a special case here. Basically, we don't remap all | ||
| 785 | * busses on it so we don't create the pci-OF-map. However, we do | ||
| 786 | * remap the AGP bus and so have to deal with it. A future better | ||
| 787 | * fix has to be done by making the remapping per-host and always | ||
| 788 | * filling the pci_to_OF map. --BenH | ||
| 789 | */ | ||
| 790 | if (_machine == _MACH_Pmac && busnr >= 0xf0) | ||
| 791 | busnr -= 0xf0; | ||
| 792 | else | ||
| 793 | #endif | ||
| 794 | if (pci_to_OF_bus_map) | ||
| 795 | busnr = pci_to_OF_bus_map[busnr]; | ||
| 796 | if (busnr == 0xff) | ||
| 797 | return NULL; | ||
| 798 | |||
| 799 | /* Now, lookup childs of the hose */ | ||
| 800 | return scan_OF_childs_for_device(node->child, busnr, devfn); | ||
| 801 | } | ||
| 802 | EXPORT_SYMBOL(pci_busdev_to_OF_node); | ||
| 803 | |||
| 804 | struct device_node* | ||
| 805 | pci_device_to_OF_node(struct pci_dev *dev) | ||
| 806 | { | ||
| 807 | return pci_busdev_to_OF_node(dev->bus, dev->devfn); | ||
| 808 | } | ||
| 809 | EXPORT_SYMBOL(pci_device_to_OF_node); | ||
| 810 | |||
| 811 | /* This routine is meant to be used early during boot, when the | ||
| 812 | * PCI bus numbers have not yet been assigned, and you need to | ||
| 813 | * issue PCI config cycles to an OF device. | ||
| 814 | * It could also be used to "fix" RTAS config cycles if you want | ||
| 815 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
| 816 | * config cycles. | ||
| 817 | */ | ||
| 818 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
| 819 | { | ||
| 820 | if (!have_of) | ||
| 821 | return NULL; | ||
| 822 | while(node) { | ||
| 823 | struct pci_controller* hose; | ||
| 824 | for (hose=hose_head;hose;hose=hose->next) | ||
| 825 | if (hose->arch_data == node) | ||
| 826 | return hose; | ||
| 827 | node=node->parent; | ||
| 828 | } | ||
| 829 | return NULL; | ||
| 830 | } | ||
| 831 | |||
| 832 | static int | ||
| 833 | find_OF_pci_device_filter(struct device_node* node, void* data) | ||
| 834 | { | ||
| 835 | return ((void *)node == data); | ||
| 836 | } | ||
| 837 | |||
| 838 | /* | ||
| 839 | * Returns the PCI device matching a given OF node | ||
| 840 | */ | ||
| 841 | int | ||
| 842 | pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) | ||
| 843 | { | ||
| 844 | unsigned int *reg; | ||
| 845 | struct pci_controller* hose; | ||
| 846 | struct pci_dev* dev = NULL; | ||
| 847 | |||
| 848 | if (!have_of) | ||
| 849 | return -ENODEV; | ||
| 850 | /* Make sure it's really a PCI device */ | ||
| 851 | hose = pci_find_hose_for_OF_device(node); | ||
| 852 | if (!hose || !hose->arch_data) | ||
| 853 | return -ENODEV; | ||
| 854 | if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child, | ||
| 855 | find_OF_pci_device_filter, (void *)node)) | ||
| 856 | return -ENODEV; | ||
| 857 | reg = (unsigned int *) get_property(node, "reg", NULL); | ||
| 858 | if (!reg) | ||
| 859 | return -ENODEV; | ||
| 860 | *bus = (reg[0] >> 16) & 0xff; | ||
| 861 | *devfn = ((reg[0] >> 8) & 0xff); | ||
| 862 | |||
| 863 | /* Ok, here we need some tweak. If we have already renumbered | ||
| 864 | * all busses, we can't rely on the OF bus number any more. | ||
| 865 | * the pci_to_OF_bus_map is not enough as several PCI busses | ||
| 866 | * may match the same OF bus number. | ||
| 867 | */ | ||
| 868 | if (!pci_to_OF_bus_map) | ||
| 869 | return 0; | ||
| 870 | |||
| 871 | for_each_pci_dev(dev) | ||
| 872 | if (pci_to_OF_bus_map[dev->bus->number] == *bus && | ||
| 873 | dev->devfn == *devfn) { | ||
| 874 | *bus = dev->bus->number; | ||
| 875 | pci_dev_put(dev); | ||
| 876 | return 0; | ||
| 877 | } | ||
| 878 | |||
| 879 | return -ENODEV; | ||
| 880 | } | ||
| 881 | EXPORT_SYMBOL(pci_device_from_OF_node); | ||
| 882 | |||
| 883 | void __init | ||
| 884 | pci_process_bridge_OF_ranges(struct pci_controller *hose, | ||
| 885 | struct device_node *dev, int primary) | ||
| 886 | { | ||
| 887 | static unsigned int static_lc_ranges[256] __initdata; | ||
| 888 | unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; | ||
| 889 | unsigned int size; | ||
| 890 | int rlen = 0, orig_rlen; | ||
| 891 | int memno = 0; | ||
| 892 | struct resource *res; | ||
| 893 | int np, na = prom_n_addr_cells(dev); | ||
| 894 | np = na + 5; | ||
| 895 | |||
| 896 | /* First we try to merge ranges to fix a problem with some pmacs | ||
| 897 | * that can have more than 3 ranges, fortunately using contiguous | ||
| 898 | * addresses -- BenH | ||
| 899 | */ | ||
| 900 | dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); | ||
| 901 | if (!dt_ranges) | ||
| 902 | return; | ||
| 903 | /* Sanity check, though hopefully that never happens */ | ||
| 904 | if (rlen > sizeof(static_lc_ranges)) { | ||
| 905 | printk(KERN_WARNING "OF ranges property too large !\n"); | ||
| 906 | rlen = sizeof(static_lc_ranges); | ||
| 907 | } | ||
| 908 | lc_ranges = static_lc_ranges; | ||
| 909 | memcpy(lc_ranges, dt_ranges, rlen); | ||
| 910 | orig_rlen = rlen; | ||
| 911 | |||
| 912 | /* Let's work on a copy of the "ranges" property instead of damaging | ||
| 913 | * the device-tree image in memory | ||
| 914 | */ | ||
| 915 | ranges = lc_ranges; | ||
| 916 | prev = NULL; | ||
| 917 | while ((rlen -= np * sizeof(unsigned int)) >= 0) { | ||
| 918 | if (prev) { | ||
| 919 | if (prev[0] == ranges[0] && prev[1] == ranges[1] && | ||
| 920 | (prev[2] + prev[na+4]) == ranges[2] && | ||
| 921 | (prev[na+2] + prev[na+4]) == ranges[na+2]) { | ||
| 922 | prev[na+4] += ranges[na+4]; | ||
| 923 | ranges[0] = 0; | ||
| 924 | ranges += np; | ||
| 925 | continue; | ||
| 926 | } | ||
| 927 | } | ||
| 928 | prev = ranges; | ||
| 929 | ranges += np; | ||
| 930 | } | ||
| 931 | |||
| 932 | /* | ||
| 933 | * The ranges property is laid out as an array of elements, | ||
| 934 | * each of which comprises: | ||
| 935 | * cells 0 - 2: a PCI address | ||
| 936 | * cells 3 or 3+4: a CPU physical address | ||
| 937 | * (size depending on dev->n_addr_cells) | ||
| 938 | * cells 4+5 or 5+6: the size of the range | ||
| 939 | */ | ||
| 940 | ranges = lc_ranges; | ||
| 941 | rlen = orig_rlen; | ||
| 942 | while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { | ||
| 943 | res = NULL; | ||
| 944 | size = ranges[na+4]; | ||
| 945 | switch ((ranges[0] >> 24) & 0x3) { | ||
| 946 | case 1: /* I/O space */ | ||
| 947 | if (ranges[2] != 0) | ||
| 948 | break; | ||
| 949 | hose->io_base_phys = ranges[na+2]; | ||
| 950 | /* limit I/O space to 16MB */ | ||
| 951 | if (size > 0x01000000) | ||
| 952 | size = 0x01000000; | ||
| 953 | hose->io_base_virt = ioremap(ranges[na+2], size); | ||
| 954 | if (primary) | ||
| 955 | isa_io_base = (unsigned long) hose->io_base_virt; | ||
| 956 | res = &hose->io_resource; | ||
| 957 | res->flags = IORESOURCE_IO; | ||
| 958 | res->start = ranges[2]; | ||
| 959 | DBG("PCI: IO 0x%lx -> 0x%lx\n", | ||
| 960 | res->start, res->start + size - 1); | ||
| 961 | break; | ||
| 962 | case 2: /* memory space */ | ||
| 963 | memno = 0; | ||
| 964 | if (ranges[1] == 0 && ranges[2] == 0 | ||
| 965 | && ranges[na+4] <= (16 << 20)) { | ||
| 966 | /* 1st 16MB, i.e. ISA memory area */ | ||
| 967 | if (primary) | ||
| 968 | isa_mem_base = ranges[na+2]; | ||
| 969 | memno = 1; | ||
| 970 | } | ||
| 971 | while (memno < 3 && hose->mem_resources[memno].flags) | ||
| 972 | ++memno; | ||
| 973 | if (memno == 0) | ||
| 974 | hose->pci_mem_offset = ranges[na+2] - ranges[2]; | ||
| 975 | if (memno < 3) { | ||
| 976 | res = &hose->mem_resources[memno]; | ||
| 977 | res->flags = IORESOURCE_MEM; | ||
| 978 | if(ranges[0] & 0x40000000) | ||
| 979 | res->flags |= IORESOURCE_PREFETCH; | ||
| 980 | res->start = ranges[na+2]; | ||
| 981 | DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno, | ||
| 982 | res->start, res->start + size - 1); | ||
| 983 | } | ||
| 984 | break; | ||
| 985 | } | ||
| 986 | if (res != NULL) { | ||
| 987 | res->name = dev->full_name; | ||
| 988 | res->end = res->start + size - 1; | ||
| 989 | res->parent = NULL; | ||
| 990 | res->sibling = NULL; | ||
| 991 | res->child = NULL; | ||
| 992 | } | ||
| 993 | ranges += np; | ||
| 994 | } | ||
| 995 | } | ||
| 996 | |||
| 997 | /* We create the "pci-OF-bus-map" property now so it appears in the | ||
| 998 | * /proc device tree | ||
| 999 | */ | ||
| 1000 | void __init | ||
| 1001 | pci_create_OF_bus_map(void) | ||
| 1002 | { | ||
| 1003 | struct property* of_prop; | ||
| 1004 | |||
| 1005 | of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256); | ||
| 1006 | if (of_prop && find_path_device("/")) { | ||
| 1007 | memset(of_prop, -1, sizeof(struct property) + 256); | ||
| 1008 | of_prop->name = "pci-OF-bus-map"; | ||
| 1009 | of_prop->length = 256; | ||
| 1010 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
| 1011 | prom_add_property(find_path_device("/"), of_prop); | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 1016 | { | ||
| 1017 | struct pci_dev *pdev; | ||
| 1018 | struct device_node *np; | ||
| 1019 | |||
| 1020 | pdev = to_pci_dev (dev); | ||
| 1021 | np = pci_device_to_OF_node(pdev); | ||
| 1022 | if (np == NULL || np->full_name == NULL) | ||
| 1023 | return 0; | ||
| 1024 | return sprintf(buf, "%s", np->full_name); | ||
| 1025 | } | ||
| 1026 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
| 1027 | |||
| 1028 | #else /* CONFIG_PPC_OF */ | ||
| 1029 | void pcibios_make_OF_bus_map(void) | ||
| 1030 | { | ||
| 1031 | } | ||
| 1032 | #endif /* CONFIG_PPC_OF */ | ||
| 1033 | |||
| 1034 | /* Add sysfs properties */ | ||
| 1035 | void pcibios_add_platform_entries(struct pci_dev *pdev) | ||
| 1036 | { | ||
| 1037 | #ifdef CONFIG_PPC_OF | ||
| 1038 | device_create_file(&pdev->dev, &dev_attr_devspec); | ||
| 1039 | #endif /* CONFIG_PPC_OF */ | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | |||
| 1043 | #ifdef CONFIG_PPC_PMAC | ||
| 1044 | /* | ||
| 1045 | * This set of routines checks for PCI<->PCI bridges that have closed | ||
| 1046 | * IO resources and have child devices. It tries to re-open an IO | ||
| 1047 | * window on them. | ||
| 1048 | * | ||
| 1049 | * This is a _temporary_ fix to workaround a problem with Apple's OF | ||
| 1050 | * closing IO windows on P2P bridges when the OF drivers of cards | ||
| 1051 | * below this bridge don't claim any IO range (typically ATI or | ||
| 1052 | * Adaptec). | ||
| 1053 | * | ||
| 1054 | * A more complete fix would be to use drivers/pci/setup-bus.c, which | ||
| 1055 | * involves a working pcibios_fixup_pbus_ranges(), some more care about | ||
| 1056 | * ordering when creating the host bus resources, and maybe a few more | ||
| 1057 | * minor tweaks | ||
| 1058 | */ | ||
| 1059 | |||
| 1060 | /* Initialize bridges with base/limit values we have collected */ | ||
| 1061 | static void __init | ||
| 1062 | do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) | ||
| 1063 | { | ||
| 1064 | struct pci_dev *bridge = bus->self; | ||
| 1065 | struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; | ||
| 1066 | u32 l; | ||
| 1067 | u16 w; | ||
| 1068 | struct resource res; | ||
| 1069 | |||
| 1070 | if (bus->resource[0] == NULL) | ||
| 1071 | return; | ||
| 1072 | res = *(bus->resource[0]); | ||
| 1073 | |||
| 1074 | DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); | ||
| 1075 | res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
| 1076 | res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
| 1077 | DBG(" IO window: %08lx-%08lx\n", res.start, res.end); | ||
| 1078 | |||
| 1079 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | ||
| 1080 | pci_read_config_dword(bridge, PCI_IO_BASE, &l); | ||
| 1081 | l &= 0xffff000f; | ||
| 1082 | l |= (res.start >> 8) & 0x00f0; | ||
| 1083 | l |= res.end & 0xf000; | ||
| 1084 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | ||
| 1085 | |||
| 1086 | if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { | ||
| 1087 | l = (res.start >> 16) | (res.end & 0xffff0000); | ||
| 1088 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | pci_read_config_word(bridge, PCI_COMMAND, &w); | ||
| 1092 | w |= PCI_COMMAND_IO; | ||
| 1093 | pci_write_config_word(bridge, PCI_COMMAND, w); | ||
| 1094 | |||
| 1095 | #if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ | ||
| 1096 | if (enable_vga) { | ||
| 1097 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); | ||
| 1098 | w |= PCI_BRIDGE_CTL_VGA; | ||
| 1099 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); | ||
| 1100 | } | ||
| 1101 | #endif | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | /* This function is pretty basic and actually quite broken for the | ||
| 1105 | * general case, it's enough for us right now though. It's supposed | ||
| 1106 | * to tell us if we need to open an IO range at all or not and what | ||
| 1107 | * size. | ||
| 1108 | */ | ||
| 1109 | static int __init | ||
| 1110 | check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) | ||
| 1111 | { | ||
| 1112 | struct pci_dev *dev; | ||
| 1113 | int i; | ||
| 1114 | int rc = 0; | ||
| 1115 | |||
| 1116 | #define push_end(res, size) do { unsigned long __sz = (size) ; \ | ||
| 1117 | res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ | ||
| 1118 | } while (0) | ||
| 1119 | |||
| 1120 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 1121 | u16 class = dev->class >> 8; | ||
| 1122 | |||
| 1123 | if (class == PCI_CLASS_DISPLAY_VGA || | ||
| 1124 | class == PCI_CLASS_NOT_DEFINED_VGA) | ||
| 1125 | *found_vga = 1; | ||
| 1126 | if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) | ||
| 1127 | rc |= check_for_io_childs(dev->subordinate, res, found_vga); | ||
| 1128 | if (class == PCI_CLASS_BRIDGE_CARDBUS) | ||
| 1129 | push_end(res, 0xfff); | ||
| 1130 | |||
| 1131 | for (i=0; i<PCI_NUM_RESOURCES; i++) { | ||
| 1132 | struct resource *r; | ||
| 1133 | unsigned long r_size; | ||
| 1134 | |||
| 1135 | if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI | ||
| 1136 | && i >= PCI_BRIDGE_RESOURCES) | ||
| 1137 | continue; | ||
| 1138 | r = &dev->resource[i]; | ||
| 1139 | r_size = r->end - r->start; | ||
| 1140 | if (r_size < 0xfff) | ||
| 1141 | r_size = 0xfff; | ||
| 1142 | if (r->flags & IORESOURCE_IO && (r_size) != 0) { | ||
| 1143 | rc = 1; | ||
| 1144 | push_end(res, r_size); | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | return rc; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /* Here we scan all P2P bridges of a given level that have a closed | ||
| 1153 | * IO window. Note that the test for the presence of a VGA card should | ||
| 1154 | * be improved to take into account already configured P2P bridges, | ||
| 1155 | * currently, we don't see them and might end up configuring 2 bridges | ||
| 1156 | * with VGA pass through enabled | ||
| 1157 | */ | ||
| 1158 | static void __init | ||
| 1159 | do_fixup_p2p_level(struct pci_bus *bus) | ||
| 1160 | { | ||
| 1161 | struct pci_bus *b; | ||
| 1162 | int i, parent_io; | ||
| 1163 | int has_vga = 0; | ||
| 1164 | |||
| 1165 | for (parent_io=0; parent_io<4; parent_io++) | ||
| 1166 | if (bus->resource[parent_io] | ||
| 1167 | && bus->resource[parent_io]->flags & IORESOURCE_IO) | ||
| 1168 | break; | ||
| 1169 | if (parent_io >= 4) | ||
| 1170 | return; | ||
| 1171 | |||
| 1172 | list_for_each_entry(b, &bus->children, node) { | ||
| 1173 | struct pci_dev *d = b->self; | ||
| 1174 | struct pci_controller* hose = (struct pci_controller *)d->sysdata; | ||
| 1175 | struct resource *res = b->resource[0]; | ||
| 1176 | struct resource tmp_res; | ||
| 1177 | unsigned long max; | ||
| 1178 | int found_vga = 0; | ||
| 1179 | |||
| 1180 | memset(&tmp_res, 0, sizeof(tmp_res)); | ||
| 1181 | tmp_res.start = bus->resource[parent_io]->start; | ||
| 1182 | |||
| 1183 | /* We don't let low addresses go through that closed P2P bridge, well, | ||
| 1184 | * that may not be necessary but I feel safer that way | ||
| 1185 | */ | ||
| 1186 | if (tmp_res.start == 0) | ||
| 1187 | tmp_res.start = 0x1000; | ||
| 1188 | |||
| 1189 | if (!list_empty(&b->devices) && res && res->flags == 0 && | ||
| 1190 | res != bus->resource[parent_io] && | ||
| 1191 | (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && | ||
| 1192 | check_for_io_childs(b, &tmp_res, &found_vga)) { | ||
| 1193 | u8 io_base_lo; | ||
| 1194 | |||
| 1195 | printk(KERN_INFO "Fixing up IO bus %s\n", b->name); | ||
| 1196 | |||
| 1197 | if (found_vga) { | ||
| 1198 | if (has_vga) { | ||
| 1199 | printk(KERN_WARNING "Skipping VGA, already active" | ||
| 1200 | " on bus segment\n"); | ||
| 1201 | found_vga = 0; | ||
| 1202 | } else | ||
| 1203 | has_vga = 1; | ||
| 1204 | } | ||
| 1205 | pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); | ||
| 1206 | |||
| 1207 | if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) | ||
| 1208 | max = ((unsigned long) hose->io_base_virt | ||
| 1209 | - isa_io_base) + 0xffffffff; | ||
| 1210 | else | ||
| 1211 | max = ((unsigned long) hose->io_base_virt | ||
| 1212 | - isa_io_base) + 0xffff; | ||
| 1213 | |||
| 1214 | *res = tmp_res; | ||
| 1215 | res->flags = IORESOURCE_IO; | ||
| 1216 | res->name = b->name; | ||
| 1217 | |||
| 1218 | /* Find a resource in the parent where we can allocate */ | ||
| 1219 | for (i = 0 ; i < 4; i++) { | ||
| 1220 | struct resource *r = bus->resource[i]; | ||
| 1221 | if (!r) | ||
| 1222 | continue; | ||
| 1223 | if ((r->flags & IORESOURCE_IO) == 0) | ||
| 1224 | continue; | ||
| 1225 | DBG("Trying to allocate from %08lx, size %08lx from parent" | ||
| 1226 | " res %d: %08lx -> %08lx\n", | ||
| 1227 | res->start, res->end, i, r->start, r->end); | ||
| 1228 | |||
| 1229 | if (allocate_resource(r, res, res->end + 1, res->start, max, | ||
| 1230 | res->end + 1, NULL, NULL) < 0) { | ||
| 1231 | DBG("Failed !\n"); | ||
| 1232 | continue; | ||
| 1233 | } | ||
| 1234 | do_update_p2p_io_resource(b, found_vga); | ||
| 1235 | break; | ||
| 1236 | } | ||
| 1237 | } | ||
| 1238 | do_fixup_p2p_level(b); | ||
| 1239 | } | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static void | ||
| 1243 | pcibios_fixup_p2p_bridges(void) | ||
| 1244 | { | ||
| 1245 | struct pci_bus *b; | ||
| 1246 | |||
| 1247 | list_for_each_entry(b, &pci_root_buses, node) | ||
| 1248 | do_fixup_p2p_level(b); | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1252 | |||
| 1253 | static int __init | ||
| 1254 | pcibios_init(void) | ||
| 1255 | { | ||
| 1256 | struct pci_controller *hose; | ||
| 1257 | struct pci_bus *bus; | ||
| 1258 | int next_busno; | ||
| 1259 | |||
| 1260 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); | ||
| 1261 | |||
| 1262 | /* Scan all of the recorded PCI controllers. */ | ||
| 1263 | for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | ||
| 1264 | if (pci_assign_all_buses) | ||
| 1265 | hose->first_busno = next_busno; | ||
| 1266 | hose->last_busno = 0xff; | ||
| 1267 | bus = pci_scan_bus(hose->first_busno, hose->ops, hose); | ||
| 1268 | hose->last_busno = bus->subordinate; | ||
| 1269 | if (pci_assign_all_buses || next_busno <= hose->last_busno) | ||
| 1270 | next_busno = hose->last_busno + pcibios_assign_bus_offset; | ||
| 1271 | } | ||
| 1272 | pci_bus_count = next_busno; | ||
| 1273 | |||
| 1274 | /* OpenFirmware based machines need a map of OF bus | ||
| 1275 | * numbers vs. kernel bus numbers since we may have to | ||
| 1276 | * remap them. | ||
| 1277 | */ | ||
| 1278 | if (pci_assign_all_buses && have_of) | ||
| 1279 | pcibios_make_OF_bus_map(); | ||
| 1280 | |||
| 1281 | /* Do machine dependent PCI interrupt routing */ | ||
| 1282 | if (ppc_md.pci_swizzle && ppc_md.pci_map_irq) | ||
| 1283 | pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq); | ||
| 1284 | |||
| 1285 | /* Call machine dependent fixup */ | ||
| 1286 | if (ppc_md.pcibios_fixup) | ||
| 1287 | ppc_md.pcibios_fixup(); | ||
| 1288 | |||
| 1289 | /* Allocate and assign resources */ | ||
| 1290 | pcibios_allocate_bus_resources(&pci_root_buses); | ||
| 1291 | pcibios_allocate_resources(0); | ||
| 1292 | pcibios_allocate_resources(1); | ||
| 1293 | #ifdef CONFIG_PPC_PMAC | ||
| 1294 | pcibios_fixup_p2p_bridges(); | ||
| 1295 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1296 | pcibios_assign_resources(); | ||
| 1297 | |||
| 1298 | /* Call machine dependent post-init code */ | ||
| 1299 | if (ppc_md.pcibios_after_init) | ||
| 1300 | ppc_md.pcibios_after_init(); | ||
| 1301 | |||
| 1302 | return 0; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | subsys_initcall(pcibios_init); | ||
| 1306 | |||
| 1307 | unsigned char __init | ||
| 1308 | common_swizzle(struct pci_dev *dev, unsigned char *pinp) | ||
| 1309 | { | ||
| 1310 | struct pci_controller *hose = dev->sysdata; | ||
| 1311 | |||
| 1312 | if (dev->bus->number != hose->first_busno) { | ||
| 1313 | u8 pin = *pinp; | ||
| 1314 | do { | ||
| 1315 | pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); | ||
| 1316 | /* Move up the chain of bridges. */ | ||
| 1317 | dev = dev->bus->self; | ||
| 1318 | } while (dev->bus->self); | ||
| 1319 | *pinp = pin; | ||
| 1320 | |||
| 1321 | /* The slot is the idsel of the last bridge. */ | ||
| 1322 | } | ||
| 1323 | return PCI_SLOT(dev->devfn); | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, | ||
| 1327 | unsigned long start, unsigned long size) | ||
| 1328 | { | ||
| 1329 | return start; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | void __init pcibios_fixup_bus(struct pci_bus *bus) | ||
| 1333 | { | ||
| 1334 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | ||
| 1335 | unsigned long io_offset; | ||
| 1336 | struct resource *res; | ||
| 1337 | int i; | ||
| 1338 | |||
| 1339 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; | ||
| 1340 | if (bus->parent == NULL) { | ||
| 1341 | /* This is a host bridge - fill in its resources */ | ||
| 1342 | hose->bus = bus; | ||
| 1343 | |||
| 1344 | bus->resource[0] = res = &hose->io_resource; | ||
| 1345 | if (!res->flags) { | ||
| 1346 | if (io_offset) | ||
| 1347 | printk(KERN_ERR "I/O resource not set for host" | ||
| 1348 | " bridge %d\n", hose->index); | ||
| 1349 | res->start = 0; | ||
| 1350 | res->end = IO_SPACE_LIMIT; | ||
| 1351 | res->flags = IORESOURCE_IO; | ||
| 1352 | } | ||
| 1353 | res->start += io_offset; | ||
| 1354 | res->end += io_offset; | ||
| 1355 | |||
| 1356 | for (i = 0; i < 3; ++i) { | ||
| 1357 | res = &hose->mem_resources[i]; | ||
| 1358 | if (!res->flags) { | ||
| 1359 | if (i > 0) | ||
| 1360 | continue; | ||
| 1361 | printk(KERN_ERR "Memory resource not set for " | ||
| 1362 | "host bridge %d\n", hose->index); | ||
| 1363 | res->start = hose->pci_mem_offset; | ||
| 1364 | res->end = ~0U; | ||
| 1365 | res->flags = IORESOURCE_MEM; | ||
| 1366 | } | ||
| 1367 | bus->resource[i+1] = res; | ||
| 1368 | } | ||
| 1369 | } else { | ||
| 1370 | /* This is a subordinate bridge */ | ||
| 1371 | pci_read_bridge_bases(bus); | ||
| 1372 | |||
| 1373 | for (i = 0; i < 4; ++i) { | ||
| 1374 | if ((res = bus->resource[i]) == NULL) | ||
| 1375 | continue; | ||
| 1376 | if (!res->flags) | ||
| 1377 | continue; | ||
| 1378 | if (io_offset && (res->flags & IORESOURCE_IO)) { | ||
| 1379 | res->start += io_offset; | ||
| 1380 | res->end += io_offset; | ||
| 1381 | } else if (hose->pci_mem_offset | ||
| 1382 | && (res->flags & IORESOURCE_MEM)) { | ||
| 1383 | res->start += hose->pci_mem_offset; | ||
| 1384 | res->end += hose->pci_mem_offset; | ||
| 1385 | } | ||
| 1386 | } | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | if (ppc_md.pcibios_fixup_bus) | ||
| 1390 | ppc_md.pcibios_fixup_bus(bus); | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | char __init *pcibios_setup(char *str) | ||
| 1394 | { | ||
| 1395 | return str; | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | /* the next one is stolen from the alpha port... */ | ||
| 1399 | void __init | ||
| 1400 | pcibios_update_irq(struct pci_dev *dev, int irq) | ||
| 1401 | { | ||
| 1402 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
| 1403 | /* XXX FIXME - update OF device tree node interrupt property */ | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
| 1407 | { | ||
| 1408 | u16 cmd, old_cmd; | ||
| 1409 | int idx; | ||
| 1410 | struct resource *r; | ||
| 1411 | |||
| 1412 | if (ppc_md.pcibios_enable_device_hook) | ||
| 1413 | if (ppc_md.pcibios_enable_device_hook(dev, 0)) | ||
| 1414 | return -EINVAL; | ||
| 1415 | |||
| 1416 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 1417 | old_cmd = cmd; | ||
| 1418 | for (idx=0; idx<6; idx++) { | ||
| 1419 | r = &dev->resource[idx]; | ||
| 1420 | if (r->flags & IORESOURCE_UNSET) { | ||
| 1421 | printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||
| 1422 | return -EINVAL; | ||
| 1423 | } | ||
| 1424 | if (r->flags & IORESOURCE_IO) | ||
| 1425 | cmd |= PCI_COMMAND_IO; | ||
| 1426 | if (r->flags & IORESOURCE_MEM) | ||
| 1427 | cmd |= PCI_COMMAND_MEMORY; | ||
| 1428 | } | ||
| 1429 | if (cmd != old_cmd) { | ||
| 1430 | printk("PCI: Enabling device %s (%04x -> %04x)\n", | ||
| 1431 | pci_name(dev), old_cmd, cmd); | ||
| 1432 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 1433 | } | ||
| 1434 | return 0; | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | struct pci_controller* | ||
| 1438 | pci_bus_to_hose(int bus) | ||
| 1439 | { | ||
| 1440 | struct pci_controller* hose = hose_head; | ||
| 1441 | |||
| 1442 | for (; hose; hose = hose->next) | ||
| 1443 | if (bus >= hose->first_busno && bus <= hose->last_busno) | ||
| 1444 | return hose; | ||
| 1445 | return NULL; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | void __iomem * | ||
| 1449 | pci_bus_io_base(unsigned int bus) | ||
| 1450 | { | ||
| 1451 | struct pci_controller *hose; | ||
| 1452 | |||
| 1453 | hose = pci_bus_to_hose(bus); | ||
| 1454 | if (!hose) | ||
| 1455 | return NULL; | ||
| 1456 | return hose->io_base_virt; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | unsigned long | ||
| 1460 | pci_bus_io_base_phys(unsigned int bus) | ||
| 1461 | { | ||
| 1462 | struct pci_controller *hose; | ||
| 1463 | |||
| 1464 | hose = pci_bus_to_hose(bus); | ||
| 1465 | if (!hose) | ||
| 1466 | return 0; | ||
| 1467 | return hose->io_base_phys; | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | unsigned long | ||
| 1471 | pci_bus_mem_base_phys(unsigned int bus) | ||
| 1472 | { | ||
| 1473 | struct pci_controller *hose; | ||
| 1474 | |||
| 1475 | hose = pci_bus_to_hose(bus); | ||
| 1476 | if (!hose) | ||
| 1477 | return 0; | ||
| 1478 | return hose->pci_mem_offset; | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | unsigned long | ||
| 1482 | pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) | ||
| 1483 | { | ||
| 1484 | /* Hack alert again ! See comments in chrp_pci.c | ||
| 1485 | */ | ||
| 1486 | struct pci_controller* hose = | ||
| 1487 | (struct pci_controller *)pdev->sysdata; | ||
| 1488 | if (hose && res->flags & IORESOURCE_MEM) | ||
| 1489 | return res->start - hose->pci_mem_offset; | ||
| 1490 | /* We may want to do something with IOs here... */ | ||
| 1491 | return res->start; | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | |||
| 1495 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
| 1496 | unsigned long *offset, | ||
| 1497 | enum pci_mmap_state mmap_state) | ||
| 1498 | { | ||
| 1499 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
| 1500 | unsigned long io_offset = 0; | ||
| 1501 | int i, res_bit; | ||
| 1502 | |||
| 1503 | if (hose == 0) | ||
| 1504 | return NULL; /* should never happen */ | ||
| 1505 | |||
| 1506 | /* If memory, add on the PCI bridge address offset */ | ||
| 1507 | if (mmap_state == pci_mmap_mem) { | ||
| 1508 | *offset += hose->pci_mem_offset; | ||
| 1509 | res_bit = IORESOURCE_MEM; | ||
| 1510 | } else { | ||
| 1511 | io_offset = hose->io_base_virt - ___IO_BASE; | ||
| 1512 | *offset += io_offset; | ||
| 1513 | res_bit = IORESOURCE_IO; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | /* | ||
| 1517 | * Check that the offset requested corresponds to one of the | ||
| 1518 | * resources of the device. | ||
| 1519 | */ | ||
| 1520 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 1521 | struct resource *rp = &dev->resource[i]; | ||
| 1522 | int flags = rp->flags; | ||
| 1523 | |||
| 1524 | /* treat ROM as memory (should be already) */ | ||
| 1525 | if (i == PCI_ROM_RESOURCE) | ||
| 1526 | flags |= IORESOURCE_MEM; | ||
| 1527 | |||
| 1528 | /* Active and same type? */ | ||
| 1529 | if ((flags & res_bit) == 0) | ||
| 1530 | continue; | ||
| 1531 | |||
| 1532 | /* In the range of this resource? */ | ||
| 1533 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
| 1534 | continue; | ||
| 1535 | |||
| 1536 | /* found it! construct the final physical address */ | ||
| 1537 | if (mmap_state == pci_mmap_io) | ||
| 1538 | *offset += hose->io_base_phys - io_offset; | ||
| 1539 | return rp; | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | return NULL; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /* | ||
| 1546 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
| 1547 | * device mapping. | ||
| 1548 | */ | ||
| 1549 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
| 1550 | pgprot_t protection, | ||
| 1551 | enum pci_mmap_state mmap_state, | ||
| 1552 | int write_combine) | ||
| 1553 | { | ||
| 1554 | unsigned long prot = pgprot_val(protection); | ||
| 1555 | |||
| 1556 | /* Write combine is always 0 on non-memory space mappings. On | ||
| 1557 | * memory space, if the user didn't pass 1, we check for a | ||
| 1558 | * "prefetchable" resource. This is a bit hackish, but we use | ||
| 1559 | * this to workaround the inability of /sysfs to provide a write | ||
| 1560 | * combine bit | ||
| 1561 | */ | ||
| 1562 | if (mmap_state != pci_mmap_mem) | ||
| 1563 | write_combine = 0; | ||
| 1564 | else if (write_combine == 0) { | ||
| 1565 | if (rp->flags & IORESOURCE_PREFETCH) | ||
| 1566 | write_combine = 1; | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | /* XXX would be nice to have a way to ask for write-through */ | ||
| 1570 | prot |= _PAGE_NO_CACHE; | ||
| 1571 | if (write_combine) | ||
| 1572 | prot &= ~_PAGE_GUARDED; | ||
| 1573 | else | ||
| 1574 | prot |= _PAGE_GUARDED; | ||
| 1575 | |||
| 1576 | printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, | ||
| 1577 | prot); | ||
| 1578 | |||
| 1579 | return __pgprot(prot); | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | /* | ||
| 1583 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
| 1584 | * PCI device, it tries to find the PCI device first and calls the | ||
| 1585 | * above routine | ||
| 1586 | */ | ||
| 1587 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
| 1588 | unsigned long pfn, | ||
| 1589 | unsigned long size, | ||
| 1590 | pgprot_t protection) | ||
| 1591 | { | ||
| 1592 | struct pci_dev *pdev = NULL; | ||
| 1593 | struct resource *found = NULL; | ||
| 1594 | unsigned long prot = pgprot_val(protection); | ||
| 1595 | unsigned long offset = pfn << PAGE_SHIFT; | ||
| 1596 | int i; | ||
| 1597 | |||
| 1598 | if (page_is_ram(pfn)) | ||
| 1599 | return prot; | ||
| 1600 | |||
| 1601 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
| 1602 | |||
| 1603 | for_each_pci_dev(pdev) { | ||
| 1604 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
| 1605 | struct resource *rp = &pdev->resource[i]; | ||
| 1606 | int flags = rp->flags; | ||
| 1607 | |||
| 1608 | /* Active and same type? */ | ||
| 1609 | if ((flags & IORESOURCE_MEM) == 0) | ||
| 1610 | continue; | ||
| 1611 | /* In the range of this resource? */ | ||
| 1612 | if (offset < (rp->start & PAGE_MASK) || | ||
| 1613 | offset > rp->end) | ||
| 1614 | continue; | ||
| 1615 | found = rp; | ||
| 1616 | break; | ||
| 1617 | } | ||
| 1618 | if (found) | ||
| 1619 | break; | ||
| 1620 | } | ||
| 1621 | if (found) { | ||
| 1622 | if (found->flags & IORESOURCE_PREFETCH) | ||
| 1623 | prot &= ~_PAGE_GUARDED; | ||
| 1624 | pci_dev_put(pdev); | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
| 1628 | |||
| 1629 | return __pgprot(prot); | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | |||
| 1633 | /* | ||
| 1634 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
| 1635 | * appropriate for this architecture. The region in the process to map | ||
| 1636 | * is described by vm_start and vm_end members of VMA, the base physical | ||
| 1637 | * address is found in vm_pgoff. | ||
| 1638 | * The pci device structure is provided so that architectures may make mapping | ||
| 1639 | * decisions on a per-device or per-bus basis. | ||
| 1640 | * | ||
| 1641 | * Returns a negative error code on failure, zero on success. | ||
| 1642 | */ | ||
| 1643 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
| 1644 | enum pci_mmap_state mmap_state, | ||
| 1645 | int write_combine) | ||
| 1646 | { | ||
| 1647 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 1648 | struct resource *rp; | ||
| 1649 | int ret; | ||
| 1650 | |||
| 1651 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
| 1652 | if (rp == NULL) | ||
| 1653 | return -EINVAL; | ||
| 1654 | |||
| 1655 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
| 1656 | vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO; | ||
| 1657 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
| 1658 | vma->vm_page_prot, | ||
| 1659 | mmap_state, write_combine); | ||
| 1660 | |||
| 1661 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
| 1662 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
| 1663 | |||
| 1664 | return ret; | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | /* Obsolete functions. Should be removed once the symbios driver | ||
| 1668 | * is fixed | ||
| 1669 | */ | ||
| 1670 | unsigned long | ||
| 1671 | phys_to_bus(unsigned long pa) | ||
| 1672 | { | ||
| 1673 | struct pci_controller *hose; | ||
| 1674 | int i; | ||
| 1675 | |||
| 1676 | for (hose = hose_head; hose; hose = hose->next) { | ||
| 1677 | for (i = 0; i < 3; ++i) { | ||
| 1678 | if (pa >= hose->mem_resources[i].start | ||
| 1679 | && pa <= hose->mem_resources[i].end) { | ||
| 1680 | /* | ||
| 1681 | * XXX the hose->pci_mem_offset really | ||
| 1682 | * only applies to mem_resources[0]. | ||
| 1683 | * We need a way to store an offset for | ||
| 1684 | * the others. -- paulus | ||
| 1685 | */ | ||
| 1686 | if (i == 0) | ||
| 1687 | pa -= hose->pci_mem_offset; | ||
| 1688 | return pa; | ||
| 1689 | } | ||
| 1690 | } | ||
| 1691 | } | ||
| 1692 | /* hmmm, didn't find it */ | ||
| 1693 | return 0; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | unsigned long | ||
| 1697 | pci_phys_to_bus(unsigned long pa, int busnr) | ||
| 1698 | { | ||
| 1699 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
| 1700 | if (!hose) | ||
| 1701 | return pa; | ||
| 1702 | return pa - hose->pci_mem_offset; | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | unsigned long | ||
| 1706 | pci_bus_to_phys(unsigned int ba, int busnr) | ||
| 1707 | { | ||
| 1708 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
| 1709 | if (!hose) | ||
| 1710 | return ba; | ||
| 1711 | return ba + hose->pci_mem_offset; | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | /* Provide information on locations of various I/O regions in physical | ||
| 1715 | * memory. Do this on a per-card basis so that we choose the right | ||
| 1716 | * root bridge. | ||
| 1717 | * Note that the returned IO or memory base is a physical address | ||
| 1718 | */ | ||
| 1719 | |||
| 1720 | long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | ||
| 1721 | { | ||
| 1722 | struct pci_controller* hose; | ||
| 1723 | long result = -EOPNOTSUPP; | ||
| 1724 | |||
| 1725 | /* Argh ! Please forgive me for that hack, but that's the | ||
| 1726 | * simplest way to get existing XFree to not lockup on some | ||
| 1727 | * G5 machines... So when something asks for bus 0 io base | ||
| 1728 | * (bus 0 is HT root), we return the AGP one instead. | ||
| 1729 | */ | ||
| 1730 | #ifdef CONFIG_PPC_PMAC | ||
| 1731 | if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) | ||
| 1732 | if (bus == 0) | ||
| 1733 | bus = 0xf0; | ||
| 1734 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1735 | |||
| 1736 | hose = pci_bus_to_hose(bus); | ||
| 1737 | if (!hose) | ||
| 1738 | return -ENODEV; | ||
| 1739 | |||
| 1740 | switch (which) { | ||
| 1741 | case IOBASE_BRIDGE_NUMBER: | ||
| 1742 | return (long)hose->first_busno; | ||
| 1743 | case IOBASE_MEMORY: | ||
| 1744 | return (long)hose->pci_mem_offset; | ||
| 1745 | case IOBASE_IO: | ||
| 1746 | return (long)hose->io_base_phys; | ||
| 1747 | case IOBASE_ISA_IO: | ||
| 1748 | return (long)isa_io_base; | ||
| 1749 | case IOBASE_ISA_MEM: | ||
| 1750 | return (long)isa_mem_base; | ||
| 1751 | } | ||
| 1752 | |||
| 1753 | return result; | ||
| 1754 | } | ||
| 1755 | |||
| 1756 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 1757 | const struct resource *rsrc, | ||
| 1758 | u64 *start, u64 *end) | ||
| 1759 | { | ||
| 1760 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
| 1761 | unsigned long offset = 0; | ||
| 1762 | |||
| 1763 | if (hose == NULL) | ||
| 1764 | return; | ||
| 1765 | |||
| 1766 | if (rsrc->flags & IORESOURCE_IO) | ||
| 1767 | offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; | ||
| 1768 | |||
| 1769 | *start = rsrc->start + offset; | ||
| 1770 | *end = rsrc->end + offset; | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | void __init | ||
| 1774 | pci_init_resource(struct resource *res, unsigned long start, unsigned long end, | ||
| 1775 | int flags, char *name) | ||
| 1776 | { | ||
| 1777 | res->start = start; | ||
| 1778 | res->end = end; | ||
| 1779 | res->flags = flags; | ||
| 1780 | res->name = name; | ||
| 1781 | res->parent = NULL; | ||
| 1782 | res->sibling = NULL; | ||
| 1783 | res->child = NULL; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) | ||
| 1787 | { | ||
| 1788 | unsigned long start = pci_resource_start(dev, bar); | ||
| 1789 | unsigned long len = pci_resource_len(dev, bar); | ||
| 1790 | unsigned long flags = pci_resource_flags(dev, bar); | ||
| 1791 | |||
| 1792 | if (!len) | ||
| 1793 | return NULL; | ||
| 1794 | if (max && len > max) | ||
| 1795 | len = max; | ||
| 1796 | if (flags & IORESOURCE_IO) | ||
| 1797 | return ioport_map(start, len); | ||
| 1798 | if (flags & IORESOURCE_MEM) | ||
| 1799 | /* Not checking IORESOURCE_CACHEABLE because PPC does | ||
| 1800 | * not currently distinguish between ioremap and | ||
| 1801 | * ioremap_nocache. | ||
| 1802 | */ | ||
| 1803 | return ioremap(start, len); | ||
| 1804 | /* What? */ | ||
| 1805 | return NULL; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
| 1809 | { | ||
| 1810 | /* Nothing to do */ | ||
| 1811 | } | ||
| 1812 | EXPORT_SYMBOL(pci_iomap); | ||
| 1813 | EXPORT_SYMBOL(pci_iounmap); | ||
| 1814 | |||
| 1815 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
| 1816 | { | ||
| 1817 | struct pci_controller* hose = hose_head; | ||
| 1818 | |||
| 1819 | for (; hose; hose = hose->next) { | ||
| 1820 | unsigned int size = hose->io_resource.end - | ||
| 1821 | hose->io_resource.start + 1; | ||
| 1822 | if (address >= hose->io_base_phys && | ||
| 1823 | address < (hose->io_base_phys + size)) { | ||
| 1824 | unsigned long base = | ||
| 1825 | (unsigned long)hose->io_base_virt - _IO_BASE; | ||
| 1826 | return base + (address - hose->io_base_phys); | ||
| 1827 | } | ||
| 1828 | } | ||
| 1829 | return (unsigned int)-1; | ||
| 1830 | } | ||
| 1831 | EXPORT_SYMBOL(pci_address_to_pio); | ||
| 1832 | |||
| 1833 | /* | ||
| 1834 | * Null PCI config access functions, for the case when we can't | ||
| 1835 | * find a hose. | ||
| 1836 | */ | ||
| 1837 | #define NULL_PCI_OP(rw, size, type) \ | ||
| 1838 | static int \ | ||
| 1839 | null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ | ||
| 1840 | { \ | ||
| 1841 | return PCIBIOS_DEVICE_NOT_FOUND; \ | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | static int | ||
| 1845 | null_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 1846 | int len, u32 *val) | ||
| 1847 | { | ||
| 1848 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | static int | ||
| 1852 | null_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 1853 | int len, u32 val) | ||
| 1854 | { | ||
| 1855 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 1856 | } | ||
| 1857 | |||
| 1858 | static struct pci_ops null_pci_ops = | ||
| 1859 | { | ||
| 1860 | null_read_config, | ||
| 1861 | null_write_config | ||
| 1862 | }; | ||
| 1863 | |||
| 1864 | /* | ||
| 1865 | * These functions are used early on before PCI scanning is done | ||
| 1866 | * and all of the pci_dev and pci_bus structures have been created. | ||
| 1867 | */ | ||
| 1868 | static struct pci_bus * | ||
| 1869 | fake_pci_bus(struct pci_controller *hose, int busnr) | ||
| 1870 | { | ||
| 1871 | static struct pci_bus bus; | ||
| 1872 | |||
| 1873 | if (hose == 0) { | ||
| 1874 | hose = pci_bus_to_hose(busnr); | ||
| 1875 | if (hose == 0) | ||
| 1876 | printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); | ||
| 1877 | } | ||
| 1878 | bus.number = busnr; | ||
| 1879 | bus.sysdata = hose; | ||
| 1880 | bus.ops = hose? hose->ops: &null_pci_ops; | ||
| 1881 | return &bus; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | #define EARLY_PCI_OP(rw, size, type) \ | ||
| 1885 | int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ | ||
| 1886 | int devfn, int offset, type value) \ | ||
| 1887 | { \ | ||
| 1888 | return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \ | ||
| 1889 | devfn, offset, value); \ | ||
| 1890 | } | ||
| 1891 | |||
| 1892 | EARLY_PCI_OP(read, byte, u8 *) | ||
| 1893 | EARLY_PCI_OP(read, word, u16 *) | ||
| 1894 | EARLY_PCI_OP(read, dword, u32 *) | ||
| 1895 | EARLY_PCI_OP(write, byte, u8) | ||
| 1896 | EARLY_PCI_OP(write, word, u16) | ||
| 1897 | EARLY_PCI_OP(write, dword, u32) | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d963a12ec640..7881ec96ef11 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c  | |||
| @@ -605,7 +605,8 @@ static void __init early_cmdline_parse(void) | |||
| 605 | opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); | 605 | opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); | 
| 606 | if (opt) { | 606 | if (opt) { | 
| 607 | opt += 12; | 607 | opt += 12; | 
| 608 | RELOC(prom_crashk_size) = prom_memparse(opt, &opt); | 608 | RELOC(prom_crashk_size) = | 
| 609 | prom_memparse(opt, (const char **)&opt); | ||
| 609 | 610 | ||
| 610 | if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != | 611 | if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != | 
| 611 | RELOC(prom_crashk_size)) { | 612 | RELOC(prom_crashk_size)) { | 
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index f40451da037c..7d4099a34f92 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c  | |||
| @@ -316,7 +316,6 @@ static int __init add_bridge(struct device_node *dev) | |||
| 316 | char* disp_name; | 316 | char* disp_name; | 
| 317 | int *bus_range; | 317 | int *bus_range; | 
| 318 | int primary = 1; | 318 | int primary = 1; | 
| 319 | struct property *of_prop; | ||
| 320 | 319 | ||
| 321 | DBG("Adding PCI host bridge %s\n", dev->full_name); | 320 | DBG("Adding PCI host bridge %s\n", dev->full_name); | 
| 322 | 321 | ||
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index a1cb4d236720..ec5c1e10c407 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c  | |||
| @@ -71,38 +71,60 @@ | |||
| 71 | #define DBG(fmt...) | 71 | #define DBG(fmt...) | 
| 72 | #endif | 72 | #endif | 
| 73 | 73 | ||
| 74 | static unsigned long maple_find_nvram_base(void) | ||
| 75 | { | ||
| 76 | struct device_node *rtcs; | ||
| 77 | unsigned long result = 0; | ||
| 78 | |||
| 79 | /* find NVRAM device */ | ||
| 80 | rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111"); | ||
| 81 | if (rtcs) { | ||
| 82 | struct resource r; | ||
| 83 | if (of_address_to_resource(rtcs, 0, &r)) { | ||
| 84 | printk(KERN_EMERG "Maple: Unable to translate NVRAM" | ||
| 85 | " address\n"); | ||
| 86 | goto bail; | ||
| 87 | } | ||
| 88 | if (!(r.flags & IORESOURCE_IO)) { | ||
| 89 | printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n"); | ||
| 90 | goto bail; | ||
| 91 | } | ||
| 92 | result = r.start; | ||
| 93 | } else | ||
| 94 | printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); | ||
| 95 | bail: | ||
| 96 | of_node_put(rtcs); | ||
| 97 | return result; | ||
| 98 | } | ||
| 99 | |||
| 74 | static void maple_restart(char *cmd) | 100 | static void maple_restart(char *cmd) | 
| 75 | { | 101 | { | 
| 76 | unsigned int maple_nvram_base; | 102 | unsigned int maple_nvram_base; | 
| 77 | unsigned int maple_nvram_offset; | 103 | unsigned int maple_nvram_offset; | 
| 78 | unsigned int maple_nvram_command; | 104 | unsigned int maple_nvram_command; | 
| 79 | struct device_node *rtcs; | 105 | struct device_node *sp; | 
| 80 | 106 | ||
| 81 | /* find NVRAM device */ | 107 | maple_nvram_base = maple_find_nvram_base(); | 
| 82 | rtcs = find_compatible_devices("nvram", "AMD8111"); | 108 | if (maple_nvram_base == 0) | 
| 83 | if (rtcs && rtcs->addrs) { | 109 | goto fail; | 
| 84 | maple_nvram_base = rtcs->addrs[0].address; | ||
| 85 | } else { | ||
| 86 | printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); | ||
| 87 | printk(KERN_EMERG "Maple: Manual Restart Required\n"); | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | 110 | ||
| 91 | /* find service processor device */ | 111 | /* find service processor device */ | 
| 92 | rtcs = find_devices("service-processor"); | 112 | sp = of_find_node_by_name(NULL, "service-processor"); | 
| 93 | if (!rtcs) { | 113 | if (!sp) { | 
| 94 | printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); | 114 | printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); | 
| 95 | printk(KERN_EMERG "Maple: Manual Restart Required\n"); | 115 | goto fail; | 
| 96 | return; | ||
| 97 | } | 116 | } | 
| 98 | maple_nvram_offset = *(unsigned int*) get_property(rtcs, | 117 | maple_nvram_offset = *(unsigned int*) get_property(sp, | 
| 99 | "restart-addr", NULL); | 118 | "restart-addr", NULL); | 
| 100 | maple_nvram_command = *(unsigned int*) get_property(rtcs, | 119 | maple_nvram_command = *(unsigned int*) get_property(sp, | 
| 101 | "restart-value", NULL); | 120 | "restart-value", NULL); | 
| 121 | of_node_put(sp); | ||
| 102 | 122 | ||
| 103 | /* send command */ | 123 | /* send command */ | 
| 104 | outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); | 124 | outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); | 
| 105 | for (;;) ; | 125 | for (;;) ; | 
| 126 | fail: | ||
| 127 | printk(KERN_EMERG "Maple: Manual Restart Required\n"); | ||
| 106 | } | 128 | } | 
| 107 | 129 | ||
| 108 | static void maple_power_off(void) | 130 | static void maple_power_off(void) | 
| @@ -110,33 +132,29 @@ static void maple_power_off(void) | |||
| 110 | unsigned int maple_nvram_base; | 132 | unsigned int maple_nvram_base; | 
| 111 | unsigned int maple_nvram_offset; | 133 | unsigned int maple_nvram_offset; | 
| 112 | unsigned int maple_nvram_command; | 134 | unsigned int maple_nvram_command; | 
| 113 | struct device_node *rtcs; | 135 | struct device_node *sp; | 
| 114 | 136 | ||
| 115 | /* find NVRAM device */ | 137 | maple_nvram_base = maple_find_nvram_base(); | 
| 116 | rtcs = find_compatible_devices("nvram", "AMD8111"); | 138 | if (maple_nvram_base == 0) | 
| 117 | if (rtcs && rtcs->addrs) { | 139 | goto fail; | 
| 118 | maple_nvram_base = rtcs->addrs[0].address; | ||
| 119 | } else { | ||
| 120 | printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); | ||
| 121 | printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | 140 | ||
| 125 | /* find service processor device */ | 141 | /* find service processor device */ | 
| 126 | rtcs = find_devices("service-processor"); | 142 | sp = of_find_node_by_name(NULL, "service-processor"); | 
| 127 | if (!rtcs) { | 143 | if (!sp) { | 
| 128 | printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); | 144 | printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); | 
| 129 | printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); | 145 | goto fail; | 
| 130 | return; | ||
| 131 | } | 146 | } | 
| 132 | maple_nvram_offset = *(unsigned int*) get_property(rtcs, | 147 | maple_nvram_offset = *(unsigned int*) get_property(sp, | 
| 133 | "power-off-addr", NULL); | 148 | "power-off-addr", NULL); | 
| 134 | maple_nvram_command = *(unsigned int*) get_property(rtcs, | 149 | maple_nvram_command = *(unsigned int*) get_property(sp, | 
| 135 | "power-off-value", NULL); | 150 | "power-off-value", NULL); | 
| 151 | of_node_put(sp); | ||
| 136 | 152 | ||
| 137 | /* send command */ | 153 | /* send command */ | 
| 138 | outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); | 154 | outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); | 
| 139 | for (;;) ; | 155 | for (;;) ; | 
| 156 | fail: | ||
| 157 | printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); | ||
| 140 | } | 158 | } | 
| 141 | 159 | ||
| 142 | static void maple_halt(void) | 160 | static void maple_halt(void) | 
| @@ -179,9 +197,6 @@ void __init maple_setup_arch(void) | |||
| 179 | */ | 197 | */ | 
| 180 | static void __init maple_init_early(void) | 198 | static void __init maple_init_early(void) | 
| 181 | { | 199 | { | 
| 182 | unsigned int default_speed; | ||
| 183 | u64 physport; | ||
| 184 | |||
| 185 | DBG(" -> maple_init_early\n"); | 200 | DBG(" -> maple_init_early\n"); | 
| 186 | 201 | ||
| 187 | /* Initialize hash table, from now on, we can take hash faults | 202 | /* Initialize hash table, from now on, we can take hash faults | 
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 15846cc938ac..50bc4eb85353 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c  | |||
| @@ -168,11 +168,24 @@ unsigned long __init maple_get_boot_time(void) | |||
| 168 | struct rtc_time tm; | 168 | struct rtc_time tm; | 
| 169 | struct device_node *rtcs; | 169 | struct device_node *rtcs; | 
| 170 | 170 | ||
| 171 | rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); | 171 | rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); | 
| 172 | if (rtcs && rtcs->addrs) { | 172 | if (rtcs) { | 
| 173 | maple_rtc_addr = rtcs->addrs[0].address; | 173 | struct resource r; | 
| 174 | printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr); | 174 | if (of_address_to_resource(rtcs, 0, &r)) { | 
| 175 | } else { | 175 | printk(KERN_EMERG "Maple: Unable to translate RTC" | 
| 176 | " address\n"); | ||
| 177 | goto bail; | ||
| 178 | } | ||
| 179 | if (!(r.flags & IORESOURCE_IO)) { | ||
| 180 | printk(KERN_EMERG "Maple: RTC address isn't PIO!\n"); | ||
| 181 | goto bail; | ||
| 182 | } | ||
| 183 | maple_rtc_addr = r.start; | ||
| 184 | printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n", | ||
| 185 | maple_rtc_addr); | ||
| 186 | } | ||
| 187 | bail: | ||
| 188 | if (maple_rtc_addr == 0) { | ||
| 176 | maple_rtc_addr = RTC_PORT(0); /* legacy address */ | 189 | maple_rtc_addr = RTC_PORT(0); /* legacy address */ | 
| 177 | printk(KERN_INFO "Maple: No device node for RTC, assuming " | 190 | printk(KERN_INFO "Maple: No device node for RTC, assuming " | 
| 178 | "legacy address (0x%x)\n", maple_rtc_addr); | 191 | "legacy address (0x%x)\n", maple_rtc_addr); | 
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index d65810108bc3..11899f06bf06 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig  | |||
| @@ -58,11 +58,11 @@ config 6xx | |||
| 58 | help | 58 | help | 
| 59 | There are four types of PowerPC chips supported. The more common | 59 | There are four types of PowerPC chips supported. The more common | 
| 60 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded | 60 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded | 
| 61 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded | 61 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM | 
| 62 | versions (403 and 405) and the high end 64 bit Power processors | 62 | embedded versions (403 and 405) and the POWER3 processor. | 
| 63 | (POWER 3, POWER4, and IBM 970 also known as G5) | 63 | (For support for more recent 64-bit processors, set ARCH=powerpc.) | 
| 64 | Unless you are building a kernel for one of the embedded processor | 64 | Unless you are building a kernel for one of the embedded processor | 
| 65 | systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx. | 65 | systems or a POWER3-based IBM RS/6000, choose 6xx. | 
| 66 | Note that the kernel runs in 32-bit mode even on 64-bit chips. | 66 | Note that the kernel runs in 32-bit mode even on 64-bit chips. | 
| 67 | Also note that because the 52xx, 82xx, & 83xx family has a 603e core, | 67 | Also note that because the 52xx, 82xx, & 83xx family has a 603e core, | 
| 68 | specific support for that chipset is asked later on. | 68 | specific support for that chipset is asked later on. | 
| @@ -77,10 +77,6 @@ config POWER3 | |||
| 77 | select PPC_FPU | 77 | select PPC_FPU | 
| 78 | bool "POWER3" | 78 | bool "POWER3" | 
| 79 | 79 | ||
| 80 | config POWER4 | ||
| 81 | select PPC_FPU | ||
| 82 | bool "POWER4 and 970 (G5)" | ||
| 83 | |||
| 84 | config 8xx | 80 | config 8xx | 
| 85 | bool "8xx" | 81 | bool "8xx" | 
| 86 | 82 | ||
| @@ -123,7 +119,7 @@ config PHYS_64BIT | |||
| 123 | 119 | ||
| 124 | config ALTIVEC | 120 | config ALTIVEC | 
| 125 | bool "AltiVec Support" | 121 | bool "AltiVec Support" | 
| 126 | depends on 6xx || POWER4 | 122 | depends on 6xx | 
| 127 | depends on !8260 && !83xx | 123 | depends on !8260 && !83xx | 
| 128 | ---help--- | 124 | ---help--- | 
| 129 | This option enables kernel support for the Altivec extensions to the | 125 | This option enables kernel support for the Altivec extensions to the | 
| @@ -235,18 +231,9 @@ config KEXEC | |||
| 235 | 231 | ||
| 236 | source "drivers/cpufreq/Kconfig" | 232 | source "drivers/cpufreq/Kconfig" | 
| 237 | 233 | ||
| 238 | config CPU_FREQ_PMAC | ||
| 239 | bool "Support for Apple PowerBooks" | ||
| 240 | depends on CPU_FREQ && ADB_PMU | ||
| 241 | select CPU_FREQ_TABLE | ||
| 242 | help | ||
| 243 | This adds support for frequency switching on Apple PowerBooks, | ||
| 244 | this currently includes some models of iBook & Titanium | ||
| 245 | PowerBook. | ||
| 246 | |||
| 247 | config PPC601_SYNC_FIX | 234 | config PPC601_SYNC_FIX | 
| 248 | bool "Workarounds for PPC601 bugs" | 235 | bool "Workarounds for PPC601 bugs" | 
| 249 | depends on 6xx && (PPC_PREP || PPC_PMAC) | 236 | depends on 6xx && PPC_PREP | 
| 250 | help | 237 | help | 
| 251 | Some versions of the PPC601 (the first PowerPC chip) have bugs which | 238 | Some versions of the PPC601 (the first PowerPC chip) have bugs which | 
| 252 | mean that extra synchronization instructions are required near | 239 | mean that extra synchronization instructions are required near | 
| @@ -258,26 +245,17 @@ config PPC601_SYNC_FIX | |||
| 258 | 245 | ||
| 259 | If in doubt, say Y here. | 246 | If in doubt, say Y here. | 
| 260 | 247 | ||
| 261 | config HOTPLUG_CPU | ||
| 262 | bool "Support for enabling/disabling CPUs" | ||
| 263 | depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC | ||
| 264 | ---help--- | ||
| 265 | Say Y here to be able to disable and re-enable individual | ||
| 266 | CPUs at runtime on SMP machines. | ||
| 267 | |||
| 268 | Say N if you are unsure. | ||
| 269 | |||
| 270 | source arch/ppc/platforms/4xx/Kconfig | 248 | source arch/ppc/platforms/4xx/Kconfig | 
| 271 | source arch/ppc/platforms/85xx/Kconfig | 249 | source arch/ppc/platforms/85xx/Kconfig | 
| 272 | 250 | ||
| 273 | config PPC64BRIDGE | 251 | config PPC64BRIDGE | 
| 274 | bool | 252 | bool | 
| 275 | depends on POWER3 || POWER4 | 253 | depends on POWER3 | 
| 276 | default y | 254 | default y | 
| 277 | 255 | ||
| 278 | config PPC_STD_MMU | 256 | config PPC_STD_MMU | 
| 279 | bool | 257 | bool | 
| 280 | depends on 6xx || POWER3 || POWER4 | 258 | depends on 6xx || POWER3 | 
| 281 | default y | 259 | default y | 
| 282 | 260 | ||
| 283 | config NOT_COHERENT_CACHE | 261 | config NOT_COHERENT_CACHE | 
| @@ -505,7 +483,7 @@ endchoice | |||
| 505 | 483 | ||
| 506 | choice | 484 | choice | 
| 507 | prompt "Machine Type" | 485 | prompt "Machine Type" | 
| 508 | depends on 6xx || POWER3 || POWER4 | 486 | depends on 6xx || POWER3 | 
| 509 | default PPC_MULTIPLATFORM | 487 | default PPC_MULTIPLATFORM | 
| 510 | ---help--- | 488 | ---help--- | 
| 511 | Linux currently supports several different kinds of PowerPC-based | 489 | Linux currently supports several different kinds of PowerPC-based | 
| @@ -516,11 +494,15 @@ choice | |||
| 516 | Platform) machines (including all of the recent IBM RS/6000 and | 494 | Platform) machines (including all of the recent IBM RS/6000 and | 
| 517 | pSeries machines), and several embedded PowerPC systems containing | 495 | pSeries machines), and several embedded PowerPC systems containing | 
| 518 | 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the | 496 | 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the | 
| 519 | default option is to build a kernel which works on the first three. | 497 | default option is to build a kernel which works on PReP and CHRP. | 
| 520 | 498 | ||
| 521 | Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or | 499 | Note that support for Apple machines is now only available with | 
| 522 | pSeries machine, a Power Macintosh (including iMacs, iBooks and | 500 | ARCH=powerpc, and has been removed from this menu. If you wish | 
| 523 | Powerbooks), or a PReP machine. | 501 | to build a kernel for an Apple machine, exit this configuration | 
| 502 | process and re-run it with ARCH=powerpc. | ||
| 503 | |||
| 504 | Select CHRP/PReP if configuring for an IBM RS/6000 or | ||
| 505 | pSeries machine, or a PReP machine. | ||
| 524 | 506 | ||
| 525 | Select Gemini if configuring for a Synergy Microsystems' Gemini | 507 | Select Gemini if configuring for a Synergy Microsystems' Gemini | 
| 526 | series Single Board Computer. More information is available at: | 508 | series Single Board Computer. More information is available at: | 
| @@ -530,7 +512,7 @@ choice | |||
| 530 | available at: <http://linux-apus.sourceforge.net/>. | 512 | available at: <http://linux-apus.sourceforge.net/>. | 
| 531 | 513 | ||
| 532 | config PPC_MULTIPLATFORM | 514 | config PPC_MULTIPLATFORM | 
| 533 | bool "CHRP/PowerMac/PReP" | 515 | bool "CHRP/PReP" | 
| 534 | 516 | ||
| 535 | config APUS | 517 | config APUS | 
| 536 | bool "Amiga-APUS" | 518 | bool "Amiga-APUS" | 
| @@ -768,25 +750,14 @@ config CPM2 | |||
| 768 | on it (826x, 827x, 8560). | 750 | on it (826x, 827x, 8560). | 
| 769 | 751 | ||
| 770 | config PPC_CHRP | 752 | config PPC_CHRP | 
| 771 | bool | 753 | bool "Support for CHRP (Common Hardware Reference Platform) machines" | 
| 772 | depends on PPC_MULTIPLATFORM | 754 | depends on PPC_MULTIPLATFORM | 
| 773 | select PPC_I8259 | 755 | select PPC_I8259 | 
| 774 | select PPC_INDIRECT_PCI | 756 | select PPC_INDIRECT_PCI | 
| 775 | default y | 757 | default y | 
| 776 | 758 | ||
| 777 | config PPC_PMAC | ||
| 778 | bool | ||
| 779 | depends on PPC_MULTIPLATFORM | ||
| 780 | select PPC_INDIRECT_PCI | ||
| 781 | default y | ||
| 782 | |||
| 783 | config PPC_PMAC64 | ||
| 784 | bool | ||
| 785 | depends on PPC_PMAC && POWER4 | ||
| 786 | default y | ||
| 787 | |||
| 788 | config PPC_PREP | 759 | config PPC_PREP | 
| 789 | bool | 760 | bool "Support for PReP (PowerPC Reference Platform) machines" | 
| 790 | depends on PPC_MULTIPLATFORM | 761 | depends on PPC_MULTIPLATFORM | 
| 791 | select PPC_I8259 | 762 | select PPC_I8259 | 
| 792 | select PPC_INDIRECT_PCI | 763 | select PPC_INDIRECT_PCI | 
| @@ -794,7 +765,7 @@ config PPC_PREP | |||
| 794 | 765 | ||
| 795 | config PPC_OF | 766 | config PPC_OF | 
| 796 | bool | 767 | bool | 
| 797 | depends on PPC_PMAC || PPC_CHRP | 768 | depends on PPC_CHRP | 
| 798 | default y | 769 | default y | 
| 799 | 770 | ||
| 800 | config PPC_GEN550 | 771 | config PPC_GEN550 | 
| @@ -1166,7 +1137,7 @@ config ISA | |||
| 1166 | 1137 | ||
| 1167 | config GENERIC_ISA_DMA | 1138 | config GENERIC_ISA_DMA | 
| 1168 | bool | 1139 | bool | 
| 1169 | depends on POWER3 || POWER4 || 6xx && !CPM2 | 1140 | depends on POWER3 || 6xx && !CPM2 | 
| 1170 | default y | 1141 | default y | 
| 1171 | 1142 | ||
| 1172 | config PPC_I8259 | 1143 | config PPC_I8259 | 
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile index 995f89bb049c..efd8ce515d5f 100644 --- a/arch/ppc/boot/Makefile +++ b/arch/ppc/boot/Makefile  | |||
| @@ -18,7 +18,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd | |||
| 18 | bootdir-y := simple | 18 | bootdir-y := simple | 
| 19 | bootdir-$(CONFIG_PPC_OF) += openfirmware | 19 | bootdir-$(CONFIG_PPC_OF) += openfirmware | 
| 20 | subdir-y := lib common images | 20 | subdir-y := lib common images | 
| 21 | subdir-$(CONFIG_PPC_OF) += of1275 | 21 | subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275 | 
| 22 | 22 | ||
| 23 | # for cleaning | 23 | # for cleaning | 
| 24 | subdir- += simple openfirmware | 24 | subdir- += simple openfirmware | 
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile index 83a6433459ce..2a411ec2e650 100644 --- a/arch/ppc/boot/openfirmware/Makefile +++ b/arch/ppc/boot/openfirmware/Makefile  | |||
| @@ -21,26 +21,16 @@ bootlib := $(boot)/lib | |||
| 21 | of1275 := $(boot)/of1275 | 21 | of1275 := $(boot)/of1275 | 
| 22 | images := $(boot)/images | 22 | images := $(boot)/images | 
| 23 | 23 | ||
| 24 | OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment | ||
| 25 | COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \ | ||
| 26 | -Bstatic | ||
| 27 | CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 | 24 | CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000 | 
| 28 | NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000 | ||
| 29 | 25 | ||
| 30 | COMMONOBJS := start.o misc.o common.o | 26 | COMMONOBJS := start.o misc.o common.o | 
| 31 | COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o | ||
| 32 | CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o | 27 | CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o | 
| 33 | NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o | ||
| 34 | 28 | ||
| 35 | targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o | 29 | targets := $(CHRPOBJS) dummy.o | 
| 36 | COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS)) | ||
| 37 | CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) | 30 | CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) | 
| 38 | NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS)) | ||
| 39 | 31 | ||
| 40 | LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a | 32 | LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a | 
| 41 | 33 | ||
| 42 | HACKCOFF := $(utils)/hack-coff | ||
| 43 | |||
| 44 | ifdef CONFIG_SMP | 34 | ifdef CONFIG_SMP | 
| 45 | END := .smp | 35 | END := .smp | 
| 46 | endif | 36 | endif | 
| @@ -72,56 +62,11 @@ targets += image.initrd.o | |||
| 72 | $(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE | 62 | $(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE | 
| 73 | $(call if_changed,genimage-initrd) | 63 | $(call if_changed,genimage-initrd) | 
| 74 | 64 | ||
| 75 | # Create the note section for New-World PowerMacs. | ||
| 76 | quiet_cmd_mknote = MKNOTE $@ | ||
| 77 | cmd_mknote = $(utils)/mknote > $@ | ||
| 78 | targets += note | ||
| 79 | $(obj)/note: $(utils)/mknote FORCE | ||
| 80 | $(call if_changed,mknote) | ||
| 81 | |||
| 82 | 65 | ||
| 83 | $(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF | 66 | targets += crt0.o | 
| 84 | targets += coffcrt0.o crt0.o | 67 | $(obj)/crt0.o: $(common)/crt0.S FORCE | 
| 85 | $(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE | ||
| 86 | $(call if_changed_dep,as_o_S) | 68 | $(call if_changed_dep,as_o_S) | 
| 87 | 69 | ||
| 88 | quiet_cmd_gencoffb = COFF $@ | ||
| 89 | cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \ | ||
| 90 | $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) | ||
| 91 | targets += coffboot | ||
| 92 | $(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE | ||
| 93 | $(call if_changed,gencoffb) | ||
| 94 | targets += coffboot.initrd | ||
| 95 | $(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \ | ||
| 96 | $(srctree)/$(boot)/ld.script FORCE | ||
| 97 | $(call if_changed,gencoffb) | ||
| 98 | |||
| 99 | |||
| 100 | quiet_cmd_gen-coff = COFF $@ | ||
| 101 | cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \ | ||
| 102 | $(HACKCOFF) $@ && \ | ||
| 103 | ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac | ||
| 104 | |||
| 105 | $(images)/vmlinux.coff: $(obj)/coffboot | ||
| 106 | $(call cmd,gen-coff) | ||
| 107 | |||
| 108 | $(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd | ||
| 109 | $(call cmd,gen-coff) | ||
| 110 | |||
| 111 | quiet_cmd_gen-elf-pmac = ELF $@ | ||
| 112 | cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \ | ||
| 113 | $(NEWWORLDOBJS) $(LIBS) $< && \ | ||
| 114 | $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \ | ||
| 115 | -R .comment $(del-ramdisk-sec) | ||
| 116 | |||
| 117 | $(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \ | ||
| 118 | $(obj)/note $(srctree)/$(boot)/ld.script | ||
| 119 | $(call cmd,gen-elf-pmac) | ||
| 120 | $(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ | ||
| 121 | $(LIBS) $(obj)/note \ | ||
| 122 | $(srctree)/$(boot)/ld.script | ||
| 123 | $(call cmd,gen-elf-pmac) | ||
| 124 | |||
| 125 | quiet_cmd_gen-chrp = CHRP $@ | 70 | quiet_cmd_gen-chrp = CHRP $@ | 
| 126 | cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ | 71 | cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \ | 
| 127 | $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) | 72 | $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) | 
| @@ -139,46 +84,23 @@ $(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \ | |||
| 139 | %-rs6k: % | 84 | %-rs6k: % | 
| 140 | $(call cmd,addnote) | 85 | $(call cmd,addnote) | 
| 141 | 86 | ||
| 142 | quiet_cmd_gen-miboot = GEN $@ | ||
| 143 | cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \ | ||
| 144 | --add-section=$1=$(word 2, $^) $< $@ | ||
| 145 | $(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz | ||
| 146 | $(call cmd,gen-miboot,image) | ||
| 147 | |||
| 148 | $(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz | ||
| 149 | $(call cmd,gen-miboot,initrd) | ||
| 150 | |||
| 151 | # The targets used on the make command-line | 87 | # The targets used on the make command-line | 
| 152 | 88 | ||
| 153 | .PHONY: zImage zImage.initrd | 89 | .PHONY: zImage zImage.initrd | 
| 154 | zImage: $(images)/vmlinux.coff \ | 90 | zImage: $(images)/zImage.chrp \ | 
| 155 | $(images)/vmlinux.elf-pmac \ | 91 | $(images)/zImage.chrp-rs6k | 
| 156 | $(images)/zImage.chrp \ | ||
| 157 | $(images)/zImage.chrp-rs6k \ | ||
| 158 | $(images)/miboot.image | ||
| 159 | @echo ' kernel: $@ is ready ($<)' | 92 | @echo ' kernel: $@ is ready ($<)' | 
| 160 | zImage.initrd: $(images)/vmlinux.initrd.coff \ | 93 | zImage.initrd: $(images)/zImage.initrd.chrp \ | 
| 161 | $(images)/vmlinux.initrd.elf-pmac \ | 94 | $(images)/zImage.initrd.chrp-rs6k | 
| 162 | $(images)/zImage.initrd.chrp \ | ||
| 163 | $(images)/zImage.initrd.chrp-rs6k \ | ||
| 164 | $(images)/miboot.initrd.image | ||
| 165 | @echo ' kernel: $@ is ready ($<)' | 95 | @echo ' kernel: $@ is ready ($<)' | 
| 166 | 96 | ||
| 167 | TFTPIMAGE := /tftpboot/zImage | 97 | TFTPIMAGE := /tftpboot/zImage | 
| 168 | 98 | ||
| 169 | .PHONY: znetboot znetboot.initrd | 99 | .PHONY: znetboot znetboot.initrd | 
| 170 | znetboot: $(images)/vmlinux.coff \ | 100 | znetboot: $(images)/zImage.chrp | 
| 171 | $(images)/vmlinux.elf-pmac \ | ||
| 172 | $(images)/zImage.chrp | ||
| 173 | cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) | ||
| 174 | cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf | ||
| 175 | cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) | 101 | cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) | 
| 176 | @echo ' kernel: $@ is ready ($<)' | 102 | @echo ' kernel: $@ is ready ($<)' | 
| 177 | znetboot.initrd:$(images)/vmlinux.initrd.coff \ | 103 | znetboot.initrd:$(images)/zImage.initrd.chrp | 
| 178 | $(images)/vmlinux.initrd.elf-pmac \ | ||
| 179 | $(images)/zImage.initrd.chrp | ||
| 180 | cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) | ||
| 181 | cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf | ||
| 182 | cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) | 104 | cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) | 
| 183 | @echo ' kernel: $@ is ready ($<)' | 105 | @echo ' kernel: $@ is ready ($<)' | 
| 184 | 106 | ||
diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c deleted file mode 100644 index 2da8855e2be0..000000000000 --- a/arch/ppc/boot/openfirmware/coffmain.c +++ /dev/null  | |||
| @@ -1,101 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Paul Mackerras 1997. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | #include <linux/string.h> | ||
| 10 | #include <asm/processor.h> | ||
| 11 | #include <asm/page.h> | ||
| 12 | |||
| 13 | #include "nonstdio.h" | ||
| 14 | #include "of1275.h" | ||
| 15 | |||
| 16 | /* Passed from the linker */ | ||
| 17 | extern char __image_begin, __image_end; | ||
| 18 | extern char __ramdisk_begin[], __ramdisk_end; | ||
| 19 | extern char _start, _end; | ||
| 20 | |||
| 21 | extern char image_data[], initrd_data[]; | ||
| 22 | extern int initrd_len, image_len; | ||
| 23 | extern unsigned int heap_max; | ||
| 24 | extern void flush_cache(void *start, unsigned int len); | ||
| 25 | extern void gunzip(void *, int, unsigned char *, int *); | ||
| 26 | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
| 27 | unsigned int progend); | ||
| 28 | extern void setup_bats(unsigned long start); | ||
| 29 | |||
| 30 | char *avail_ram; | ||
| 31 | char *begin_avail, *end_avail; | ||
| 32 | char *avail_high; | ||
| 33 | |||
| 34 | #define SCRATCH_SIZE (128 << 10) | ||
| 35 | |||
| 36 | static char heap[SCRATCH_SIZE]; | ||
| 37 | |||
| 38 | static unsigned long ram_start = 0; | ||
| 39 | static unsigned long ram_end = 0x1000000; | ||
| 40 | |||
| 41 | static unsigned long prog_start = 0x800000; | ||
| 42 | static unsigned long prog_size = 0x700000; | ||
| 43 | |||
| 44 | typedef void (*kernel_start_t)(int, int, void *); | ||
| 45 | |||
| 46 | void boot(int a1, int a2, void *prom) | ||
| 47 | { | ||
| 48 | unsigned sa, len; | ||
| 49 | void *dst; | ||
| 50 | unsigned char *im; | ||
| 51 | unsigned initrd_start, initrd_size; | ||
| 52 | |||
| 53 | printf("coffboot starting: loaded at 0x%p\n", &_start); | ||
| 54 | setup_bats(ram_start); | ||
| 55 | |||
| 56 | initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); | ||
| 57 | if (initrd_size) { | ||
| 58 | initrd_start = (ram_end - initrd_size) & ~0xFFF; | ||
| 59 | a1 = initrd_start; | ||
| 60 | a2 = initrd_size; | ||
| 61 | claim(initrd_start, ram_end - initrd_start, 0); | ||
| 62 | printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | ||
| 63 | initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
| 64 | memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
| 65 | prog_size = initrd_start - prog_start; | ||
| 66 | } else | ||
| 67 | a2 = 0xdeadbeef; | ||
| 68 | |||
| 69 | im = (char *)(&__image_begin); | ||
| 70 | len = (char *)(&__image_end) - (char *)(&__image_begin); | ||
| 71 | /* claim 4MB starting at PROG_START */ | ||
| 72 | claim(prog_start, prog_size, 0); | ||
| 73 | map(prog_start, prog_start, prog_size); | ||
| 74 | dst = (void *) prog_start; | ||
| 75 | if (im[0] == 0x1f && im[1] == 0x8b) { | ||
| 76 | /* set up scratch space */ | ||
| 77 | begin_avail = avail_high = avail_ram = heap; | ||
| 78 | end_avail = heap + sizeof(heap); | ||
| 79 | printf("heap at 0x%p\n", avail_ram); | ||
| 80 | printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | ||
| 81 | gunzip(dst, prog_size, im, &len); | ||
| 82 | printf("done %u bytes\n", len); | ||
| 83 | printf("%u bytes of heap consumed, max in use %u\n", | ||
| 84 | avail_high - begin_avail, heap_max); | ||
| 85 | } else { | ||
| 86 | memmove(dst, im, len); | ||
| 87 | } | ||
| 88 | |||
| 89 | flush_cache(dst, len); | ||
| 90 | make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac, | ||
| 91 | (prog_start + prog_size)); | ||
| 92 | |||
| 93 | sa = (unsigned long)prog_start; | ||
| 94 | printf("start address = 0x%x\n", sa); | ||
| 95 | |||
| 96 | (*(kernel_start_t)sa)(a1, a2, prom); | ||
| 97 | |||
| 98 | printf("returned?\n"); | ||
| 99 | |||
| 100 | pause(); | ||
| 101 | } | ||
diff --git a/arch/ppc/boot/openfirmware/newworldmain.c b/arch/ppc/boot/openfirmware/newworldmain.c deleted file mode 100644 index fa8a8f9313f9..000000000000 --- a/arch/ppc/boot/openfirmware/newworldmain.c +++ /dev/null  | |||
| @@ -1,94 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) Paul Mackerras 1997. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | #include <linux/string.h> | ||
| 10 | #include "nonstdio.h" | ||
| 11 | #include "of1275.h" | ||
| 12 | #include <asm/processor.h> | ||
| 13 | #include <asm/page.h> | ||
| 14 | |||
| 15 | /* Passed from the linker */ | ||
| 16 | extern char __image_begin, __image_end; | ||
| 17 | extern char __ramdisk_begin[], __ramdisk_end; | ||
| 18 | extern char _start, _end; | ||
| 19 | |||
| 20 | extern unsigned int heap_max; | ||
| 21 | extern void flush_cache(void *start, unsigned int len); | ||
| 22 | extern void gunzip(void *, int, unsigned char *, int *); | ||
| 23 | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | ||
| 24 | unsigned int progend); | ||
| 25 | |||
| 26 | char *avail_ram; | ||
| 27 | char *begin_avail, *end_avail; | ||
| 28 | char *avail_high; | ||
| 29 | |||
| 30 | |||
| 31 | #define RAM_END (16 << 20) | ||
| 32 | |||
| 33 | #define PROG_START 0x00010000 | ||
| 34 | #define PROG_SIZE 0x007f0000 | ||
| 35 | |||
| 36 | #define SCRATCH_SIZE (128 << 10) | ||
| 37 | |||
| 38 | typedef void (*kernel_start_t)(int, int, void *); | ||
| 39 | |||
| 40 | void boot(int a1, int a2, void *prom) | ||
| 41 | { | ||
| 42 | unsigned sa, len; | ||
| 43 | void *dst; | ||
| 44 | unsigned char *im; | ||
| 45 | unsigned initrd_start, initrd_size; | ||
| 46 | |||
| 47 | printf("chrpboot starting: loaded at 0x%p\n", &_start); | ||
| 48 | |||
| 49 | initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin); | ||
| 50 | if (initrd_size) { | ||
| 51 | initrd_start = (RAM_END - initrd_size) & ~0xFFF; | ||
| 52 | a1 = initrd_start; | ||
| 53 | a2 = initrd_size; | ||
| 54 | claim(initrd_start, RAM_END - initrd_start, 0); | ||
| 55 | printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | ||
| 56 | initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
| 57 | memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size); | ||
| 58 | } else | ||
| 59 | a2 = 0xdeadbeef; | ||
| 60 | |||
| 61 | im = (char *)(&__image_begin); | ||
| 62 | len = (char *)(&__image_end) - (char *)(&__image_begin); | ||
| 63 | /* claim 3MB starting at PROG_START */ | ||
| 64 | claim(PROG_START, PROG_SIZE, 0); | ||
| 65 | dst = (void *) PROG_START; | ||
| 66 | if (im[0] == 0x1f && im[1] == 0x8b) { | ||
| 67 | /* claim some memory for scratch space */ | ||
| 68 | avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10); | ||
| 69 | begin_avail = avail_high = avail_ram; | ||
| 70 | end_avail = avail_ram + SCRATCH_SIZE; | ||
| 71 | printf("heap at 0x%p\n", avail_ram); | ||
| 72 | printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | ||
| 73 | gunzip(dst, PROG_SIZE, im, &len); | ||
| 74 | printf("done %u bytes\n", len); | ||
| 75 | printf("%u bytes of heap consumed, max in use %u\n", | ||
| 76 | avail_high - begin_avail, heap_max); | ||
| 77 | release(begin_avail, SCRATCH_SIZE); | ||
| 78 | } else { | ||
| 79 | memmove(dst, im, len); | ||
| 80 | } | ||
| 81 | |||
| 82 | flush_cache(dst, len); | ||
| 83 | make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac, | ||
| 84 | (PROG_START + PROG_SIZE)); | ||
| 85 | |||
| 86 | sa = (unsigned long)PROG_START; | ||
| 87 | printf("start address = 0x%x\n", sa); | ||
| 88 | |||
| 89 | (*(kernel_start_t)sa)(a1, a2, prom); | ||
| 90 | |||
| 91 | printf("returned?\n"); | ||
| 92 | |||
| 93 | pause(); | ||
| 94 | } | ||
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index ca0201300868..e399bbb969a4 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile  | |||
| @@ -9,7 +9,6 @@ extra-$(CONFIG_44x) := head_44x.o | |||
| 9 | extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | 9 | extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | 
| 10 | extra-$(CONFIG_8xx) := head_8xx.o | 10 | extra-$(CONFIG_8xx) := head_8xx.o | 
| 11 | extra-$(CONFIG_6xx) += idle_6xx.o | 11 | extra-$(CONFIG_6xx) += idle_6xx.o | 
| 12 | extra-$(CONFIG_POWER4) += idle_power4.o | ||
| 13 | extra-y += vmlinux.lds | 12 | extra-y += vmlinux.lds | 
| 14 | 13 | ||
| 15 | obj-y := entry.o traps.o idle.o time.o misc.o \ | 14 | obj-y := entry.o traps.o idle.o time.o misc.o \ | 
| @@ -17,7 +16,6 @@ obj-y := entry.o traps.o idle.o time.o misc.o \ | |||
| 17 | ppc_htab.o | 16 | ppc_htab.o | 
| 18 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | 17 | obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | 
| 19 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 18 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 
| 20 | obj-$(CONFIG_POWER4) += cpu_setup_power4.o | ||
| 21 | obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o | 19 | obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o | 
| 22 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o | 20 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o | 
| 23 | obj-$(CONFIG_PCI) += pci.o | 21 | obj-$(CONFIG_PCI) += pci.o | 
| @@ -42,7 +40,6 @@ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o | |||
| 42 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 40 | obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o | 
| 43 | obj-$(CONFIG_MODULES) += module.o | 41 | obj-$(CONFIG_MODULES) += module.o | 
| 44 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o | 42 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o | 
| 45 | obj-$(CONFIG_PCI) += pci.o | ||
| 46 | obj-$(CONFIG_KGDB) += ppc-stub.o | 43 | obj-$(CONFIG_KGDB) += ppc-stub.o | 
| 47 | obj-$(CONFIG_TAU) += temp.o | 44 | obj-$(CONFIG_TAU) += temp.o | 
| 48 | ifndef CONFIG_E200 | 45 | ifndef CONFIG_E200 | 
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index fb5658bba285..c3427eed8345 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S  | |||
| @@ -204,78 +204,6 @@ _GLOBAL(call_setup_cpu) | |||
| 204 | mtctr r5 | 204 | mtctr r5 | 
| 205 | bctr | 205 | bctr | 
| 206 | 206 | ||
| 207 | #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) | ||
| 208 | |||
| 209 | /* This gets called by via-pmu.c to switch the PLL selection | ||
| 210 | * on 750fx CPU. This function should really be moved to some | ||
| 211 | * other place (as most of the cpufreq code in via-pmu | ||
| 212 | */ | ||
| 213 | _GLOBAL(low_choose_750fx_pll) | ||
| 214 | /* Clear MSR:EE */ | ||
| 215 | mfmsr r7 | ||
| 216 | rlwinm r0,r7,0,17,15 | ||
| 217 | mtmsr r0 | ||
| 218 | |||
| 219 | /* If switching to PLL1, disable HID0:BTIC */ | ||
| 220 | cmplwi cr0,r3,0 | ||
| 221 | beq 1f | ||
| 222 | mfspr r5,SPRN_HID0 | ||
| 223 | rlwinm r5,r5,0,27,25 | ||
| 224 | sync | ||
| 225 | mtspr SPRN_HID0,r5 | ||
| 226 | isync | ||
| 227 | sync | ||
| 228 | |||
| 229 | 1: | ||
| 230 | /* Calc new HID1 value */ | ||
| 231 | mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ | ||
| 232 | rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ | ||
| 233 | rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ | ||
| 234 | or r4,r4,r5 | ||
| 235 | mtspr SPRN_HID1,r4 | ||
| 236 | |||
| 237 | /* Store new HID1 image */ | ||
| 238 | rlwinm r6,r1,0,0,18 | ||
| 239 | lwz r6,TI_CPU(r6) | ||
| 240 | slwi r6,r6,2 | ||
| 241 | addis r6,r6,nap_save_hid1@ha | ||
| 242 | stw r4,nap_save_hid1@l(r6) | ||
| 243 | |||
| 244 | /* If switching to PLL0, enable HID0:BTIC */ | ||
| 245 | cmplwi cr0,r3,0 | ||
| 246 | bne 1f | ||
| 247 | mfspr r5,SPRN_HID0 | ||
| 248 | ori r5,r5,HID0_BTIC | ||
| 249 | sync | ||
| 250 | mtspr SPRN_HID0,r5 | ||
| 251 | isync | ||
| 252 | sync | ||
| 253 | |||
| 254 | 1: | ||
| 255 | /* Return */ | ||
| 256 | mtmsr r7 | ||
| 257 | blr | ||
| 258 | |||
| 259 | _GLOBAL(low_choose_7447a_dfs) | ||
| 260 | /* Clear MSR:EE */ | ||
| 261 | mfmsr r7 | ||
| 262 | rlwinm r0,r7,0,17,15 | ||
| 263 | mtmsr r0 | ||
| 264 | |||
| 265 | /* Calc new HID1 value */ | ||
| 266 | mfspr r4,SPRN_HID1 | ||
| 267 | insrwi r4,r3,1,9 /* insert parameter into bit 9 */ | ||
| 268 | sync | ||
| 269 | mtspr SPRN_HID1,r4 | ||
| 270 | sync | ||
| 271 | isync | ||
| 272 | |||
| 273 | /* Return */ | ||
| 274 | mtmsr r7 | ||
| 275 | blr | ||
| 276 | |||
| 277 | #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ | ||
| 278 | |||
| 279 | /* | 207 | /* | 
| 280 | * complement mask on the msr then "or" some values on. | 208 | * complement mask on the msr then "or" some values on. | 
| 281 | * _nmask_and_or_msr(nmask, value_to_or) | 209 | * _nmask_and_or_msr(nmask, value_to_or) | 
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 704c846b2b0f..04d04c5bfdd0 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c  | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* | 
| 2 | * Common pmac/prep/chrp pci routines. -- Cort | 2 | * Common prep/chrp pci routines. -- Cort | 
| 3 | */ | 3 | */ | 
| 4 | 4 | ||
| 5 | #include <linux/config.h> | 5 | #include <linux/config.h> | 
| @@ -50,8 +50,7 @@ static void fixup_cpc710_pci64(struct pci_dev* dev); | |||
| 50 | static u8* pci_to_OF_bus_map; | 50 | static u8* pci_to_OF_bus_map; | 
| 51 | #endif | 51 | #endif | 
| 52 | 52 | ||
| 53 | /* By default, we don't re-assign bus numbers. We do this only on | 53 | /* By default, we don't re-assign bus numbers. | 
| 54 | * some pmacs | ||
| 55 | */ | 54 | */ | 
| 56 | int pci_assign_all_buses; | 55 | int pci_assign_all_buses; | 
| 57 | 56 | ||
| @@ -780,17 +779,6 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) | |||
| 780 | return NULL; | 779 | return NULL; | 
| 781 | 780 | ||
| 782 | /* Fixup bus number according to what OF think it is. */ | 781 | /* Fixup bus number according to what OF think it is. */ | 
| 783 | #ifdef CONFIG_PPC_PMAC | ||
| 784 | /* The G5 need a special case here. Basically, we don't remap all | ||
| 785 | * busses on it so we don't create the pci-OF-map. However, we do | ||
| 786 | * remap the AGP bus and so have to deal with it. A future better | ||
| 787 | * fix has to be done by making the remapping per-host and always | ||
| 788 | * filling the pci_to_OF map. --BenH | ||
| 789 | */ | ||
| 790 | if (_machine == _MACH_Pmac && busnr >= 0xf0) | ||
| 791 | busnr -= 0xf0; | ||
| 792 | else | ||
| 793 | #endif | ||
| 794 | if (pci_to_OF_bus_map) | 782 | if (pci_to_OF_bus_map) | 
| 795 | busnr = pci_to_OF_bus_map[busnr]; | 783 | busnr = pci_to_OF_bus_map[busnr]; | 
| 796 | if (busnr == 0xff) | 784 | if (busnr == 0xff) | 
| @@ -1040,216 +1028,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) | |||
| 1040 | } | 1028 | } | 
| 1041 | 1029 | ||
| 1042 | 1030 | ||
| 1043 | #ifdef CONFIG_PPC_PMAC | ||
| 1044 | /* | ||
| 1045 | * This set of routines checks for PCI<->PCI bridges that have closed | ||
| 1046 | * IO resources and have child devices. It tries to re-open an IO | ||
| 1047 | * window on them. | ||
| 1048 | * | ||
| 1049 | * This is a _temporary_ fix to workaround a problem with Apple's OF | ||
| 1050 | * closing IO windows on P2P bridges when the OF drivers of cards | ||
| 1051 | * below this bridge don't claim any IO range (typically ATI or | ||
| 1052 | * Adaptec). | ||
| 1053 | * | ||
| 1054 | * A more complete fix would be to use drivers/pci/setup-bus.c, which | ||
| 1055 | * involves a working pcibios_fixup_pbus_ranges(), some more care about | ||
| 1056 | * ordering when creating the host bus resources, and maybe a few more | ||
| 1057 | * minor tweaks | ||
| 1058 | */ | ||
| 1059 | |||
| 1060 | /* Initialize bridges with base/limit values we have collected */ | ||
| 1061 | static void __init | ||
| 1062 | do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) | ||
| 1063 | { | ||
| 1064 | struct pci_dev *bridge = bus->self; | ||
| 1065 | struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; | ||
| 1066 | u32 l; | ||
| 1067 | u16 w; | ||
| 1068 | struct resource res; | ||
| 1069 | |||
| 1070 | if (bus->resource[0] == NULL) | ||
| 1071 | return; | ||
| 1072 | res = *(bus->resource[0]); | ||
| 1073 | |||
| 1074 | DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); | ||
| 1075 | res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
| 1076 | res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
| 1077 | DBG(" IO window: %08lx-%08lx\n", res.start, res.end); | ||
| 1078 | |||
| 1079 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | ||
| 1080 | pci_read_config_dword(bridge, PCI_IO_BASE, &l); | ||
| 1081 | l &= 0xffff000f; | ||
| 1082 | l |= (res.start >> 8) & 0x00f0; | ||
| 1083 | l |= res.end & 0xf000; | ||
| 1084 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | ||
| 1085 | |||
| 1086 | if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { | ||
| 1087 | l = (res.start >> 16) | (res.end & 0xffff0000); | ||
| 1088 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | pci_read_config_word(bridge, PCI_COMMAND, &w); | ||
| 1092 | w |= PCI_COMMAND_IO; | ||
| 1093 | pci_write_config_word(bridge, PCI_COMMAND, w); | ||
| 1094 | |||
| 1095 | #if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ | ||
| 1096 | if (enable_vga) { | ||
| 1097 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); | ||
| 1098 | w |= PCI_BRIDGE_CTL_VGA; | ||
| 1099 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); | ||
| 1100 | } | ||
| 1101 | #endif | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | /* This function is pretty basic and actually quite broken for the | ||
| 1105 | * general case, it's enough for us right now though. It's supposed | ||
| 1106 | * to tell us if we need to open an IO range at all or not and what | ||
| 1107 | * size. | ||
| 1108 | */ | ||
| 1109 | static int __init | ||
| 1110 | check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) | ||
| 1111 | { | ||
| 1112 | struct pci_dev *dev; | ||
| 1113 | int i; | ||
| 1114 | int rc = 0; | ||
| 1115 | |||
| 1116 | #define push_end(res, size) do { unsigned long __sz = (size) ; \ | ||
| 1117 | res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ | ||
| 1118 | } while (0) | ||
| 1119 | |||
| 1120 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 1121 | u16 class = dev->class >> 8; | ||
| 1122 | |||
| 1123 | if (class == PCI_CLASS_DISPLAY_VGA || | ||
| 1124 | class == PCI_CLASS_NOT_DEFINED_VGA) | ||
| 1125 | *found_vga = 1; | ||
| 1126 | if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) | ||
| 1127 | rc |= check_for_io_childs(dev->subordinate, res, found_vga); | ||
| 1128 | if (class == PCI_CLASS_BRIDGE_CARDBUS) | ||
| 1129 | push_end(res, 0xfff); | ||
| 1130 | |||
| 1131 | for (i=0; i<PCI_NUM_RESOURCES; i++) { | ||
| 1132 | struct resource *r; | ||
| 1133 | unsigned long r_size; | ||
| 1134 | |||
| 1135 | if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI | ||
| 1136 | && i >= PCI_BRIDGE_RESOURCES) | ||
| 1137 | continue; | ||
| 1138 | r = &dev->resource[i]; | ||
| 1139 | r_size = r->end - r->start; | ||
| 1140 | if (r_size < 0xfff) | ||
| 1141 | r_size = 0xfff; | ||
| 1142 | if (r->flags & IORESOURCE_IO && (r_size) != 0) { | ||
| 1143 | rc = 1; | ||
| 1144 | push_end(res, r_size); | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | return rc; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /* Here we scan all P2P bridges of a given level that have a closed | ||
| 1153 | * IO window. Note that the test for the presence of a VGA card should | ||
| 1154 | * be improved to take into account already configured P2P bridges, | ||
| 1155 | * currently, we don't see them and might end up configuring 2 bridges | ||
| 1156 | * with VGA pass through enabled | ||
| 1157 | */ | ||
| 1158 | static void __init | ||
| 1159 | do_fixup_p2p_level(struct pci_bus *bus) | ||
| 1160 | { | ||
| 1161 | struct pci_bus *b; | ||
| 1162 | int i, parent_io; | ||
| 1163 | int has_vga = 0; | ||
| 1164 | |||
| 1165 | for (parent_io=0; parent_io<4; parent_io++) | ||
| 1166 | if (bus->resource[parent_io] | ||
| 1167 | && bus->resource[parent_io]->flags & IORESOURCE_IO) | ||
| 1168 | break; | ||
| 1169 | if (parent_io >= 4) | ||
| 1170 | return; | ||
| 1171 | |||
| 1172 | list_for_each_entry(b, &bus->children, node) { | ||
| 1173 | struct pci_dev *d = b->self; | ||
| 1174 | struct pci_controller* hose = (struct pci_controller *)d->sysdata; | ||
| 1175 | struct resource *res = b->resource[0]; | ||
| 1176 | struct resource tmp_res; | ||
| 1177 | unsigned long max; | ||
| 1178 | int found_vga = 0; | ||
| 1179 | |||
| 1180 | memset(&tmp_res, 0, sizeof(tmp_res)); | ||
| 1181 | tmp_res.start = bus->resource[parent_io]->start; | ||
| 1182 | |||
| 1183 | /* We don't let low addresses go through that closed P2P bridge, well, | ||
| 1184 | * that may not be necessary but I feel safer that way | ||
| 1185 | */ | ||
| 1186 | if (tmp_res.start == 0) | ||
| 1187 | tmp_res.start = 0x1000; | ||
| 1188 | |||
| 1189 | if (!list_empty(&b->devices) && res && res->flags == 0 && | ||
| 1190 | res != bus->resource[parent_io] && | ||
| 1191 | (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && | ||
| 1192 | check_for_io_childs(b, &tmp_res, &found_vga)) { | ||
| 1193 | u8 io_base_lo; | ||
| 1194 | |||
| 1195 | printk(KERN_INFO "Fixing up IO bus %s\n", b->name); | ||
| 1196 | |||
| 1197 | if (found_vga) { | ||
| 1198 | if (has_vga) { | ||
| 1199 | printk(KERN_WARNING "Skipping VGA, already active" | ||
| 1200 | " on bus segment\n"); | ||
| 1201 | found_vga = 0; | ||
| 1202 | } else | ||
| 1203 | has_vga = 1; | ||
| 1204 | } | ||
| 1205 | pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); | ||
| 1206 | |||
| 1207 | if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) | ||
| 1208 | max = ((unsigned long) hose->io_base_virt | ||
| 1209 | - isa_io_base) + 0xffffffff; | ||
| 1210 | else | ||
| 1211 | max = ((unsigned long) hose->io_base_virt | ||
| 1212 | - isa_io_base) + 0xffff; | ||
| 1213 | |||
| 1214 | *res = tmp_res; | ||
| 1215 | res->flags = IORESOURCE_IO; | ||
| 1216 | res->name = b->name; | ||
| 1217 | |||
| 1218 | /* Find a resource in the parent where we can allocate */ | ||
| 1219 | for (i = 0 ; i < 4; i++) { | ||
| 1220 | struct resource *r = bus->resource[i]; | ||
| 1221 | if (!r) | ||
| 1222 | continue; | ||
| 1223 | if ((r->flags & IORESOURCE_IO) == 0) | ||
| 1224 | continue; | ||
| 1225 | DBG("Trying to allocate from %08lx, size %08lx from parent" | ||
| 1226 | " res %d: %08lx -> %08lx\n", | ||
| 1227 | res->start, res->end, i, r->start, r->end); | ||
| 1228 | |||
| 1229 | if (allocate_resource(r, res, res->end + 1, res->start, max, | ||
| 1230 | res->end + 1, NULL, NULL) < 0) { | ||
| 1231 | DBG("Failed !\n"); | ||
| 1232 | continue; | ||
| 1233 | } | ||
| 1234 | do_update_p2p_io_resource(b, found_vga); | ||
| 1235 | break; | ||
| 1236 | } | ||
| 1237 | } | ||
| 1238 | do_fixup_p2p_level(b); | ||
| 1239 | } | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static void | ||
| 1243 | pcibios_fixup_p2p_bridges(void) | ||
| 1244 | { | ||
| 1245 | struct pci_bus *b; | ||
| 1246 | |||
| 1247 | list_for_each_entry(b, &pci_root_buses, node) | ||
| 1248 | do_fixup_p2p_level(b); | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1252 | |||
| 1253 | static int __init | 1031 | static int __init | 
| 1254 | pcibios_init(void) | 1032 | pcibios_init(void) | 
| 1255 | { | 1033 | { | 
| @@ -1290,9 +1068,6 @@ pcibios_init(void) | |||
| 1290 | pcibios_allocate_bus_resources(&pci_root_buses); | 1068 | pcibios_allocate_bus_resources(&pci_root_buses); | 
| 1291 | pcibios_allocate_resources(0); | 1069 | pcibios_allocate_resources(0); | 
| 1292 | pcibios_allocate_resources(1); | 1070 | pcibios_allocate_resources(1); | 
| 1293 | #ifdef CONFIG_PPC_PMAC | ||
| 1294 | pcibios_fixup_p2p_bridges(); | ||
| 1295 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1296 | pcibios_assign_resources(); | 1071 | pcibios_assign_resources(); | 
| 1297 | 1072 | ||
| 1298 | /* Call machine dependent post-init code */ | 1073 | /* Call machine dependent post-init code */ | 
| @@ -1722,17 +1497,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
| 1722 | struct pci_controller* hose; | 1497 | struct pci_controller* hose; | 
| 1723 | long result = -EOPNOTSUPP; | 1498 | long result = -EOPNOTSUPP; | 
| 1724 | 1499 | ||
| 1725 | /* Argh ! Please forgive me for that hack, but that's the | ||
| 1726 | * simplest way to get existing XFree to not lockup on some | ||
| 1727 | * G5 machines... So when something asks for bus 0 io base | ||
| 1728 | * (bus 0 is HT root), we return the AGP one instead. | ||
| 1729 | */ | ||
| 1730 | #ifdef CONFIG_PPC_PMAC | ||
| 1731 | if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) | ||
| 1732 | if (bus == 0) | ||
| 1733 | bus = 0xf0; | ||
| 1734 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1735 | |||
| 1736 | hose = pci_bus_to_hose(bus); | 1500 | hose = pci_bus_to_hose(bus); | 
| 1737 | if (!hose) | 1501 | if (!hose) | 
| 1738 | return -ENODEV; | 1502 | return -ENODEV; | 
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index fb0da7c209db..3a6e4bcb3c53 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c  | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <asm/system.h> | 34 | #include <asm/system.h> | 
| 35 | #include <asm/pci-bridge.h> | 35 | #include <asm/pci-bridge.h> | 
| 36 | #include <asm/irq.h> | 36 | #include <asm/irq.h> | 
| 37 | #include <asm/pmac_feature.h> | ||
| 38 | #include <asm/dma.h> | 37 | #include <asm/dma.h> | 
| 39 | #include <asm/machdep.h> | 38 | #include <asm/machdep.h> | 
| 40 | #include <asm/hw_irq.h> | 39 | #include <asm/hw_irq.h> | 
| @@ -58,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
| 58 | extern void alignment_exception(struct pt_regs *regs); | 57 | extern void alignment_exception(struct pt_regs *regs); | 
| 59 | extern void program_check_exception(struct pt_regs *regs); | 58 | extern void program_check_exception(struct pt_regs *regs); | 
| 60 | extern void single_step_exception(struct pt_regs *regs); | 59 | extern void single_step_exception(struct pt_regs *regs); | 
| 61 | extern int pmac_newworld; | ||
| 62 | extern int sys_sigreturn(struct pt_regs *regs); | 60 | extern int sys_sigreturn(struct pt_regs *regs); | 
| 63 | 61 | ||
| 64 | long long __ashrdi3(long long, int); | 62 | long long __ashrdi3(long long, int); | 
| @@ -213,10 +211,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
| 213 | EXPORT_SYMBOL(cuda_request); | 211 | EXPORT_SYMBOL(cuda_request); | 
| 214 | EXPORT_SYMBOL(cuda_poll); | 212 | EXPORT_SYMBOL(cuda_poll); | 
| 215 | #endif /* CONFIG_ADB_CUDA */ | 213 | #endif /* CONFIG_ADB_CUDA */ | 
| 216 | #ifdef CONFIG_PPC_PMAC | ||
| 217 | EXPORT_SYMBOL(sys_ctrler); | ||
| 218 | EXPORT_SYMBOL(pmac_newworld); | ||
| 219 | #endif | ||
| 220 | #ifdef CONFIG_PPC_OF | 214 | #ifdef CONFIG_PPC_OF | 
| 221 | EXPORT_SYMBOL(find_devices); | 215 | EXPORT_SYMBOL(find_devices); | 
| 222 | EXPORT_SYMBOL(find_type_devices); | 216 | EXPORT_SYMBOL(find_type_devices); | 
| @@ -241,9 +235,6 @@ EXPORT_SYMBOL(of_node_put); | |||
| 241 | #if defined(CONFIG_BOOTX_TEXT) | 235 | #if defined(CONFIG_BOOTX_TEXT) | 
| 242 | EXPORT_SYMBOL(btext_update_display); | 236 | EXPORT_SYMBOL(btext_update_display); | 
| 243 | #endif | 237 | #endif | 
| 244 | #if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC) | ||
| 245 | EXPORT_SYMBOL(note_scsi_host); | ||
| 246 | #endif | ||
| 247 | #ifdef CONFIG_VT | 238 | #ifdef CONFIG_VT | 
| 248 | EXPORT_SYMBOL(kd_mksound); | 239 | EXPORT_SYMBOL(kd_mksound); | 
| 249 | #endif | 240 | #endif | 
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index e707c6f6e61b..c08ab432e958 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c  | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* | 
| 2 | * Common prep/pmac/chrp boot and setup code. | 2 | * Common prep/chrp boot and setup code. | 
| 3 | */ | 3 | */ | 
| 4 | 4 | ||
| 5 | #include <linux/config.h> | 5 | #include <linux/config.h> | 
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <asm/machdep.h> | 35 | #include <asm/machdep.h> | 
| 36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> | 
| 37 | #include <asm/system.h> | 37 | #include <asm/system.h> | 
| 38 | #include <asm/pmac_feature.h> | ||
| 39 | #include <asm/sections.h> | 38 | #include <asm/sections.h> | 
| 40 | #include <asm/nvram.h> | 39 | #include <asm/nvram.h> | 
| 41 | #include <asm/xmon.h> | 40 | #include <asm/xmon.h> | 
| @@ -55,7 +54,6 @@ | |||
| 55 | 54 | ||
| 56 | extern void platform_init(unsigned long r3, unsigned long r4, | 55 | extern void platform_init(unsigned long r3, unsigned long r4, | 
| 57 | unsigned long r5, unsigned long r6, unsigned long r7); | 56 | unsigned long r5, unsigned long r6, unsigned long r7); | 
| 58 | extern void bootx_init(unsigned long r4, unsigned long phys); | ||
| 59 | extern void identify_cpu(unsigned long offset, unsigned long cpu); | 57 | extern void identify_cpu(unsigned long offset, unsigned long cpu); | 
| 60 | extern void do_cpu_ftr_fixups(unsigned long offset); | 58 | extern void do_cpu_ftr_fixups(unsigned long offset); | 
| 61 | extern void reloc_got2(unsigned long offset); | 59 | extern void reloc_got2(unsigned long offset); | 
| @@ -80,8 +78,6 @@ EXPORT_SYMBOL(_machine); | |||
| 80 | 78 | ||
| 81 | extern void prep_init(unsigned long r3, unsigned long r4, | 79 | extern void prep_init(unsigned long r3, unsigned long r4, | 
| 82 | unsigned long r5, unsigned long r6, unsigned long r7); | 80 | unsigned long r5, unsigned long r6, unsigned long r7); | 
| 83 | extern void pmac_init(unsigned long r3, unsigned long r4, | ||
| 84 | unsigned long r5, unsigned long r6, unsigned long r7); | ||
| 85 | extern void chrp_init(unsigned long r3, unsigned long r4, | 81 | extern void chrp_init(unsigned long r3, unsigned long r4, | 
| 86 | unsigned long r5, unsigned long r6, unsigned long r7); | 82 | unsigned long r5, unsigned long r6, unsigned long r7); | 
| 87 | 83 | ||
| @@ -324,20 +320,15 @@ early_init(int r3, int r4, int r5) | |||
| 324 | identify_cpu(offset, 0); | 320 | identify_cpu(offset, 0); | 
| 325 | do_cpu_ftr_fixups(offset); | 321 | do_cpu_ftr_fixups(offset); | 
| 326 | 322 | ||
| 327 | #if defined(CONFIG_PPC_MULTIPLATFORM) | 323 | #if defined(CONFIG_PPC_OF) | 
| 328 | reloc_got2(offset); | 324 | reloc_got2(offset); | 
| 329 | 325 | ||
| 330 | /* If we came here from BootX, clear the screen, | ||
| 331 | * set up some pointers and return. */ | ||
| 332 | if ((r3 == 0x426f6f58) && (r5 == 0)) | ||
| 333 | bootx_init(r4, phys); | ||
| 334 | |||
| 335 | /* | 326 | /* | 
| 336 | * don't do anything on prep | 327 | * don't do anything on prep | 
| 337 | * for now, don't use bootinfo because it breaks yaboot 0.5 | 328 | * for now, don't use bootinfo because it breaks yaboot 0.5 | 
| 338 | * and assume that if we didn't find a magic number, we have OF | 329 | * and assume that if we didn't find a magic number, we have OF | 
| 339 | */ | 330 | */ | 
| 340 | else if (*(unsigned long *)(0) != 0xdeadc0de) | 331 | if (*(unsigned long *)(0) != 0xdeadc0de) | 
| 341 | phys = prom_init(r3, r4, (prom_entry)r5); | 332 | phys = prom_init(r3, r4, (prom_entry)r5); | 
| 342 | 333 | ||
| 343 | reloc_got2(-offset); | 334 | reloc_got2(-offset); | 
| @@ -424,6 +415,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | |||
| 424 | } | 415 | } | 
| 425 | #endif | 416 | #endif | 
| 426 | 417 | ||
| 418 | #ifdef CONFIG_PPC_OF | ||
| 427 | have_of = 1; | 419 | have_of = 1; | 
| 428 | 420 | ||
| 429 | /* prom_init has already been called from __start */ | 421 | /* prom_init has already been called from __start */ | 
| @@ -495,19 +487,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | |||
| 495 | #endif /* CONFIG_ADB */ | 487 | #endif /* CONFIG_ADB */ | 
| 496 | 488 | ||
| 497 | switch (_machine) { | 489 | switch (_machine) { | 
| 498 | #ifdef CONFIG_PPC_PMAC | ||
| 499 | case _MACH_Pmac: | ||
| 500 | pmac_init(r3, r4, r5, r6, r7); | ||
| 501 | break; | ||
| 502 | #endif | ||
| 503 | #ifdef CONFIG_PPC_CHRP | 490 | #ifdef CONFIG_PPC_CHRP | 
| 504 | case _MACH_chrp: | 491 | case _MACH_chrp: | 
| 505 | chrp_init(r3, r4, r5, r6, r7); | 492 | chrp_init(r3, r4, r5, r6, r7); | 
| 506 | break; | 493 | break; | 
| 507 | #endif | 494 | #endif | 
| 508 | } | 495 | } | 
| 496 | #endif /* CONFIG_PPC_OF */ | ||
| 509 | } | 497 | } | 
| 498 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
| 510 | 499 | ||
| 500 | #ifdef CONFIG_PPC_OF | ||
| 511 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | 501 | #ifdef CONFIG_SERIAL_CORE_CONSOLE | 
| 512 | extern char *of_stdout_device; | 502 | extern char *of_stdout_device; | 
| 513 | 503 | ||
| @@ -564,7 +554,7 @@ static int __init set_preferred_console(void) | |||
| 564 | } | 554 | } | 
| 565 | console_initcall(set_preferred_console); | 555 | console_initcall(set_preferred_console); | 
| 566 | #endif /* CONFIG_SERIAL_CORE_CONSOLE */ | 556 | #endif /* CONFIG_SERIAL_CORE_CONSOLE */ | 
| 567 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 557 | #endif /* CONFIG_PPC_OF */ | 
| 568 | 558 | ||
| 569 | struct bi_record *find_bootinfo(void) | 559 | struct bi_record *find_bootinfo(void) | 
| 570 | { | 560 | { | 
| @@ -747,14 +737,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 747 | if (ppc_md.init_early) | 737 | if (ppc_md.init_early) | 
| 748 | ppc_md.init_early(); | 738 | ppc_md.init_early(); | 
| 749 | 739 | ||
| 750 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
| 751 | /* This could be called "early setup arch", it must be done | ||
| 752 | * now because xmon need it | ||
| 753 | */ | ||
| 754 | if (_machine == _MACH_Pmac) | ||
| 755 | pmac_feature_init(); /* New cool way */ | ||
| 756 | #endif | ||
| 757 | |||
| 758 | #ifdef CONFIG_XMON | 740 | #ifdef CONFIG_XMON | 
| 759 | xmon_init(1); | 741 | xmon_init(1); | 
| 760 | if (strstr(cmd_line, "xmon")) | 742 | if (strstr(cmd_line, "xmon")) | 
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 9dbc4d28fa28..6d0a1838d94c 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c  | |||
| @@ -38,9 +38,6 @@ | |||
| 38 | #include <asm/io.h> | 38 | #include <asm/io.h> | 
| 39 | #include <asm/reg.h> | 39 | #include <asm/reg.h> | 
| 40 | #include <asm/xmon.h> | 40 | #include <asm/xmon.h> | 
| 41 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 42 | #include <asm/backlight.h> | ||
| 43 | #endif | ||
| 44 | #include <asm/pmc.h> | 41 | #include <asm/pmc.h> | 
| 45 | 42 | ||
| 46 | #ifdef CONFIG_XMON | 43 | #ifdef CONFIG_XMON | 
| @@ -85,12 +82,6 @@ int die(const char * str, struct pt_regs * fp, long err) | |||
| 85 | int nl = 0; | 82 | int nl = 0; | 
| 86 | console_verbose(); | 83 | console_verbose(); | 
| 87 | spin_lock_irq(&die_lock); | 84 | spin_lock_irq(&die_lock); | 
| 88 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 89 | if (_machine == _MACH_Pmac) { | ||
| 90 | set_backlight_enable(1); | ||
| 91 | set_backlight_level(BACKLIGHT_MAX); | ||
| 92 | } | ||
| 93 | #endif | ||
| 94 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); | 85 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); | 
| 95 | #ifdef CONFIG_PREEMPT | 86 | #ifdef CONFIG_PREEMPT | 
| 96 | printk("PREEMPT "); | 87 | printk("PREEMPT "); | 
| @@ -159,7 +150,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
| 159 | */ | 150 | */ | 
| 160 | static inline int check_io_access(struct pt_regs *regs) | 151 | static inline int check_io_access(struct pt_regs *regs) | 
| 161 | { | 152 | { | 
| 162 | #if defined CONFIG_PPC_PMAC || defined CONFIG_8xx | 153 | #if defined CONFIG_8xx | 
| 163 | unsigned long msr = regs->msr; | 154 | unsigned long msr = regs->msr; | 
| 164 | const struct exception_table_entry *entry; | 155 | const struct exception_table_entry *entry; | 
| 165 | unsigned int *nip = (unsigned int *)regs->nip; | 156 | unsigned int *nip = (unsigned int *)regs->nip; | 
| @@ -196,7 +187,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
| 196 | return 1; | 187 | return 1; | 
| 197 | } | 188 | } | 
| 198 | } | 189 | } | 
| 199 | #endif /* CONFIG_PPC_PMAC */ | 190 | #endif /* CONFIG_8xx */ | 
| 200 | return 0; | 191 | return 0; | 
| 201 | } | 192 | } | 
| 202 | 193 | ||
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 45f0782059f1..134db5c04203 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c  | |||
| @@ -67,10 +67,6 @@ unsigned long ppc_memoffset = PAGE_OFFSET; | |||
| 67 | int mem_init_done; | 67 | int mem_init_done; | 
| 68 | int init_bootmem_done; | 68 | int init_bootmem_done; | 
| 69 | int boot_mapsize; | 69 | int boot_mapsize; | 
| 70 | #ifdef CONFIG_PPC_PMAC | ||
| 71 | unsigned long agp_special_page; | ||
| 72 | EXPORT_SYMBOL(agp_special_page); | ||
| 73 | #endif | ||
| 74 | 70 | ||
| 75 | extern char _end[]; | 71 | extern char _end[]; | 
| 76 | extern char etext[], _stext[]; | 72 | extern char etext[], _stext[]; | 
| @@ -424,10 +420,6 @@ void __init mem_init(void) | |||
| 424 | addr += PAGE_SIZE) | 420 | addr += PAGE_SIZE) | 
| 425 | SetPageReserved(virt_to_page(addr)); | 421 | SetPageReserved(virt_to_page(addr)); | 
| 426 | #endif | 422 | #endif | 
| 427 | #ifdef CONFIG_PPC_PMAC | ||
| 428 | if (agp_special_page) | ||
| 429 | SetPageReserved(virt_to_page(agp_special_page)); | ||
| 430 | #endif | ||
| 431 | for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory; | 423 | for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory; | 
| 432 | addr += PAGE_SIZE) { | 424 | addr += PAGE_SIZE) { | 
| 433 | if (!PageReserved(virt_to_page(addr))) | 425 | if (!PageReserved(virt_to_page(addr))) | 
| @@ -463,11 +455,6 @@ void __init mem_init(void) | |||
| 463 | initpages<< (PAGE_SHIFT-10), | 455 | initpages<< (PAGE_SHIFT-10), | 
| 464 | (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); | 456 | (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); | 
| 465 | 457 | ||
| 466 | #ifdef CONFIG_PPC_PMAC | ||
| 467 | if (agp_special_page) | ||
| 468 | printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page); | ||
| 469 | #endif | ||
| 470 | |||
| 471 | mem_init_done = 1; | 458 | mem_init_done = 1; | 
| 472 | } | 459 | } | 
| 473 | 460 | ||
| @@ -512,22 +499,6 @@ set_phys_avail(unsigned long total_memory) | |||
| 512 | if (rtas_data) | 499 | if (rtas_data) | 
| 513 | mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); | 500 | mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1); | 
| 514 | #endif | 501 | #endif | 
| 515 | #ifdef CONFIG_PPC_PMAC | ||
| 516 | /* Because of some uninorth weirdness, we need a page of | ||
| 517 | * memory as high as possible (it must be outside of the | ||
| 518 | * bus address seen as the AGP aperture). It will be used | ||
| 519 | * by the r128 DRM driver | ||
| 520 | * | ||
| 521 | * FIXME: We need to make sure that page doesn't overlap any of the\ | ||
| 522 | * above. This could be done by improving mem_pieces_find to be able | ||
| 523 | * to do a backward search from the end of the list. | ||
| 524 | */ | ||
| 525 | if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) { | ||
| 526 | agp_special_page = (total_memory - PAGE_SIZE); | ||
| 527 | mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0); | ||
| 528 | agp_special_page = (unsigned long)__va(agp_special_page); | ||
| 529 | } | ||
| 530 | #endif /* CONFIG_PPC_PMAC */ | ||
| 531 | } | 502 | } | 
| 532 | 503 | ||
| 533 | /* Mark some memory as reserved by removing it from phys_avail. */ | 504 | /* Mark some memory as reserved by removing it from phys_avail. */ | 
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile index 7c5cdabf6f3c..51430e294b32 100644 --- a/arch/ppc/platforms/Makefile +++ b/arch/ppc/platforms/Makefile  | |||
| @@ -3,26 +3,18 @@ | |||
| 3 | # | 3 | # | 
| 4 | 4 | ||
| 5 | # Extra CFLAGS so we don't have to do relative includes | 5 | # Extra CFLAGS so we don't have to do relative includes | 
| 6 | CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm | 6 | CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm | 
| 7 | 7 | ||
| 8 | obj-$(CONFIG_APUS) += apus_setup.o | 8 | obj-$(CONFIG_APUS) += apus_setup.o | 
| 9 | ifeq ($(CONFIG_APUS),y) | 9 | ifeq ($(CONFIG_APUS),y) | 
| 10 | obj-$(CONFIG_PCI) += apus_pci.o | 10 | obj-$(CONFIG_PCI) += apus_pci.o | 
| 11 | endif | 11 | endif | 
| 12 | obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \ | ||
| 13 | pmac_feature.o pmac_pci.o pmac_sleep.o \ | ||
| 14 | pmac_low_i2c.o pmac_cache.o | ||
| 15 | obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \ | 12 | obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \ | 
| 16 | chrp_pegasos_eth.o | 13 | chrp_pegasos_eth.o | 
| 17 | ifeq ($(CONFIG_PPC_CHRP),y) | 14 | ifeq ($(CONFIG_PPC_CHRP),y) | 
| 18 | obj-$(CONFIG_NVRAM) += chrp_nvram.o | 15 | obj-$(CONFIG_NVRAM) += chrp_nvram.o | 
| 19 | endif | 16 | endif | 
| 20 | obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o | 17 | obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o | 
| 21 | ifeq ($(CONFIG_PPC_PMAC),y) | ||
| 22 | obj-$(CONFIG_NVRAM) += pmac_nvram.o | ||
| 23 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o | ||
| 24 | endif | ||
| 25 | obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o | ||
| 26 | obj-$(CONFIG_PREP_RESIDUAL) += residual.o | 18 | obj-$(CONFIG_PREP_RESIDUAL) += residual.o | 
| 27 | obj-$(CONFIG_PQ2ADS) += pq2ads.o | 19 | obj-$(CONFIG_PQ2ADS) += pq2ads.o | 
| 28 | obj-$(CONFIG_TQM8260) += tqm8260_setup.o | 20 | obj-$(CONFIG_TQM8260) += tqm8260_setup.o | 
| @@ -47,6 +39,5 @@ obj-$(CONFIG_LITE5200) += lite5200.o | |||
| 47 | obj-$(CONFIG_EV64360) += ev64360.o | 39 | obj-$(CONFIG_EV64360) += ev64360.o | 
| 48 | 40 | ||
| 49 | ifeq ($(CONFIG_SMP),y) | 41 | ifeq ($(CONFIG_SMP),y) | 
| 50 | obj-$(CONFIG_PPC_PMAC) += pmac_smp.o | ||
| 51 | obj-$(CONFIG_PPC_CHRP) += chrp_smp.o | 42 | obj-$(CONFIG_PPC_CHRP) += chrp_smp.o | 
| 52 | endif | 43 | endif | 
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c index bd047aac01b1..c7fe6182bb77 100644 --- a/arch/ppc/platforms/chrp_pci.c +++ b/arch/ppc/platforms/chrp_pci.c  | |||
| @@ -275,7 +275,7 @@ chrp_find_bridges(void) | |||
| 275 | setup_python(hose, dev); | 275 | setup_python(hose, dev); | 
| 276 | } else if (is_mot | 276 | } else if (is_mot | 
| 277 | || strncmp(model, "Motorola, Grackle", 17) == 0) { | 277 | || strncmp(model, "Motorola, Grackle", 17) == 0) { | 
| 278 | setup_grackle(hose); | 278 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | 
| 279 | } else if (is_longtrail) { | 279 | } else if (is_longtrail) { | 
| 280 | void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); | 280 | void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); | 
| 281 | hose->ops = &gg2_pci_ops; | 281 | hose->ops = &gg2_pci_ops; | 
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c index 056ac2a7b5c1..48996b787378 100644 --- a/arch/ppc/platforms/chrp_setup.c +++ b/arch/ppc/platforms/chrp_setup.c  | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <asm/i8259.h> | 53 | #include <asm/i8259.h> | 
| 54 | #include <asm/open_pic.h> | 54 | #include <asm/open_pic.h> | 
| 55 | #include <asm/xmon.h> | 55 | #include <asm/xmon.h> | 
| 56 | #include "mem_pieces.h" | ||
| 56 | 57 | ||
| 57 | unsigned long chrp_get_rtc_time(void); | 58 | unsigned long chrp_get_rtc_time(void); | 
| 58 | int chrp_set_rtc_time(unsigned long nowtime); | 59 | int chrp_set_rtc_time(unsigned long nowtime); | 
| @@ -65,7 +66,6 @@ void rtas_display_progress(char *, unsigned short); | |||
| 65 | void rtas_indicator_progress(char *, unsigned short); | 66 | void rtas_indicator_progress(char *, unsigned short); | 
| 66 | void btext_progress(char *, unsigned short); | 67 | void btext_progress(char *, unsigned short); | 
| 67 | 68 | ||
| 68 | extern unsigned long pmac_find_end_of_memory(void); | ||
| 69 | extern int of_show_percpuinfo(struct seq_file *, int); | 69 | extern int of_show_percpuinfo(struct seq_file *, int); | 
| 70 | 70 | ||
| 71 | int _chrp_type; | 71 | int _chrp_type; | 
| @@ -467,6 +467,75 @@ chrp_init2(void) | |||
| 467 | ppc_md.progress(" Have fun! ", 0x7777); | 467 | ppc_md.progress(" Have fun! ", 0x7777); | 
| 468 | } | 468 | } | 
| 469 | 469 | ||
| 470 | static struct device_node *memory_node; | ||
| 471 | |||
| 472 | static int __init get_mem_prop(char *name, struct mem_pieces *mp) | ||
| 473 | { | ||
| 474 | struct reg_property *rp; | ||
| 475 | int i, s; | ||
| 476 | unsigned int *ip; | ||
| 477 | int nac = prom_n_addr_cells(memory_node); | ||
| 478 | int nsc = prom_n_size_cells(memory_node); | ||
| 479 | |||
| 480 | ip = (unsigned int *) get_property(memory_node, name, &s); | ||
| 481 | if (ip == NULL) { | ||
| 482 | printk(KERN_ERR "error: couldn't get %s property on /memory\n", | ||
| 483 | name); | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | s /= (nsc + nac) * 4; | ||
| 487 | rp = mp->regions; | ||
| 488 | for (i = 0; i < s; ++i, ip += nac+nsc) { | ||
| 489 | if (nac >= 2 && ip[nac-2] != 0) | ||
| 490 | continue; | ||
| 491 | rp->address = ip[nac-1]; | ||
| 492 | if (nsc >= 2 && ip[nac+nsc-2] != 0) | ||
| 493 | rp->size = ~0U; | ||
| 494 | else | ||
| 495 | rp->size = ip[nac+nsc-1]; | ||
| 496 | ++rp; | ||
| 497 | } | ||
| 498 | mp->n_regions = rp - mp->regions; | ||
| 499 | |||
| 500 | /* Make sure the pieces are sorted. */ | ||
| 501 | mem_pieces_sort(mp); | ||
| 502 | mem_pieces_coalesce(mp); | ||
| 503 | return 1; | ||
| 504 | } | ||
| 505 | |||
| 506 | static unsigned long __init chrp_find_end_of_memory(void) | ||
| 507 | { | ||
| 508 | unsigned long a, total; | ||
| 509 | struct mem_pieces phys_mem; | ||
| 510 | |||
| 511 | /* | ||
| 512 | * Find out where physical memory is, and check that it | ||
| 513 | * starts at 0 and is contiguous. It seems that RAM is | ||
| 514 | * always physically contiguous on Power Macintoshes. | ||
| 515 | * | ||
| 516 | * Supporting discontiguous physical memory isn't hard, | ||
| 517 | * it just makes the virtual <-> physical mapping functions | ||
| 518 | * more complicated (or else you end up wasting space | ||
| 519 | * in mem_map). | ||
| 520 | */ | ||
| 521 | memory_node = find_devices("memory"); | ||
| 522 | if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) | ||
| 523 | || phys_mem.n_regions == 0) | ||
| 524 | panic("No RAM??"); | ||
| 525 | a = phys_mem.regions[0].address; | ||
| 526 | if (a != 0) | ||
| 527 | panic("RAM doesn't start at physical address 0"); | ||
| 528 | total = phys_mem.regions[0].size; | ||
| 529 | |||
| 530 | if (phys_mem.n_regions > 1) { | ||
| 531 | printk("RAM starting at 0x%x is not contiguous\n", | ||
| 532 | phys_mem.regions[1].address); | ||
| 533 | printk("Using RAM from 0 to 0x%lx\n", total-1); | ||
| 534 | } | ||
| 535 | |||
| 536 | return total; | ||
| 537 | } | ||
| 538 | |||
| 470 | void __init | 539 | void __init | 
| 471 | chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, | 540 | chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, | 
| 472 | unsigned long r6, unsigned long r7) | 541 | unsigned long r6, unsigned long r7) | 
| @@ -525,7 +594,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, | |||
| 525 | ppc_md.get_rtc_time = chrp_get_rtc_time; | 594 | ppc_md.get_rtc_time = chrp_get_rtc_time; | 
| 526 | ppc_md.calibrate_decr = chrp_calibrate_decr; | 595 | ppc_md.calibrate_decr = chrp_calibrate_decr; | 
| 527 | 596 | ||
| 528 | ppc_md.find_end_of_memory = pmac_find_end_of_memory; | 597 | ppc_md.find_end_of_memory = chrp_find_end_of_memory; | 
| 529 | 598 | ||
| 530 | if (rtas_data) { | 599 | if (rtas_data) { | 
| 531 | struct device_node *rtas; | 600 | struct device_node *rtas; | 
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c index 29d074c305f0..57753a55b580 100644 --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c  | |||
| @@ -163,13 +163,75 @@ unsigned long chrp_get_rtc_time(void) | |||
| 163 | return mktime(year, mon, day, hour, min, sec); | 163 | return mktime(year, mon, day, hour, min, sec); | 
| 164 | } | 164 | } | 
| 165 | 165 | ||
| 166 | /* | ||
| 167 | * Calibrate the decrementer frequency with the VIA timer 1. | ||
| 168 | */ | ||
| 169 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ | ||
| 170 | |||
| 171 | /* VIA registers */ | ||
| 172 | #define RS 0x200 /* skip between registers */ | ||
| 173 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
| 174 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
| 175 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
| 176 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
| 177 | #define ACR (11*RS) /* Auxiliary control register */ | ||
| 178 | #define IFR (13*RS) /* Interrupt flag register */ | ||
| 179 | |||
| 180 | /* Bits in ACR */ | ||
| 181 | #define T1MODE 0xc0 /* Timer 1 mode */ | ||
| 182 | #define T1MODE_CONT 0x40 /* continuous interrupts */ | ||
| 183 | |||
| 184 | /* Bits in IFR and IER */ | ||
| 185 | #define T1_INT 0x40 /* Timer 1 interrupt */ | ||
| 186 | |||
| 187 | static int __init chrp_via_calibrate_decr(void) | ||
| 188 | { | ||
| 189 | struct device_node *vias; | ||
| 190 | volatile unsigned char __iomem *via; | ||
| 191 | int count = VIA_TIMER_FREQ_6 / 100; | ||
| 192 | unsigned int dstart, dend; | ||
| 193 | |||
| 194 | vias = find_devices("via-cuda"); | ||
| 195 | if (vias == 0) | ||
| 196 | vias = find_devices("via"); | ||
| 197 | if (vias == 0 || vias->n_addrs == 0) | ||
| 198 | return 0; | ||
| 199 | via = ioremap(vias->addrs[0].address, vias->addrs[0].size); | ||
| 200 | |||
| 201 | /* set timer 1 for continuous interrupts */ | ||
| 202 | out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); | ||
| 203 | /* set the counter to a small value */ | ||
| 204 | out_8(&via[T1CH], 2); | ||
| 205 | /* set the latch to `count' */ | ||
| 206 | out_8(&via[T1LL], count); | ||
| 207 | out_8(&via[T1LH], count >> 8); | ||
| 208 | /* wait until it hits 0 */ | ||
| 209 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
| 210 | ; | ||
| 211 | dstart = get_dec(); | ||
| 212 | /* clear the interrupt & wait until it hits 0 again */ | ||
| 213 | in_8(&via[T1CL]); | ||
| 214 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
| 215 | ; | ||
| 216 | dend = get_dec(); | ||
| 217 | |||
| 218 | tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); | ||
| 219 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); | ||
| 220 | |||
| 221 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", | ||
| 222 | tb_ticks_per_jiffy, dstart - dend); | ||
| 223 | |||
| 224 | iounmap(via); | ||
| 225 | |||
| 226 | return 1; | ||
| 227 | } | ||
| 166 | 228 | ||
| 167 | void __init chrp_calibrate_decr(void) | 229 | void __init chrp_calibrate_decr(void) | 
| 168 | { | 230 | { | 
| 169 | struct device_node *cpu; | 231 | struct device_node *cpu; | 
| 170 | unsigned int freq, *fp; | 232 | unsigned int freq, *fp; | 
| 171 | 233 | ||
| 172 | if (via_calibrate_decr()) | 234 | if (chrp_via_calibrate_decr()) | 
| 173 | return; | 235 | return; | 
| 174 | 236 | ||
| 175 | /* | 237 | /* | 
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c deleted file mode 100644 index 8be2f7d071f0..000000000000 --- a/arch/ppc/platforms/pmac_backlight.c +++ /dev/null  | |||
| @@ -1,202 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Miscellaneous procedures for dealing with the PowerMac hardware. | ||
| 3 | * Contains support for the backlight. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2000 Benjamin Herrenschmidt | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/config.h> | ||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/stddef.h> | ||
| 13 | #include <linux/reboot.h> | ||
| 14 | #include <linux/nvram.h> | ||
| 15 | #include <linux/console.h> | ||
| 16 | #include <asm/sections.h> | ||
| 17 | #include <asm/ptrace.h> | ||
| 18 | #include <asm/io.h> | ||
| 19 | #include <asm/pgtable.h> | ||
| 20 | #include <asm/system.h> | ||
| 21 | #include <asm/prom.h> | ||
| 22 | #include <asm/machdep.h> | ||
| 23 | #include <asm/nvram.h> | ||
| 24 | #include <asm/backlight.h> | ||
| 25 | |||
| 26 | #include <linux/adb.h> | ||
| 27 | #include <linux/pmu.h> | ||
| 28 | |||
| 29 | static struct backlight_controller *backlighter; | ||
| 30 | static void* backlighter_data; | ||
| 31 | static int backlight_autosave; | ||
| 32 | static int backlight_level = BACKLIGHT_MAX; | ||
| 33 | static int backlight_enabled = 1; | ||
| 34 | static int backlight_req_level = -1; | ||
| 35 | static int backlight_req_enable = -1; | ||
| 36 | |||
| 37 | static void backlight_callback(void *); | ||
| 38 | static DECLARE_WORK(backlight_work, backlight_callback, NULL); | ||
| 39 | |||
| 40 | void register_backlight_controller(struct backlight_controller *ctrler, | ||
| 41 | void *data, char *type) | ||
| 42 | { | ||
| 43 | struct device_node* bk_node; | ||
| 44 | char *prop; | ||
| 45 | int valid = 0; | ||
| 46 | |||
| 47 | /* There's already a matching controller, bail out */ | ||
| 48 | if (backlighter != NULL) | ||
| 49 | return; | ||
| 50 | |||
| 51 | bk_node = find_devices("backlight"); | ||
| 52 | |||
| 53 | #ifdef CONFIG_ADB_PMU | ||
| 54 | /* Special case for the old PowerBook since I can't test on it */ | ||
| 55 | backlight_autosave = machine_is_compatible("AAPL,3400/2400") | ||
| 56 | || machine_is_compatible("AAPL,3500"); | ||
| 57 | if ((backlight_autosave | ||
| 58 | || machine_is_compatible("AAPL,PowerBook1998") | ||
| 59 | || machine_is_compatible("PowerBook1,1")) | ||
| 60 | && !strcmp(type, "pmu")) | ||
| 61 | valid = 1; | ||
| 62 | #endif | ||
| 63 | if (bk_node) { | ||
| 64 | prop = get_property(bk_node, "backlight-control", NULL); | ||
| 65 | if (prop && !strncmp(prop, type, strlen(type))) | ||
| 66 | valid = 1; | ||
| 67 | } | ||
| 68 | if (!valid) | ||
| 69 | return; | ||
| 70 | backlighter = ctrler; | ||
| 71 | backlighter_data = data; | ||
| 72 | |||
| 73 | if (bk_node && !backlight_autosave) | ||
| 74 | prop = get_property(bk_node, "bklt", NULL); | ||
| 75 | else | ||
| 76 | prop = NULL; | ||
| 77 | if (prop) { | ||
| 78 | backlight_level = ((*prop)+1) >> 1; | ||
| 79 | if (backlight_level > BACKLIGHT_MAX) | ||
| 80 | backlight_level = BACKLIGHT_MAX; | ||
| 81 | } | ||
| 82 | |||
| 83 | #ifdef CONFIG_ADB_PMU | ||
| 84 | if (backlight_autosave) { | ||
| 85 | struct adb_request req; | ||
| 86 | pmu_request(&req, NULL, 2, 0xd9, 0); | ||
| 87 | while (!req.complete) | ||
| 88 | pmu_poll(); | ||
| 89 | backlight_level = req.reply[0] >> 4; | ||
| 90 | } | ||
| 91 | #endif | ||
| 92 | acquire_console_sem(); | ||
| 93 | if (!backlighter->set_enable(1, backlight_level, data)) | ||
| 94 | backlight_enabled = 1; | ||
| 95 | release_console_sem(); | ||
| 96 | |||
| 97 | printk(KERN_INFO "Registered \"%s\" backlight controller," | ||
| 98 | "level: %d/15\n", type, backlight_level); | ||
| 99 | } | ||
| 100 | EXPORT_SYMBOL(register_backlight_controller); | ||
| 101 | |||
| 102 | void unregister_backlight_controller(struct backlight_controller | ||
| 103 | *ctrler, void *data) | ||
| 104 | { | ||
| 105 | /* We keep the current backlight level (for now) */ | ||
| 106 | if (ctrler == backlighter && data == backlighter_data) | ||
| 107 | backlighter = NULL; | ||
| 108 | } | ||
| 109 | EXPORT_SYMBOL(unregister_backlight_controller); | ||
| 110 | |||
| 111 | static int __set_backlight_enable(int enable) | ||
| 112 | { | ||
| 113 | int rc; | ||
| 114 | |||
| 115 | if (!backlighter) | ||
| 116 | return -ENODEV; | ||
| 117 | acquire_console_sem(); | ||
| 118 | rc = backlighter->set_enable(enable, backlight_level, | ||
| 119 | backlighter_data); | ||
| 120 | if (!rc) | ||
| 121 | backlight_enabled = enable; | ||
| 122 | release_console_sem(); | ||
| 123 | return rc; | ||
| 124 | } | ||
| 125 | int set_backlight_enable(int enable) | ||
| 126 | { | ||
| 127 | if (!backlighter) | ||
| 128 | return -ENODEV; | ||
| 129 | backlight_req_enable = enable; | ||
| 130 | schedule_work(&backlight_work); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | EXPORT_SYMBOL(set_backlight_enable); | ||
| 135 | |||
| 136 | int get_backlight_enable(void) | ||
| 137 | { | ||
| 138 | if (!backlighter) | ||
| 139 | return -ENODEV; | ||
| 140 | return backlight_enabled; | ||
| 141 | } | ||
| 142 | EXPORT_SYMBOL(get_backlight_enable); | ||
| 143 | |||
| 144 | static int __set_backlight_level(int level) | ||
| 145 | { | ||
| 146 | int rc = 0; | ||
| 147 | |||
| 148 | if (!backlighter) | ||
| 149 | return -ENODEV; | ||
| 150 | if (level < BACKLIGHT_MIN) | ||
| 151 | level = BACKLIGHT_OFF; | ||
| 152 | if (level > BACKLIGHT_MAX) | ||
| 153 | level = BACKLIGHT_MAX; | ||
| 154 | acquire_console_sem(); | ||
| 155 | if (backlight_enabled) | ||
| 156 | rc = backlighter->set_level(level, backlighter_data); | ||
| 157 | if (!rc) | ||
| 158 | backlight_level = level; | ||
| 159 | release_console_sem(); | ||
| 160 | if (!rc && !backlight_autosave) { | ||
| 161 | level <<=1; | ||
| 162 | if (level & 0x10) | ||
| 163 | level |= 0x01; | ||
| 164 | // -- todo: save to property "bklt" | ||
| 165 | } | ||
| 166 | return rc; | ||
| 167 | } | ||
| 168 | int set_backlight_level(int level) | ||
| 169 | { | ||
| 170 | if (!backlighter) | ||
| 171 | return -ENODEV; | ||
| 172 | backlight_req_level = level; | ||
| 173 | schedule_work(&backlight_work); | ||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | EXPORT_SYMBOL(set_backlight_level); | ||
| 178 | |||
| 179 | int get_backlight_level(void) | ||
| 180 | { | ||
| 181 | if (!backlighter) | ||
| 182 | return -ENODEV; | ||
| 183 | return backlight_level; | ||
| 184 | } | ||
| 185 | EXPORT_SYMBOL(get_backlight_level); | ||
| 186 | |||
| 187 | static void backlight_callback(void *dummy) | ||
| 188 | { | ||
| 189 | int level, enable; | ||
| 190 | |||
| 191 | do { | ||
| 192 | level = backlight_req_level; | ||
| 193 | enable = backlight_req_enable; | ||
| 194 | mb(); | ||
| 195 | |||
| 196 | if (level >= 0) | ||
| 197 | __set_backlight_level(level); | ||
| 198 | if (enable >= 0) | ||
| 199 | __set_backlight_enable(enable); | ||
| 200 | } while(cmpxchg(&backlight_req_level, level, -1) != level || | ||
| 201 | cmpxchg(&backlight_req_enable, enable, -1) != enable); | ||
| 202 | } | ||
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S deleted file mode 100644 index fb977de6b704..000000000000 --- a/arch/ppc/platforms/pmac_cache.S +++ /dev/null  | |||
| @@ -1,359 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file contains low-level cache management functions | ||
| 3 | * used for sleep and CPU speed changes on Apple machines. | ||
| 4 | * (In fact the only thing that is Apple-specific is that we assume | ||
| 5 | * that we can read from ROM at physical address 0xfff00000.) | ||
| 6 | * | ||
| 7 | * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and | ||
| 8 | * Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <asm/processor.h> | ||
| 19 | #include <asm/ppc_asm.h> | ||
| 20 | #include <asm/cputable.h> | ||
| 21 | |||
| 22 | /* | ||
| 23 | * Flush and disable all data caches (dL1, L2, L3). This is used | ||
| 24 | * when going to sleep, when doing a PMU based cpufreq transition, | ||
| 25 | * or when "offlining" a CPU on SMP machines. This code is over | ||
| 26 | * paranoid, but I've had enough issues with various CPU revs and | ||
| 27 | * bugs that I decided it was worth beeing over cautious | ||
| 28 | */ | ||
| 29 | |||
| 30 | _GLOBAL(flush_disable_caches) | ||
| 31 | #ifndef CONFIG_6xx | ||
| 32 | blr | ||
| 33 | #else | ||
| 34 | BEGIN_FTR_SECTION | ||
| 35 | b flush_disable_745x | ||
| 36 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
| 37 | BEGIN_FTR_SECTION | ||
| 38 | b flush_disable_75x | ||
| 39 | END_FTR_SECTION_IFSET(CPU_FTR_L2CR) | ||
| 40 | b __flush_disable_L1 | ||
| 41 | |||
| 42 | /* This is the code for G3 and 74[01]0 */ | ||
| 43 | flush_disable_75x: | ||
| 44 | mflr r10 | ||
| 45 | |||
| 46 | /* Turn off EE and DR in MSR */ | ||
| 47 | mfmsr r11 | ||
| 48 | rlwinm r0,r11,0,~MSR_EE | ||
| 49 | rlwinm r0,r0,0,~MSR_DR | ||
| 50 | sync | ||
| 51 | mtmsr r0 | ||
| 52 | isync | ||
| 53 | |||
| 54 | /* Stop DST streams */ | ||
| 55 | BEGIN_FTR_SECTION | ||
| 56 | DSSALL | ||
| 57 | sync | ||
| 58 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
| 59 | |||
| 60 | /* Stop DPM */ | ||
| 61 | mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */ | ||
| 62 | rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ | ||
| 63 | sync | ||
| 64 | mtspr SPRN_HID0,r4 /* Disable DPM */ | ||
| 65 | sync | ||
| 66 | |||
| 67 | /* Disp-flush L1. We have a weird problem here that I never | ||
| 68 | * totally figured out. On 750FX, using the ROM for the flush | ||
| 69 | * results in a non-working flush. We use that workaround for | ||
| 70 | * now until I finally understand what's going on. --BenH | ||
| 71 | */ | ||
| 72 | |||
| 73 | /* ROM base by default */ | ||
| 74 | lis r4,0xfff0 | ||
| 75 | mfpvr r3 | ||
| 76 | srwi r3,r3,16 | ||
| 77 | cmplwi cr0,r3,0x7000 | ||
| 78 | bne+ 1f | ||
| 79 | /* RAM base on 750FX */ | ||
| 80 | li r4,0 | ||
| 81 | 1: li r4,0x4000 | ||
| 82 | mtctr r4 | ||
| 83 | 1: lwz r0,0(r4) | ||
| 84 | addi r4,r4,32 | ||
| 85 | bdnz 1b | ||
| 86 | sync | ||
| 87 | isync | ||
| 88 | |||
| 89 | /* Disable / invalidate / enable L1 data */ | ||
| 90 | mfspr r3,SPRN_HID0 | ||
| 91 | rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE) | ||
| 92 | mtspr SPRN_HID0,r3 | ||
| 93 | sync | ||
| 94 | isync | ||
| 95 | ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI) | ||
| 96 | sync | ||
| 97 | isync | ||
| 98 | mtspr SPRN_HID0,r3 | ||
| 99 | xori r3,r3,(HID0_DCI|HID0_ICFI) | ||
| 100 | mtspr SPRN_HID0,r3 | ||
| 101 | sync | ||
| 102 | |||
| 103 | /* Get the current enable bit of the L2CR into r4 */ | ||
| 104 | mfspr r5,SPRN_L2CR | ||
| 105 | /* Set to data-only (pre-745x bit) */ | ||
| 106 | oris r3,r5,L2CR_L2DO@h | ||
| 107 | b 2f | ||
| 108 | /* When disabling L2, code must be in L1 */ | ||
| 109 | .balign 32 | ||
| 110 | 1: mtspr SPRN_L2CR,r3 | ||
| 111 | 3: sync | ||
| 112 | isync | ||
| 113 | b 1f | ||
| 114 | 2: b 3f | ||
| 115 | 3: sync | ||
| 116 | isync | ||
| 117 | b 1b | ||
| 118 | 1: /* disp-flush L2. The interesting thing here is that the L2 can be | ||
| 119 | * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory | ||
| 120 | * but that is probbaly fine. We disp-flush over 4Mb to be safe | ||
| 121 | */ | ||
| 122 | lis r4,2 | ||
| 123 | mtctr r4 | ||
| 124 | lis r4,0xfff0 | ||
| 125 | 1: lwz r0,0(r4) | ||
| 126 | addi r4,r4,32 | ||
| 127 | bdnz 1b | ||
| 128 | sync | ||
| 129 | isync | ||
| 130 | lis r4,2 | ||
| 131 | mtctr r4 | ||
| 132 | lis r4,0xfff0 | ||
| 133 | 1: dcbf 0,r4 | ||
| 134 | addi r4,r4,32 | ||
| 135 | bdnz 1b | ||
| 136 | sync | ||
| 137 | isync | ||
| 138 | |||
| 139 | /* now disable L2 */ | ||
| 140 | rlwinm r5,r5,0,~L2CR_L2E | ||
| 141 | b 2f | ||
| 142 | /* When disabling L2, code must be in L1 */ | ||
| 143 | .balign 32 | ||
| 144 | 1: mtspr SPRN_L2CR,r5 | ||
| 145 | 3: sync | ||
| 146 | isync | ||
| 147 | b 1f | ||
| 148 | 2: b 3f | ||
| 149 | 3: sync | ||
| 150 | isync | ||
| 151 | b 1b | ||
| 152 | 1: sync | ||
| 153 | isync | ||
| 154 | /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */ | ||
| 155 | oris r4,r5,L2CR_L2I@h | ||
| 156 | mtspr SPRN_L2CR,r4 | ||
| 157 | sync | ||
| 158 | isync | ||
| 159 | |||
| 160 | /* Wait for the invalidation to complete */ | ||
| 161 | 1: mfspr r3,SPRN_L2CR | ||
| 162 | rlwinm. r0,r3,0,31,31 | ||
| 163 | bne 1b | ||
| 164 | |||
| 165 | /* Clear L2I */ | ||
| 166 | xoris r4,r4,L2CR_L2I@h | ||
| 167 | sync | ||
| 168 | mtspr SPRN_L2CR,r4 | ||
| 169 | sync | ||
| 170 | |||
| 171 | /* now disable the L1 data cache */ | ||
| 172 | mfspr r0,SPRN_HID0 | ||
| 173 | rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE) | ||
| 174 | mtspr SPRN_HID0,r0 | ||
| 175 | sync | ||
| 176 | isync | ||
| 177 | |||
| 178 | /* Restore HID0[DPM] to whatever it was before */ | ||
| 179 | sync | ||
| 180 | mfspr r0,SPRN_HID0 | ||
| 181 | rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */ | ||
| 182 | mtspr SPRN_HID0,r0 | ||
| 183 | sync | ||
| 184 | |||
| 185 | /* restore DR and EE */ | ||
| 186 | sync | ||
| 187 | mtmsr r11 | ||
| 188 | isync | ||
| 189 | |||
| 190 | mtlr r10 | ||
| 191 | blr | ||
| 192 | |||
| 193 | /* This code is for 745x processors */ | ||
| 194 | flush_disable_745x: | ||
| 195 | /* Turn off EE and DR in MSR */ | ||
| 196 | mfmsr r11 | ||
| 197 | rlwinm r0,r11,0,~MSR_EE | ||
| 198 | rlwinm r0,r0,0,~MSR_DR | ||
| 199 | sync | ||
| 200 | mtmsr r0 | ||
| 201 | isync | ||
| 202 | |||
| 203 | /* Stop prefetch streams */ | ||
| 204 | DSSALL | ||
| 205 | sync | ||
| 206 | |||
| 207 | /* Disable L2 prefetching */ | ||
| 208 | mfspr r0,SPRN_MSSCR0 | ||
| 209 | rlwinm r0,r0,0,0,29 | ||
| 210 | mtspr SPRN_MSSCR0,r0 | ||
| 211 | sync | ||
| 212 | isync | ||
| 213 | lis r4,0 | ||
| 214 | dcbf 0,r4 | ||
| 215 | dcbf 0,r4 | ||
| 216 | dcbf 0,r4 | ||
| 217 | dcbf 0,r4 | ||
| 218 | dcbf 0,r4 | ||
| 219 | dcbf 0,r4 | ||
| 220 | dcbf 0,r4 | ||
| 221 | dcbf 0,r4 | ||
| 222 | |||
| 223 | /* Due to a bug with the HW flush on some CPU revs, we occasionally | ||
| 224 | * experience data corruption. I'm adding a displacement flush along | ||
| 225 | * with a dcbf loop over a few Mb to "help". The problem isn't totally | ||
| 226 | * fixed by this in theory, but at least, in practice, I couldn't reproduce | ||
| 227 | * it even with a big hammer... | ||
| 228 | */ | ||
| 229 | |||
| 230 | lis r4,0x0002 | ||
| 231 | mtctr r4 | ||
| 232 | li r4,0 | ||
| 233 | 1: | ||
| 234 | lwz r0,0(r4) | ||
| 235 | addi r4,r4,32 /* Go to start of next cache line */ | ||
| 236 | bdnz 1b | ||
| 237 | isync | ||
| 238 | |||
| 239 | /* Now, flush the first 4MB of memory */ | ||
| 240 | lis r4,0x0002 | ||
| 241 | mtctr r4 | ||
| 242 | li r4,0 | ||
| 243 | sync | ||
| 244 | 1: | ||
| 245 | dcbf 0,r4 | ||
| 246 | addi r4,r4,32 /* Go to start of next cache line */ | ||
| 247 | bdnz 1b | ||
| 248 | |||
| 249 | /* Flush and disable the L1 data cache */ | ||
| 250 | mfspr r6,SPRN_LDSTCR | ||
| 251 | lis r3,0xfff0 /* read from ROM for displacement flush */ | ||
| 252 | li r4,0xfe /* start with only way 0 unlocked */ | ||
| 253 | li r5,128 /* 128 lines in each way */ | ||
| 254 | 1: mtctr r5 | ||
| 255 | rlwimi r6,r4,0,24,31 | ||
| 256 | mtspr SPRN_LDSTCR,r6 | ||
| 257 | sync | ||
| 258 | isync | ||
| 259 | 2: lwz r0,0(r3) /* touch each cache line */ | ||
| 260 | addi r3,r3,32 | ||
| 261 | bdnz 2b | ||
| 262 | rlwinm r4,r4,1,24,30 /* move on to the next way */ | ||
| 263 | ori r4,r4,1 | ||
| 264 | cmpwi r4,0xff /* all done? */ | ||
| 265 | bne 1b | ||
| 266 | /* now unlock the L1 data cache */ | ||
| 267 | li r4,0 | ||
| 268 | rlwimi r6,r4,0,24,31 | ||
| 269 | sync | ||
| 270 | mtspr SPRN_LDSTCR,r6 | ||
| 271 | sync | ||
| 272 | isync | ||
| 273 | |||
| 274 | /* Flush the L2 cache using the hardware assist */ | ||
| 275 | mfspr r3,SPRN_L2CR | ||
| 276 | cmpwi r3,0 /* check if it is enabled first */ | ||
| 277 | bge 4f | ||
| 278 | oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h | ||
| 279 | b 2f | ||
| 280 | /* When disabling/locking L2, code must be in L1 */ | ||
| 281 | .balign 32 | ||
| 282 | 1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */ | ||
| 283 | 3: sync | ||
| 284 | isync | ||
| 285 | b 1f | ||
| 286 | 2: b 3f | ||
| 287 | 3: sync | ||
| 288 | isync | ||
| 289 | b 1b | ||
| 290 | 1: sync | ||
| 291 | isync | ||
| 292 | ori r0,r3,L2CR_L2HWF_745x | ||
| 293 | sync | ||
| 294 | mtspr SPRN_L2CR,r0 /* set the hardware flush bit */ | ||
| 295 | 3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */ | ||
| 296 | andi. r0,r0,L2CR_L2HWF_745x | ||
| 297 | bne 3b | ||
| 298 | sync | ||
| 299 | rlwinm r3,r3,0,~L2CR_L2E | ||
| 300 | b 2f | ||
| 301 | /* When disabling L2, code must be in L1 */ | ||
| 302 | .balign 32 | ||
| 303 | 1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */ | ||
| 304 | 3: sync | ||
| 305 | isync | ||
| 306 | b 1f | ||
| 307 | 2: b 3f | ||
| 308 | 3: sync | ||
| 309 | isync | ||
| 310 | b 1b | ||
| 311 | 1: sync | ||
| 312 | isync | ||
| 313 | oris r4,r3,L2CR_L2I@h | ||
| 314 | mtspr SPRN_L2CR,r4 | ||
| 315 | sync | ||
| 316 | isync | ||
| 317 | 1: mfspr r4,SPRN_L2CR | ||
| 318 | andis. r0,r4,L2CR_L2I@h | ||
| 319 | bne 1b | ||
| 320 | sync | ||
| 321 | |||
| 322 | BEGIN_FTR_SECTION | ||
| 323 | /* Flush the L3 cache using the hardware assist */ | ||
| 324 | 4: mfspr r3,SPRN_L3CR | ||
| 325 | cmpwi r3,0 /* check if it is enabled */ | ||
| 326 | bge 6f | ||
| 327 | oris r0,r3,L3CR_L3IO@h | ||
| 328 | ori r0,r0,L3CR_L3DO | ||
| 329 | sync | ||
| 330 | mtspr SPRN_L3CR,r0 /* lock the L3 cache */ | ||
| 331 | sync | ||
| 332 | isync | ||
| 333 | ori r0,r0,L3CR_L3HWF | ||
| 334 | sync | ||
| 335 | mtspr SPRN_L3CR,r0 /* set the hardware flush bit */ | ||
| 336 | 5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */ | ||
| 337 | andi. r0,r0,L3CR_L3HWF | ||
| 338 | bne 5b | ||
| 339 | rlwinm r3,r3,0,~L3CR_L3E | ||
| 340 | sync | ||
| 341 | mtspr SPRN_L3CR,r3 /* disable the L3 cache */ | ||
| 342 | sync | ||
| 343 | ori r4,r3,L3CR_L3I | ||
| 344 | mtspr SPRN_L3CR,r4 | ||
| 345 | 1: mfspr r4,SPRN_L3CR | ||
| 346 | andi. r0,r4,L3CR_L3I | ||
| 347 | bne 1b | ||
| 348 | sync | ||
| 349 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
| 350 | |||
| 351 | 6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */ | ||
| 352 | rlwinm r0,r0,0,~HID0_DCE | ||
| 353 | mtspr SPRN_HID0,r0 | ||
| 354 | sync | ||
| 355 | isync | ||
| 356 | mtmsr r11 /* restore DR and EE */ | ||
| 357 | isync | ||
| 358 | blr | ||
| 359 | #endif /* CONFIG_6xx */ | ||
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c deleted file mode 100644 index fba7e4d7c0bf..000000000000 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ /dev/null  | |||
| @@ -1,735 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/ppc/platforms/pmac_cpufreq.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
| 5 | * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * TODO: Need a big cleanup here. Basically, we need to have different | ||
| 12 | * cpufreq_driver structures for the different type of HW instead of the | ||
| 13 | * current mess. We also need to better deal with the detection of the | ||
| 14 | * type of machine. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/config.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/delay.h> | ||
| 24 | #include <linux/sched.h> | ||
| 25 | #include <linux/adb.h> | ||
| 26 | #include <linux/pmu.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/sysdev.h> | ||
| 31 | #include <linux/i2c.h> | ||
| 32 | #include <linux/hardirq.h> | ||
| 33 | #include <asm/prom.h> | ||
| 34 | #include <asm/machdep.h> | ||
| 35 | #include <asm/irq.h> | ||
| 36 | #include <asm/pmac_feature.h> | ||
| 37 | #include <asm/mmu_context.h> | ||
| 38 | #include <asm/sections.h> | ||
| 39 | #include <asm/cputable.h> | ||
| 40 | #include <asm/time.h> | ||
| 41 | #include <asm/system.h> | ||
| 42 | #include <asm/open_pic.h> | ||
| 43 | #include <asm/keylargo.h> | ||
| 44 | |||
| 45 | /* WARNING !!! This will cause calibrate_delay() to be called, | ||
| 46 | * but this is an __init function ! So you MUST go edit | ||
| 47 | * init/main.c to make it non-init before enabling DEBUG_FREQ | ||
| 48 | */ | ||
| 49 | #undef DEBUG_FREQ | ||
| 50 | |||
| 51 | /* | ||
| 52 | * There is a problem with the core cpufreq code on SMP kernels, | ||
| 53 | * it won't recalculate the Bogomips properly | ||
| 54 | */ | ||
| 55 | #ifdef CONFIG_SMP | ||
| 56 | #warning "WARNING, CPUFREQ not recommended on SMP kernels" | ||
| 57 | #endif | ||
| 58 | |||
| 59 | extern void low_choose_7447a_dfs(int dfs); | ||
| 60 | extern void low_choose_750fx_pll(int pll); | ||
| 61 | extern void low_sleep_handler(void); | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Currently, PowerMac cpufreq supports only high & low frequencies | ||
| 65 | * that are set by the firmware | ||
| 66 | */ | ||
| 67 | static unsigned int low_freq; | ||
| 68 | static unsigned int hi_freq; | ||
| 69 | static unsigned int cur_freq; | ||
| 70 | static unsigned int sleep_freq; | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Different models uses different mecanisms to switch the frequency | ||
| 74 | */ | ||
| 75 | static int (*set_speed_proc)(int low_speed); | ||
| 76 | static unsigned int (*get_speed_proc)(void); | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Some definitions used by the various speedprocs | ||
| 80 | */ | ||
| 81 | static u32 voltage_gpio; | ||
| 82 | static u32 frequency_gpio; | ||
| 83 | static u32 slew_done_gpio; | ||
| 84 | static int no_schedule; | ||
| 85 | static int has_cpu_l2lve; | ||
| 86 | static int is_pmu_based; | ||
| 87 | |||
| 88 | /* There are only two frequency states for each processor. Values | ||
| 89 | * are in kHz for the time being. | ||
| 90 | */ | ||
| 91 | #define CPUFREQ_HIGH 0 | ||
| 92 | #define CPUFREQ_LOW 1 | ||
| 93 | |||
| 94 | static struct cpufreq_frequency_table pmac_cpu_freqs[] = { | ||
| 95 | {CPUFREQ_HIGH, 0}, | ||
| 96 | {CPUFREQ_LOW, 0}, | ||
| 97 | {0, CPUFREQ_TABLE_END}, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static struct freq_attr* pmac_cpu_freqs_attr[] = { | ||
| 101 | &cpufreq_freq_attr_scaling_available_freqs, | ||
| 102 | NULL, | ||
| 103 | }; | ||
| 104 | |||
| 105 | static inline void local_delay(unsigned long ms) | ||
| 106 | { | ||
| 107 | if (no_schedule) | ||
| 108 | mdelay(ms); | ||
| 109 | else | ||
| 110 | msleep(ms); | ||
| 111 | } | ||
| 112 | |||
| 113 | static inline void wakeup_decrementer(void) | ||
| 114 | { | ||
| 115 | set_dec(tb_ticks_per_jiffy); | ||
| 116 | /* No currently-supported powerbook has a 601, | ||
| 117 | * so use get_tbl, not native | ||
| 118 | */ | ||
| 119 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
| 120 | } | ||
| 121 | |||
| 122 | #ifdef DEBUG_FREQ | ||
| 123 | static inline void debug_calc_bogomips(void) | ||
| 124 | { | ||
| 125 | /* This will cause a recalc of bogomips and display the | ||
| 126 | * result. We backup/restore the value to avoid affecting the | ||
| 127 | * core cpufreq framework's own calculation. | ||
| 128 | */ | ||
| 129 | extern void calibrate_delay(void); | ||
| 130 | |||
| 131 | unsigned long save_lpj = loops_per_jiffy; | ||
| 132 | calibrate_delay(); | ||
| 133 | loops_per_jiffy = save_lpj; | ||
| 134 | } | ||
| 135 | #endif /* DEBUG_FREQ */ | ||
| 136 | |||
| 137 | /* Switch CPU speed under 750FX CPU control | ||
| 138 | */ | ||
| 139 | static int cpu_750fx_cpu_speed(int low_speed) | ||
| 140 | { | ||
| 141 | u32 hid2; | ||
| 142 | |||
| 143 | if (low_speed == 0) { | ||
| 144 | /* ramping up, set voltage first */ | ||
| 145 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 146 | /* Make sure we sleep for at least 1ms */ | ||
| 147 | local_delay(10); | ||
| 148 | |||
| 149 | /* tweak L2 for high voltage */ | ||
| 150 | if (has_cpu_l2lve) { | ||
| 151 | hid2 = mfspr(SPRN_HID2); | ||
| 152 | hid2 &= ~0x2000; | ||
| 153 | mtspr(SPRN_HID2, hid2); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | #ifdef CONFIG_6xx | ||
| 157 | low_choose_750fx_pll(low_speed); | ||
| 158 | #endif | ||
| 159 | if (low_speed == 1) { | ||
| 160 | /* tweak L2 for low voltage */ | ||
| 161 | if (has_cpu_l2lve) { | ||
| 162 | hid2 = mfspr(SPRN_HID2); | ||
| 163 | hid2 |= 0x2000; | ||
| 164 | mtspr(SPRN_HID2, hid2); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* ramping down, set voltage last */ | ||
| 168 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 169 | local_delay(10); | ||
| 170 | } | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | static unsigned int cpu_750fx_get_cpu_speed(void) | ||
| 176 | { | ||
| 177 | if (mfspr(SPRN_HID1) & HID1_PS) | ||
| 178 | return low_freq; | ||
| 179 | else | ||
| 180 | return hi_freq; | ||
| 181 | } | ||
| 182 | |||
| 183 | /* Switch CPU speed using DFS */ | ||
| 184 | static int dfs_set_cpu_speed(int low_speed) | ||
| 185 | { | ||
| 186 | if (low_speed == 0) { | ||
| 187 | /* ramping up, set voltage first */ | ||
| 188 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 189 | /* Make sure we sleep for at least 1ms */ | ||
| 190 | local_delay(1); | ||
| 191 | } | ||
| 192 | |||
| 193 | /* set frequency */ | ||
| 194 | #ifdef CONFIG_6xx | ||
| 195 | low_choose_7447a_dfs(low_speed); | ||
| 196 | #endif | ||
| 197 | udelay(100); | ||
| 198 | |||
| 199 | if (low_speed == 1) { | ||
| 200 | /* ramping down, set voltage last */ | ||
| 201 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 202 | local_delay(1); | ||
| 203 | } | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | static unsigned int dfs_get_cpu_speed(void) | ||
| 209 | { | ||
| 210 | if (mfspr(SPRN_HID1) & HID1_DFS) | ||
| 211 | return low_freq; | ||
| 212 | else | ||
| 213 | return hi_freq; | ||
| 214 | } | ||
| 215 | |||
| 216 | |||
| 217 | /* Switch CPU speed using slewing GPIOs | ||
| 218 | */ | ||
| 219 | static int gpios_set_cpu_speed(int low_speed) | ||
| 220 | { | ||
| 221 | int gpio, timeout = 0; | ||
| 222 | |||
| 223 | /* If ramping up, set voltage first */ | ||
| 224 | if (low_speed == 0) { | ||
| 225 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
| 226 | /* Delay is way too big but it's ok, we schedule */ | ||
| 227 | local_delay(10); | ||
| 228 | } | ||
| 229 | |||
| 230 | /* Set frequency */ | ||
| 231 | gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); | ||
| 232 | if (low_speed == ((gpio & 0x01) == 0)) | ||
| 233 | goto skip; | ||
| 234 | |||
| 235 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, | ||
| 236 | low_speed ? 0x04 : 0x05); | ||
| 237 | udelay(200); | ||
| 238 | do { | ||
| 239 | if (++timeout > 100) | ||
| 240 | break; | ||
| 241 | local_delay(1); | ||
| 242 | gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); | ||
| 243 | } while((gpio & 0x02) == 0); | ||
| 244 | skip: | ||
| 245 | /* If ramping down, set voltage last */ | ||
| 246 | if (low_speed == 1) { | ||
| 247 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
| 248 | /* Delay is way too big but it's ok, we schedule */ | ||
| 249 | local_delay(10); | ||
| 250 | } | ||
| 251 | |||
| 252 | #ifdef DEBUG_FREQ | ||
| 253 | debug_calc_bogomips(); | ||
| 254 | #endif | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | /* Switch CPU speed under PMU control | ||
| 260 | */ | ||
| 261 | static int pmu_set_cpu_speed(int low_speed) | ||
| 262 | { | ||
| 263 | struct adb_request req; | ||
| 264 | unsigned long save_l2cr; | ||
| 265 | unsigned long save_l3cr; | ||
| 266 | unsigned int pic_prio; | ||
| 267 | unsigned long flags; | ||
| 268 | |||
| 269 | preempt_disable(); | ||
| 270 | |||
| 271 | #ifdef DEBUG_FREQ | ||
| 272 | printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); | ||
| 273 | #endif | ||
| 274 | pmu_suspend(); | ||
| 275 | |||
| 276 | /* Disable all interrupt sources on openpic */ | ||
| 277 | pic_prio = openpic_get_priority(); | ||
| 278 | openpic_set_priority(0xf); | ||
| 279 | |||
| 280 | /* Make sure the decrementer won't interrupt us */ | ||
| 281 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 282 | /* Make sure any pending DEC interrupt occuring while we did | ||
| 283 | * the above didn't re-enable the DEC */ | ||
| 284 | mb(); | ||
| 285 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 286 | |||
| 287 | /* We can now disable MSR_EE */ | ||
| 288 | local_irq_save(flags); | ||
| 289 | |||
| 290 | /* Giveup the FPU & vec */ | ||
| 291 | enable_kernel_fp(); | ||
| 292 | |||
| 293 | #ifdef CONFIG_ALTIVEC | ||
| 294 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
| 295 | enable_kernel_altivec(); | ||
| 296 | #endif /* CONFIG_ALTIVEC */ | ||
| 297 | |||
| 298 | /* Save & disable L2 and L3 caches */ | ||
| 299 | save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ | ||
| 300 | save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ | ||
| 301 | |||
| 302 | /* Send the new speed command. My assumption is that this command | ||
| 303 | * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep | ||
| 304 | */ | ||
| 305 | pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); | ||
| 306 | while (!req.complete) | ||
| 307 | pmu_poll(); | ||
| 308 | |||
| 309 | /* Prepare the northbridge for the speed transition */ | ||
| 310 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); | ||
| 311 | |||
| 312 | /* Call low level code to backup CPU state and recover from | ||
| 313 | * hardware reset | ||
| 314 | */ | ||
| 315 | low_sleep_handler(); | ||
| 316 | |||
| 317 | /* Restore the northbridge */ | ||
| 318 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); | ||
| 319 | |||
| 320 | /* Restore L2 cache */ | ||
| 321 | if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) | ||
| 322 | _set_L2CR(save_l2cr); | ||
| 323 | /* Restore L3 cache */ | ||
| 324 | if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) | ||
| 325 | _set_L3CR(save_l3cr); | ||
| 326 | |||
| 327 | /* Restore userland MMU context */ | ||
| 328 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
| 329 | |||
| 330 | #ifdef DEBUG_FREQ | ||
| 331 | printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); | ||
| 332 | #endif | ||
| 333 | |||
| 334 | /* Restore low level PMU operations */ | ||
| 335 | pmu_unlock(); | ||
| 336 | |||
| 337 | /* Restore decrementer */ | ||
| 338 | wakeup_decrementer(); | ||
| 339 | |||
| 340 | /* Restore interrupts */ | ||
| 341 | openpic_set_priority(pic_prio); | ||
| 342 | |||
| 343 | /* Let interrupts flow again ... */ | ||
| 344 | local_irq_restore(flags); | ||
| 345 | |||
| 346 | #ifdef DEBUG_FREQ | ||
| 347 | debug_calc_bogomips(); | ||
| 348 | #endif | ||
| 349 | |||
| 350 | pmu_resume(); | ||
| 351 | |||
| 352 | preempt_enable(); | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int do_set_cpu_speed(int speed_mode, int notify) | ||
| 358 | { | ||
| 359 | struct cpufreq_freqs freqs; | ||
| 360 | unsigned long l3cr; | ||
| 361 | static unsigned long prev_l3cr; | ||
| 362 | |||
| 363 | freqs.old = cur_freq; | ||
| 364 | freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | ||
| 365 | freqs.cpu = smp_processor_id(); | ||
| 366 | |||
| 367 | if (freqs.old == freqs.new) | ||
| 368 | return 0; | ||
| 369 | |||
| 370 | if (notify) | ||
| 371 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
| 372 | if (speed_mode == CPUFREQ_LOW && | ||
| 373 | cpu_has_feature(CPU_FTR_L3CR)) { | ||
| 374 | l3cr = _get_L3CR(); | ||
| 375 | if (l3cr & L3CR_L3E) { | ||
| 376 | prev_l3cr = l3cr; | ||
| 377 | _set_L3CR(0); | ||
| 378 | } | ||
| 379 | } | ||
| 380 | set_speed_proc(speed_mode == CPUFREQ_LOW); | ||
| 381 | if (speed_mode == CPUFREQ_HIGH && | ||
| 382 | cpu_has_feature(CPU_FTR_L3CR)) { | ||
| 383 | l3cr = _get_L3CR(); | ||
| 384 | if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr) | ||
| 385 | _set_L3CR(prev_l3cr); | ||
| 386 | } | ||
| 387 | if (notify) | ||
| 388 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
| 389 | cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq; | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static unsigned int pmac_cpufreq_get_speed(unsigned int cpu) | ||
| 395 | { | ||
| 396 | return cur_freq; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int pmac_cpufreq_verify(struct cpufreq_policy *policy) | ||
| 400 | { | ||
| 401 | return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); | ||
| 402 | } | ||
| 403 | |||
| 404 | static int pmac_cpufreq_target( struct cpufreq_policy *policy, | ||
| 405 | unsigned int target_freq, | ||
| 406 | unsigned int relation) | ||
| 407 | { | ||
| 408 | unsigned int newstate = 0; | ||
| 409 | |||
| 410 | if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, | ||
| 411 | target_freq, relation, &newstate)) | ||
| 412 | return -EINVAL; | ||
| 413 | |||
| 414 | return do_set_cpu_speed(newstate, 1); | ||
| 415 | } | ||
| 416 | |||
| 417 | unsigned int pmac_get_one_cpufreq(int i) | ||
| 418 | { | ||
| 419 | /* Supports only one CPU for now */ | ||
| 420 | return (i == 0) ? cur_freq : 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
| 424 | { | ||
| 425 | if (policy->cpu != 0) | ||
| 426 | return -ENODEV; | ||
| 427 | |||
| 428 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
| 429 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
| 430 | policy->cur = cur_freq; | ||
| 431 | |||
| 432 | cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu); | ||
| 433 | return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs); | ||
| 434 | } | ||
| 435 | |||
| 436 | static u32 read_gpio(struct device_node *np) | ||
| 437 | { | ||
| 438 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | ||
| 439 | u32 offset; | ||
| 440 | |||
| 441 | if (reg == NULL) | ||
| 442 | return 0; | ||
| 443 | /* That works for all keylargos but shall be fixed properly | ||
| 444 | * some day... The problem is that it seems we can't rely | ||
| 445 | * on the "reg" property of the GPIO nodes, they are either | ||
| 446 | * relative to the base of KeyLargo or to the base of the | ||
| 447 | * GPIO space, and the device-tree doesn't help. | ||
| 448 | */ | ||
| 449 | offset = *reg; | ||
| 450 | if (offset < KEYLARGO_GPIO_LEVELS0) | ||
| 451 | offset += KEYLARGO_GPIO_LEVELS0; | ||
| 452 | return offset; | ||
| 453 | } | ||
| 454 | |||
| 455 | static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) | ||
| 456 | { | ||
| 457 | /* Ok, this could be made a bit smarter, but let's be robust for now. We | ||
| 458 | * always force a speed change to high speed before sleep, to make sure | ||
| 459 | * we have appropriate voltage and/or bus speed for the wakeup process, | ||
| 460 | * and to make sure our loops_per_jiffies are "good enough", that is will | ||
| 461 | * not cause too short delays if we sleep in low speed and wake in high | ||
| 462 | * speed.. | ||
| 463 | */ | ||
| 464 | no_schedule = 1; | ||
| 465 | sleep_freq = cur_freq; | ||
| 466 | if (cur_freq == low_freq && !is_pmu_based) | ||
| 467 | do_set_cpu_speed(CPUFREQ_HIGH, 0); | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 471 | static int pmac_cpufreq_resume(struct cpufreq_policy *policy) | ||
| 472 | { | ||
| 473 | /* If we resume, first check if we have a get() function */ | ||
| 474 | if (get_speed_proc) | ||
| 475 | cur_freq = get_speed_proc(); | ||
| 476 | else | ||
| 477 | cur_freq = 0; | ||
| 478 | |||
| 479 | /* We don't, hrm... we don't really know our speed here, best | ||
| 480 | * is that we force a switch to whatever it was, which is | ||
| 481 | * probably high speed due to our suspend() routine | ||
| 482 | */ | ||
| 483 | do_set_cpu_speed(sleep_freq == low_freq ? | ||
| 484 | CPUFREQ_LOW : CPUFREQ_HIGH, 0); | ||
| 485 | |||
| 486 | no_schedule = 0; | ||
| 487 | return 0; | ||
| 488 | } | ||
| 489 | |||
| 490 | static struct cpufreq_driver pmac_cpufreq_driver = { | ||
| 491 | .verify = pmac_cpufreq_verify, | ||
| 492 | .target = pmac_cpufreq_target, | ||
| 493 | .get = pmac_cpufreq_get_speed, | ||
| 494 | .init = pmac_cpufreq_cpu_init, | ||
| 495 | .suspend = pmac_cpufreq_suspend, | ||
| 496 | .resume = pmac_cpufreq_resume, | ||
| 497 | .flags = CPUFREQ_PM_NO_WARN, | ||
| 498 | .attr = pmac_cpu_freqs_attr, | ||
| 499 | .name = "powermac", | ||
| 500 | .owner = THIS_MODULE, | ||
| 501 | }; | ||
| 502 | |||
| 503 | |||
| 504 | static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) | ||
| 505 | { | ||
| 506 | struct device_node *volt_gpio_np = of_find_node_by_name(NULL, | ||
| 507 | "voltage-gpio"); | ||
| 508 | struct device_node *freq_gpio_np = of_find_node_by_name(NULL, | ||
| 509 | "frequency-gpio"); | ||
| 510 | struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, | ||
| 511 | "slewing-done"); | ||
| 512 | u32 *value; | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Check to see if it's GPIO driven or PMU only | ||
| 516 | * | ||
| 517 | * The way we extract the GPIO address is slightly hackish, but it | ||
| 518 | * works well enough for now. We need to abstract the whole GPIO | ||
| 519 | * stuff sooner or later anyway | ||
| 520 | */ | ||
| 521 | |||
| 522 | if (volt_gpio_np) | ||
| 523 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 524 | if (freq_gpio_np) | ||
| 525 | frequency_gpio = read_gpio(freq_gpio_np); | ||
| 526 | if (slew_done_gpio_np) | ||
| 527 | slew_done_gpio = read_gpio(slew_done_gpio_np); | ||
| 528 | |||
| 529 | /* If we use the frequency GPIOs, calculate the min/max speeds based | ||
| 530 | * on the bus frequencies | ||
| 531 | */ | ||
| 532 | if (frequency_gpio && slew_done_gpio) { | ||
| 533 | int lenp, rc; | ||
| 534 | u32 *freqs, *ratio; | ||
| 535 | |||
| 536 | freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); | ||
| 537 | lenp /= sizeof(u32); | ||
| 538 | if (freqs == NULL || lenp != 2) { | ||
| 539 | printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); | ||
| 540 | return 1; | ||
| 541 | } | ||
| 542 | ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); | ||
| 543 | if (ratio == NULL) { | ||
| 544 | printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); | ||
| 545 | return 1; | ||
| 546 | } | ||
| 547 | |||
| 548 | /* Get the min/max bus frequencies */ | ||
| 549 | low_freq = min(freqs[0], freqs[1]); | ||
| 550 | hi_freq = max(freqs[0], freqs[1]); | ||
| 551 | |||
| 552 | /* Grrrr.. It _seems_ that the device-tree is lying on the low bus | ||
| 553 | * frequency, it claims it to be around 84Mhz on some models while | ||
| 554 | * it appears to be approx. 101Mhz on all. Let's hack around here... | ||
| 555 | * fortunately, we don't need to be too precise | ||
| 556 | */ | ||
| 557 | if (low_freq < 98000000) | ||
| 558 | low_freq = 101000000; | ||
| 559 | |||
| 560 | /* Convert those to CPU core clocks */ | ||
| 561 | low_freq = (low_freq * (*ratio)) / 2000; | ||
| 562 | hi_freq = (hi_freq * (*ratio)) / 2000; | ||
| 563 | |||
| 564 | /* Now we get the frequencies, we read the GPIO to see what is out current | ||
| 565 | * speed | ||
| 566 | */ | ||
| 567 | rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); | ||
| 568 | cur_freq = (rc & 0x01) ? hi_freq : low_freq; | ||
| 569 | |||
| 570 | set_speed_proc = gpios_set_cpu_speed; | ||
| 571 | return 1; | ||
| 572 | } | ||
| 573 | |||
| 574 | /* If we use the PMU, look for the min & max frequencies in the | ||
| 575 | * device-tree | ||
| 576 | */ | ||
| 577 | value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); | ||
| 578 | if (!value) | ||
| 579 | return 1; | ||
| 580 | low_freq = (*value) / 1000; | ||
| 581 | /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree | ||
| 582 | * here */ | ||
| 583 | if (low_freq < 100000) | ||
| 584 | low_freq *= 10; | ||
| 585 | |||
| 586 | value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); | ||
| 587 | if (!value) | ||
| 588 | return 1; | ||
| 589 | hi_freq = (*value) / 1000; | ||
| 590 | set_speed_proc = pmu_set_cpu_speed; | ||
| 591 | is_pmu_based = 1; | ||
| 592 | |||
| 593 | return 0; | ||
| 594 | } | ||
| 595 | |||
| 596 | static int pmac_cpufreq_init_7447A(struct device_node *cpunode) | ||
| 597 | { | ||
| 598 | struct device_node *volt_gpio_np; | ||
| 599 | |||
| 600 | if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) | ||
| 601 | return 1; | ||
| 602 | |||
| 603 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
| 604 | if (volt_gpio_np) | ||
| 605 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 606 | if (!voltage_gpio){ | ||
| 607 | printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); | ||
| 608 | return 1; | ||
| 609 | } | ||
| 610 | |||
| 611 | /* OF only reports the high frequency */ | ||
| 612 | hi_freq = cur_freq; | ||
| 613 | low_freq = cur_freq/2; | ||
| 614 | |||
| 615 | /* Read actual frequency from CPU */ | ||
| 616 | cur_freq = dfs_get_cpu_speed(); | ||
| 617 | set_speed_proc = dfs_set_cpu_speed; | ||
| 618 | get_speed_proc = dfs_get_cpu_speed; | ||
| 619 | |||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | |||
| 623 | static int pmac_cpufreq_init_750FX(struct device_node *cpunode) | ||
| 624 | { | ||
| 625 | struct device_node *volt_gpio_np; | ||
| 626 | u32 pvr, *value; | ||
| 627 | |||
| 628 | if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) | ||
| 629 | return 1; | ||
| 630 | |||
| 631 | hi_freq = cur_freq; | ||
| 632 | value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); | ||
| 633 | if (!value) | ||
| 634 | return 1; | ||
| 635 | low_freq = (*value) / 1000; | ||
| 636 | |||
| 637 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
| 638 | if (volt_gpio_np) | ||
| 639 | voltage_gpio = read_gpio(volt_gpio_np); | ||
| 640 | |||
| 641 | pvr = mfspr(SPRN_PVR); | ||
| 642 | has_cpu_l2lve = !((pvr & 0xf00) == 0x100); | ||
| 643 | |||
| 644 | set_speed_proc = cpu_750fx_cpu_speed; | ||
| 645 | get_speed_proc = cpu_750fx_get_cpu_speed; | ||
| 646 | cur_freq = cpu_750fx_get_cpu_speed(); | ||
| 647 | |||
| 648 | return 0; | ||
| 649 | } | ||
| 650 | |||
| 651 | /* Currently, we support the following machines: | ||
| 652 | * | ||
| 653 | * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) | ||
| 654 | * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) | ||
| 655 | * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) | ||
| 656 | * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) | ||
| 657 | * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) | ||
| 658 | * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) | ||
| 659 | * - Recent MacRISC3 laptops | ||
| 660 | * - All new machines with 7447A CPUs | ||
| 661 | */ | ||
| 662 | static int __init pmac_cpufreq_setup(void) | ||
| 663 | { | ||
| 664 | struct device_node *cpunode; | ||
| 665 | u32 *value; | ||
| 666 | |||
| 667 | if (strstr(cmd_line, "nocpufreq")) | ||
| 668 | return 0; | ||
| 669 | |||
| 670 | /* Assume only one CPU */ | ||
| 671 | cpunode = find_type_devices("cpu"); | ||
| 672 | if (!cpunode) | ||
| 673 | goto out; | ||
| 674 | |||
| 675 | /* Get current cpu clock freq */ | ||
| 676 | value = (u32 *)get_property(cpunode, "clock-frequency", NULL); | ||
| 677 | if (!value) | ||
| 678 | goto out; | ||
| 679 | cur_freq = (*value) / 1000; | ||
| 680 | |||
| 681 | /* Check for 7447A based MacRISC3 */ | ||
| 682 | if (machine_is_compatible("MacRISC3") && | ||
| 683 | get_property(cpunode, "dynamic-power-step", NULL) && | ||
| 684 | PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { | ||
| 685 | pmac_cpufreq_init_7447A(cpunode); | ||
| 686 | /* Check for other MacRISC3 machines */ | ||
| 687 | } else if (machine_is_compatible("PowerBook3,4") || | ||
| 688 | machine_is_compatible("PowerBook3,5") || | ||
| 689 | machine_is_compatible("MacRISC3")) { | ||
| 690 | pmac_cpufreq_init_MacRISC3(cpunode); | ||
| 691 | /* Else check for iBook2 500/600 */ | ||
| 692 | } else if (machine_is_compatible("PowerBook4,1")) { | ||
| 693 | hi_freq = cur_freq; | ||
| 694 | low_freq = 400000; | ||
| 695 | set_speed_proc = pmu_set_cpu_speed; | ||
| 696 | is_pmu_based = 1; | ||
| 697 | } | ||
| 698 | /* Else check for TiPb 550 */ | ||
| 699 | else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) { | ||
| 700 | hi_freq = cur_freq; | ||
| 701 | low_freq = 500000; | ||
| 702 | set_speed_proc = pmu_set_cpu_speed; | ||
| 703 | is_pmu_based = 1; | ||
| 704 | } | ||
| 705 | /* Else check for TiPb 400 & 500 */ | ||
| 706 | else if (machine_is_compatible("PowerBook3,2")) { | ||
| 707 | /* We only know about the 400 MHz and the 500Mhz model | ||
| 708 | * they both have 300 MHz as low frequency | ||
| 709 | */ | ||
| 710 | if (cur_freq < 350000 || cur_freq > 550000) | ||
| 711 | goto out; | ||
| 712 | hi_freq = cur_freq; | ||
| 713 | low_freq = 300000; | ||
| 714 | set_speed_proc = pmu_set_cpu_speed; | ||
| 715 | is_pmu_based = 1; | ||
| 716 | } | ||
| 717 | /* Else check for 750FX */ | ||
| 718 | else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) | ||
| 719 | pmac_cpufreq_init_750FX(cpunode); | ||
| 720 | out: | ||
| 721 | if (set_speed_proc == NULL) | ||
| 722 | return -ENODEV; | ||
| 723 | |||
| 724 | pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; | ||
| 725 | pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; | ||
| 726 | |||
| 727 | printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); | ||
| 728 | printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", | ||
| 729 | low_freq/1000, hi_freq/1000, cur_freq/1000); | ||
| 730 | |||
| 731 | return cpufreq_register_driver(&pmac_cpufreq_driver); | ||
| 732 | } | ||
| 733 | |||
| 734 | module_init(pmac_cpufreq_setup); | ||
| 735 | |||
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c deleted file mode 100644 index 6b7b3a150631..000000000000 --- a/arch/ppc/platforms/pmac_feature.c +++ /dev/null  | |||
| @@ -1,3023 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/ppc/platforms/pmac_feature.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) | ||
| 5 | * Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * TODO: | ||
| 13 | * | ||
| 14 | * - Replace mdelay with some schedule loop if possible | ||
| 15 | * - Shorten some obfuscated delays on some routines (like modem | ||
| 16 | * power) | ||
| 17 | * - Refcount some clocks (see darwin) | ||
| 18 | * - Split split split... | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | #include <linux/config.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/delay.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | #include <linux/spinlock.h> | ||
| 28 | #include <linux/adb.h> | ||
| 29 | #include <linux/pmu.h> | ||
| 30 | #include <linux/ioport.h> | ||
| 31 | #include <linux/pci.h> | ||
| 32 | #include <asm/sections.h> | ||
| 33 | #include <asm/errno.h> | ||
| 34 | #include <asm/ohare.h> | ||
| 35 | #include <asm/heathrow.h> | ||
| 36 | #include <asm/keylargo.h> | ||
| 37 | #include <asm/uninorth.h> | ||
| 38 | #include <asm/io.h> | ||
| 39 | #include <asm/prom.h> | ||
| 40 | #include <asm/machdep.h> | ||
| 41 | #include <asm/pmac_feature.h> | ||
| 42 | #include <asm/dbdma.h> | ||
| 43 | #include <asm/pci-bridge.h> | ||
| 44 | #include <asm/pmac_low_i2c.h> | ||
| 45 | |||
| 46 | #undef DEBUG_FEATURE | ||
| 47 | |||
| 48 | #ifdef DEBUG_FEATURE | ||
| 49 | #define DBG(fmt,...) printk(KERN_DEBUG fmt) | ||
| 50 | #else | ||
| 51 | #define DBG(fmt,...) | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #ifdef CONFIG_6xx | ||
| 55 | extern int powersave_lowspeed; | ||
| 56 | #endif | ||
| 57 | |||
| 58 | extern int powersave_nap; | ||
| 59 | extern struct device_node *k2_skiplist[2]; | ||
| 60 | |||
| 61 | |||
| 62 | /* | ||
| 63 | * We use a single global lock to protect accesses. Each driver has | ||
| 64 | * to take care of its own locking | ||
| 65 | */ | ||
| 66 | static DEFINE_SPINLOCK(feature_lock); | ||
| 67 | |||
| 68 | #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); | ||
| 69 | #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); | ||
| 70 | |||
| 71 | |||
| 72 | /* | ||
| 73 | * Instance of some macio stuffs | ||
| 74 | */ | ||
| 75 | struct macio_chip macio_chips[MAX_MACIO_CHIPS]; | ||
| 76 | |||
| 77 | struct macio_chip* macio_find(struct device_node* child, int type) | ||
| 78 | { | ||
| 79 | while(child) { | ||
| 80 | int i; | ||
| 81 | |||
| 82 | for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) | ||
| 83 | if (child == macio_chips[i].of_node && | ||
| 84 | (!type || macio_chips[i].type == type)) | ||
| 85 | return &macio_chips[i]; | ||
| 86 | child = child->parent; | ||
| 87 | } | ||
| 88 | return NULL; | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL_GPL(macio_find); | ||
| 91 | |||
| 92 | static const char* macio_names[] = | ||
| 93 | { | ||
| 94 | "Unknown", | ||
| 95 | "Grand Central", | ||
| 96 | "OHare", | ||
| 97 | "OHareII", | ||
| 98 | "Heathrow", | ||
| 99 | "Gatwick", | ||
| 100 | "Paddington", | ||
| 101 | "Keylargo", | ||
| 102 | "Pangea", | ||
| 103 | "Intrepid", | ||
| 104 | "K2" | ||
| 105 | }; | ||
| 106 | |||
| 107 | |||
| 108 | |||
| 109 | /* | ||
| 110 | * Uninorth reg. access. Note that Uni-N regs are big endian | ||
| 111 | */ | ||
| 112 | |||
| 113 | #define UN_REG(r) (uninorth_base + ((r) >> 2)) | ||
| 114 | #define UN_IN(r) (in_be32(UN_REG(r))) | ||
| 115 | #define UN_OUT(r,v) (out_be32(UN_REG(r), (v))) | ||
| 116 | #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) | ||
| 117 | #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) | ||
| 118 | |||
| 119 | static struct device_node* uninorth_node; | ||
| 120 | static u32 __iomem * uninorth_base; | ||
| 121 | static u32 uninorth_rev; | ||
| 122 | static int uninorth_u3; | ||
| 123 | static void __iomem *u3_ht; | ||
| 124 | |||
| 125 | /* | ||
| 126 | * For each motherboard family, we have a table of functions pointers | ||
| 127 | * that handle the various features. | ||
| 128 | */ | ||
| 129 | |||
| 130 | typedef long (*feature_call)(struct device_node* node, long param, long value); | ||
| 131 | |||
| 132 | struct feature_table_entry { | ||
| 133 | unsigned int selector; | ||
| 134 | feature_call function; | ||
| 135 | }; | ||
| 136 | |||
| 137 | struct pmac_mb_def | ||
| 138 | { | ||
| 139 | const char* model_string; | ||
| 140 | const char* model_name; | ||
| 141 | int model_id; | ||
| 142 | struct feature_table_entry* features; | ||
| 143 | unsigned long board_flags; | ||
| 144 | }; | ||
| 145 | static struct pmac_mb_def pmac_mb; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Here are the chip specific feature functions | ||
| 149 | */ | ||
| 150 | |||
| 151 | static inline int | ||
| 152 | simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value) | ||
| 153 | { | ||
| 154 | struct macio_chip* macio; | ||
| 155 | unsigned long flags; | ||
| 156 | |||
| 157 | macio = macio_find(node, type); | ||
| 158 | if (!macio) | ||
| 159 | return -ENODEV; | ||
| 160 | LOCK(flags); | ||
| 161 | if (value) | ||
| 162 | MACIO_BIS(reg, mask); | ||
| 163 | else | ||
| 164 | MACIO_BIC(reg, mask); | ||
| 165 | (void)MACIO_IN32(reg); | ||
| 166 | UNLOCK(flags); | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | #ifndef CONFIG_POWER4 | ||
| 172 | |||
| 173 | static long | ||
| 174 | ohare_htw_scc_enable(struct device_node* node, long param, long value) | ||
| 175 | { | ||
| 176 | struct macio_chip* macio; | ||
| 177 | unsigned long chan_mask; | ||
| 178 | unsigned long fcr; | ||
| 179 | unsigned long flags; | ||
| 180 | int htw, trans; | ||
| 181 | unsigned long rmask; | ||
| 182 | |||
| 183 | macio = macio_find(node, 0); | ||
| 184 | if (!macio) | ||
| 185 | return -ENODEV; | ||
| 186 | if (!strcmp(node->name, "ch-a")) | ||
| 187 | chan_mask = MACIO_FLAG_SCCA_ON; | ||
| 188 | else if (!strcmp(node->name, "ch-b")) | ||
| 189 | chan_mask = MACIO_FLAG_SCCB_ON; | ||
| 190 | else | ||
| 191 | return -ENODEV; | ||
| 192 | |||
| 193 | htw = (macio->type == macio_heathrow || macio->type == macio_paddington | ||
| 194 | || macio->type == macio_gatwick); | ||
| 195 | /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ | ||
| 196 | trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && | ||
| 197 | pmac_mb.model_id != PMAC_TYPE_YIKES); | ||
| 198 | if (value) { | ||
| 199 | #ifdef CONFIG_ADB_PMU | ||
| 200 | if ((param & 0xfff) == PMAC_SCC_IRDA) | ||
| 201 | pmu_enable_irled(1); | ||
| 202 | #endif /* CONFIG_ADB_PMU */ | ||
| 203 | LOCK(flags); | ||
| 204 | fcr = MACIO_IN32(OHARE_FCR); | ||
| 205 | /* Check if scc cell need enabling */ | ||
| 206 | if (!(fcr & OH_SCC_ENABLE)) { | ||
| 207 | fcr |= OH_SCC_ENABLE; | ||
| 208 | if (htw) { | ||
| 209 | /* Side effect: this will also power up the | ||
| 210 | * modem, but it's too messy to figure out on which | ||
| 211 | * ports this controls the tranceiver and on which | ||
| 212 | * it controls the modem | ||
| 213 | */ | ||
| 214 | if (trans) | ||
| 215 | fcr &= ~HRW_SCC_TRANS_EN_N; | ||
| 216 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 217 | fcr |= (rmask = HRW_RESET_SCC); | ||
| 218 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 219 | } else { | ||
| 220 | fcr |= (rmask = OH_SCC_RESET); | ||
| 221 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 222 | } | ||
| 223 | UNLOCK(flags); | ||
| 224 | (void)MACIO_IN32(OHARE_FCR); | ||
| 225 | mdelay(15); | ||
| 226 | LOCK(flags); | ||
| 227 | fcr &= ~rmask; | ||
| 228 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 229 | } | ||
| 230 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
| 231 | fcr |= OH_SCCA_IO; | ||
| 232 | if (chan_mask & MACIO_FLAG_SCCB_ON) | ||
| 233 | fcr |= OH_SCCB_IO; | ||
| 234 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 235 | macio->flags |= chan_mask; | ||
| 236 | UNLOCK(flags); | ||
| 237 | if (param & PMAC_SCC_FLAG_XMON) | ||
| 238 | macio->flags |= MACIO_FLAG_SCC_LOCKED; | ||
| 239 | } else { | ||
| 240 | if (macio->flags & MACIO_FLAG_SCC_LOCKED) | ||
| 241 | return -EPERM; | ||
| 242 | LOCK(flags); | ||
| 243 | fcr = MACIO_IN32(OHARE_FCR); | ||
| 244 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
| 245 | fcr &= ~OH_SCCA_IO; | ||
| 246 | if (chan_mask & MACIO_FLAG_SCCB_ON) | ||
| 247 | fcr &= ~OH_SCCB_IO; | ||
| 248 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 249 | if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { | ||
| 250 | fcr &= ~OH_SCC_ENABLE; | ||
| 251 | if (htw && trans) | ||
| 252 | fcr |= HRW_SCC_TRANS_EN_N; | ||
| 253 | MACIO_OUT32(OHARE_FCR, fcr); | ||
| 254 | } | ||
| 255 | macio->flags &= ~(chan_mask); | ||
| 256 | UNLOCK(flags); | ||
| 257 | mdelay(10); | ||
| 258 | #ifdef CONFIG_ADB_PMU | ||
| 259 | if ((param & 0xfff) == PMAC_SCC_IRDA) | ||
| 260 | pmu_enable_irled(0); | ||
| 261 | #endif /* CONFIG_ADB_PMU */ | ||
| 262 | } | ||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static long | ||
| 267 | ohare_floppy_enable(struct device_node* node, long param, long value) | ||
| 268 | { | ||
| 269 | return simple_feature_tweak(node, macio_ohare, | ||
| 270 | OHARE_FCR, OH_FLOPPY_ENABLE, value); | ||
| 271 | } | ||
| 272 | |||
| 273 | static long | ||
| 274 | ohare_mesh_enable(struct device_node* node, long param, long value) | ||
| 275 | { | ||
| 276 | return simple_feature_tweak(node, macio_ohare, | ||
| 277 | OHARE_FCR, OH_MESH_ENABLE, value); | ||
| 278 | } | ||
| 279 | |||
| 280 | static long | ||
| 281 | ohare_ide_enable(struct device_node* node, long param, long value) | ||
| 282 | { | ||
| 283 | switch(param) { | ||
| 284 | case 0: | ||
| 285 | /* For some reason, setting the bit in set_initial_features() | ||
| 286 | * doesn't stick. I'm still investigating... --BenH. | ||
| 287 | */ | ||
| 288 | if (value) | ||
| 289 | simple_feature_tweak(node, macio_ohare, | ||
| 290 | OHARE_FCR, OH_IOBUS_ENABLE, 1); | ||
| 291 | return simple_feature_tweak(node, macio_ohare, | ||
| 292 | OHARE_FCR, OH_IDE0_ENABLE, value); | ||
| 293 | case 1: | ||
| 294 | return simple_feature_tweak(node, macio_ohare, | ||
| 295 | OHARE_FCR, OH_BAY_IDE_ENABLE, value); | ||
| 296 | default: | ||
| 297 | return -ENODEV; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | static long | ||
| 302 | ohare_ide_reset(struct device_node* node, long param, long value) | ||
| 303 | { | ||
| 304 | switch(param) { | ||
| 305 | case 0: | ||
| 306 | return simple_feature_tweak(node, macio_ohare, | ||
| 307 | OHARE_FCR, OH_IDE0_RESET_N, !value); | ||
| 308 | case 1: | ||
| 309 | return simple_feature_tweak(node, macio_ohare, | ||
| 310 | OHARE_FCR, OH_IDE1_RESET_N, !value); | ||
| 311 | default: | ||
| 312 | return -ENODEV; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | static long | ||
| 317 | ohare_sleep_state(struct device_node* node, long param, long value) | ||
| 318 | { | ||
| 319 | struct macio_chip* macio = &macio_chips[0]; | ||
| 320 | |||
| 321 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
| 322 | return -EPERM; | ||
| 323 | if (value == 1) { | ||
| 324 | MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); | ||
| 325 | } else if (value == 0) { | ||
| 326 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
| 327 | } | ||
| 328 | |||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | static long | ||
| 333 | heathrow_modem_enable(struct device_node* node, long param, long value) | ||
| 334 | { | ||
| 335 | struct macio_chip* macio; | ||
| 336 | u8 gpio; | ||
| 337 | unsigned long flags; | ||
| 338 | |||
| 339 | macio = macio_find(node, macio_unknown); | ||
| 340 | if (!macio) | ||
| 341 | return -ENODEV; | ||
| 342 | gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; | ||
| 343 | if (!value) { | ||
| 344 | LOCK(flags); | ||
| 345 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); | ||
| 346 | UNLOCK(flags); | ||
| 347 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
| 348 | mdelay(250); | ||
| 349 | } | ||
| 350 | if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && | ||
| 351 | pmac_mb.model_id != PMAC_TYPE_YIKES) { | ||
| 352 | LOCK(flags); | ||
| 353 | if (value) | ||
| 354 | MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
| 355 | else | ||
| 356 | MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
| 357 | UNLOCK(flags); | ||
| 358 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 359 | mdelay(250); | ||
| 360 | } | ||
| 361 | if (value) { | ||
| 362 | LOCK(flags); | ||
| 363 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); | ||
| 364 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
| 365 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 366 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); | ||
| 367 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
| 368 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 369 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); | ||
| 370 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
| 371 | UNLOCK(flags); mdelay(250); | ||
| 372 | } | ||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static long | ||
| 377 | heathrow_floppy_enable(struct device_node* node, long param, long value) | ||
| 378 | { | ||
| 379 | return simple_feature_tweak(node, macio_unknown, | ||
| 380 | HEATHROW_FCR, | ||
| 381 | HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, | ||
| 382 | value); | ||
| 383 | } | ||
| 384 | |||
| 385 | static long | ||
| 386 | heathrow_mesh_enable(struct device_node* node, long param, long value) | ||
| 387 | { | ||
| 388 | struct macio_chip* macio; | ||
| 389 | unsigned long flags; | ||
| 390 | |||
| 391 | macio = macio_find(node, macio_unknown); | ||
| 392 | if (!macio) | ||
| 393 | return -ENODEV; | ||
| 394 | LOCK(flags); | ||
| 395 | /* Set clear mesh cell enable */ | ||
| 396 | if (value) | ||
| 397 | MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); | ||
| 398 | else | ||
| 399 | MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); | ||
| 400 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 401 | udelay(10); | ||
| 402 | /* Set/Clear termination power */ | ||
| 403 | if (value) | ||
| 404 | MACIO_BIC(HEATHROW_MBCR, 0x04000000); | ||
| 405 | else | ||
| 406 | MACIO_BIS(HEATHROW_MBCR, 0x04000000); | ||
| 407 | (void)MACIO_IN32(HEATHROW_MBCR); | ||
| 408 | udelay(10); | ||
| 409 | UNLOCK(flags); | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | static long | ||
| 415 | heathrow_ide_enable(struct device_node* node, long param, long value) | ||
| 416 | { | ||
| 417 | switch(param) { | ||
| 418 | case 0: | ||
| 419 | return simple_feature_tweak(node, macio_unknown, | ||
| 420 | HEATHROW_FCR, HRW_IDE0_ENABLE, value); | ||
| 421 | case 1: | ||
| 422 | return simple_feature_tweak(node, macio_unknown, | ||
| 423 | HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); | ||
| 424 | default: | ||
| 425 | return -ENODEV; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | static long | ||
| 430 | heathrow_ide_reset(struct device_node* node, long param, long value) | ||
| 431 | { | ||
| 432 | switch(param) { | ||
| 433 | case 0: | ||
| 434 | return simple_feature_tweak(node, macio_unknown, | ||
| 435 | HEATHROW_FCR, HRW_IDE0_RESET_N, !value); | ||
| 436 | case 1: | ||
| 437 | return simple_feature_tweak(node, macio_unknown, | ||
| 438 | HEATHROW_FCR, HRW_IDE1_RESET_N, !value); | ||
| 439 | default: | ||
| 440 | return -ENODEV; | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | static long | ||
| 445 | heathrow_bmac_enable(struct device_node* node, long param, long value) | ||
| 446 | { | ||
| 447 | struct macio_chip* macio; | ||
| 448 | unsigned long flags; | ||
| 449 | |||
| 450 | macio = macio_find(node, 0); | ||
| 451 | if (!macio) | ||
| 452 | return -ENODEV; | ||
| 453 | if (value) { | ||
| 454 | LOCK(flags); | ||
| 455 | MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); | ||
| 456 | MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); | ||
| 457 | UNLOCK(flags); | ||
| 458 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 459 | mdelay(10); | ||
| 460 | LOCK(flags); | ||
| 461 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); | ||
| 462 | UNLOCK(flags); | ||
| 463 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 464 | mdelay(10); | ||
| 465 | } else { | ||
| 466 | LOCK(flags); | ||
| 467 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); | ||
| 468 | UNLOCK(flags); | ||
| 469 | } | ||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | static long | ||
| 474 | heathrow_sound_enable(struct device_node* node, long param, long value) | ||
| 475 | { | ||
| 476 | struct macio_chip* macio; | ||
| 477 | unsigned long flags; | ||
| 478 | |||
| 479 | /* B&W G3 and Yikes don't support that properly (the | ||
| 480 | * sound appear to never come back after beeing shut down). | ||
| 481 | */ | ||
| 482 | if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || | ||
| 483 | pmac_mb.model_id == PMAC_TYPE_YIKES) | ||
| 484 | return 0; | ||
| 485 | |||
| 486 | macio = macio_find(node, 0); | ||
| 487 | if (!macio) | ||
| 488 | return -ENODEV; | ||
| 489 | if (value) { | ||
| 490 | LOCK(flags); | ||
| 491 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
| 492 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
| 493 | UNLOCK(flags); | ||
| 494 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 495 | } else { | ||
| 496 | LOCK(flags); | ||
| 497 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
| 498 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
| 499 | UNLOCK(flags); | ||
| 500 | } | ||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | static u32 save_fcr[6]; | ||
| 505 | static u32 save_mbcr; | ||
| 506 | static u32 save_gpio_levels[2]; | ||
| 507 | static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; | ||
| 508 | static u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; | ||
| 509 | static u32 save_unin_clock_ctl; | ||
| 510 | static struct dbdma_regs save_dbdma[13]; | ||
| 511 | static struct dbdma_regs save_alt_dbdma[13]; | ||
| 512 | |||
| 513 | static void | ||
| 514 | dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) | ||
| 515 | { | ||
| 516 | int i; | ||
| 517 | |||
| 518 | /* Save state & config of DBDMA channels */ | ||
| 519 | for (i=0; i<13; i++) { | ||
| 520 | volatile struct dbdma_regs __iomem * chan = (void __iomem *) | ||
| 521 | (macio->base + ((0x8000+i*0x100)>>2)); | ||
| 522 | save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); | ||
| 523 | save[i].cmdptr = in_le32(&chan->cmdptr); | ||
| 524 | save[i].intr_sel = in_le32(&chan->intr_sel); | ||
| 525 | save[i].br_sel = in_le32(&chan->br_sel); | ||
| 526 | save[i].wait_sel = in_le32(&chan->wait_sel); | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | static void | ||
| 531 | dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) | ||
| 532 | { | ||
| 533 | int i; | ||
| 534 | |||
| 535 | /* Save state & config of DBDMA channels */ | ||
| 536 | for (i=0; i<13; i++) { | ||
| 537 | volatile struct dbdma_regs __iomem * chan = (void __iomem *) | ||
| 538 | (macio->base + ((0x8000+i*0x100)>>2)); | ||
| 539 | out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); | ||
| 540 | while (in_le32(&chan->status) & ACTIVE) | ||
| 541 | mb(); | ||
| 542 | out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); | ||
| 543 | out_le32(&chan->cmdptr, save[i].cmdptr); | ||
| 544 | out_le32(&chan->intr_sel, save[i].intr_sel); | ||
| 545 | out_le32(&chan->br_sel, save[i].br_sel); | ||
| 546 | out_le32(&chan->wait_sel, save[i].wait_sel); | ||
| 547 | } | ||
| 548 | } | ||
| 549 | |||
| 550 | static void | ||
| 551 | heathrow_sleep(struct macio_chip* macio, int secondary) | ||
| 552 | { | ||
| 553 | if (secondary) { | ||
| 554 | dbdma_save(macio, save_alt_dbdma); | ||
| 555 | save_fcr[2] = MACIO_IN32(0x38); | ||
| 556 | save_fcr[3] = MACIO_IN32(0x3c); | ||
| 557 | } else { | ||
| 558 | dbdma_save(macio, save_dbdma); | ||
| 559 | save_fcr[0] = MACIO_IN32(0x38); | ||
| 560 | save_fcr[1] = MACIO_IN32(0x3c); | ||
| 561 | save_mbcr = MACIO_IN32(0x34); | ||
| 562 | /* Make sure sound is shut down */ | ||
| 563 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
| 564 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
| 565 | /* This seems to be necessary as well or the fan | ||
| 566 | * keeps coming up and battery drains fast */ | ||
| 567 | MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); | ||
| 568 | MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); | ||
| 569 | /* Make sure eth is down even if module or sleep | ||
| 570 | * won't work properly */ | ||
| 571 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); | ||
| 572 | } | ||
| 573 | /* Make sure modem is shut down */ | ||
| 574 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, | ||
| 575 | MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); | ||
| 576 | MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
| 577 | MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); | ||
| 578 | |||
| 579 | /* Let things settle */ | ||
| 580 | (void)MACIO_IN32(HEATHROW_FCR); | ||
| 581 | } | ||
| 582 | |||
| 583 | static void | ||
| 584 | heathrow_wakeup(struct macio_chip* macio, int secondary) | ||
| 585 | { | ||
| 586 | if (secondary) { | ||
| 587 | MACIO_OUT32(0x38, save_fcr[2]); | ||
| 588 | (void)MACIO_IN32(0x38); | ||
| 589 | mdelay(1); | ||
| 590 | MACIO_OUT32(0x3c, save_fcr[3]); | ||
| 591 | (void)MACIO_IN32(0x38); | ||
| 592 | mdelay(10); | ||
| 593 | dbdma_restore(macio, save_alt_dbdma); | ||
| 594 | } else { | ||
| 595 | MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); | ||
| 596 | (void)MACIO_IN32(0x38); | ||
| 597 | mdelay(1); | ||
| 598 | MACIO_OUT32(0x3c, save_fcr[1]); | ||
| 599 | (void)MACIO_IN32(0x38); | ||
| 600 | mdelay(1); | ||
| 601 | MACIO_OUT32(0x34, save_mbcr); | ||
| 602 | (void)MACIO_IN32(0x38); | ||
| 603 | mdelay(10); | ||
| 604 | dbdma_restore(macio, save_dbdma); | ||
| 605 | } | ||
| 606 | } | ||
| 607 | |||
| 608 | static long | ||
| 609 | heathrow_sleep_state(struct device_node* node, long param, long value) | ||
| 610 | { | ||
| 611 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
| 612 | return -EPERM; | ||
| 613 | if (value == 1) { | ||
| 614 | if (macio_chips[1].type == macio_gatwick) | ||
| 615 | heathrow_sleep(&macio_chips[0], 1); | ||
| 616 | heathrow_sleep(&macio_chips[0], 0); | ||
| 617 | } else if (value == 0) { | ||
| 618 | heathrow_wakeup(&macio_chips[0], 0); | ||
| 619 | if (macio_chips[1].type == macio_gatwick) | ||
| 620 | heathrow_wakeup(&macio_chips[0], 1); | ||
| 621 | } | ||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | static long | ||
| 626 | core99_scc_enable(struct device_node* node, long param, long value) | ||
| 627 | { | ||
| 628 | struct macio_chip* macio; | ||
| 629 | unsigned long flags; | ||
| 630 | unsigned long chan_mask; | ||
| 631 | u32 fcr; | ||
| 632 | |||
| 633 | macio = macio_find(node, 0); | ||
| 634 | if (!macio) | ||
| 635 | return -ENODEV; | ||
| 636 | if (!strcmp(node->name, "ch-a")) | ||
| 637 | chan_mask = MACIO_FLAG_SCCA_ON; | ||
| 638 | else if (!strcmp(node->name, "ch-b")) | ||
| 639 | chan_mask = MACIO_FLAG_SCCB_ON; | ||
| 640 | else | ||
| 641 | return -ENODEV; | ||
| 642 | |||
| 643 | if (value) { | ||
| 644 | int need_reset_scc = 0; | ||
| 645 | int need_reset_irda = 0; | ||
| 646 | |||
| 647 | LOCK(flags); | ||
| 648 | fcr = MACIO_IN32(KEYLARGO_FCR0); | ||
| 649 | /* Check if scc cell need enabling */ | ||
| 650 | if (!(fcr & KL0_SCC_CELL_ENABLE)) { | ||
| 651 | fcr |= KL0_SCC_CELL_ENABLE; | ||
| 652 | need_reset_scc = 1; | ||
| 653 | } | ||
| 654 | if (chan_mask & MACIO_FLAG_SCCA_ON) { | ||
| 655 | fcr |= KL0_SCCA_ENABLE; | ||
| 656 | /* Don't enable line drivers for I2S modem */ | ||
| 657 | if ((param & 0xfff) == PMAC_SCC_I2S1) | ||
| 658 | fcr &= ~KL0_SCC_A_INTF_ENABLE; | ||
| 659 | else | ||
| 660 | fcr |= KL0_SCC_A_INTF_ENABLE; | ||
| 661 | } | ||
| 662 | if (chan_mask & MACIO_FLAG_SCCB_ON) { | ||
| 663 | fcr |= KL0_SCCB_ENABLE; | ||
| 664 | /* Perform irda specific inits */ | ||
| 665 | if ((param & 0xfff) == PMAC_SCC_IRDA) { | ||
| 666 | fcr &= ~KL0_SCC_B_INTF_ENABLE; | ||
| 667 | fcr |= KL0_IRDA_ENABLE; | ||
| 668 | fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; | ||
| 669 | fcr |= KL0_IRDA_SOURCE1_SEL; | ||
| 670 | fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); | ||
| 671 | fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); | ||
| 672 | need_reset_irda = 1; | ||
| 673 | } else | ||
| 674 | fcr |= KL0_SCC_B_INTF_ENABLE; | ||
| 675 | } | ||
| 676 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
| 677 | macio->flags |= chan_mask; | ||
| 678 | if (need_reset_scc) { | ||
| 679 | MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); | ||
| 680 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 681 | UNLOCK(flags); | ||
| 682 | mdelay(15); | ||
| 683 | LOCK(flags); | ||
| 684 | MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); | ||
| 685 | } | ||
| 686 | if (need_reset_irda) { | ||
| 687 | MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); | ||
| 688 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 689 | UNLOCK(flags); | ||
| 690 | mdelay(15); | ||
| 691 | LOCK(flags); | ||
| 692 | MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); | ||
| 693 | } | ||
| 694 | UNLOCK(flags); | ||
| 695 | if (param & PMAC_SCC_FLAG_XMON) | ||
| 696 | macio->flags |= MACIO_FLAG_SCC_LOCKED; | ||
| 697 | } else { | ||
| 698 | if (macio->flags & MACIO_FLAG_SCC_LOCKED) | ||
| 699 | return -EPERM; | ||
| 700 | LOCK(flags); | ||
| 701 | fcr = MACIO_IN32(KEYLARGO_FCR0); | ||
| 702 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
| 703 | fcr &= ~KL0_SCCA_ENABLE; | ||
| 704 | if (chan_mask & MACIO_FLAG_SCCB_ON) { | ||
| 705 | fcr &= ~KL0_SCCB_ENABLE; | ||
| 706 | /* Perform irda specific clears */ | ||
| 707 | if ((param & 0xfff) == PMAC_SCC_IRDA) { | ||
| 708 | fcr &= ~KL0_IRDA_ENABLE; | ||
| 709 | fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); | ||
| 710 | fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); | ||
| 711 | fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); | ||
| 712 | } | ||
| 713 | } | ||
| 714 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
| 715 | if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { | ||
| 716 | fcr &= ~KL0_SCC_CELL_ENABLE; | ||
| 717 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
| 718 | } | ||
| 719 | macio->flags &= ~(chan_mask); | ||
| 720 | UNLOCK(flags); | ||
| 721 | mdelay(10); | ||
| 722 | } | ||
| 723 | return 0; | ||
| 724 | } | ||
| 725 | |||
| 726 | static long | ||
| 727 | core99_modem_enable(struct device_node* node, long param, long value) | ||
| 728 | { | ||
| 729 | struct macio_chip* macio; | ||
| 730 | u8 gpio; | ||
| 731 | unsigned long flags; | ||
| 732 | |||
| 733 | /* Hack for internal USB modem */ | ||
| 734 | if (node == NULL) { | ||
| 735 | if (macio_chips[0].type != macio_keylargo) | ||
| 736 | return -ENODEV; | ||
| 737 | node = macio_chips[0].of_node; | ||
| 738 | } | ||
| 739 | macio = macio_find(node, 0); | ||
| 740 | if (!macio) | ||
| 741 | return -ENODEV; | ||
| 742 | gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 743 | gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; | ||
| 744 | gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; | ||
| 745 | |||
| 746 | if (!value) { | ||
| 747 | LOCK(flags); | ||
| 748 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
| 749 | UNLOCK(flags); | ||
| 750 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 751 | mdelay(250); | ||
| 752 | } | ||
| 753 | LOCK(flags); | ||
| 754 | if (value) { | ||
| 755 | MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
| 756 | UNLOCK(flags); | ||
| 757 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
| 758 | mdelay(250); | ||
| 759 | } else { | ||
| 760 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
| 761 | UNLOCK(flags); | ||
| 762 | } | ||
| 763 | if (value) { | ||
| 764 | LOCK(flags); | ||
| 765 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 766 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 767 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 768 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
| 769 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 770 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 771 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 772 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 773 | UNLOCK(flags); mdelay(250); | ||
| 774 | } | ||
| 775 | return 0; | ||
| 776 | } | ||
| 777 | |||
| 778 | static long | ||
| 779 | pangea_modem_enable(struct device_node* node, long param, long value) | ||
| 780 | { | ||
| 781 | struct macio_chip* macio; | ||
| 782 | u8 gpio; | ||
| 783 | unsigned long flags; | ||
| 784 | |||
| 785 | /* Hack for internal USB modem */ | ||
| 786 | if (node == NULL) { | ||
| 787 | if (macio_chips[0].type != macio_pangea && | ||
| 788 | macio_chips[0].type != macio_intrepid) | ||
| 789 | return -ENODEV; | ||
| 790 | node = macio_chips[0].of_node; | ||
| 791 | } | ||
| 792 | macio = macio_find(node, 0); | ||
| 793 | if (!macio) | ||
| 794 | return -ENODEV; | ||
| 795 | gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 796 | gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; | ||
| 797 | gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; | ||
| 798 | |||
| 799 | if (!value) { | ||
| 800 | LOCK(flags); | ||
| 801 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
| 802 | UNLOCK(flags); | ||
| 803 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 804 | mdelay(250); | ||
| 805 | } | ||
| 806 | LOCK(flags); | ||
| 807 | if (value) { | ||
| 808 | MACIO_OUT8(KL_GPIO_MODEM_POWER, | ||
| 809 | KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
| 810 | UNLOCK(flags); | ||
| 811 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
| 812 | mdelay(250); | ||
| 813 | } else { | ||
| 814 | MACIO_OUT8(KL_GPIO_MODEM_POWER, | ||
| 815 | KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 816 | UNLOCK(flags); | ||
| 817 | } | ||
| 818 | if (value) { | ||
| 819 | LOCK(flags); | ||
| 820 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 821 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 822 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 823 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
| 824 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 825 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
| 826 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 827 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
| 828 | UNLOCK(flags); mdelay(250); | ||
| 829 | } | ||
| 830 | return 0; | ||
| 831 | } | ||
| 832 | |||
| 833 | static long | ||
| 834 | core99_ata100_enable(struct device_node* node, long value) | ||
| 835 | { | ||
| 836 | unsigned long flags; | ||
| 837 | struct pci_dev *pdev = NULL; | ||
| 838 | u8 pbus, pid; | ||
| 839 | |||
| 840 | if (uninorth_rev < 0x24) | ||
| 841 | return -ENODEV; | ||
| 842 | |||
| 843 | LOCK(flags); | ||
| 844 | if (value) | ||
| 845 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); | ||
| 846 | else | ||
| 847 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); | ||
| 848 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
| 849 | UNLOCK(flags); | ||
| 850 | udelay(20); | ||
| 851 | |||
| 852 | if (value) { | ||
| 853 | if (pci_device_from_OF_node(node, &pbus, &pid) == 0) | ||
| 854 | pdev = pci_find_slot(pbus, pid); | ||
| 855 | if (pdev == NULL) | ||
| 856 | return 0; | ||
| 857 | pci_enable_device(pdev); | ||
| 858 | pci_set_master(pdev); | ||
| 859 | } | ||
| 860 | return 0; | ||
| 861 | } | ||
| 862 | |||
| 863 | static long | ||
| 864 | core99_ide_enable(struct device_node* node, long param, long value) | ||
| 865 | { | ||
| 866 | /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 | ||
| 867 | * based ata-100 | ||
| 868 | */ | ||
| 869 | switch(param) { | ||
| 870 | case 0: | ||
| 871 | return simple_feature_tweak(node, macio_unknown, | ||
| 872 | KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); | ||
| 873 | case 1: | ||
| 874 | return simple_feature_tweak(node, macio_unknown, | ||
| 875 | KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); | ||
| 876 | case 2: | ||
| 877 | return simple_feature_tweak(node, macio_unknown, | ||
| 878 | KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); | ||
| 879 | case 3: | ||
| 880 | return core99_ata100_enable(node, value); | ||
| 881 | default: | ||
| 882 | return -ENODEV; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | static long | ||
| 887 | core99_ide_reset(struct device_node* node, long param, long value) | ||
| 888 | { | ||
| 889 | switch(param) { | ||
| 890 | case 0: | ||
| 891 | return simple_feature_tweak(node, macio_unknown, | ||
| 892 | KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); | ||
| 893 | case 1: | ||
| 894 | return simple_feature_tweak(node, macio_unknown, | ||
| 895 | KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); | ||
| 896 | case 2: | ||
| 897 | return simple_feature_tweak(node, macio_unknown, | ||
| 898 | KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); | ||
| 899 | default: | ||
| 900 | return -ENODEV; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | static long | ||
| 905 | core99_gmac_enable(struct device_node* node, long param, long value) | ||
| 906 | { | ||
| 907 | unsigned long flags; | ||
| 908 | |||
| 909 | LOCK(flags); | ||
| 910 | if (value) | ||
| 911 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); | ||
| 912 | else | ||
| 913 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); | ||
| 914 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
| 915 | UNLOCK(flags); | ||
| 916 | udelay(20); | ||
| 917 | |||
| 918 | return 0; | ||
| 919 | } | ||
| 920 | |||
| 921 | static long | ||
| 922 | core99_gmac_phy_reset(struct device_node* node, long param, long value) | ||
| 923 | { | ||
| 924 | unsigned long flags; | ||
| 925 | struct macio_chip* macio; | ||
| 926 | |||
| 927 | macio = &macio_chips[0]; | ||
| 928 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 929 | macio->type != macio_intrepid) | ||
| 930 | return -ENODEV; | ||
| 931 | |||
| 932 | LOCK(flags); | ||
| 933 | MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
| 934 | (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); | ||
| 935 | UNLOCK(flags); | ||
| 936 | mdelay(10); | ||
| 937 | LOCK(flags); | ||
| 938 | MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ | ||
| 939 | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 940 | UNLOCK(flags); | ||
| 941 | mdelay(10); | ||
| 942 | |||
| 943 | return 0; | ||
| 944 | } | ||
| 945 | |||
| 946 | static long | ||
| 947 | core99_sound_chip_enable(struct device_node* node, long param, long value) | ||
| 948 | { | ||
| 949 | struct macio_chip* macio; | ||
| 950 | unsigned long flags; | ||
| 951 | |||
| 952 | macio = macio_find(node, 0); | ||
| 953 | if (!macio) | ||
| 954 | return -ENODEV; | ||
| 955 | |||
| 956 | /* Do a better probe code, screamer G4 desktops & | ||
| 957 | * iMacs can do that too, add a recalibrate in | ||
| 958 | * the driver as well | ||
| 959 | */ | ||
| 960 | if (pmac_mb.model_id == PMAC_TYPE_PISMO || | ||
| 961 | pmac_mb.model_id == PMAC_TYPE_TITANIUM) { | ||
| 962 | LOCK(flags); | ||
| 963 | if (value) | ||
| 964 | MACIO_OUT8(KL_GPIO_SOUND_POWER, | ||
| 965 | KEYLARGO_GPIO_OUTPUT_ENABLE | | ||
| 966 | KEYLARGO_GPIO_OUTOUT_DATA); | ||
| 967 | else | ||
| 968 | MACIO_OUT8(KL_GPIO_SOUND_POWER, | ||
| 969 | KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
| 970 | (void)MACIO_IN8(KL_GPIO_SOUND_POWER); | ||
| 971 | UNLOCK(flags); | ||
| 972 | } | ||
| 973 | return 0; | ||
| 974 | } | ||
| 975 | |||
| 976 | static long | ||
| 977 | core99_airport_enable(struct device_node* node, long param, long value) | ||
| 978 | { | ||
| 979 | struct macio_chip* macio; | ||
| 980 | unsigned long flags; | ||
| 981 | int state; | ||
| 982 | |||
| 983 | macio = macio_find(node, 0); | ||
| 984 | if (!macio) | ||
| 985 | return -ENODEV; | ||
| 986 | |||
| 987 | /* Hint: we allow passing of macio itself for the sake of the | ||
| 988 | * sleep code | ||
| 989 | */ | ||
| 990 | if (node != macio->of_node && | ||
| 991 | (!node->parent || node->parent != macio->of_node)) | ||
| 992 | return -ENODEV; | ||
| 993 | state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; | ||
| 994 | if (value == state) | ||
| 995 | return 0; | ||
| 996 | if (value) { | ||
| 997 | /* This code is a reproduction of OF enable-cardslot | ||
| 998 | * and init-wireless methods, slightly hacked until | ||
| 999 | * I got it working. | ||
| 1000 | */ | ||
| 1001 | LOCK(flags); | ||
| 1002 | MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); | ||
| 1003 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); | ||
| 1004 | UNLOCK(flags); | ||
| 1005 | mdelay(10); | ||
| 1006 | LOCK(flags); | ||
| 1007 | MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); | ||
| 1008 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); | ||
| 1009 | UNLOCK(flags); | ||
| 1010 | |||
| 1011 | mdelay(10); | ||
| 1012 | |||
| 1013 | LOCK(flags); | ||
| 1014 | MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
| 1015 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
| 1016 | udelay(10); | ||
| 1017 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); | ||
| 1018 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); | ||
| 1019 | udelay(10); | ||
| 1020 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); | ||
| 1021 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); | ||
| 1022 | udelay(10); | ||
| 1023 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); | ||
| 1024 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); | ||
| 1025 | udelay(10); | ||
| 1026 | MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); | ||
| 1027 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); | ||
| 1028 | udelay(10); | ||
| 1029 | MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); | ||
| 1030 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); | ||
| 1031 | UNLOCK(flags); | ||
| 1032 | udelay(10); | ||
| 1033 | MACIO_OUT32(0x1c000, 0); | ||
| 1034 | mdelay(1); | ||
| 1035 | MACIO_OUT8(0x1a3e0, 0x41); | ||
| 1036 | (void)MACIO_IN8(0x1a3e0); | ||
| 1037 | udelay(10); | ||
| 1038 | LOCK(flags); | ||
| 1039 | MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
| 1040 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
| 1041 | UNLOCK(flags); | ||
| 1042 | mdelay(100); | ||
| 1043 | |||
| 1044 | macio->flags |= MACIO_FLAG_AIRPORT_ON; | ||
| 1045 | } else { | ||
| 1046 | LOCK(flags); | ||
| 1047 | MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
| 1048 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
| 1049 | MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); | ||
| 1050 | MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); | ||
| 1051 | MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); | ||
| 1052 | MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); | ||
| 1053 | MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); | ||
| 1054 | (void)MACIO_IN8(KL_GPIO_AIRPORT_4); | ||
| 1055 | UNLOCK(flags); | ||
| 1056 | |||
| 1057 | macio->flags &= ~MACIO_FLAG_AIRPORT_ON; | ||
| 1058 | } | ||
| 1059 | return 0; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | #ifdef CONFIG_SMP | ||
| 1063 | static long | ||
| 1064 | core99_reset_cpu(struct device_node* node, long param, long value) | ||
| 1065 | { | ||
| 1066 | unsigned int reset_io = 0; | ||
| 1067 | unsigned long flags; | ||
| 1068 | struct macio_chip* macio; | ||
| 1069 | struct device_node* np; | ||
| 1070 | const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, | ||
| 1071 | KL_GPIO_RESET_CPU1, | ||
| 1072 | KL_GPIO_RESET_CPU2, | ||
| 1073 | KL_GPIO_RESET_CPU3 }; | ||
| 1074 | |||
| 1075 | macio = &macio_chips[0]; | ||
| 1076 | if (macio->type != macio_keylargo) | ||
| 1077 | return -ENODEV; | ||
| 1078 | |||
| 1079 | np = find_path_device("/cpus"); | ||
| 1080 | if (np == NULL) | ||
| 1081 | return -ENODEV; | ||
| 1082 | for (np = np->child; np != NULL; np = np->sibling) { | ||
| 1083 | u32* num = (u32 *)get_property(np, "reg", NULL); | ||
| 1084 | u32* rst = (u32 *)get_property(np, "soft-reset", NULL); | ||
| 1085 | if (num == NULL || rst == NULL) | ||
| 1086 | continue; | ||
| 1087 | if (param == *num) { | ||
| 1088 | reset_io = *rst; | ||
| 1089 | break; | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | if (np == NULL || reset_io == 0) | ||
| 1093 | reset_io = dflt_reset_lines[param]; | ||
| 1094 | |||
| 1095 | LOCK(flags); | ||
| 1096 | MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
| 1097 | (void)MACIO_IN8(reset_io); | ||
| 1098 | udelay(1); | ||
| 1099 | MACIO_OUT8(reset_io, 0); | ||
| 1100 | (void)MACIO_IN8(reset_io); | ||
| 1101 | UNLOCK(flags); | ||
| 1102 | |||
| 1103 | return 0; | ||
| 1104 | } | ||
| 1105 | #endif /* CONFIG_SMP */ | ||
| 1106 | |||
| 1107 | static long | ||
| 1108 | core99_usb_enable(struct device_node* node, long param, long value) | ||
| 1109 | { | ||
| 1110 | struct macio_chip* macio; | ||
| 1111 | unsigned long flags; | ||
| 1112 | char* prop; | ||
| 1113 | int number; | ||
| 1114 | u32 reg; | ||
| 1115 | |||
| 1116 | macio = &macio_chips[0]; | ||
| 1117 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 1118 | macio->type != macio_intrepid) | ||
| 1119 | return -ENODEV; | ||
| 1120 | |||
| 1121 | prop = (char *)get_property(node, "AAPL,clock-id", NULL); | ||
| 1122 | if (!prop) | ||
| 1123 | return -ENODEV; | ||
| 1124 | if (strncmp(prop, "usb0u048", 8) == 0) | ||
| 1125 | number = 0; | ||
| 1126 | else if (strncmp(prop, "usb1u148", 8) == 0) | ||
| 1127 | number = 2; | ||
| 1128 | else if (strncmp(prop, "usb2u248", 8) == 0) | ||
| 1129 | number = 4; | ||
| 1130 | else | ||
| 1131 | return -ENODEV; | ||
| 1132 | |||
| 1133 | /* Sorry for the brute-force locking, but this is only used during | ||
| 1134 | * sleep and the timing seem to be critical | ||
| 1135 | */ | ||
| 1136 | LOCK(flags); | ||
| 1137 | if (value) { | ||
| 1138 | /* Turn ON */ | ||
| 1139 | if (number == 0) { | ||
| 1140 | MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); | ||
| 1141 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1142 | UNLOCK(flags); | ||
| 1143 | mdelay(1); | ||
| 1144 | LOCK(flags); | ||
| 1145 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); | ||
| 1146 | } else if (number == 2) { | ||
| 1147 | MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); | ||
| 1148 | UNLOCK(flags); | ||
| 1149 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1150 | mdelay(1); | ||
| 1151 | LOCK(flags); | ||
| 1152 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); | ||
| 1153 | } else if (number == 4) { | ||
| 1154 | MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); | ||
| 1155 | UNLOCK(flags); | ||
| 1156 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
| 1157 | mdelay(1); | ||
| 1158 | LOCK(flags); | ||
| 1159 | MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); | ||
| 1160 | } | ||
| 1161 | if (number < 4) { | ||
| 1162 | reg = MACIO_IN32(KEYLARGO_FCR4); | ||
| 1163 | reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | | ||
| 1164 | KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); | ||
| 1165 | reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | | ||
| 1166 | KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); | ||
| 1167 | MACIO_OUT32(KEYLARGO_FCR4, reg); | ||
| 1168 | (void)MACIO_IN32(KEYLARGO_FCR4); | ||
| 1169 | udelay(10); | ||
| 1170 | } else { | ||
| 1171 | reg = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1172 | reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | | ||
| 1173 | KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); | ||
| 1174 | reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | | ||
| 1175 | KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); | ||
| 1176 | MACIO_OUT32(KEYLARGO_FCR3, reg); | ||
| 1177 | (void)MACIO_IN32(KEYLARGO_FCR3); | ||
| 1178 | udelay(10); | ||
| 1179 | } | ||
| 1180 | if (macio->type == macio_intrepid) { | ||
| 1181 | /* wait for clock stopped bits to clear */ | ||
| 1182 | u32 test0 = 0, test1 = 0; | ||
| 1183 | u32 status0, status1; | ||
| 1184 | int timeout = 1000; | ||
| 1185 | |||
| 1186 | UNLOCK(flags); | ||
| 1187 | switch (number) { | ||
| 1188 | case 0: | ||
| 1189 | test0 = UNI_N_CLOCK_STOPPED_USB0; | ||
| 1190 | test1 = UNI_N_CLOCK_STOPPED_USB0PCI; | ||
| 1191 | break; | ||
| 1192 | case 2: | ||
| 1193 | test0 = UNI_N_CLOCK_STOPPED_USB1; | ||
| 1194 | test1 = UNI_N_CLOCK_STOPPED_USB1PCI; | ||
| 1195 | break; | ||
| 1196 | case 4: | ||
| 1197 | test0 = UNI_N_CLOCK_STOPPED_USB2; | ||
| 1198 | test1 = UNI_N_CLOCK_STOPPED_USB2PCI; | ||
| 1199 | break; | ||
| 1200 | } | ||
| 1201 | do { | ||
| 1202 | if (--timeout <= 0) { | ||
| 1203 | printk(KERN_ERR "core99_usb_enable: " | ||
| 1204 | "Timeout waiting for clocks\n"); | ||
| 1205 | break; | ||
| 1206 | } | ||
| 1207 | mdelay(1); | ||
| 1208 | status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); | ||
| 1209 | status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); | ||
| 1210 | } while ((status0 & test0) | (status1 & test1)); | ||
| 1211 | LOCK(flags); | ||
| 1212 | } | ||
| 1213 | } else { | ||
| 1214 | /* Turn OFF */ | ||
| 1215 | if (number < 4) { | ||
| 1216 | reg = MACIO_IN32(KEYLARGO_FCR4); | ||
| 1217 | reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | | ||
| 1218 | KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); | ||
| 1219 | reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | | ||
| 1220 | KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); | ||
| 1221 | MACIO_OUT32(KEYLARGO_FCR4, reg); | ||
| 1222 | (void)MACIO_IN32(KEYLARGO_FCR4); | ||
| 1223 | udelay(1); | ||
| 1224 | } else { | ||
| 1225 | reg = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1226 | reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | | ||
| 1227 | KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); | ||
| 1228 | reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | | ||
| 1229 | KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); | ||
| 1230 | MACIO_OUT32(KEYLARGO_FCR3, reg); | ||
| 1231 | (void)MACIO_IN32(KEYLARGO_FCR3); | ||
| 1232 | udelay(1); | ||
| 1233 | } | ||
| 1234 | if (number == 0) { | ||
| 1235 | if (macio->type != macio_intrepid) | ||
| 1236 | MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); | ||
| 1237 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1238 | udelay(1); | ||
| 1239 | MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); | ||
| 1240 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1241 | } else if (number == 2) { | ||
| 1242 | if (macio->type != macio_intrepid) | ||
| 1243 | MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); | ||
| 1244 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1245 | udelay(1); | ||
| 1246 | MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); | ||
| 1247 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1248 | } else if (number == 4) { | ||
| 1249 | udelay(1); | ||
| 1250 | MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); | ||
| 1251 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
| 1252 | } | ||
| 1253 | udelay(1); | ||
| 1254 | } | ||
| 1255 | UNLOCK(flags); | ||
| 1256 | |||
| 1257 | return 0; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | static long | ||
| 1261 | core99_firewire_enable(struct device_node* node, long param, long value) | ||
| 1262 | { | ||
| 1263 | unsigned long flags; | ||
| 1264 | struct macio_chip* macio; | ||
| 1265 | |||
| 1266 | macio = &macio_chips[0]; | ||
| 1267 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 1268 | macio->type != macio_intrepid) | ||
| 1269 | return -ENODEV; | ||
| 1270 | if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) | ||
| 1271 | return -ENODEV; | ||
| 1272 | |||
| 1273 | LOCK(flags); | ||
| 1274 | if (value) { | ||
| 1275 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); | ||
| 1276 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
| 1277 | } else { | ||
| 1278 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); | ||
| 1279 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
| 1280 | } | ||
| 1281 | UNLOCK(flags); | ||
| 1282 | mdelay(1); | ||
| 1283 | |||
| 1284 | return 0; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | static long | ||
| 1288 | core99_firewire_cable_power(struct device_node* node, long param, long value) | ||
| 1289 | { | ||
| 1290 | unsigned long flags; | ||
| 1291 | struct macio_chip* macio; | ||
| 1292 | |||
| 1293 | /* Trick: we allow NULL node */ | ||
| 1294 | if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) | ||
| 1295 | return -ENODEV; | ||
| 1296 | macio = &macio_chips[0]; | ||
| 1297 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 1298 | macio->type != macio_intrepid) | ||
| 1299 | return -ENODEV; | ||
| 1300 | if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) | ||
| 1301 | return -ENODEV; | ||
| 1302 | |||
| 1303 | LOCK(flags); | ||
| 1304 | if (value) { | ||
| 1305 | MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); | ||
| 1306 | MACIO_IN8(KL_GPIO_FW_CABLE_POWER); | ||
| 1307 | udelay(10); | ||
| 1308 | } else { | ||
| 1309 | MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); | ||
| 1310 | MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); | ||
| 1311 | } | ||
| 1312 | UNLOCK(flags); | ||
| 1313 | mdelay(1); | ||
| 1314 | |||
| 1315 | return 0; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | static long | ||
| 1319 | intrepid_aack_delay_enable(struct device_node* node, long param, long value) | ||
| 1320 | { | ||
| 1321 | unsigned long flags; | ||
| 1322 | |||
| 1323 | if (uninorth_rev < 0xd2) | ||
| 1324 | return -ENODEV; | ||
| 1325 | |||
| 1326 | LOCK(flags); | ||
| 1327 | if (param) | ||
| 1328 | UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); | ||
| 1329 | else | ||
| 1330 | UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); | ||
| 1331 | UNLOCK(flags); | ||
| 1332 | |||
| 1333 | return 0; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | |||
| 1337 | #endif /* CONFIG_POWER4 */ | ||
| 1338 | |||
| 1339 | static long | ||
| 1340 | core99_read_gpio(struct device_node* node, long param, long value) | ||
| 1341 | { | ||
| 1342 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1343 | |||
| 1344 | return MACIO_IN8(param); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | |||
| 1348 | static long | ||
| 1349 | core99_write_gpio(struct device_node* node, long param, long value) | ||
| 1350 | { | ||
| 1351 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1352 | |||
| 1353 | MACIO_OUT8(param, (u8)(value & 0xff)); | ||
| 1354 | return 0; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | #ifdef CONFIG_POWER4 | ||
| 1358 | |||
| 1359 | static long | ||
| 1360 | g5_gmac_enable(struct device_node* node, long param, long value) | ||
| 1361 | { | ||
| 1362 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1363 | unsigned long flags; | ||
| 1364 | u8 pbus, pid; | ||
| 1365 | |||
| 1366 | LOCK(flags); | ||
| 1367 | if (value) { | ||
| 1368 | MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); | ||
| 1369 | mb(); | ||
| 1370 | k2_skiplist[0] = NULL; | ||
| 1371 | } else { | ||
| 1372 | k2_skiplist[0] = node; | ||
| 1373 | mb(); | ||
| 1374 | MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | UNLOCK(flags); | ||
| 1378 | mdelay(1); | ||
| 1379 | |||
| 1380 | return 0; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | static long | ||
| 1384 | g5_fw_enable(struct device_node* node, long param, long value) | ||
| 1385 | { | ||
| 1386 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1387 | unsigned long flags; | ||
| 1388 | |||
| 1389 | LOCK(flags); | ||
| 1390 | if (value) { | ||
| 1391 | MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); | ||
| 1392 | mb(); | ||
| 1393 | k2_skiplist[1] = NULL; | ||
| 1394 | } else { | ||
| 1395 | k2_skiplist[1] = node; | ||
| 1396 | mb(); | ||
| 1397 | MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | UNLOCK(flags); | ||
| 1401 | mdelay(1); | ||
| 1402 | |||
| 1403 | return 0; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static long | ||
| 1407 | g5_mpic_enable(struct device_node* node, long param, long value) | ||
| 1408 | { | ||
| 1409 | unsigned long flags; | ||
| 1410 | |||
| 1411 | if (node->parent == NULL || strcmp(node->parent->name, "u3")) | ||
| 1412 | return 0; | ||
| 1413 | |||
| 1414 | LOCK(flags); | ||
| 1415 | UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); | ||
| 1416 | UNLOCK(flags); | ||
| 1417 | |||
| 1418 | return 0; | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | #ifdef CONFIG_SMP | ||
| 1422 | static long | ||
| 1423 | g5_reset_cpu(struct device_node* node, long param, long value) | ||
| 1424 | { | ||
| 1425 | unsigned int reset_io = 0; | ||
| 1426 | unsigned long flags; | ||
| 1427 | struct macio_chip* macio; | ||
| 1428 | struct device_node* np; | ||
| 1429 | |||
| 1430 | macio = &macio_chips[0]; | ||
| 1431 | if (macio->type != macio_keylargo2) | ||
| 1432 | return -ENODEV; | ||
| 1433 | |||
| 1434 | np = find_path_device("/cpus"); | ||
| 1435 | if (np == NULL) | ||
| 1436 | return -ENODEV; | ||
| 1437 | for (np = np->child; np != NULL; np = np->sibling) { | ||
| 1438 | u32* num = (u32 *)get_property(np, "reg", NULL); | ||
| 1439 | u32* rst = (u32 *)get_property(np, "soft-reset", NULL); | ||
| 1440 | if (num == NULL || rst == NULL) | ||
| 1441 | continue; | ||
| 1442 | if (param == *num) { | ||
| 1443 | reset_io = *rst; | ||
| 1444 | break; | ||
| 1445 | } | ||
| 1446 | } | ||
| 1447 | if (np == NULL || reset_io == 0) | ||
| 1448 | return -ENODEV; | ||
| 1449 | |||
| 1450 | LOCK(flags); | ||
| 1451 | MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
| 1452 | (void)MACIO_IN8(reset_io); | ||
| 1453 | udelay(1); | ||
| 1454 | MACIO_OUT8(reset_io, 0); | ||
| 1455 | (void)MACIO_IN8(reset_io); | ||
| 1456 | UNLOCK(flags); | ||
| 1457 | |||
| 1458 | return 0; | ||
| 1459 | } | ||
| 1460 | #endif /* CONFIG_SMP */ | ||
| 1461 | |||
| 1462 | /* | ||
| 1463 | * This can be called from pmac_smp so isn't static | ||
| 1464 | * | ||
| 1465 | * This takes the second CPU off the bus on dual CPU machines | ||
| 1466 | * running UP | ||
| 1467 | */ | ||
| 1468 | void g5_phy_disable_cpu1(void) | ||
| 1469 | { | ||
| 1470 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | #endif /* CONFIG_POWER4 */ | ||
| 1474 | |||
| 1475 | #ifndef CONFIG_POWER4 | ||
| 1476 | |||
| 1477 | static void | ||
| 1478 | keylargo_shutdown(struct macio_chip* macio, int sleep_mode) | ||
| 1479 | { | ||
| 1480 | u32 temp; | ||
| 1481 | |||
| 1482 | if (sleep_mode) { | ||
| 1483 | mdelay(1); | ||
| 1484 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); | ||
| 1485 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1486 | mdelay(1); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
| 1490 | KL0_SCC_CELL_ENABLE | | ||
| 1491 | KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | | ||
| 1492 | KL0_IRDA_CLK19_ENABLE); | ||
| 1493 | |||
| 1494 | MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); | ||
| 1495 | MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); | ||
| 1496 | |||
| 1497 | MACIO_BIC(KEYLARGO_FCR1, | ||
| 1498 | KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | | ||
| 1499 | KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | | ||
| 1500 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
| 1501 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
| 1502 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | | ||
| 1503 | KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | | ||
| 1504 | KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | | ||
| 1505 | KL1_UIDE_ENABLE); | ||
| 1506 | |||
| 1507 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
| 1508 | MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); | ||
| 1509 | |||
| 1510 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1511 | if (macio->rev >= 2) { | ||
| 1512 | temp |= KL3_SHUTDOWN_PLL2X; | ||
| 1513 | if (sleep_mode) | ||
| 1514 | temp |= KL3_SHUTDOWN_PLL_TOTAL; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | | ||
| 1518 | KL3_SHUTDOWN_PLLKW35; | ||
| 1519 | if (sleep_mode) | ||
| 1520 | temp |= KL3_SHUTDOWN_PLLKW12; | ||
| 1521 | temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | ||
| 1522 | | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); | ||
| 1523 | if (sleep_mode) | ||
| 1524 | temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); | ||
| 1525 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
| 1526 | |||
| 1527 | /* Flush posted writes & wait a bit */ | ||
| 1528 | (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | static void | ||
| 1532 | pangea_shutdown(struct macio_chip* macio, int sleep_mode) | ||
| 1533 | { | ||
| 1534 | u32 temp; | ||
| 1535 | |||
| 1536 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
| 1537 | KL0_SCC_CELL_ENABLE | | ||
| 1538 | KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); | ||
| 1539 | |||
| 1540 | MACIO_BIC(KEYLARGO_FCR1, | ||
| 1541 | KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | | ||
| 1542 | KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | | ||
| 1543 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
| 1544 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
| 1545 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | | ||
| 1546 | KL1_UIDE_ENABLE); | ||
| 1547 | if (pmac_mb.board_flags & PMAC_MB_MOBILE) | ||
| 1548 | MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); | ||
| 1549 | |||
| 1550 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
| 1551 | |||
| 1552 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1553 | temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | | ||
| 1554 | KL3_SHUTDOWN_PLLKW35; | ||
| 1555 | temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE | ||
| 1556 | | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); | ||
| 1557 | if (sleep_mode) | ||
| 1558 | temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); | ||
| 1559 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
| 1560 | |||
| 1561 | /* Flush posted writes & wait a bit */ | ||
| 1562 | (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | static void | ||
| 1566 | intrepid_shutdown(struct macio_chip* macio, int sleep_mode) | ||
| 1567 | { | ||
| 1568 | u32 temp; | ||
| 1569 | |||
| 1570 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
| 1571 | KL0_SCC_CELL_ENABLE); | ||
| 1572 | |||
| 1573 | MACIO_BIC(KEYLARGO_FCR1, | ||
| 1574 | /*KL1_USB2_CELL_ENABLE |*/ | ||
| 1575 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
| 1576 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
| 1577 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE); | ||
| 1578 | if (pmac_mb.board_flags & PMAC_MB_MOBILE) | ||
| 1579 | MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); | ||
| 1580 | |||
| 1581 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1582 | temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | | ||
| 1583 | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); | ||
| 1584 | if (sleep_mode) | ||
| 1585 | temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); | ||
| 1586 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
| 1587 | |||
| 1588 | /* Flush posted writes & wait a bit */ | ||
| 1589 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
| 1590 | mdelay(10); | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | |||
| 1594 | void pmac_tweak_clock_spreading(int enable) | ||
| 1595 | { | ||
| 1596 | struct macio_chip* macio = &macio_chips[0]; | ||
| 1597 | |||
| 1598 | /* Hack for doing clock spreading on some machines PowerBooks and | ||
| 1599 | * iBooks. This implements the "platform-do-clockspreading" OF | ||
| 1600 | * property as decoded manually on various models. For safety, we also | ||
| 1601 | * check the product ID in the device-tree in cases we'll whack the i2c | ||
| 1602 | * chip to make reasonably sure we won't set wrong values in there | ||
| 1603 | * | ||
| 1604 | * Of course, ultimately, we have to implement a real parser for | ||
| 1605 | * the platform-do-* stuff... | ||
| 1606 | */ | ||
| 1607 | |||
| 1608 | if (macio->type == macio_intrepid) { | ||
| 1609 | struct device_node *clock = | ||
| 1610 | of_find_node_by_path("/uni-n@f8000000/hw-clock"); | ||
| 1611 | if (clock && get_property(clock, "platform-do-clockspreading", | ||
| 1612 | NULL)) { | ||
| 1613 | printk(KERN_INFO "%sabling clock spreading on Intrepid" | ||
| 1614 | " ASIC\n", enable ? "En" : "Dis"); | ||
| 1615 | if (enable) | ||
| 1616 | UN_OUT(UNI_N_CLOCK_SPREADING, 2); | ||
| 1617 | else | ||
| 1618 | UN_OUT(UNI_N_CLOCK_SPREADING, 0); | ||
| 1619 | mdelay(40); | ||
| 1620 | } | ||
| 1621 | of_node_put(clock); | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | while (machine_is_compatible("PowerBook5,2") || | ||
| 1625 | machine_is_compatible("PowerBook5,3") || | ||
| 1626 | machine_is_compatible("PowerBook6,2") || | ||
| 1627 | machine_is_compatible("PowerBook6,3")) { | ||
| 1628 | struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); | ||
| 1629 | struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); | ||
| 1630 | u8 buffer[9]; | ||
| 1631 | u32 *productID; | ||
| 1632 | int i, rc, changed = 0; | ||
| 1633 | |||
| 1634 | if (dt == NULL) | ||
| 1635 | break; | ||
| 1636 | productID = (u32 *)get_property(dt, "pid#", NULL); | ||
| 1637 | if (productID == NULL) | ||
| 1638 | break; | ||
| 1639 | while(ui2c) { | ||
| 1640 | struct device_node *p = of_get_parent(ui2c); | ||
| 1641 | if (p && !strcmp(p->name, "uni-n")) | ||
| 1642 | break; | ||
| 1643 | ui2c = of_find_node_by_type(ui2c, "i2c"); | ||
| 1644 | } | ||
| 1645 | if (ui2c == NULL) | ||
| 1646 | break; | ||
| 1647 | DBG("Trying to bump clock speed for PID: %08x...\n", *productID); | ||
| 1648 | rc = pmac_low_i2c_open(ui2c, 1); | ||
| 1649 | if (rc != 0) | ||
| 1650 | break; | ||
| 1651 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 1652 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 1653 | DBG("read result: %d,", rc); | ||
| 1654 | if (rc != 0) { | ||
| 1655 | pmac_low_i2c_close(ui2c); | ||
| 1656 | break; | ||
| 1657 | } | ||
| 1658 | for (i=0; i<9; i++) | ||
| 1659 | DBG(" %02x", buffer[i]); | ||
| 1660 | DBG("\n"); | ||
| 1661 | |||
| 1662 | switch(*productID) { | ||
| 1663 | case 0x1182: /* AlBook 12" rev 2 */ | ||
| 1664 | case 0x1183: /* iBook G4 12" */ | ||
| 1665 | buffer[0] = (buffer[0] & 0x8f) | 0x70; | ||
| 1666 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 1667 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 1668 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 1669 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba); | ||
| 1670 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 1671 | changed = 1; | ||
| 1672 | break; | ||
| 1673 | case 0x3142: /* AlBook 15" (ATI M10) */ | ||
| 1674 | case 0x3143: /* AlBook 17" (ATI M10) */ | ||
| 1675 | buffer[0] = (buffer[0] & 0xaf) | 0x50; | ||
| 1676 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
| 1677 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
| 1678 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
| 1679 | buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0); | ||
| 1680 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
| 1681 | changed = 1; | ||
| 1682 | break; | ||
| 1683 | default: | ||
| 1684 | DBG("i2c-hwclock: Machine model not handled\n"); | ||
| 1685 | break; | ||
| 1686 | } | ||
| 1687 | if (!changed) { | ||
| 1688 | pmac_low_i2c_close(ui2c); | ||
| 1689 | break; | ||
| 1690 | } | ||
| 1691 | printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n", | ||
| 1692 | enable ? "En" : "Dis"); | ||
| 1693 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); | ||
| 1694 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); | ||
| 1695 | DBG("write result: %d,", rc); | ||
| 1696 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
| 1697 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
| 1698 | DBG("read result: %d,", rc); | ||
| 1699 | if (rc != 0) { | ||
| 1700 | pmac_low_i2c_close(ui2c); | ||
| 1701 | break; | ||
| 1702 | } | ||
| 1703 | for (i=0; i<9; i++) | ||
| 1704 | DBG(" %02x", buffer[i]); | ||
| 1705 | pmac_low_i2c_close(ui2c); | ||
| 1706 | break; | ||
| 1707 | } | ||
| 1708 | } | ||
| 1709 | |||
| 1710 | |||
| 1711 | static int | ||
| 1712 | core99_sleep(void) | ||
| 1713 | { | ||
| 1714 | struct macio_chip* macio; | ||
| 1715 | int i; | ||
| 1716 | |||
| 1717 | macio = &macio_chips[0]; | ||
| 1718 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 1719 | macio->type != macio_intrepid) | ||
| 1720 | return -ENODEV; | ||
| 1721 | |||
| 1722 | /* We power off the wireless slot in case it was not done | ||
| 1723 | * by the driver. We don't power it on automatically however | ||
| 1724 | */ | ||
| 1725 | if (macio->flags & MACIO_FLAG_AIRPORT_ON) | ||
| 1726 | core99_airport_enable(macio->of_node, 0, 0); | ||
| 1727 | |||
| 1728 | /* We power off the FW cable. Should be done by the driver... */ | ||
| 1729 | if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { | ||
| 1730 | core99_firewire_enable(NULL, 0, 0); | ||
| 1731 | core99_firewire_cable_power(NULL, 0, 0); | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | /* We make sure int. modem is off (in case driver lost it) */ | ||
| 1735 | if (macio->type == macio_keylargo) | ||
| 1736 | core99_modem_enable(macio->of_node, 0, 0); | ||
| 1737 | else | ||
| 1738 | pangea_modem_enable(macio->of_node, 0, 0); | ||
| 1739 | |||
| 1740 | /* We make sure the sound is off as well */ | ||
| 1741 | core99_sound_chip_enable(macio->of_node, 0, 0); | ||
| 1742 | |||
| 1743 | /* | ||
| 1744 | * Save various bits of KeyLargo | ||
| 1745 | */ | ||
| 1746 | |||
| 1747 | /* Save the state of the various GPIOs */ | ||
| 1748 | save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); | ||
| 1749 | save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); | ||
| 1750 | for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) | ||
| 1751 | save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i); | ||
| 1752 | for (i=0; i<KEYLARGO_GPIO_CNT; i++) | ||
| 1753 | save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i); | ||
| 1754 | |||
| 1755 | /* Save the FCRs */ | ||
| 1756 | if (macio->type == macio_keylargo) | ||
| 1757 | save_mbcr = MACIO_IN32(KEYLARGO_MBCR); | ||
| 1758 | save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); | ||
| 1759 | save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); | ||
| 1760 | save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); | ||
| 1761 | save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); | ||
| 1762 | save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); | ||
| 1763 | if (macio->type == macio_pangea || macio->type == macio_intrepid) | ||
| 1764 | save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); | ||
| 1765 | |||
| 1766 | /* Save state & config of DBDMA channels */ | ||
| 1767 | dbdma_save(macio, save_dbdma); | ||
| 1768 | |||
| 1769 | /* | ||
| 1770 | * Turn off as much as we can | ||
| 1771 | */ | ||
| 1772 | if (macio->type == macio_pangea) | ||
| 1773 | pangea_shutdown(macio, 1); | ||
| 1774 | else if (macio->type == macio_intrepid) | ||
| 1775 | intrepid_shutdown(macio, 1); | ||
| 1776 | else if (macio->type == macio_keylargo) | ||
| 1777 | keylargo_shutdown(macio, 1); | ||
| 1778 | |||
| 1779 | /* | ||
| 1780 | * Put the host bridge to sleep | ||
| 1781 | */ | ||
| 1782 | |||
| 1783 | save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); | ||
| 1784 | /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it | ||
| 1785 | * enabled ! | ||
| 1786 | */ | ||
| 1787 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & | ||
| 1788 | ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); | ||
| 1789 | udelay(100); | ||
| 1790 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); | ||
| 1791 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); | ||
| 1792 | mdelay(10); | ||
| 1793 | |||
| 1794 | /* | ||
| 1795 | * FIXME: A bit of black magic with OpenPIC (don't ask me why) | ||
| 1796 | */ | ||
| 1797 | if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { | ||
| 1798 | MACIO_BIS(0x506e0, 0x00400000); | ||
| 1799 | MACIO_BIS(0x506e0, 0x80000000); | ||
| 1800 | } | ||
| 1801 | return 0; | ||
| 1802 | } | ||
| 1803 | |||
| 1804 | static int | ||
| 1805 | core99_wake_up(void) | ||
| 1806 | { | ||
| 1807 | struct macio_chip* macio; | ||
| 1808 | int i; | ||
| 1809 | |||
| 1810 | macio = &macio_chips[0]; | ||
| 1811 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
| 1812 | macio->type != macio_intrepid) | ||
| 1813 | return -ENODEV; | ||
| 1814 | |||
| 1815 | /* | ||
| 1816 | * Wakeup the host bridge | ||
| 1817 | */ | ||
| 1818 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); | ||
| 1819 | udelay(10); | ||
| 1820 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); | ||
| 1821 | udelay(10); | ||
| 1822 | |||
| 1823 | /* | ||
| 1824 | * Restore KeyLargo | ||
| 1825 | */ | ||
| 1826 | |||
| 1827 | if (macio->type == macio_keylargo) { | ||
| 1828 | MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); | ||
| 1829 | (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); | ||
| 1830 | } | ||
| 1831 | MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); | ||
| 1832 | (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); | ||
| 1833 | MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); | ||
| 1834 | (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); | ||
| 1835 | MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); | ||
| 1836 | (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); | ||
| 1837 | MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); | ||
| 1838 | (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); | ||
| 1839 | MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); | ||
| 1840 | (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); | ||
| 1841 | if (macio->type == macio_pangea || macio->type == macio_intrepid) { | ||
| 1842 | MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); | ||
| 1843 | (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | dbdma_restore(macio, save_dbdma); | ||
| 1847 | |||
| 1848 | MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); | ||
| 1849 | MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); | ||
| 1850 | for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) | ||
| 1851 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]); | ||
| 1852 | for (i=0; i<KEYLARGO_GPIO_CNT; i++) | ||
| 1853 | MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]); | ||
| 1854 | |||
| 1855 | /* FIXME more black magic with OpenPIC ... */ | ||
| 1856 | if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { | ||
| 1857 | MACIO_BIC(0x506e0, 0x00400000); | ||
| 1858 | MACIO_BIC(0x506e0, 0x80000000); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); | ||
| 1862 | udelay(100); | ||
| 1863 | |||
| 1864 | return 0; | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | static long | ||
| 1868 | core99_sleep_state(struct device_node* node, long param, long value) | ||
| 1869 | { | ||
| 1870 | /* Param == 1 means to enter the "fake sleep" mode that is | ||
| 1871 | * used for CPU speed switch | ||
| 1872 | */ | ||
| 1873 | if (param == 1) { | ||
| 1874 | if (value == 1) { | ||
| 1875 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); | ||
| 1876 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2); | ||
| 1877 | } else { | ||
| 1878 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); | ||
| 1879 | udelay(10); | ||
| 1880 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); | ||
| 1881 | udelay(10); | ||
| 1882 | } | ||
| 1883 | return 0; | ||
| 1884 | } | ||
| 1885 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
| 1886 | return -EPERM; | ||
| 1887 | |||
| 1888 | if (value == 1) | ||
| 1889 | return core99_sleep(); | ||
| 1890 | else if (value == 0) | ||
| 1891 | return core99_wake_up(); | ||
| 1892 | return 0; | ||
| 1893 | } | ||
| 1894 | |||
| 1895 | #endif /* CONFIG_POWER4 */ | ||
| 1896 | |||
| 1897 | static long | ||
| 1898 | generic_dev_can_wake(struct device_node* node, long param, long value) | ||
| 1899 | { | ||
| 1900 | /* Todo: eventually check we are really dealing with on-board | ||
| 1901 | * video device ... | ||
| 1902 | */ | ||
| 1903 | |||
| 1904 | if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP) | ||
| 1905 | pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP; | ||
| 1906 | return 0; | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | static long | ||
| 1910 | generic_get_mb_info(struct device_node* node, long param, long value) | ||
| 1911 | { | ||
| 1912 | switch(param) { | ||
| 1913 | case PMAC_MB_INFO_MODEL: | ||
| 1914 | return pmac_mb.model_id; | ||
| 1915 | case PMAC_MB_INFO_FLAGS: | ||
| 1916 | return pmac_mb.board_flags; | ||
| 1917 | case PMAC_MB_INFO_NAME: | ||
| 1918 | /* hack hack hack... but should work */ | ||
| 1919 | *((const char **)value) = pmac_mb.model_name; | ||
| 1920 | return 0; | ||
| 1921 | } | ||
| 1922 | return -EINVAL; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | |||
| 1926 | /* | ||
| 1927 | * Table definitions | ||
| 1928 | */ | ||
| 1929 | |||
| 1930 | /* Used on any machine | ||
| 1931 | */ | ||
| 1932 | static struct feature_table_entry any_features[] = { | ||
| 1933 | { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, | ||
| 1934 | { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake }, | ||
| 1935 | { 0, NULL } | ||
| 1936 | }; | ||
| 1937 | |||
| 1938 | #ifndef CONFIG_POWER4 | ||
| 1939 | |||
| 1940 | /* OHare based motherboards. Currently, we only use these on the | ||
| 1941 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem | ||
| 1942 | * to have issues with turning on/off those asic cells | ||
| 1943 | */ | ||
| 1944 | static struct feature_table_entry ohare_features[] = { | ||
| 1945 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
| 1946 | { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable }, | ||
| 1947 | { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable }, | ||
| 1948 | { PMAC_FTR_IDE_ENABLE, ohare_ide_enable}, | ||
| 1949 | { PMAC_FTR_IDE_RESET, ohare_ide_reset}, | ||
| 1950 | { PMAC_FTR_SLEEP_STATE, ohare_sleep_state }, | ||
| 1951 | { 0, NULL } | ||
| 1952 | }; | ||
| 1953 | |||
| 1954 | /* Heathrow desktop machines (Beige G3). | ||
| 1955 | * Separated as some features couldn't be properly tested | ||
| 1956 | * and the serial port control bits appear to confuse it. | ||
| 1957 | */ | ||
| 1958 | static struct feature_table_entry heathrow_desktop_features[] = { | ||
| 1959 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
| 1960 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
| 1961 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
| 1962 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
| 1963 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
| 1964 | { 0, NULL } | ||
| 1965 | }; | ||
| 1966 | |||
| 1967 | /* Heathrow based laptop, that is the Wallstreet and mainstreet | ||
| 1968 | * powerbooks. | ||
| 1969 | */ | ||
| 1970 | static struct feature_table_entry heathrow_laptop_features[] = { | ||
| 1971 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
| 1972 | { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, | ||
| 1973 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
| 1974 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
| 1975 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
| 1976 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
| 1977 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
| 1978 | { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, | ||
| 1979 | { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, | ||
| 1980 | { 0, NULL } | ||
| 1981 | }; | ||
| 1982 | |||
| 1983 | /* Paddington based machines | ||
| 1984 | * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4. | ||
| 1985 | */ | ||
| 1986 | static struct feature_table_entry paddington_features[] = { | ||
| 1987 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
| 1988 | { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, | ||
| 1989 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
| 1990 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
| 1991 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
| 1992 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
| 1993 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
| 1994 | { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, | ||
| 1995 | { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, | ||
| 1996 | { 0, NULL } | ||
| 1997 | }; | ||
| 1998 | |||
| 1999 | /* Core99 & MacRISC 2 machines (all machines released since the | ||
| 2000 | * iBook (included), that is all AGP machines, except pangea | ||
| 2001 | * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo | ||
| 2002 | * used on iBook2 & iMac "flow power". | ||
| 2003 | */ | ||
| 2004 | static struct feature_table_entry core99_features[] = { | ||
| 2005 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
| 2006 | { PMAC_FTR_MODEM_ENABLE, core99_modem_enable }, | ||
| 2007 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
| 2008 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
| 2009 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
| 2010 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
| 2011 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
| 2012 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
| 2013 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
| 2014 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
| 2015 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
| 2016 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
| 2017 | #ifdef CONFIG_SMP | ||
| 2018 | { PMAC_FTR_RESET_CPU, core99_reset_cpu }, | ||
| 2019 | #endif /* CONFIG_SMP */ | ||
| 2020 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
| 2021 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
| 2022 | { 0, NULL } | ||
| 2023 | }; | ||
| 2024 | |||
| 2025 | /* RackMac | ||
| 2026 | */ | ||
| 2027 | static struct feature_table_entry rackmac_features[] = { | ||
| 2028 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
| 2029 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
| 2030 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
| 2031 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
| 2032 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
| 2033 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
| 2034 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
| 2035 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
| 2036 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
| 2037 | #ifdef CONFIG_SMP | ||
| 2038 | { PMAC_FTR_RESET_CPU, core99_reset_cpu }, | ||
| 2039 | #endif /* CONFIG_SMP */ | ||
| 2040 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
| 2041 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
| 2042 | { 0, NULL } | ||
| 2043 | }; | ||
| 2044 | |||
| 2045 | /* Pangea features | ||
| 2046 | */ | ||
| 2047 | static struct feature_table_entry pangea_features[] = { | ||
| 2048 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
| 2049 | { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, | ||
| 2050 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
| 2051 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
| 2052 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
| 2053 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
| 2054 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
| 2055 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
| 2056 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
| 2057 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
| 2058 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
| 2059 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
| 2060 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
| 2061 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
| 2062 | { 0, NULL } | ||
| 2063 | }; | ||
| 2064 | |||
| 2065 | /* Intrepid features | ||
| 2066 | */ | ||
| 2067 | static struct feature_table_entry intrepid_features[] = { | ||
| 2068 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
| 2069 | { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, | ||
| 2070 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
| 2071 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
| 2072 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
| 2073 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
| 2074 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
| 2075 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
| 2076 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
| 2077 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
| 2078 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
| 2079 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
| 2080 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
| 2081 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
| 2082 | { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable }, | ||
| 2083 | { 0, NULL } | ||
| 2084 | }; | ||
| 2085 | |||
| 2086 | #else /* CONFIG_POWER4 */ | ||
| 2087 | |||
| 2088 | /* G5 features | ||
| 2089 | */ | ||
| 2090 | static struct feature_table_entry g5_features[] = { | ||
| 2091 | { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, | ||
| 2092 | { PMAC_FTR_1394_ENABLE, g5_fw_enable }, | ||
| 2093 | { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, | ||
| 2094 | #ifdef CONFIG_SMP | ||
| 2095 | { PMAC_FTR_RESET_CPU, g5_reset_cpu }, | ||
| 2096 | #endif /* CONFIG_SMP */ | ||
| 2097 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
| 2098 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
| 2099 | { 0, NULL } | ||
| 2100 | }; | ||
| 2101 | |||
| 2102 | #endif /* CONFIG_POWER4 */ | ||
| 2103 | |||
| 2104 | static struct pmac_mb_def pmac_mb_defs[] = { | ||
| 2105 | #ifndef CONFIG_POWER4 | ||
| 2106 | /* | ||
| 2107 | * Desktops | ||
| 2108 | */ | ||
| 2109 | |||
| 2110 | { "AAPL,8500", "PowerMac 8500/8600", | ||
| 2111 | PMAC_TYPE_PSURGE, NULL, | ||
| 2112 | 0 | ||
| 2113 | }, | ||
| 2114 | { "AAPL,9500", "PowerMac 9500/9600", | ||
| 2115 | PMAC_TYPE_PSURGE, NULL, | ||
| 2116 | 0 | ||
| 2117 | }, | ||
| 2118 | { "AAPL,7200", "PowerMac 7200", | ||
| 2119 | PMAC_TYPE_PSURGE, NULL, | ||
| 2120 | 0 | ||
| 2121 | }, | ||
| 2122 | { "AAPL,7300", "PowerMac 7200/7300", | ||
| 2123 | PMAC_TYPE_PSURGE, NULL, | ||
| 2124 | 0 | ||
| 2125 | }, | ||
| 2126 | { "AAPL,7500", "PowerMac 7500", | ||
| 2127 | PMAC_TYPE_PSURGE, NULL, | ||
| 2128 | 0 | ||
| 2129 | }, | ||
| 2130 | { "AAPL,ShinerESB", "Apple Network Server", | ||
| 2131 | PMAC_TYPE_ANS, NULL, | ||
| 2132 | 0 | ||
| 2133 | }, | ||
| 2134 | { "AAPL,e407", "Alchemy", | ||
| 2135 | PMAC_TYPE_ALCHEMY, NULL, | ||
| 2136 | 0 | ||
| 2137 | }, | ||
| 2138 | { "AAPL,e411", "Gazelle", | ||
| 2139 | PMAC_TYPE_GAZELLE, NULL, | ||
| 2140 | 0 | ||
| 2141 | }, | ||
| 2142 | { "AAPL,Gossamer", "PowerMac G3 (Gossamer)", | ||
| 2143 | PMAC_TYPE_GOSSAMER, heathrow_desktop_features, | ||
| 2144 | 0 | ||
| 2145 | }, | ||
| 2146 | { "AAPL,PowerMac G3", "PowerMac G3 (Silk)", | ||
| 2147 | PMAC_TYPE_SILK, heathrow_desktop_features, | ||
| 2148 | 0 | ||
| 2149 | }, | ||
| 2150 | { "PowerMac1,1", "Blue&White G3", | ||
| 2151 | PMAC_TYPE_YOSEMITE, paddington_features, | ||
| 2152 | 0 | ||
| 2153 | }, | ||
| 2154 | { "PowerMac1,2", "PowerMac G4 PCI Graphics", | ||
| 2155 | PMAC_TYPE_YIKES, paddington_features, | ||
| 2156 | 0 | ||
| 2157 | }, | ||
| 2158 | { "PowerMac2,1", "iMac FireWire", | ||
| 2159 | PMAC_TYPE_FW_IMAC, core99_features, | ||
| 2160 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
| 2161 | }, | ||
| 2162 | { "PowerMac2,2", "iMac FireWire", | ||
| 2163 | PMAC_TYPE_FW_IMAC, core99_features, | ||
| 2164 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
| 2165 | }, | ||
| 2166 | { "PowerMac3,1", "PowerMac G4 AGP Graphics", | ||
| 2167 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
| 2168 | PMAC_MB_OLD_CORE99 | ||
| 2169 | }, | ||
| 2170 | { "PowerMac3,2", "PowerMac G4 AGP Graphics", | ||
| 2171 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
| 2172 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
| 2173 | }, | ||
| 2174 | { "PowerMac3,3", "PowerMac G4 AGP Graphics", | ||
| 2175 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
| 2176 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
| 2177 | }, | ||
| 2178 | { "PowerMac3,4", "PowerMac G4 Silver", | ||
| 2179 | PMAC_TYPE_QUICKSILVER, core99_features, | ||
| 2180 | PMAC_MB_MAY_SLEEP | ||
| 2181 | }, | ||
| 2182 | { "PowerMac3,5", "PowerMac G4 Silver", | ||
| 2183 | PMAC_TYPE_QUICKSILVER, core99_features, | ||
| 2184 | PMAC_MB_MAY_SLEEP | ||
| 2185 | }, | ||
| 2186 | { "PowerMac3,6", "PowerMac G4 Windtunnel", | ||
| 2187 | PMAC_TYPE_WINDTUNNEL, core99_features, | ||
| 2188 | PMAC_MB_MAY_SLEEP, | ||
| 2189 | }, | ||
| 2190 | { "PowerMac4,1", "iMac \"Flower Power\"", | ||
| 2191 | PMAC_TYPE_PANGEA_IMAC, pangea_features, | ||
| 2192 | PMAC_MB_MAY_SLEEP | ||
| 2193 | }, | ||
| 2194 | { "PowerMac4,2", "Flat panel iMac", | ||
| 2195 | PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features, | ||
| 2196 | PMAC_MB_CAN_SLEEP | ||
| 2197 | }, | ||
| 2198 | { "PowerMac4,4", "eMac", | ||
| 2199 | PMAC_TYPE_EMAC, core99_features, | ||
| 2200 | PMAC_MB_MAY_SLEEP | ||
| 2201 | }, | ||
| 2202 | { "PowerMac5,1", "PowerMac G4 Cube", | ||
| 2203 | PMAC_TYPE_CUBE, core99_features, | ||
| 2204 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
| 2205 | }, | ||
| 2206 | { "PowerMac6,1", "Flat panel iMac", | ||
| 2207 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2208 | PMAC_MB_MAY_SLEEP, | ||
| 2209 | }, | ||
| 2210 | { "PowerMac6,3", "Flat panel iMac", | ||
| 2211 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2212 | PMAC_MB_MAY_SLEEP, | ||
| 2213 | }, | ||
| 2214 | { "PowerMac6,4", "eMac", | ||
| 2215 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2216 | PMAC_MB_MAY_SLEEP, | ||
| 2217 | }, | ||
| 2218 | { "PowerMac10,1", "Mac mini", | ||
| 2219 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2220 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER, | ||
| 2221 | }, | ||
| 2222 | { "iMac,1", "iMac (first generation)", | ||
| 2223 | PMAC_TYPE_ORIG_IMAC, paddington_features, | ||
| 2224 | 0 | ||
| 2225 | }, | ||
| 2226 | |||
| 2227 | /* | ||
| 2228 | * Xserve's | ||
| 2229 | */ | ||
| 2230 | |||
| 2231 | { "RackMac1,1", "XServe", | ||
| 2232 | PMAC_TYPE_RACKMAC, rackmac_features, | ||
| 2233 | 0, | ||
| 2234 | }, | ||
| 2235 | { "RackMac1,2", "XServe rev. 2", | ||
| 2236 | PMAC_TYPE_RACKMAC, rackmac_features, | ||
| 2237 | 0, | ||
| 2238 | }, | ||
| 2239 | |||
| 2240 | /* | ||
| 2241 | * Laptops | ||
| 2242 | */ | ||
| 2243 | |||
| 2244 | { "AAPL,3400/2400", "PowerBook 3400", | ||
| 2245 | PMAC_TYPE_HOOPER, ohare_features, | ||
| 2246 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
| 2247 | }, | ||
| 2248 | { "AAPL,3500", "PowerBook 3500", | ||
| 2249 | PMAC_TYPE_KANGA, ohare_features, | ||
| 2250 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
| 2251 | }, | ||
| 2252 | { "AAPL,PowerBook1998", "PowerBook Wallstreet", | ||
| 2253 | PMAC_TYPE_WALLSTREET, heathrow_laptop_features, | ||
| 2254 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
| 2255 | }, | ||
| 2256 | { "PowerBook1,1", "PowerBook 101 (Lombard)", | ||
| 2257 | PMAC_TYPE_101_PBOOK, paddington_features, | ||
| 2258 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
| 2259 | }, | ||
| 2260 | { "PowerBook2,1", "iBook (first generation)", | ||
| 2261 | PMAC_TYPE_ORIG_IBOOK, core99_features, | ||
| 2262 | PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
| 2263 | }, | ||
| 2264 | { "PowerBook2,2", "iBook FireWire", | ||
| 2265 | PMAC_TYPE_FW_IBOOK, core99_features, | ||
| 2266 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | | ||
| 2267 | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
| 2268 | }, | ||
| 2269 | { "PowerBook3,1", "PowerBook Pismo", | ||
| 2270 | PMAC_TYPE_PISMO, core99_features, | ||
| 2271 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | | ||
| 2272 | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
| 2273 | }, | ||
| 2274 | { "PowerBook3,2", "PowerBook Titanium", | ||
| 2275 | PMAC_TYPE_TITANIUM, core99_features, | ||
| 2276 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2277 | }, | ||
| 2278 | { "PowerBook3,3", "PowerBook Titanium II", | ||
| 2279 | PMAC_TYPE_TITANIUM2, core99_features, | ||
| 2280 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2281 | }, | ||
| 2282 | { "PowerBook3,4", "PowerBook Titanium III", | ||
| 2283 | PMAC_TYPE_TITANIUM3, core99_features, | ||
| 2284 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2285 | }, | ||
| 2286 | { "PowerBook3,5", "PowerBook Titanium IV", | ||
| 2287 | PMAC_TYPE_TITANIUM4, core99_features, | ||
| 2288 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2289 | }, | ||
| 2290 | { "PowerBook4,1", "iBook 2", | ||
| 2291 | PMAC_TYPE_IBOOK2, pangea_features, | ||
| 2292 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2293 | }, | ||
| 2294 | { "PowerBook4,2", "iBook 2", | ||
| 2295 | PMAC_TYPE_IBOOK2, pangea_features, | ||
| 2296 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2297 | }, | ||
| 2298 | { "PowerBook4,3", "iBook 2 rev. 2", | ||
| 2299 | PMAC_TYPE_IBOOK2, pangea_features, | ||
| 2300 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
| 2301 | }, | ||
| 2302 | { "PowerBook5,1", "PowerBook G4 17\"", | ||
| 2303 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2304 | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2305 | }, | ||
| 2306 | { "PowerBook5,2", "PowerBook G4 15\"", | ||
| 2307 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2308 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2309 | }, | ||
| 2310 | { "PowerBook5,3", "PowerBook G4 17\"", | ||
| 2311 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2312 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2313 | }, | ||
| 2314 | { "PowerBook5,4", "PowerBook G4 15\"", | ||
| 2315 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2316 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2317 | }, | ||
| 2318 | { "PowerBook5,5", "PowerBook G4 17\"", | ||
| 2319 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2320 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2321 | }, | ||
| 2322 | { "PowerBook5,6", "PowerBook G4 15\"", | ||
| 2323 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2324 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2325 | }, | ||
| 2326 | { "PowerBook5,7", "PowerBook G4 17\"", | ||
| 2327 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2328 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2329 | }, | ||
| 2330 | { "PowerBook5,8", "PowerBook G4 15\"", | ||
| 2331 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2332 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2333 | }, | ||
| 2334 | { "PowerBook5,9", "PowerBook G4 17\"", | ||
| 2335 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2336 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2337 | }, | ||
| 2338 | { "PowerBook6,1", "PowerBook G4 12\"", | ||
| 2339 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2340 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2341 | }, | ||
| 2342 | { "PowerBook6,2", "PowerBook G4", | ||
| 2343 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2344 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2345 | }, | ||
| 2346 | { "PowerBook6,3", "iBook G4", | ||
| 2347 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2348 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2349 | }, | ||
| 2350 | { "PowerBook6,4", "PowerBook G4 12\"", | ||
| 2351 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2352 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2353 | }, | ||
| 2354 | { "PowerBook6,5", "iBook G4", | ||
| 2355 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2356 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2357 | }, | ||
| 2358 | { "PowerBook6,7", "iBook G4", | ||
| 2359 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2360 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2361 | }, | ||
| 2362 | { "PowerBook6,8", "PowerBook G4 12\"", | ||
| 2363 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
| 2364 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
| 2365 | }, | ||
| 2366 | #else /* CONFIG_POWER4 */ | ||
| 2367 | { "PowerMac7,2", "PowerMac G5", | ||
| 2368 | PMAC_TYPE_POWERMAC_G5, g5_features, | ||
| 2369 | 0, | ||
| 2370 | }, | ||
| 2371 | #endif /* CONFIG_POWER4 */ | ||
| 2372 | }; | ||
| 2373 | |||
| 2374 | /* | ||
| 2375 | * The toplevel feature_call callback | ||
| 2376 | */ | ||
| 2377 | long | ||
| 2378 | pmac_do_feature_call(unsigned int selector, ...) | ||
| 2379 | { | ||
| 2380 | struct device_node* node; | ||
| 2381 | long param, value; | ||
| 2382 | int i; | ||
| 2383 | feature_call func = NULL; | ||
| 2384 | va_list args; | ||
| 2385 | |||
| 2386 | if (pmac_mb.features) | ||
| 2387 | for (i=0; pmac_mb.features[i].function; i++) | ||
| 2388 | if (pmac_mb.features[i].selector == selector) { | ||
| 2389 | func = pmac_mb.features[i].function; | ||
| 2390 | break; | ||
| 2391 | } | ||
| 2392 | if (!func) | ||
| 2393 | for (i=0; any_features[i].function; i++) | ||
| 2394 | if (any_features[i].selector == selector) { | ||
| 2395 | func = any_features[i].function; | ||
| 2396 | break; | ||
| 2397 | } | ||
| 2398 | if (!func) | ||
| 2399 | return -ENODEV; | ||
| 2400 | |||
| 2401 | va_start(args, selector); | ||
| 2402 | node = (struct device_node*)va_arg(args, void*); | ||
| 2403 | param = va_arg(args, long); | ||
| 2404 | value = va_arg(args, long); | ||
| 2405 | va_end(args); | ||
| 2406 | |||
| 2407 | return func(node, param, value); | ||
| 2408 | } | ||
| 2409 | |||
| 2410 | static int __init | ||
| 2411 | probe_motherboard(void) | ||
| 2412 | { | ||
| 2413 | int i; | ||
| 2414 | struct macio_chip* macio = &macio_chips[0]; | ||
| 2415 | const char* model = NULL; | ||
| 2416 | struct device_node *dt; | ||
| 2417 | |||
| 2418 | /* Lookup known motherboard type in device-tree. First try an | ||
| 2419 | * exact match on the "model" property, then try a "compatible" | ||
| 2420 | * match is none is found. | ||
| 2421 | */ | ||
| 2422 | dt = find_devices("device-tree"); | ||
| 2423 | if (dt != NULL) | ||
| 2424 | model = (const char *) get_property(dt, "model", NULL); | ||
| 2425 | for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { | ||
| 2426 | if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { | ||
| 2427 | pmac_mb = pmac_mb_defs[i]; | ||
| 2428 | goto found; | ||
| 2429 | } | ||
| 2430 | } | ||
| 2431 | for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { | ||
| 2432 | if (machine_is_compatible(pmac_mb_defs[i].model_string)) { | ||
| 2433 | pmac_mb = pmac_mb_defs[i]; | ||
| 2434 | goto found; | ||
| 2435 | } | ||
| 2436 | } | ||
| 2437 | |||
| 2438 | /* Fallback to selection depending on mac-io chip type */ | ||
| 2439 | switch(macio->type) { | ||
| 2440 | #ifndef CONFIG_POWER4 | ||
| 2441 | case macio_grand_central: | ||
| 2442 | pmac_mb.model_id = PMAC_TYPE_PSURGE; | ||
| 2443 | pmac_mb.model_name = "Unknown PowerSurge"; | ||
| 2444 | break; | ||
| 2445 | case macio_ohare: | ||
| 2446 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; | ||
| 2447 | pmac_mb.model_name = "Unknown OHare-based"; | ||
| 2448 | break; | ||
| 2449 | case macio_heathrow: | ||
| 2450 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; | ||
| 2451 | pmac_mb.model_name = "Unknown Heathrow-based"; | ||
| 2452 | pmac_mb.features = heathrow_desktop_features; | ||
| 2453 | break; | ||
| 2454 | case macio_paddington: | ||
| 2455 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; | ||
| 2456 | pmac_mb.model_name = "Unknown Paddington-based"; | ||
| 2457 | pmac_mb.features = paddington_features; | ||
| 2458 | break; | ||
| 2459 | case macio_keylargo: | ||
| 2460 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; | ||
| 2461 | pmac_mb.model_name = "Unknown Keylargo-based"; | ||
| 2462 | pmac_mb.features = core99_features; | ||
| 2463 | break; | ||
| 2464 | case macio_pangea: | ||
| 2465 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; | ||
| 2466 | pmac_mb.model_name = "Unknown Pangea-based"; | ||
| 2467 | pmac_mb.features = pangea_features; | ||
| 2468 | break; | ||
| 2469 | case macio_intrepid: | ||
| 2470 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; | ||
| 2471 | pmac_mb.model_name = "Unknown Intrepid-based"; | ||
| 2472 | pmac_mb.features = intrepid_features; | ||
| 2473 | break; | ||
| 2474 | #else /* CONFIG_POWER4 */ | ||
| 2475 | case macio_keylargo2: | ||
| 2476 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; | ||
| 2477 | pmac_mb.model_name = "Unknown G5"; | ||
| 2478 | pmac_mb.features = g5_features; | ||
| 2479 | break; | ||
| 2480 | #endif /* CONFIG_POWER4 */ | ||
| 2481 | default: | ||
| 2482 | return -ENODEV; | ||
| 2483 | } | ||
| 2484 | found: | ||
| 2485 | #ifndef CONFIG_POWER4 | ||
| 2486 | /* Fixup Hooper vs. Comet */ | ||
| 2487 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { | ||
| 2488 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); | ||
| 2489 | if (!mach_id_ptr) | ||
| 2490 | return -ENODEV; | ||
| 2491 | /* Here, I used to disable the media-bay on comet. It | ||
| 2492 | * appears this is wrong, the floppy connector is actually | ||
| 2493 | * a kind of media-bay and works with the current driver. | ||
| 2494 | */ | ||
| 2495 | if (__raw_readl(mach_id_ptr) & 0x20000000UL) | ||
| 2496 | pmac_mb.model_id = PMAC_TYPE_COMET; | ||
| 2497 | iounmap(mach_id_ptr); | ||
| 2498 | } | ||
| 2499 | #endif /* CONFIG_POWER4 */ | ||
| 2500 | |||
| 2501 | #ifdef CONFIG_6xx | ||
| 2502 | /* Set default value of powersave_nap on machines that support it. | ||
| 2503 | * It appears that uninorth rev 3 has a problem with it, we don't | ||
| 2504 | * enable it on those. In theory, the flush-on-lock property is | ||
| 2505 | * supposed to be set when not supported, but I'm not very confident | ||
| 2506 | * that all Apple OF revs did it properly, I do it the paranoid way. | ||
| 2507 | */ | ||
| 2508 | while (uninorth_base && uninorth_rev > 3) { | ||
| 2509 | struct device_node* np = find_path_device("/cpus"); | ||
| 2510 | if (!np || !np->child) { | ||
| 2511 | printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); | ||
| 2512 | break; | ||
| 2513 | } | ||
| 2514 | np = np->child; | ||
| 2515 | /* Nap mode not supported on SMP */ | ||
| 2516 | if (np->sibling) | ||
| 2517 | break; | ||
| 2518 | /* Nap mode not supported if flush-on-lock property is present */ | ||
| 2519 | if (get_property(np, "flush-on-lock", NULL)) | ||
| 2520 | break; | ||
| 2521 | powersave_nap = 1; | ||
| 2522 | printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); | ||
| 2523 | break; | ||
| 2524 | } | ||
| 2525 | |||
| 2526 | /* On CPUs that support it (750FX), lowspeed by default during | ||
| 2527 | * NAP mode | ||
| 2528 | */ | ||
| 2529 | powersave_lowspeed = 1; | ||
| 2530 | #endif /* CONFIG_6xx */ | ||
| 2531 | #ifdef CONFIG_POWER4 | ||
| 2532 | powersave_nap = 1; | ||
| 2533 | #endif | ||
| 2534 | /* Check for "mobile" machine */ | ||
| 2535 | if (model && (strncmp(model, "PowerBook", 9) == 0 | ||
| 2536 | || strncmp(model, "iBook", 5) == 0)) | ||
| 2537 | pmac_mb.board_flags |= PMAC_MB_MOBILE; | ||
| 2538 | |||
| 2539 | |||
| 2540 | printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); | ||
| 2541 | return 0; | ||
| 2542 | } | ||
| 2543 | |||
| 2544 | /* Initialize the Core99 UniNorth host bridge and memory controller | ||
| 2545 | */ | ||
| 2546 | static void __init | ||
| 2547 | probe_uninorth(void) | ||
| 2548 | { | ||
| 2549 | unsigned long actrl; | ||
| 2550 | |||
| 2551 | /* Locate core99 Uni-N */ | ||
| 2552 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); | ||
| 2553 | /* Locate G5 u3 */ | ||
| 2554 | if (uninorth_node == NULL) { | ||
| 2555 | uninorth_node = of_find_node_by_name(NULL, "u3"); | ||
| 2556 | uninorth_u3 = 1; | ||
| 2557 | } | ||
| 2558 | if (uninorth_node && uninorth_node->n_addrs > 0) { | ||
| 2559 | unsigned long address = uninorth_node->addrs[0].address; | ||
| 2560 | uninorth_base = ioremap(address, 0x40000); | ||
| 2561 | uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); | ||
| 2562 | if (uninorth_u3) | ||
| 2563 | u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); | ||
| 2564 | } else | ||
| 2565 | uninorth_node = NULL; | ||
| 2566 | |||
| 2567 | if (!uninorth_node) | ||
| 2568 | return; | ||
| 2569 | |||
| 2570 | printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", | ||
| 2571 | uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); | ||
| 2572 | printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); | ||
| 2573 | |||
| 2574 | /* Set the arbitrer QAck delay according to what Apple does | ||
| 2575 | */ | ||
| 2576 | if (uninorth_rev < 0x11) { | ||
| 2577 | actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; | ||
| 2578 | actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : | ||
| 2579 | UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; | ||
| 2580 | UN_OUT(UNI_N_ARB_CTRL, actrl); | ||
| 2581 | } | ||
| 2582 | |||
| 2583 | /* Some more magic as done by them in recent MacOS X on UniNorth | ||
| 2584 | * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI | ||
| 2585 | * memory timeout | ||
| 2586 | */ | ||
| 2587 | if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) | ||
| 2588 | UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); | ||
| 2589 | } | ||
| 2590 | |||
| 2591 | static void __init | ||
| 2592 | probe_one_macio(const char* name, const char* compat, int type) | ||
| 2593 | { | ||
| 2594 | struct device_node* node; | ||
| 2595 | int i; | ||
| 2596 | volatile u32 __iomem * base; | ||
| 2597 | u32* revp; | ||
| 2598 | |||
| 2599 | node = find_devices(name); | ||
| 2600 | if (!node || !node->n_addrs) | ||
| 2601 | return; | ||
| 2602 | if (compat) | ||
| 2603 | do { | ||
| 2604 | if (device_is_compatible(node, compat)) | ||
| 2605 | break; | ||
| 2606 | node = node->next; | ||
| 2607 | } while (node); | ||
| 2608 | if (!node) | ||
| 2609 | return; | ||
| 2610 | for(i=0; i<MAX_MACIO_CHIPS; i++) { | ||
| 2611 | if (!macio_chips[i].of_node) | ||
| 2612 | break; | ||
| 2613 | if (macio_chips[i].of_node == node) | ||
| 2614 | return; | ||
| 2615 | } | ||
| 2616 | if (i >= MAX_MACIO_CHIPS) { | ||
| 2617 | printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); | ||
| 2618 | printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); | ||
| 2619 | return; | ||
| 2620 | } | ||
| 2621 | base = ioremap(node->addrs[0].address, node->addrs[0].size); | ||
| 2622 | if (!base) { | ||
| 2623 | printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); | ||
| 2624 | return; | ||
| 2625 | } | ||
| 2626 | if (type == macio_keylargo) { | ||
| 2627 | u32* did = (u32 *)get_property(node, "device-id", NULL); | ||
| 2628 | if (*did == 0x00000025) | ||
| 2629 | type = macio_pangea; | ||
| 2630 | if (*did == 0x0000003e) | ||
| 2631 | type = macio_intrepid; | ||
| 2632 | } | ||
| 2633 | macio_chips[i].of_node = node; | ||
| 2634 | macio_chips[i].type = type; | ||
| 2635 | macio_chips[i].base = base; | ||
| 2636 | macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; | ||
| 2637 | macio_chips[i].name = macio_names[type]; | ||
| 2638 | revp = (u32 *)get_property(node, "revision-id", NULL); | ||
| 2639 | if (revp) | ||
| 2640 | macio_chips[i].rev = *revp; | ||
| 2641 | printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", | ||
| 2642 | macio_names[type], macio_chips[i].rev, macio_chips[i].base); | ||
| 2643 | } | ||
| 2644 | |||
| 2645 | static int __init | ||
| 2646 | probe_macios(void) | ||
| 2647 | { | ||
| 2648 | /* Warning, ordering is important */ | ||
| 2649 | probe_one_macio("gc", NULL, macio_grand_central); | ||
| 2650 | probe_one_macio("ohare", NULL, macio_ohare); | ||
| 2651 | probe_one_macio("pci106b,7", NULL, macio_ohareII); | ||
| 2652 | probe_one_macio("mac-io", "keylargo", macio_keylargo); | ||
| 2653 | probe_one_macio("mac-io", "paddington", macio_paddington); | ||
| 2654 | probe_one_macio("mac-io", "gatwick", macio_gatwick); | ||
| 2655 | probe_one_macio("mac-io", "heathrow", macio_heathrow); | ||
| 2656 | probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); | ||
| 2657 | |||
| 2658 | /* Make sure the "main" macio chip appear first */ | ||
| 2659 | if (macio_chips[0].type == macio_gatwick | ||
| 2660 | && macio_chips[1].type == macio_heathrow) { | ||
| 2661 | struct macio_chip temp = macio_chips[0]; | ||
| 2662 | macio_chips[0] = macio_chips[1]; | ||
| 2663 | macio_chips[1] = temp; | ||
| 2664 | } | ||
| 2665 | if (macio_chips[0].type == macio_ohareII | ||
| 2666 | && macio_chips[1].type == macio_ohare) { | ||
| 2667 | struct macio_chip temp = macio_chips[0]; | ||
| 2668 | macio_chips[0] = macio_chips[1]; | ||
| 2669 | macio_chips[1] = temp; | ||
| 2670 | } | ||
| 2671 | macio_chips[0].lbus.index = 0; | ||
| 2672 | macio_chips[1].lbus.index = 1; | ||
| 2673 | |||
| 2674 | return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; | ||
| 2675 | } | ||
| 2676 | |||
| 2677 | static void __init | ||
| 2678 | initial_serial_shutdown(struct device_node* np) | ||
| 2679 | { | ||
| 2680 | int len; | ||
| 2681 | struct slot_names_prop { | ||
| 2682 | int count; | ||
| 2683 | char name[1]; | ||
| 2684 | } *slots; | ||
| 2685 | char *conn; | ||
| 2686 | int port_type = PMAC_SCC_ASYNC; | ||
| 2687 | int modem = 0; | ||
| 2688 | |||
| 2689 | slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); | ||
| 2690 | conn = get_property(np, "AAPL,connector", &len); | ||
| 2691 | if (conn && (strcmp(conn, "infrared") == 0)) | ||
| 2692 | port_type = PMAC_SCC_IRDA; | ||
| 2693 | else if (device_is_compatible(np, "cobalt")) | ||
| 2694 | modem = 1; | ||
| 2695 | else if (slots && slots->count > 0) { | ||
| 2696 | if (strcmp(slots->name, "IrDA") == 0) | ||
| 2697 | port_type = PMAC_SCC_IRDA; | ||
| 2698 | else if (strcmp(slots->name, "Modem") == 0) | ||
| 2699 | modem = 1; | ||
| 2700 | } | ||
| 2701 | if (modem) | ||
| 2702 | pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); | ||
| 2703 | pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); | ||
| 2704 | } | ||
| 2705 | |||
| 2706 | static void __init | ||
| 2707 | set_initial_features(void) | ||
| 2708 | { | ||
| 2709 | struct device_node* np; | ||
| 2710 | |||
| 2711 | /* That hack appears to be necessary for some StarMax motherboards | ||
| 2712 | * but I'm not too sure it was audited for side-effects on other | ||
| 2713 | * ohare based machines... | ||
| 2714 | * Since I still have difficulties figuring the right way to | ||
| 2715 | * differenciate them all and since that hack was there for a long | ||
| 2716 | * time, I'll keep it around | ||
| 2717 | */ | ||
| 2718 | if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { | ||
| 2719 | struct macio_chip* macio = &macio_chips[0]; | ||
| 2720 | MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); | ||
| 2721 | } else if (macio_chips[0].type == macio_ohare) { | ||
| 2722 | struct macio_chip* macio = &macio_chips[0]; | ||
| 2723 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
| 2724 | } else if (macio_chips[1].type == macio_ohare) { | ||
| 2725 | struct macio_chip* macio = &macio_chips[1]; | ||
| 2726 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
| 2727 | } | ||
| 2728 | |||
| 2729 | #ifdef CONFIG_POWER4 | ||
| 2730 | if (macio_chips[0].type == macio_keylargo2) { | ||
| 2731 | #ifndef CONFIG_SMP | ||
| 2732 | /* On SMP machines running UP, we have the second CPU eating | ||
| 2733 | * bus cycles. We need to take it off the bus. This is done | ||
| 2734 | * from pmac_smp for SMP kernels running on one CPU | ||
| 2735 | */ | ||
| 2736 | np = of_find_node_by_type(NULL, "cpu"); | ||
| 2737 | if (np != NULL) | ||
| 2738 | np = of_find_node_by_type(np, "cpu"); | ||
| 2739 | if (np != NULL) { | ||
| 2740 | g5_phy_disable_cpu1(); | ||
| 2741 | of_node_put(np); | ||
| 2742 | } | ||
| 2743 | #endif /* CONFIG_SMP */ | ||
| 2744 | /* Enable GMAC for now for PCI probing. It will be disabled | ||
| 2745 | * later on after PCI probe | ||
| 2746 | */ | ||
| 2747 | np = of_find_node_by_name(NULL, "ethernet"); | ||
| 2748 | while(np) { | ||
| 2749 | if (device_is_compatible(np, "K2-GMAC")) | ||
| 2750 | g5_gmac_enable(np, 0, 1); | ||
| 2751 | np = of_find_node_by_name(np, "ethernet"); | ||
| 2752 | } | ||
| 2753 | |||
| 2754 | /* Enable FW before PCI probe. Will be disabled later on | ||
| 2755 | * Note: We should have a batter way to check that we are | ||
| 2756 | * dealing with uninorth internal cell and not a PCI cell | ||
| 2757 | * on the external PCI. The code below works though. | ||
| 2758 | */ | ||
| 2759 | np = of_find_node_by_name(NULL, "firewire"); | ||
| 2760 | while(np) { | ||
| 2761 | if (device_is_compatible(np, "pci106b,5811")) { | ||
| 2762 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | ||
| 2763 | g5_fw_enable(np, 0, 1); | ||
| 2764 | } | ||
| 2765 | np = of_find_node_by_name(np, "firewire"); | ||
| 2766 | } | ||
| 2767 | } | ||
| 2768 | #else /* CONFIG_POWER4 */ | ||
| 2769 | |||
| 2770 | if (macio_chips[0].type == macio_keylargo || | ||
| 2771 | macio_chips[0].type == macio_pangea || | ||
| 2772 | macio_chips[0].type == macio_intrepid) { | ||
| 2773 | /* Enable GMAC for now for PCI probing. It will be disabled | ||
| 2774 | * later on after PCI probe | ||
| 2775 | */ | ||
| 2776 | np = of_find_node_by_name(NULL, "ethernet"); | ||
| 2777 | while(np) { | ||
| 2778 | if (np->parent | ||
| 2779 | && device_is_compatible(np->parent, "uni-north") | ||
| 2780 | && device_is_compatible(np, "gmac")) | ||
| 2781 | core99_gmac_enable(np, 0, 1); | ||
| 2782 | np = of_find_node_by_name(np, "ethernet"); | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | /* Enable FW before PCI probe. Will be disabled later on | ||
| 2786 | * Note: We should have a batter way to check that we are | ||
| 2787 | * dealing with uninorth internal cell and not a PCI cell | ||
| 2788 | * on the external PCI. The code below works though. | ||
| 2789 | */ | ||
| 2790 | np = of_find_node_by_name(NULL, "firewire"); | ||
| 2791 | while(np) { | ||
| 2792 | if (np->parent | ||
| 2793 | && device_is_compatible(np->parent, "uni-north") | ||
| 2794 | && (device_is_compatible(np, "pci106b,18") || | ||
| 2795 | device_is_compatible(np, "pci106b,30") || | ||
| 2796 | device_is_compatible(np, "pci11c1,5811"))) { | ||
| 2797 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | ||
| 2798 | core99_firewire_enable(np, 0, 1); | ||
| 2799 | } | ||
| 2800 | np = of_find_node_by_name(np, "firewire"); | ||
| 2801 | } | ||
| 2802 | |||
| 2803 | /* Enable ATA-100 before PCI probe. */ | ||
| 2804 | np = of_find_node_by_name(NULL, "ata-6"); | ||
| 2805 | while(np) { | ||
| 2806 | if (np->parent | ||
| 2807 | && device_is_compatible(np->parent, "uni-north") | ||
| 2808 | && device_is_compatible(np, "kauai-ata")) { | ||
| 2809 | core99_ata100_enable(np, 1); | ||
| 2810 | } | ||
| 2811 | np = of_find_node_by_name(np, "ata-6"); | ||
| 2812 | } | ||
| 2813 | |||
| 2814 | /* Switch airport off */ | ||
| 2815 | np = find_devices("radio"); | ||
| 2816 | while(np) { | ||
| 2817 | if (np && np->parent == macio_chips[0].of_node) { | ||
| 2818 | macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; | ||
| 2819 | core99_airport_enable(np, 0, 0); | ||
| 2820 | } | ||
| 2821 | np = np->next; | ||
| 2822 | } | ||
| 2823 | } | ||
| 2824 | |||
| 2825 | /* On all machines that support sound PM, switch sound off */ | ||
| 2826 | if (macio_chips[0].of_node) | ||
| 2827 | pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, | ||
| 2828 | macio_chips[0].of_node, 0, 0); | ||
| 2829 | |||
| 2830 | /* While on some desktop G3s, we turn it back on */ | ||
| 2831 | if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow | ||
| 2832 | && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || | ||
| 2833 | pmac_mb.model_id == PMAC_TYPE_SILK)) { | ||
| 2834 | struct macio_chip* macio = &macio_chips[0]; | ||
| 2835 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
| 2836 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
| 2837 | } | ||
| 2838 | |||
| 2839 | /* Some machine models need the clock chip to be properly setup for | ||
| 2840 | * clock spreading now. This should be a platform function but we | ||
| 2841 | * don't do these at the moment | ||
| 2842 | */ | ||
| 2843 | pmac_tweak_clock_spreading(1); | ||
| 2844 | |||
| 2845 | #endif /* CONFIG_POWER4 */ | ||
| 2846 | |||
| 2847 | /* On all machines, switch modem & serial ports off */ | ||
| 2848 | np = find_devices("ch-a"); | ||
| 2849 | while(np) { | ||
| 2850 | initial_serial_shutdown(np); | ||
| 2851 | np = np->next; | ||
| 2852 | } | ||
| 2853 | np = find_devices("ch-b"); | ||
| 2854 | while(np) { | ||
| 2855 | initial_serial_shutdown(np); | ||
| 2856 | np = np->next; | ||
| 2857 | } | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | void __init | ||
| 2861 | pmac_feature_init(void) | ||
| 2862 | { | ||
| 2863 | /* Detect the UniNorth memory controller */ | ||
| 2864 | probe_uninorth(); | ||
| 2865 | |||
| 2866 | /* Probe mac-io controllers */ | ||
| 2867 | if (probe_macios()) { | ||
| 2868 | printk(KERN_WARNING "No mac-io chip found\n"); | ||
| 2869 | return; | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | /* Setup low-level i2c stuffs */ | ||
| 2873 | pmac_init_low_i2c(); | ||
| 2874 | |||
| 2875 | /* Probe machine type */ | ||
| 2876 | if (probe_motherboard()) | ||
| 2877 | printk(KERN_WARNING "Unknown PowerMac !\n"); | ||
| 2878 | |||
| 2879 | /* Set some initial features (turn off some chips that will | ||
| 2880 | * be later turned on) | ||
| 2881 | */ | ||
| 2882 | set_initial_features(); | ||
| 2883 | } | ||
| 2884 | |||
| 2885 | int __init | ||
| 2886 | pmac_feature_late_init(void) | ||
| 2887 | { | ||
| 2888 | struct device_node* np; | ||
| 2889 | |||
| 2890 | /* Request some resources late */ | ||
| 2891 | if (uninorth_node) | ||
| 2892 | request_OF_resource(uninorth_node, 0, NULL); | ||
| 2893 | np = find_devices("hammerhead"); | ||
| 2894 | if (np) | ||
| 2895 | request_OF_resource(np, 0, NULL); | ||
| 2896 | np = find_devices("interrupt-controller"); | ||
| 2897 | if (np) | ||
| 2898 | request_OF_resource(np, 0, NULL); | ||
| 2899 | return 0; | ||
| 2900 | } | ||
| 2901 | |||
| 2902 | device_initcall(pmac_feature_late_init); | ||
| 2903 | |||
| 2904 | #ifdef CONFIG_POWER4 | ||
| 2905 | |||
| 2906 | static void dump_HT_speeds(char *name, u32 cfg, u32 frq) | ||
| 2907 | { | ||
| 2908 | int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; | ||
| 2909 | int bits[8] = { 8,16,0,32,2,4,0,0 }; | ||
| 2910 | int freq = (frq >> 8) & 0xf; | ||
| 2911 | |||
| 2912 | if (freqs[freq] == 0) | ||
| 2913 | printk("%s: Unknown HT link frequency %x\n", name, freq); | ||
| 2914 | else | ||
| 2915 | printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", | ||
| 2916 | name, freqs[freq], | ||
| 2917 | bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | void __init pmac_check_ht_link(void) | ||
| 2921 | { | ||
| 2922 | u32 ufreq, freq, ucfg, cfg; | ||
| 2923 | struct device_node *pcix_node; | ||
| 2924 | u8 px_bus, px_devfn; | ||
| 2925 | struct pci_controller *px_hose; | ||
| 2926 | |||
| 2927 | (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); | ||
| 2928 | ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); | ||
| 2929 | ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); | ||
| 2930 | dump_HT_speeds("U3 HyperTransport", cfg, freq); | ||
| 2931 | |||
| 2932 | pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); | ||
| 2933 | if (pcix_node == NULL) { | ||
| 2934 | printk("No PCI-X bridge found\n"); | ||
| 2935 | return; | ||
| 2936 | } | ||
| 2937 | if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { | ||
| 2938 | printk("PCI-X bridge found but not matched to pci\n"); | ||
| 2939 | return; | ||
| 2940 | } | ||
| 2941 | px_hose = pci_find_hose_for_OF_device(pcix_node); | ||
| 2942 | if (px_hose == NULL) { | ||
| 2943 | printk("PCI-X bridge found but not matched to host\n"); | ||
| 2944 | return; | ||
| 2945 | } | ||
| 2946 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); | ||
| 2947 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); | ||
| 2948 | dump_HT_speeds("PCI-X HT Uplink", cfg, freq); | ||
| 2949 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); | ||
| 2950 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); | ||
| 2951 | dump_HT_speeds("PCI-X HT Downlink", cfg, freq); | ||
| 2952 | } | ||
| 2953 | |||
| 2954 | #endif /* CONFIG_POWER4 */ | ||
| 2955 | |||
| 2956 | /* | ||
| 2957 | * Early video resume hook | ||
| 2958 | */ | ||
| 2959 | |||
| 2960 | static void (*pmac_early_vresume_proc)(void *data); | ||
| 2961 | static void *pmac_early_vresume_data; | ||
| 2962 | |||
| 2963 | void pmac_set_early_video_resume(void (*proc)(void *data), void *data) | ||
| 2964 | { | ||
| 2965 | if (_machine != _MACH_Pmac) | ||
| 2966 | return; | ||
| 2967 | preempt_disable(); | ||
| 2968 | pmac_early_vresume_proc = proc; | ||
| 2969 | pmac_early_vresume_data = data; | ||
| 2970 | preempt_enable(); | ||
| 2971 | } | ||
| 2972 | EXPORT_SYMBOL(pmac_set_early_video_resume); | ||
| 2973 | |||
| 2974 | void pmac_call_early_video_resume(void) | ||
| 2975 | { | ||
| 2976 | if (pmac_early_vresume_proc) | ||
| 2977 | pmac_early_vresume_proc(pmac_early_vresume_data); | ||
| 2978 | } | ||
| 2979 | |||
| 2980 | /* | ||
| 2981 | * AGP related suspend/resume code | ||
| 2982 | */ | ||
| 2983 | |||
| 2984 | static struct pci_dev *pmac_agp_bridge; | ||
| 2985 | static int (*pmac_agp_suspend)(struct pci_dev *bridge); | ||
| 2986 | static int (*pmac_agp_resume)(struct pci_dev *bridge); | ||
| 2987 | |||
| 2988 | void pmac_register_agp_pm(struct pci_dev *bridge, | ||
| 2989 | int (*suspend)(struct pci_dev *bridge), | ||
| 2990 | int (*resume)(struct pci_dev *bridge)) | ||
| 2991 | { | ||
| 2992 | if (suspend || resume) { | ||
| 2993 | pmac_agp_bridge = bridge; | ||
| 2994 | pmac_agp_suspend = suspend; | ||
| 2995 | pmac_agp_resume = resume; | ||
| 2996 | return; | ||
| 2997 | } | ||
| 2998 | if (bridge != pmac_agp_bridge) | ||
| 2999 | return; | ||
| 3000 | pmac_agp_suspend = pmac_agp_resume = NULL; | ||
| 3001 | return; | ||
| 3002 | } | ||
| 3003 | EXPORT_SYMBOL(pmac_register_agp_pm); | ||
| 3004 | |||
| 3005 | void pmac_suspend_agp_for_card(struct pci_dev *dev) | ||
| 3006 | { | ||
| 3007 | if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) | ||
| 3008 | return; | ||
| 3009 | if (pmac_agp_bridge->bus != dev->bus) | ||
| 3010 | return; | ||
| 3011 | pmac_agp_suspend(pmac_agp_bridge); | ||
| 3012 | } | ||
| 3013 | EXPORT_SYMBOL(pmac_suspend_agp_for_card); | ||
| 3014 | |||
| 3015 | void pmac_resume_agp_for_card(struct pci_dev *dev) | ||
| 3016 | { | ||
| 3017 | if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) | ||
| 3018 | return; | ||
| 3019 | if (pmac_agp_bridge->bus != dev->bus) | ||
| 3020 | return; | ||
| 3021 | pmac_agp_resume(pmac_agp_bridge); | ||
| 3022 | } | ||
| 3023 | EXPORT_SYMBOL(pmac_resume_agp_for_card); | ||
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c deleted file mode 100644 index 08583fce1692..000000000000 --- a/arch/ppc/platforms/pmac_low_i2c.c +++ /dev/null  | |||
| @@ -1,511 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/ppc/platforms/pmac_low_i2c.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This file contains some low-level i2c access routines that | ||
| 12 | * need to be used by various bits of the PowerMac platform code | ||
| 13 | * at times where the real asynchronous & interrupt driven driver | ||
| 14 | * cannot be used. The API borrows some semantics from the darwin | ||
| 15 | * driver in order to ease the implementation of the platform | ||
| 16 | * properties parser | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/config.h> | ||
| 20 | #include <linux/types.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/sched.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/adb.h> | ||
| 26 | #include <linux/pmu.h> | ||
| 27 | #include <asm/keylargo.h> | ||
| 28 | #include <asm/uninorth.h> | ||
| 29 | #include <asm/io.h> | ||
| 30 | #include <asm/prom.h> | ||
| 31 | #include <asm/machdep.h> | ||
| 32 | #include <asm/pmac_low_i2c.h> | ||
| 33 | |||
| 34 | #define MAX_LOW_I2C_HOST 4 | ||
| 35 | |||
| 36 | #if 1 | ||
| 37 | #define DBG(x...) do {\ | ||
| 38 | printk(KERN_DEBUG "KW:" x); \ | ||
| 39 | } while(0) | ||
| 40 | #else | ||
| 41 | #define DBGG(x...) | ||
| 42 | #endif | ||
| 43 | |||
| 44 | struct low_i2c_host; | ||
| 45 | |||
| 46 | typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); | ||
| 47 | |||
| 48 | struct low_i2c_host | ||
| 49 | { | ||
| 50 | struct device_node *np; /* OF device node */ | ||
| 51 | struct semaphore mutex; /* Access mutex for use by i2c-keywest */ | ||
| 52 | low_i2c_func_t func; /* Access function */ | ||
| 53 | int is_open : 1; /* Poor man's access control */ | ||
| 54 | int mode; /* Current mode */ | ||
| 55 | int channel; /* Current channel */ | ||
| 56 | int num_channels; /* Number of channels */ | ||
| 57 | void __iomem * base; /* For keywest-i2c, base address */ | ||
| 58 | int bsteps; /* And register stepping */ | ||
| 59 | int speed; /* And speed */ | ||
| 60 | }; | ||
| 61 | |||
| 62 | static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; | ||
| 63 | |||
| 64 | /* No locking is necessary on allocation, we are running way before | ||
| 65 | * anything can race with us | ||
| 66 | */ | ||
| 67 | static struct low_i2c_host *find_low_i2c_host(struct device_node *np) | ||
| 68 | { | ||
| 69 | int i; | ||
| 70 | |||
| 71 | for (i = 0; i < MAX_LOW_I2C_HOST; i++) | ||
| 72 | if (low_i2c_hosts[i].np == np) | ||
| 73 | return &low_i2c_hosts[i]; | ||
| 74 | return NULL; | ||
| 75 | } | ||
| 76 | |||
| 77 | /* | ||
| 78 | * | ||
| 79 | * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) | ||
| 80 | * | ||
| 81 | */ | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, | ||
| 85 | * should be moved somewhere in include/asm-ppc/ | ||
| 86 | */ | ||
| 87 | /* Register indices */ | ||
| 88 | typedef enum { | ||
| 89 | reg_mode = 0, | ||
| 90 | reg_control, | ||
| 91 | reg_status, | ||
| 92 | reg_isr, | ||
| 93 | reg_ier, | ||
| 94 | reg_addr, | ||
| 95 | reg_subaddr, | ||
| 96 | reg_data | ||
| 97 | } reg_t; | ||
| 98 | |||
| 99 | |||
| 100 | /* Mode register */ | ||
| 101 | #define KW_I2C_MODE_100KHZ 0x00 | ||
| 102 | #define KW_I2C_MODE_50KHZ 0x01 | ||
| 103 | #define KW_I2C_MODE_25KHZ 0x02 | ||
| 104 | #define KW_I2C_MODE_DUMB 0x00 | ||
| 105 | #define KW_I2C_MODE_STANDARD 0x04 | ||
| 106 | #define KW_I2C_MODE_STANDARDSUB 0x08 | ||
| 107 | #define KW_I2C_MODE_COMBINED 0x0C | ||
| 108 | #define KW_I2C_MODE_MODE_MASK 0x0C | ||
| 109 | #define KW_I2C_MODE_CHAN_MASK 0xF0 | ||
| 110 | |||
| 111 | /* Control register */ | ||
| 112 | #define KW_I2C_CTL_AAK 0x01 | ||
| 113 | #define KW_I2C_CTL_XADDR 0x02 | ||
| 114 | #define KW_I2C_CTL_STOP 0x04 | ||
| 115 | #define KW_I2C_CTL_START 0x08 | ||
| 116 | |||
| 117 | /* Status register */ | ||
| 118 | #define KW_I2C_STAT_BUSY 0x01 | ||
| 119 | #define KW_I2C_STAT_LAST_AAK 0x02 | ||
| 120 | #define KW_I2C_STAT_LAST_RW 0x04 | ||
| 121 | #define KW_I2C_STAT_SDA 0x08 | ||
| 122 | #define KW_I2C_STAT_SCL 0x10 | ||
| 123 | |||
| 124 | /* IER & ISR registers */ | ||
| 125 | #define KW_I2C_IRQ_DATA 0x01 | ||
| 126 | #define KW_I2C_IRQ_ADDR 0x02 | ||
| 127 | #define KW_I2C_IRQ_STOP 0x04 | ||
| 128 | #define KW_I2C_IRQ_START 0x08 | ||
| 129 | #define KW_I2C_IRQ_MASK 0x0F | ||
| 130 | |||
| 131 | /* State machine states */ | ||
| 132 | enum { | ||
| 133 | state_idle, | ||
| 134 | state_addr, | ||
| 135 | state_read, | ||
| 136 | state_write, | ||
| 137 | state_stop, | ||
| 138 | state_dead | ||
| 139 | }; | ||
| 140 | |||
| 141 | #define WRONG_STATE(name) do {\ | ||
| 142 | printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ | ||
| 143 | name, __kw_state_names[state], isr); \ | ||
| 144 | } while(0) | ||
| 145 | |||
| 146 | static const char *__kw_state_names[] = { | ||
| 147 | "state_idle", | ||
| 148 | "state_addr", | ||
| 149 | "state_read", | ||
| 150 | "state_write", | ||
| 151 | "state_stop", | ||
| 152 | "state_dead" | ||
| 153 | }; | ||
| 154 | |||
| 155 | static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) | ||
| 156 | { | ||
| 157 | return in_8(host->base + (((unsigned)reg) << host->bsteps)); | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) | ||
| 161 | { | ||
| 162 | out_8(host->base + (((unsigned)reg) << host->bsteps), val); | ||
| 163 | (void)__kw_read_reg(host, reg_subaddr); | ||
| 164 | } | ||
| 165 | |||
| 166 | #define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) | ||
| 167 | #define kw_read_reg(reg) __kw_read_reg(host, reg) | ||
| 168 | |||
| 169 | |||
| 170 | /* Don't schedule, the g5 fan controller is too | ||
| 171 | * timing sensitive | ||
| 172 | */ | ||
| 173 | static u8 kw_wait_interrupt(struct low_i2c_host* host) | ||
| 174 | { | ||
| 175 | int i; | ||
| 176 | u8 isr; | ||
| 177 | |||
| 178 | for (i = 0; i < 200000; i++) { | ||
| 179 | isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; | ||
| 180 | if (isr != 0) | ||
| 181 | return isr; | ||
| 182 | udelay(1); | ||
| 183 | } | ||
| 184 | return isr; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) | ||
| 188 | { | ||
| 189 | u8 ack; | ||
| 190 | |||
| 191 | if (isr == 0) { | ||
| 192 | if (state != state_stop) { | ||
| 193 | DBG("KW: Timeout !\n"); | ||
| 194 | *rc = -EIO; | ||
| 195 | goto stop; | ||
| 196 | } | ||
| 197 | if (state == state_stop) { | ||
| 198 | ack = kw_read_reg(reg_status); | ||
| 199 | if (!(ack & KW_I2C_STAT_BUSY)) { | ||
| 200 | state = state_idle; | ||
| 201 | kw_write_reg(reg_ier, 0x00); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | return state; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (isr & KW_I2C_IRQ_ADDR) { | ||
| 208 | ack = kw_read_reg(reg_status); | ||
| 209 | if (state != state_addr) { | ||
| 210 | kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
| 211 | WRONG_STATE("KW_I2C_IRQ_ADDR"); | ||
| 212 | *rc = -EIO; | ||
| 213 | goto stop; | ||
| 214 | } | ||
| 215 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
| 216 | *rc = -ENODEV; | ||
| 217 | DBG("KW: NAK on address\n"); | ||
| 218 | return state_stop; | ||
| 219 | } else { | ||
| 220 | if (rw) { | ||
| 221 | state = state_read; | ||
| 222 | if (*len > 1) | ||
| 223 | kw_write_reg(reg_control, KW_I2C_CTL_AAK); | ||
| 224 | } else { | ||
| 225 | state = state_write; | ||
| 226 | kw_write_reg(reg_data, **data); | ||
| 227 | (*data)++; (*len)--; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
| 231 | } | ||
| 232 | |||
| 233 | if (isr & KW_I2C_IRQ_DATA) { | ||
| 234 | if (state == state_read) { | ||
| 235 | **data = kw_read_reg(reg_data); | ||
| 236 | (*data)++; (*len)--; | ||
| 237 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
| 238 | if ((*len) == 0) | ||
| 239 | state = state_stop; | ||
| 240 | else if ((*len) == 1) | ||
| 241 | kw_write_reg(reg_control, 0); | ||
| 242 | } else if (state == state_write) { | ||
| 243 | ack = kw_read_reg(reg_status); | ||
| 244 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
| 245 | DBG("KW: nack on data write\n"); | ||
| 246 | *rc = -EIO; | ||
| 247 | goto stop; | ||
| 248 | } else if (*len) { | ||
| 249 | kw_write_reg(reg_data, **data); | ||
| 250 | (*data)++; (*len)--; | ||
| 251 | } else { | ||
| 252 | kw_write_reg(reg_control, KW_I2C_CTL_STOP); | ||
| 253 | state = state_stop; | ||
| 254 | *rc = 0; | ||
| 255 | } | ||
| 256 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
| 257 | } else { | ||
| 258 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
| 259 | WRONG_STATE("KW_I2C_IRQ_DATA"); | ||
| 260 | if (state != state_stop) { | ||
| 261 | *rc = -EIO; | ||
| 262 | goto stop; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | if (isr & KW_I2C_IRQ_STOP) { | ||
| 268 | kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); | ||
| 269 | if (state != state_stop) { | ||
| 270 | WRONG_STATE("KW_I2C_IRQ_STOP"); | ||
| 271 | *rc = -EIO; | ||
| 272 | } | ||
| 273 | return state_idle; | ||
| 274 | } | ||
| 275 | |||
| 276 | if (isr & KW_I2C_IRQ_START) | ||
| 277 | kw_write_reg(reg_isr, KW_I2C_IRQ_START); | ||
| 278 | |||
| 279 | return state; | ||
| 280 | |||
| 281 | stop: | ||
| 282 | kw_write_reg(reg_control, KW_I2C_CTL_STOP); | ||
| 283 | return state_stop; | ||
| 284 | } | ||
| 285 | |||
| 286 | static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) | ||
| 287 | { | ||
| 288 | u8 mode_reg = host->speed; | ||
| 289 | int state = state_addr; | ||
| 290 | int rc = 0; | ||
| 291 | |||
| 292 | /* Setup mode & subaddress if any */ | ||
| 293 | switch(host->mode) { | ||
| 294 | case pmac_low_i2c_mode_dumb: | ||
| 295 | printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); | ||
| 296 | return -EINVAL; | ||
| 297 | case pmac_low_i2c_mode_std: | ||
| 298 | mode_reg |= KW_I2C_MODE_STANDARD; | ||
| 299 | break; | ||
| 300 | case pmac_low_i2c_mode_stdsub: | ||
| 301 | mode_reg |= KW_I2C_MODE_STANDARDSUB; | ||
| 302 | kw_write_reg(reg_subaddr, subaddr); | ||
| 303 | break; | ||
| 304 | case pmac_low_i2c_mode_combined: | ||
| 305 | mode_reg |= KW_I2C_MODE_COMBINED; | ||
| 306 | kw_write_reg(reg_subaddr, subaddr); | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* Setup channel & clear pending irqs */ | ||
| 311 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); | ||
| 312 | kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); | ||
| 313 | kw_write_reg(reg_status, 0); | ||
| 314 | |||
| 315 | /* Set up address and r/w bit */ | ||
| 316 | kw_write_reg(reg_addr, addr); | ||
| 317 | |||
| 318 | /* Start sending address & disable interrupt*/ | ||
| 319 | kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); | ||
| 320 | kw_write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
| 321 | |||
| 322 | /* State machine, to turn into an interrupt handler */ | ||
| 323 | while(state != state_idle) { | ||
| 324 | u8 isr = kw_wait_interrupt(host); | ||
| 325 | state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); | ||
| 326 | } | ||
| 327 | |||
| 328 | return rc; | ||
| 329 | } | ||
| 330 | |||
| 331 | static void keywest_low_i2c_add(struct device_node *np) | ||
| 332 | { | ||
| 333 | struct low_i2c_host *host = find_low_i2c_host(NULL); | ||
| 334 | unsigned long *psteps, *prate, steps, aoffset = 0; | ||
| 335 | struct device_node *parent; | ||
| 336 | |||
| 337 | if (host == NULL) { | ||
| 338 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | ||
| 339 | np->full_name); | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | memset(host, 0, sizeof(*host)); | ||
| 343 | |||
| 344 | init_MUTEX(&host->mutex); | ||
| 345 | host->np = of_node_get(np); | ||
| 346 | psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); | ||
| 347 | steps = psteps ? (*psteps) : 0x10; | ||
| 348 | for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) | ||
| 349 | steps >>= 1; | ||
| 350 | parent = of_get_parent(np); | ||
| 351 | host->num_channels = 1; | ||
| 352 | if (parent && parent->name[0] == 'u') { | ||
| 353 | host->num_channels = 2; | ||
| 354 | aoffset = 3; | ||
| 355 | } | ||
| 356 | /* Select interface rate */ | ||
| 357 | host->speed = KW_I2C_MODE_100KHZ; | ||
| 358 | prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); | ||
| 359 | if (prate) switch(*prate) { | ||
| 360 | case 100: | ||
| 361 | host->speed = KW_I2C_MODE_100KHZ; | ||
| 362 | break; | ||
| 363 | case 50: | ||
| 364 | host->speed = KW_I2C_MODE_50KHZ; | ||
| 365 | break; | ||
| 366 | case 25: | ||
| 367 | host->speed = KW_I2C_MODE_25KHZ; | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | host->mode = pmac_low_i2c_mode_std; | ||
| 371 | host->base = ioremap(np->addrs[0].address + aoffset, | ||
| 372 | np->addrs[0].size); | ||
| 373 | host->func = keywest_low_i2c_func; | ||
| 374 | } | ||
| 375 | |||
| 376 | /* | ||
| 377 | * | ||
| 378 | * PMU implementation | ||
| 379 | * | ||
| 380 | */ | ||
| 381 | |||
| 382 | |||
| 383 | #ifdef CONFIG_ADB_PMU | ||
| 384 | |||
| 385 | static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) | ||
| 386 | { | ||
| 387 | // TODO | ||
| 388 | return -ENODEV; | ||
| 389 | } | ||
| 390 | |||
| 391 | static void pmu_low_i2c_add(struct device_node *np) | ||
| 392 | { | ||
| 393 | struct low_i2c_host *host = find_low_i2c_host(NULL); | ||
| 394 | |||
| 395 | if (host == NULL) { | ||
| 396 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | ||
| 397 | np->full_name); | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | memset(host, 0, sizeof(*host)); | ||
| 401 | |||
| 402 | init_MUTEX(&host->mutex); | ||
| 403 | host->np = of_node_get(np); | ||
| 404 | host->num_channels = 3; | ||
| 405 | host->mode = pmac_low_i2c_mode_std; | ||
| 406 | host->func = pmu_low_i2c_func; | ||
| 407 | } | ||
| 408 | |||
| 409 | #endif /* CONFIG_ADB_PMU */ | ||
| 410 | |||
| 411 | void __init pmac_init_low_i2c(void) | ||
| 412 | { | ||
| 413 | struct device_node *np; | ||
| 414 | |||
| 415 | /* Probe keywest-i2c busses */ | ||
| 416 | np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); | ||
| 417 | while(np) { | ||
| 418 | keywest_low_i2c_add(np); | ||
| 419 | np = of_find_compatible_node(np, "i2c", "keywest-i2c"); | ||
| 420 | } | ||
| 421 | |||
| 422 | #ifdef CONFIG_ADB_PMU | ||
| 423 | /* Probe PMU busses */ | ||
| 424 | np = of_find_node_by_name(NULL, "via-pmu"); | ||
| 425 | if (np) | ||
| 426 | pmu_low_i2c_add(np); | ||
| 427 | #endif /* CONFIG_ADB_PMU */ | ||
| 428 | |||
| 429 | /* TODO: Add CUDA support as well */ | ||
| 430 | } | ||
| 431 | |||
| 432 | int pmac_low_i2c_lock(struct device_node *np) | ||
| 433 | { | ||
| 434 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 435 | |||
| 436 | if (!host) | ||
| 437 | return -ENODEV; | ||
| 438 | down(&host->mutex); | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | EXPORT_SYMBOL(pmac_low_i2c_lock); | ||
| 442 | |||
| 443 | int pmac_low_i2c_unlock(struct device_node *np) | ||
| 444 | { | ||
| 445 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 446 | |||
| 447 | if (!host) | ||
| 448 | return -ENODEV; | ||
| 449 | up(&host->mutex); | ||
| 450 | return 0; | ||
| 451 | } | ||
| 452 | EXPORT_SYMBOL(pmac_low_i2c_unlock); | ||
| 453 | |||
| 454 | |||
| 455 | int pmac_low_i2c_open(struct device_node *np, int channel) | ||
| 456 | { | ||
| 457 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 458 | |||
| 459 | if (!host) | ||
| 460 | return -ENODEV; | ||
| 461 | |||
| 462 | if (channel >= host->num_channels) | ||
| 463 | return -EINVAL; | ||
| 464 | |||
| 465 | down(&host->mutex); | ||
| 466 | host->is_open = 1; | ||
| 467 | host->channel = channel; | ||
| 468 | |||
| 469 | return 0; | ||
| 470 | } | ||
| 471 | EXPORT_SYMBOL(pmac_low_i2c_open); | ||
| 472 | |||
| 473 | int pmac_low_i2c_close(struct device_node *np) | ||
| 474 | { | ||
| 475 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 476 | |||
| 477 | if (!host) | ||
| 478 | return -ENODEV; | ||
| 479 | |||
| 480 | host->is_open = 0; | ||
| 481 | up(&host->mutex); | ||
| 482 | |||
| 483 | return 0; | ||
| 484 | } | ||
| 485 | EXPORT_SYMBOL(pmac_low_i2c_close); | ||
| 486 | |||
| 487 | int pmac_low_i2c_setmode(struct device_node *np, int mode) | ||
| 488 | { | ||
| 489 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 490 | |||
| 491 | if (!host) | ||
| 492 | return -ENODEV; | ||
| 493 | WARN_ON(!host->is_open); | ||
| 494 | host->mode = mode; | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | EXPORT_SYMBOL(pmac_low_i2c_setmode); | ||
| 499 | |||
| 500 | int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) | ||
| 501 | { | ||
| 502 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
| 503 | |||
| 504 | if (!host) | ||
| 505 | return -ENODEV; | ||
| 506 | WARN_ON(!host->is_open); | ||
| 507 | |||
| 508 | return host->func(host, addrdir, subaddr, data, len); | ||
| 509 | } | ||
| 510 | EXPORT_SYMBOL(pmac_low_i2c_xfer); | ||
| 511 | |||
diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c deleted file mode 100644 index 8c9b008c7226..000000000000 --- a/arch/ppc/platforms/pmac_nvram.c +++ /dev/null  | |||
| @@ -1,584 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/ppc/platforms/pmac_nvram.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * Todo: - add support for the OF persistent properties | ||
| 12 | */ | ||
| 13 | #include <linux/config.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/stddef.h> | ||
| 17 | #include <linux/string.h> | ||
| 18 | #include <linux/nvram.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/adb.h> | ||
| 24 | #include <linux/pmu.h> | ||
| 25 | #include <linux/bootmem.h> | ||
| 26 | #include <linux/completion.h> | ||
| 27 | #include <linux/spinlock.h> | ||
| 28 | #include <asm/sections.h> | ||
| 29 | #include <asm/io.h> | ||
| 30 | #include <asm/system.h> | ||
| 31 | #include <asm/prom.h> | ||
| 32 | #include <asm/machdep.h> | ||
| 33 | #include <asm/nvram.h> | ||
| 34 | |||
| 35 | #define DEBUG | ||
| 36 | |||
| 37 | #ifdef DEBUG | ||
| 38 | #define DBG(x...) printk(x) | ||
| 39 | #else | ||
| 40 | #define DBG(x...) | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ | ||
| 44 | |||
| 45 | #define CORE99_SIGNATURE 0x5a | ||
| 46 | #define CORE99_ADLER_START 0x14 | ||
| 47 | |||
| 48 | /* On Core99, nvram is either a sharp, a micron or an AMD flash */ | ||
| 49 | #define SM_FLASH_STATUS_DONE 0x80 | ||
| 50 | #define SM_FLASH_STATUS_ERR 0x38 | ||
| 51 | #define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 | ||
| 52 | #define SM_FLASH_CMD_ERASE_SETUP 0x20 | ||
| 53 | #define SM_FLASH_CMD_RESET 0xff | ||
| 54 | #define SM_FLASH_CMD_WRITE_SETUP 0x40 | ||
| 55 | #define SM_FLASH_CMD_CLEAR_STATUS 0x50 | ||
| 56 | #define SM_FLASH_CMD_READ_STATUS 0x70 | ||
| 57 | |||
| 58 | /* CHRP NVRAM header */ | ||
| 59 | struct chrp_header { | ||
| 60 | u8 signature; | ||
| 61 | u8 cksum; | ||
| 62 | u16 len; | ||
| 63 | char name[12]; | ||
| 64 | u8 data[0]; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct core99_header { | ||
| 68 | struct chrp_header hdr; | ||
| 69 | u32 adler; | ||
| 70 | u32 generation; | ||
| 71 | u32 reserved[2]; | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * Read and write the non-volatile RAM on PowerMacs and CHRP machines. | ||
| 76 | */ | ||
| 77 | static int nvram_naddrs; | ||
| 78 | static volatile unsigned char *nvram_addr; | ||
| 79 | static volatile unsigned char *nvram_data; | ||
| 80 | static int nvram_mult, is_core_99; | ||
| 81 | static int core99_bank = 0; | ||
| 82 | static int nvram_partitions[3]; | ||
| 83 | static DEFINE_SPINLOCK(nv_lock); | ||
| 84 | |||
| 85 | extern int pmac_newworld; | ||
| 86 | extern int system_running; | ||
| 87 | |||
| 88 | static int (*core99_write_bank)(int bank, u8* datas); | ||
| 89 | static int (*core99_erase_bank)(int bank); | ||
| 90 | |||
| 91 | static char *nvram_image; | ||
| 92 | |||
| 93 | |||
| 94 | static unsigned char core99_nvram_read_byte(int addr) | ||
| 95 | { | ||
| 96 | if (nvram_image == NULL) | ||
| 97 | return 0xff; | ||
| 98 | return nvram_image[addr]; | ||
| 99 | } | ||
| 100 | |||
| 101 | static void core99_nvram_write_byte(int addr, unsigned char val) | ||
| 102 | { | ||
| 103 | if (nvram_image == NULL) | ||
| 104 | return; | ||
| 105 | nvram_image[addr] = val; | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | static unsigned char direct_nvram_read_byte(int addr) | ||
| 110 | { | ||
| 111 | return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void direct_nvram_write_byte(int addr, unsigned char val) | ||
| 115 | { | ||
| 116 | out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | static unsigned char indirect_nvram_read_byte(int addr) | ||
| 121 | { | ||
| 122 | unsigned char val; | ||
| 123 | unsigned long flags; | ||
| 124 | |||
| 125 | spin_lock_irqsave(&nv_lock, flags); | ||
| 126 | out_8(nvram_addr, addr >> 5); | ||
| 127 | val = in_8(&nvram_data[(addr & 0x1f) << 4]); | ||
| 128 | spin_unlock_irqrestore(&nv_lock, flags); | ||
| 129 | |||
| 130 | return val; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void indirect_nvram_write_byte(int addr, unsigned char val) | ||
| 134 | { | ||
| 135 | unsigned long flags; | ||
| 136 | |||
| 137 | spin_lock_irqsave(&nv_lock, flags); | ||
| 138 | out_8(nvram_addr, addr >> 5); | ||
| 139 | out_8(&nvram_data[(addr & 0x1f) << 4], val); | ||
| 140 | spin_unlock_irqrestore(&nv_lock, flags); | ||
| 141 | } | ||
| 142 | |||
| 143 | |||
| 144 | #ifdef CONFIG_ADB_PMU | ||
| 145 | |||
| 146 | static void pmu_nvram_complete(struct adb_request *req) | ||
| 147 | { | ||
| 148 | if (req->arg) | ||
| 149 | complete((struct completion *)req->arg); | ||
| 150 | } | ||
| 151 | |||
| 152 | static unsigned char pmu_nvram_read_byte(int addr) | ||
| 153 | { | ||
| 154 | struct adb_request req; | ||
| 155 | DECLARE_COMPLETION(req_complete); | ||
| 156 | |||
| 157 | req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; | ||
| 158 | if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, | ||
| 159 | (addr >> 8) & 0xff, addr & 0xff)) | ||
| 160 | return 0xff; | ||
| 161 | if (system_state == SYSTEM_RUNNING) | ||
| 162 | wait_for_completion(&req_complete); | ||
| 163 | while (!req.complete) | ||
| 164 | pmu_poll(); | ||
| 165 | return req.reply[0]; | ||
| 166 | } | ||
| 167 | |||
| 168 | static void pmu_nvram_write_byte(int addr, unsigned char val) | ||
| 169 | { | ||
| 170 | struct adb_request req; | ||
| 171 | DECLARE_COMPLETION(req_complete); | ||
| 172 | |||
| 173 | req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; | ||
| 174 | if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, | ||
| 175 | (addr >> 8) & 0xff, addr & 0xff, val)) | ||
| 176 | return; | ||
| 177 | if (system_state == SYSTEM_RUNNING) | ||
| 178 | wait_for_completion(&req_complete); | ||
| 179 | while (!req.complete) | ||
| 180 | pmu_poll(); | ||
| 181 | } | ||
| 182 | |||
| 183 | #endif /* CONFIG_ADB_PMU */ | ||
| 184 | |||
| 185 | |||
| 186 | static u8 chrp_checksum(struct chrp_header* hdr) | ||
| 187 | { | ||
| 188 | u8 *ptr; | ||
| 189 | u16 sum = hdr->signature; | ||
| 190 | for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) | ||
| 191 | sum += *ptr; | ||
| 192 | while (sum > 0xFF) | ||
| 193 | sum = (sum & 0xFF) + (sum>>8); | ||
| 194 | return sum; | ||
| 195 | } | ||
| 196 | |||
| 197 | static u32 core99_calc_adler(u8 *buffer) | ||
| 198 | { | ||
| 199 | int cnt; | ||
| 200 | u32 low, high; | ||
| 201 | |||
| 202 | buffer += CORE99_ADLER_START; | ||
| 203 | low = 1; | ||
| 204 | high = 0; | ||
| 205 | for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { | ||
| 206 | if ((cnt % 5000) == 0) { | ||
| 207 | high %= 65521UL; | ||
| 208 | high %= 65521UL; | ||
| 209 | } | ||
| 210 | low += buffer[cnt]; | ||
| 211 | high += low; | ||
| 212 | } | ||
| 213 | low %= 65521UL; | ||
| 214 | high %= 65521UL; | ||
| 215 | |||
| 216 | return (high << 16) | low; | ||
| 217 | } | ||
| 218 | |||
| 219 | static u32 core99_check(u8* datas) | ||
| 220 | { | ||
| 221 | struct core99_header* hdr99 = (struct core99_header*)datas; | ||
| 222 | |||
| 223 | if (hdr99->hdr.signature != CORE99_SIGNATURE) { | ||
| 224 | DBG("Invalid signature\n"); | ||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { | ||
| 228 | DBG("Invalid checksum\n"); | ||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | if (hdr99->adler != core99_calc_adler(datas)) { | ||
| 232 | DBG("Invalid adler\n"); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | return hdr99->generation; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int sm_erase_bank(int bank) | ||
| 239 | { | ||
| 240 | int stat, i; | ||
| 241 | unsigned long timeout; | ||
| 242 | |||
| 243 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
| 244 | |||
| 245 | DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); | ||
| 246 | |||
| 247 | out_8(base, SM_FLASH_CMD_ERASE_SETUP); | ||
| 248 | out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); | ||
| 249 | timeout = 0; | ||
| 250 | do { | ||
| 251 | if (++timeout > 1000000) { | ||
| 252 | printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | out_8(base, SM_FLASH_CMD_READ_STATUS); | ||
| 256 | stat = in_8(base); | ||
| 257 | } while (!(stat & SM_FLASH_STATUS_DONE)); | ||
| 258 | |||
| 259 | out_8(base, SM_FLASH_CMD_CLEAR_STATUS); | ||
| 260 | out_8(base, SM_FLASH_CMD_RESET); | ||
| 261 | |||
| 262 | for (i=0; i<NVRAM_SIZE; i++) | ||
| 263 | if (base[i] != 0xff) { | ||
| 264 | printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n"); | ||
| 265 | return -ENXIO; | ||
| 266 | } | ||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int sm_write_bank(int bank, u8* datas) | ||
| 271 | { | ||
| 272 | int i, stat = 0; | ||
| 273 | unsigned long timeout; | ||
| 274 | |||
| 275 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
| 276 | |||
| 277 | DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); | ||
| 278 | |||
| 279 | for (i=0; i<NVRAM_SIZE; i++) { | ||
| 280 | out_8(base+i, SM_FLASH_CMD_WRITE_SETUP); | ||
| 281 | udelay(1); | ||
| 282 | out_8(base+i, datas[i]); | ||
| 283 | timeout = 0; | ||
| 284 | do { | ||
| 285 | if (++timeout > 1000000) { | ||
| 286 | printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); | ||
| 287 | break; | ||
| 288 | } | ||
| 289 | out_8(base, SM_FLASH_CMD_READ_STATUS); | ||
| 290 | stat = in_8(base); | ||
| 291 | } while (!(stat & SM_FLASH_STATUS_DONE)); | ||
| 292 | if (!(stat & SM_FLASH_STATUS_DONE)) | ||
| 293 | break; | ||
| 294 | } | ||
| 295 | out_8(base, SM_FLASH_CMD_CLEAR_STATUS); | ||
| 296 | out_8(base, SM_FLASH_CMD_RESET); | ||
| 297 | for (i=0; i<NVRAM_SIZE; i++) | ||
| 298 | if (base[i] != datas[i]) { | ||
| 299 | printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n"); | ||
| 300 | return -ENXIO; | ||
| 301 | } | ||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | static int amd_erase_bank(int bank) | ||
| 306 | { | ||
| 307 | int i, stat = 0; | ||
| 308 | unsigned long timeout; | ||
| 309 | |||
| 310 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
| 311 | |||
| 312 | DBG("nvram: AMD Erasing bank %d...\n", bank); | ||
| 313 | |||
| 314 | /* Unlock 1 */ | ||
| 315 | out_8(base+0x555, 0xaa); | ||
| 316 | udelay(1); | ||
| 317 | /* Unlock 2 */ | ||
| 318 | out_8(base+0x2aa, 0x55); | ||
| 319 | udelay(1); | ||
| 320 | |||
| 321 | /* Sector-Erase */ | ||
| 322 | out_8(base+0x555, 0x80); | ||
| 323 | udelay(1); | ||
| 324 | out_8(base+0x555, 0xaa); | ||
| 325 | udelay(1); | ||
| 326 | out_8(base+0x2aa, 0x55); | ||
| 327 | udelay(1); | ||
| 328 | out_8(base, 0x30); | ||
| 329 | udelay(1); | ||
| 330 | |||
| 331 | timeout = 0; | ||
| 332 | do { | ||
| 333 | if (++timeout > 1000000) { | ||
| 334 | printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); | ||
| 335 | break; | ||
| 336 | } | ||
| 337 | stat = in_8(base) ^ in_8(base); | ||
| 338 | } while (stat != 0); | ||
| 339 | |||
| 340 | /* Reset */ | ||
| 341 | out_8(base, 0xf0); | ||
| 342 | udelay(1); | ||
| 343 | |||
| 344 | for (i=0; i<NVRAM_SIZE; i++) | ||
| 345 | if (base[i] != 0xff) { | ||
| 346 | printk(KERN_ERR "nvram: AMD flash erase failed !\n"); | ||
| 347 | return -ENXIO; | ||
| 348 | } | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | static int amd_write_bank(int bank, u8* datas) | ||
| 353 | { | ||
| 354 | int i, stat = 0; | ||
| 355 | unsigned long timeout; | ||
| 356 | |||
| 357 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
| 358 | |||
| 359 | DBG("nvram: AMD Writing bank %d...\n", bank); | ||
| 360 | |||
| 361 | for (i=0; i<NVRAM_SIZE; i++) { | ||
| 362 | /* Unlock 1 */ | ||
| 363 | out_8(base+0x555, 0xaa); | ||
| 364 | udelay(1); | ||
| 365 | /* Unlock 2 */ | ||
| 366 | out_8(base+0x2aa, 0x55); | ||
| 367 | udelay(1); | ||
| 368 | |||
| 369 | /* Write single word */ | ||
| 370 | out_8(base+0x555, 0xa0); | ||
| 371 | udelay(1); | ||
| 372 | out_8(base+i, datas[i]); | ||
| 373 | |||
| 374 | timeout = 0; | ||
| 375 | do { | ||
| 376 | if (++timeout > 1000000) { | ||
| 377 | printk(KERN_ERR "nvram: AMD flash write timeout !\n"); | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | stat = in_8(base) ^ in_8(base); | ||
| 381 | } while (stat != 0); | ||
| 382 | if (stat != 0) | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | |||
| 386 | /* Reset */ | ||
| 387 | out_8(base, 0xf0); | ||
| 388 | udelay(1); | ||
| 389 | |||
| 390 | for (i=0; i<NVRAM_SIZE; i++) | ||
| 391 | if (base[i] != datas[i]) { | ||
| 392 | printk(KERN_ERR "nvram: AMD flash write failed !\n"); | ||
| 393 | return -ENXIO; | ||
| 394 | } | ||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | static void __init lookup_partitions(void) | ||
| 399 | { | ||
| 400 | u8 buffer[17]; | ||
| 401 | int i, offset; | ||
| 402 | struct chrp_header* hdr; | ||
| 403 | |||
| 404 | if (pmac_newworld) { | ||
| 405 | nvram_partitions[pmac_nvram_OF] = -1; | ||
| 406 | nvram_partitions[pmac_nvram_XPRAM] = -1; | ||
| 407 | nvram_partitions[pmac_nvram_NR] = -1; | ||
| 408 | hdr = (struct chrp_header *)buffer; | ||
| 409 | |||
| 410 | offset = 0; | ||
| 411 | buffer[16] = 0; | ||
| 412 | do { | ||
| 413 | for (i=0;i<16;i++) | ||
| 414 | buffer[i] = nvram_read_byte(offset+i); | ||
| 415 | if (!strcmp(hdr->name, "common")) | ||
| 416 | nvram_partitions[pmac_nvram_OF] = offset + 0x10; | ||
| 417 | if (!strcmp(hdr->name, "APL,MacOS75")) { | ||
| 418 | nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10; | ||
| 419 | nvram_partitions[pmac_nvram_NR] = offset + 0x110; | ||
| 420 | } | ||
| 421 | offset += (hdr->len * 0x10); | ||
| 422 | } while(offset < NVRAM_SIZE); | ||
| 423 | } else { | ||
| 424 | nvram_partitions[pmac_nvram_OF] = 0x1800; | ||
| 425 | nvram_partitions[pmac_nvram_XPRAM] = 0x1300; | ||
| 426 | nvram_partitions[pmac_nvram_NR] = 0x1400; | ||
| 427 | } | ||
| 428 | DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); | ||
| 429 | DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); | ||
| 430 | DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); | ||
| 431 | } | ||
| 432 | |||
| 433 | static void core99_nvram_sync(void) | ||
| 434 | { | ||
| 435 | struct core99_header* hdr99; | ||
| 436 | unsigned long flags; | ||
| 437 | |||
| 438 | if (!is_core_99 || !nvram_data || !nvram_image) | ||
| 439 | return; | ||
| 440 | |||
| 441 | spin_lock_irqsave(&nv_lock, flags); | ||
| 442 | if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, | ||
| 443 | NVRAM_SIZE)) | ||
| 444 | goto bail; | ||
| 445 | |||
| 446 | DBG("Updating nvram...\n"); | ||
| 447 | |||
| 448 | hdr99 = (struct core99_header*)nvram_image; | ||
| 449 | hdr99->generation++; | ||
| 450 | hdr99->hdr.signature = CORE99_SIGNATURE; | ||
| 451 | hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); | ||
| 452 | hdr99->adler = core99_calc_adler(nvram_image); | ||
| 453 | core99_bank = core99_bank ? 0 : 1; | ||
| 454 | if (core99_erase_bank) | ||
| 455 | if (core99_erase_bank(core99_bank)) { | ||
| 456 | printk("nvram: Error erasing bank %d\n", core99_bank); | ||
| 457 | goto bail; | ||
| 458 | } | ||
| 459 | if (core99_write_bank) | ||
| 460 | if (core99_write_bank(core99_bank, nvram_image)) | ||
| 461 | printk("nvram: Error writing bank %d\n", core99_bank); | ||
| 462 | bail: | ||
| 463 | spin_unlock_irqrestore(&nv_lock, flags); | ||
| 464 | |||
| 465 | #ifdef DEBUG | ||
| 466 | mdelay(2000); | ||
| 467 | #endif | ||
| 468 | } | ||
| 469 | |||
| 470 | void __init pmac_nvram_init(void) | ||
| 471 | { | ||
| 472 | struct device_node *dp; | ||
| 473 | |||
| 474 | nvram_naddrs = 0; | ||
| 475 | |||
| 476 | dp = find_devices("nvram"); | ||
| 477 | if (dp == NULL) { | ||
| 478 | printk(KERN_ERR "Can't find NVRAM device\n"); | ||
| 479 | return; | ||
| 480 | } | ||
| 481 | nvram_naddrs = dp->n_addrs; | ||
| 482 | is_core_99 = device_is_compatible(dp, "nvram,flash"); | ||
| 483 | if (is_core_99) { | ||
| 484 | int i; | ||
| 485 | u32 gen_bank0, gen_bank1; | ||
| 486 | |||
| 487 | if (nvram_naddrs < 1) { | ||
| 488 | printk(KERN_ERR "nvram: no address\n"); | ||
| 489 | return; | ||
| 490 | } | ||
| 491 | nvram_image = alloc_bootmem(NVRAM_SIZE); | ||
| 492 | if (nvram_image == NULL) { | ||
| 493 | printk(KERN_ERR "nvram: can't allocate ram image\n"); | ||
| 494 | return; | ||
| 495 | } | ||
| 496 | nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); | ||
| 497 | nvram_naddrs = 1; /* Make sure we get the correct case */ | ||
| 498 | |||
| 499 | DBG("nvram: Checking bank 0...\n"); | ||
| 500 | |||
| 501 | gen_bank0 = core99_check((u8 *)nvram_data); | ||
| 502 | gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); | ||
| 503 | core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; | ||
| 504 | |||
| 505 | DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); | ||
| 506 | DBG("nvram: Active bank is: %d\n", core99_bank); | ||
| 507 | |||
| 508 | for (i=0; i<NVRAM_SIZE; i++) | ||
| 509 | nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE]; | ||
| 510 | |||
| 511 | ppc_md.nvram_read_val = core99_nvram_read_byte; | ||
| 512 | ppc_md.nvram_write_val = core99_nvram_write_byte; | ||
| 513 | ppc_md.nvram_sync = core99_nvram_sync; | ||
| 514 | /* | ||
| 515 | * Maybe we could be smarter here though making an exclusive list | ||
| 516 | * of known flash chips is a bit nasty as older OF didn't provide us | ||
| 517 | * with a useful "compatible" entry. A solution would be to really | ||
| 518 | * identify the chip using flash id commands and base ourselves on | ||
| 519 | * a list of known chips IDs | ||
| 520 | */ | ||
| 521 | if (device_is_compatible(dp, "amd-0137")) { | ||
| 522 | core99_erase_bank = amd_erase_bank; | ||
| 523 | core99_write_bank = amd_write_bank; | ||
| 524 | } else { | ||
| 525 | core99_erase_bank = sm_erase_bank; | ||
| 526 | core99_write_bank = sm_write_bank; | ||
| 527 | } | ||
| 528 | } else if (_machine == _MACH_chrp && nvram_naddrs == 1) { | ||
| 529 | nvram_data = ioremap(dp->addrs[0].address + isa_mem_base, | ||
| 530 | dp->addrs[0].size); | ||
| 531 | nvram_mult = 1; | ||
| 532 | ppc_md.nvram_read_val = direct_nvram_read_byte; | ||
| 533 | ppc_md.nvram_write_val = direct_nvram_write_byte; | ||
| 534 | } else if (nvram_naddrs == 1) { | ||
| 535 | nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); | ||
| 536 | nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; | ||
| 537 | ppc_md.nvram_read_val = direct_nvram_read_byte; | ||
| 538 | ppc_md.nvram_write_val = direct_nvram_write_byte; | ||
| 539 | } else if (nvram_naddrs == 2) { | ||
| 540 | nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); | ||
| 541 | nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); | ||
| 542 | ppc_md.nvram_read_val = indirect_nvram_read_byte; | ||
| 543 | ppc_md.nvram_write_val = indirect_nvram_write_byte; | ||
| 544 | } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { | ||
| 545 | #ifdef CONFIG_ADB_PMU | ||
| 546 | nvram_naddrs = -1; | ||
| 547 | ppc_md.nvram_read_val = pmu_nvram_read_byte; | ||
| 548 | ppc_md.nvram_write_val = pmu_nvram_write_byte; | ||
| 549 | #endif /* CONFIG_ADB_PMU */ | ||
| 550 | } else { | ||
| 551 | printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", | ||
| 552 | nvram_naddrs); | ||
| 553 | } | ||
| 554 | lookup_partitions(); | ||
| 555 | } | ||
| 556 | |||
| 557 | int pmac_get_partition(int partition) | ||
| 558 | { | ||
| 559 | return nvram_partitions[partition]; | ||
| 560 | } | ||
| 561 | |||
| 562 | u8 pmac_xpram_read(int xpaddr) | ||
| 563 | { | ||
| 564 | int offset = nvram_partitions[pmac_nvram_XPRAM]; | ||
| 565 | |||
| 566 | if (offset < 0) | ||
| 567 | return 0xff; | ||
| 568 | |||
| 569 | return ppc_md.nvram_read_val(xpaddr + offset); | ||
| 570 | } | ||
| 571 | |||
| 572 | void pmac_xpram_write(int xpaddr, u8 data) | ||
| 573 | { | ||
| 574 | int offset = nvram_partitions[pmac_nvram_XPRAM]; | ||
| 575 | |||
| 576 | if (offset < 0) | ||
| 577 | return; | ||
| 578 | |||
| 579 | ppc_md.nvram_write_val(xpaddr + offset, data); | ||
| 580 | } | ||
| 581 | |||
| 582 | EXPORT_SYMBOL(pmac_get_partition); | ||
| 583 | EXPORT_SYMBOL(pmac_xpram_read); | ||
| 584 | EXPORT_SYMBOL(pmac_xpram_write); | ||
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c deleted file mode 100644 index 786295b6ddd0..000000000000 --- a/arch/ppc/platforms/pmac_pci.c +++ /dev/null  | |||
| @@ -1,1124 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support for PCI bridges found on Power Macintoshes. | ||
| 3 | * At present the "bandit" and "chaos" bridges are supported. | ||
| 4 | * Fortunately you access configuration space in the same | ||
| 5 | * way with either bridge. | ||
| 6 | * | ||
| 7 | * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version | ||
| 12 | * 2 of the License, or (at your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/pci.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/string.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | |||
| 21 | #include <asm/sections.h> | ||
| 22 | #include <asm/io.h> | ||
| 23 | #include <asm/prom.h> | ||
| 24 | #include <asm/pci-bridge.h> | ||
| 25 | #include <asm/machdep.h> | ||
| 26 | #include <asm/pmac_feature.h> | ||
| 27 | |||
| 28 | #undef DEBUG | ||
| 29 | |||
| 30 | #ifdef DEBUG | ||
| 31 | #ifdef CONFIG_XMON | ||
| 32 | extern void xmon_printf(const char *fmt, ...); | ||
| 33 | #define DBG(x...) xmon_printf(x) | ||
| 34 | #else | ||
| 35 | #define DBG(x...) printk(x) | ||
| 36 | #endif | ||
| 37 | #else | ||
| 38 | #define DBG(x...) | ||
| 39 | #endif | ||
| 40 | |||
| 41 | static int add_bridge(struct device_node *dev); | ||
| 42 | extern void pmac_check_ht_link(void); | ||
| 43 | |||
| 44 | /* XXX Could be per-controller, but I don't think we risk anything by | ||
| 45 | * assuming we won't have both UniNorth and Bandit */ | ||
| 46 | static int has_uninorth; | ||
| 47 | #ifdef CONFIG_POWER4 | ||
| 48 | static struct pci_controller *u3_agp; | ||
| 49 | #endif /* CONFIG_POWER4 */ | ||
| 50 | |||
| 51 | extern u8 pci_cache_line_size; | ||
| 52 | extern int pcibios_assign_bus_offset; | ||
| 53 | |||
| 54 | struct device_node *k2_skiplist[2]; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Magic constants for enabling cache coherency in the bandit/PSX bridge. | ||
| 58 | */ | ||
| 59 | #define BANDIT_DEVID_2 8 | ||
| 60 | #define BANDIT_REVID 3 | ||
| 61 | |||
| 62 | #define BANDIT_DEVNUM 11 | ||
| 63 | #define BANDIT_MAGIC 0x50 | ||
| 64 | #define BANDIT_COHERENT 0x40 | ||
| 65 | |||
| 66 | static int __init | ||
| 67 | fixup_one_level_bus_range(struct device_node *node, int higher) | ||
| 68 | { | ||
| 69 | for (; node != 0;node = node->sibling) { | ||
| 70 | int * bus_range; | ||
| 71 | unsigned int *class_code; | ||
| 72 | int len; | ||
| 73 | |||
| 74 | /* For PCI<->PCI bridges or CardBus bridges, we go down */ | ||
| 75 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
| 76 | if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
| 77 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) | ||
| 78 | continue; | ||
| 79 | bus_range = (int *) get_property(node, "bus-range", &len); | ||
| 80 | if (bus_range != NULL && len > 2 * sizeof(int)) { | ||
| 81 | if (bus_range[1] > higher) | ||
| 82 | higher = bus_range[1]; | ||
| 83 | } | ||
| 84 | higher = fixup_one_level_bus_range(node->child, higher); | ||
| 85 | } | ||
| 86 | return higher; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* This routine fixes the "bus-range" property of all bridges in the | ||
| 90 | * system since they tend to have their "last" member wrong on macs | ||
| 91 | * | ||
| 92 | * Note that the bus numbers manipulated here are OF bus numbers, they | ||
| 93 | * are not Linux bus numbers. | ||
| 94 | */ | ||
| 95 | static void __init | ||
| 96 | fixup_bus_range(struct device_node *bridge) | ||
| 97 | { | ||
| 98 | int * bus_range; | ||
| 99 | int len; | ||
| 100 | |||
| 101 | /* Lookup the "bus-range" property for the hose */ | ||
| 102 | bus_range = (int *) get_property(bridge, "bus-range", &len); | ||
| 103 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
| 104 | printk(KERN_WARNING "Can't get bus-range for %s\n", | ||
| 105 | bridge->full_name); | ||
| 106 | return; | ||
| 107 | } | ||
| 108 | bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); | ||
| 109 | } | ||
| 110 | |||
| 111 | /* | ||
| 112 | * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. | ||
| 113 | * | ||
| 114 | * The "Bandit" version is present in all early PCI PowerMacs, | ||
| 115 | * and up to the first ones using Grackle. Some machines may | ||
| 116 | * have 2 bandit controllers (2 PCI busses). | ||
| 117 | * | ||
| 118 | * "Chaos" is used in some "Bandit"-type machines as a bridge | ||
| 119 | * for the separate display bus. It is accessed the same | ||
| 120 | * way as bandit, but cannot be probed for devices. It therefore | ||
| 121 | * has its own config access functions. | ||
| 122 | * | ||
| 123 | * The "UniNorth" version is present in all Core99 machines | ||
| 124 | * (iBook, G4, new IMacs, and all the recent Apple machines). | ||
| 125 | * It contains 3 controllers in one ASIC. | ||
| 126 | * | ||
| 127 | * The U3 is the bridge used on G5 machines. It contains an | ||
| 128 | * AGP bus which is dealt with the old UniNorth access routines | ||
| 129 | * and a HyperTransport bus which uses its own set of access | ||
| 130 | * functions. | ||
| 131 | */ | ||
| 132 | |||
| 133 | #define MACRISC_CFA0(devfn, off) \ | ||
| 134 | ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ | ||
| 135 | | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ | ||
| 136 | | (((unsigned long)(off)) & 0xFCUL)) | ||
| 137 | |||
| 138 | #define MACRISC_CFA1(bus, devfn, off) \ | ||
| 139 | ((((unsigned long)(bus)) << 16) \ | ||
| 140 | |(((unsigned long)(devfn)) << 8) \ | ||
| 141 | |(((unsigned long)(off)) & 0xFCUL) \ | ||
| 142 | |1UL) | ||
| 143 | |||
| 144 | static void volatile __iomem * | ||
| 145 | macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) | ||
| 146 | { | ||
| 147 | unsigned int caddr; | ||
| 148 | |||
| 149 | if (bus == hose->first_busno) { | ||
| 150 | if (dev_fn < (11 << 3)) | ||
| 151 | return NULL; | ||
| 152 | caddr = MACRISC_CFA0(dev_fn, offset); | ||
| 153 | } else | ||
| 154 | caddr = MACRISC_CFA1(bus, dev_fn, offset); | ||
| 155 | |||
| 156 | /* Uninorth will return garbage if we don't read back the value ! */ | ||
| 157 | do { | ||
| 158 | out_le32(hose->cfg_addr, caddr); | ||
| 159 | } while (in_le32(hose->cfg_addr) != caddr); | ||
| 160 | |||
| 161 | offset &= has_uninorth ? 0x07 : 0x03; | ||
| 162 | return hose->cfg_data + offset; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int | ||
| 166 | macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 167 | int len, u32 *val) | ||
| 168 | { | ||
| 169 | struct pci_controller *hose = bus->sysdata; | ||
| 170 | void volatile __iomem *addr; | ||
| 171 | |||
| 172 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | ||
| 173 | if (!addr) | ||
| 174 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 175 | /* | ||
| 176 | * Note: the caller has already checked that offset is | ||
| 177 | * suitably aligned and that len is 1, 2 or 4. | ||
| 178 | */ | ||
| 179 | switch (len) { | ||
| 180 | case 1: | ||
| 181 | *val = in_8(addr); | ||
| 182 | break; | ||
| 183 | case 2: | ||
| 184 | *val = in_le16(addr); | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | *val = in_le32(addr); | ||
| 188 | break; | ||
| 189 | } | ||
| 190 | return PCIBIOS_SUCCESSFUL; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int | ||
| 194 | macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 195 | int len, u32 val) | ||
| 196 | { | ||
| 197 | struct pci_controller *hose = bus->sysdata; | ||
| 198 | void volatile __iomem *addr; | ||
| 199 | |||
| 200 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | ||
| 201 | if (!addr) | ||
| 202 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 203 | /* | ||
| 204 | * Note: the caller has already checked that offset is | ||
| 205 | * suitably aligned and that len is 1, 2 or 4. | ||
| 206 | */ | ||
| 207 | switch (len) { | ||
| 208 | case 1: | ||
| 209 | out_8(addr, val); | ||
| 210 | (void) in_8(addr); | ||
| 211 | break; | ||
| 212 | case 2: | ||
| 213 | out_le16(addr, val); | ||
| 214 | (void) in_le16(addr); | ||
| 215 | break; | ||
| 216 | default: | ||
| 217 | out_le32(addr, val); | ||
| 218 | (void) in_le32(addr); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | return PCIBIOS_SUCCESSFUL; | ||
| 222 | } | ||
| 223 | |||
| 224 | static struct pci_ops macrisc_pci_ops = | ||
| 225 | { | ||
| 226 | macrisc_read_config, | ||
| 227 | macrisc_write_config | ||
| 228 | }; | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Verifiy that a specific (bus, dev_fn) exists on chaos | ||
| 232 | */ | ||
| 233 | static int | ||
| 234 | chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) | ||
| 235 | { | ||
| 236 | struct device_node *np; | ||
| 237 | u32 *vendor, *device; | ||
| 238 | |||
| 239 | np = pci_busdev_to_OF_node(bus, devfn); | ||
| 240 | if (np == NULL) | ||
| 241 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 242 | |||
| 243 | vendor = (u32 *)get_property(np, "vendor-id", NULL); | ||
| 244 | device = (u32 *)get_property(np, "device-id", NULL); | ||
| 245 | if (vendor == NULL || device == NULL) | ||
| 246 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 247 | |||
| 248 | if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10) | ||
| 249 | && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) | ||
| 250 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
| 251 | |||
| 252 | return PCIBIOS_SUCCESSFUL; | ||
| 253 | } | ||
| 254 | |||
| 255 | static int | ||
| 256 | chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 257 | int len, u32 *val) | ||
| 258 | { | ||
| 259 | int result = chaos_validate_dev(bus, devfn, offset); | ||
| 260 | if (result == PCIBIOS_BAD_REGISTER_NUMBER) | ||
| 261 | *val = ~0U; | ||
| 262 | if (result != PCIBIOS_SUCCESSFUL) | ||
| 263 | return result; | ||
| 264 | return macrisc_read_config(bus, devfn, offset, len, val); | ||
| 265 | } | ||
| 266 | |||
| 267 | static int | ||
| 268 | chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 269 | int len, u32 val) | ||
| 270 | { | ||
| 271 | int result = chaos_validate_dev(bus, devfn, offset); | ||
| 272 | if (result != PCIBIOS_SUCCESSFUL) | ||
| 273 | return result; | ||
| 274 | return macrisc_write_config(bus, devfn, offset, len, val); | ||
| 275 | } | ||
| 276 | |||
| 277 | static struct pci_ops chaos_pci_ops = | ||
| 278 | { | ||
| 279 | chaos_read_config, | ||
| 280 | chaos_write_config | ||
| 281 | }; | ||
| 282 | |||
| 283 | #ifdef CONFIG_POWER4 | ||
| 284 | |||
| 285 | /* | ||
| 286 | * These versions of U3 HyperTransport config space access ops do not | ||
| 287 | * implement self-view of the HT host yet | ||
| 288 | */ | ||
| 289 | |||
| 290 | #define U3_HT_CFA0(devfn, off) \ | ||
| 291 | ((((unsigned long)devfn) << 8) | offset) | ||
| 292 | #define U3_HT_CFA1(bus, devfn, off) \ | ||
| 293 | (U3_HT_CFA0(devfn, off) \ | ||
| 294 | + (((unsigned long)bus) << 16) \ | ||
| 295 | + 0x01000000UL) | ||
| 296 | |||
| 297 | static void volatile __iomem * | ||
| 298 | u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) | ||
| 299 | { | ||
| 300 | if (bus == hose->first_busno) { | ||
| 301 | /* For now, we don't self probe U3 HT bridge */ | ||
| 302 | if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || | ||
| 303 | PCI_SLOT(devfn) < 1) | ||
| 304 | return 0; | ||
| 305 | return hose->cfg_data + U3_HT_CFA0(devfn, offset); | ||
| 306 | } else | ||
| 307 | return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); | ||
| 308 | } | ||
| 309 | |||
| 310 | static int | ||
| 311 | u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 312 | int len, u32 *val) | ||
| 313 | { | ||
| 314 | struct pci_controller *hose = bus->sysdata; | ||
| 315 | void volatile __iomem *addr; | ||
| 316 | int i; | ||
| 317 | |||
| 318 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | ||
| 319 | if (np == NULL) | ||
| 320 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 321 | |||
| 322 | /* | ||
| 323 | * When a device in K2 is powered down, we die on config | ||
| 324 | * cycle accesses. Fix that here. | ||
| 325 | */ | ||
| 326 | for (i=0; i<2; i++) | ||
| 327 | if (k2_skiplist[i] == np) { | ||
| 328 | switch (len) { | ||
| 329 | case 1: | ||
| 330 | *val = 0xff; break; | ||
| 331 | case 2: | ||
| 332 | *val = 0xffff; break; | ||
| 333 | default: | ||
| 334 | *val = 0xfffffffful; break; | ||
| 335 | } | ||
| 336 | return PCIBIOS_SUCCESSFUL; | ||
| 337 | } | ||
| 338 | |||
| 339 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | ||
| 340 | if (!addr) | ||
| 341 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 342 | /* | ||
| 343 | * Note: the caller has already checked that offset is | ||
| 344 | * suitably aligned and that len is 1, 2 or 4. | ||
| 345 | */ | ||
| 346 | switch (len) { | ||
| 347 | case 1: | ||
| 348 | *val = in_8(addr); | ||
| 349 | break; | ||
| 350 | case 2: | ||
| 351 | *val = in_le16(addr); | ||
| 352 | break; | ||
| 353 | default: | ||
| 354 | *val = in_le32(addr); | ||
| 355 | break; | ||
| 356 | } | ||
| 357 | return PCIBIOS_SUCCESSFUL; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int | ||
| 361 | u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 362 | int len, u32 val) | ||
| 363 | { | ||
| 364 | struct pci_controller *hose = bus->sysdata; | ||
| 365 | void volatile __iomem *addr; | ||
| 366 | int i; | ||
| 367 | |||
| 368 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | ||
| 369 | if (np == NULL) | ||
| 370 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 371 | /* | ||
| 372 | * When a device in K2 is powered down, we die on config | ||
| 373 | * cycle accesses. Fix that here. | ||
| 374 | */ | ||
| 375 | for (i=0; i<2; i++) | ||
| 376 | if (k2_skiplist[i] == np) | ||
| 377 | return PCIBIOS_SUCCESSFUL; | ||
| 378 | |||
| 379 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | ||
| 380 | if (!addr) | ||
| 381 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 382 | /* | ||
| 383 | * Note: the caller has already checked that offset is | ||
| 384 | * suitably aligned and that len is 1, 2 or 4. | ||
| 385 | */ | ||
| 386 | switch (len) { | ||
| 387 | case 1: | ||
| 388 | out_8(addr, val); | ||
| 389 | (void) in_8(addr); | ||
| 390 | break; | ||
| 391 | case 2: | ||
| 392 | out_le16(addr, val); | ||
| 393 | (void) in_le16(addr); | ||
| 394 | break; | ||
| 395 | default: | ||
| 396 | out_le32(addr, val); | ||
| 397 | (void) in_le32(addr); | ||
| 398 | break; | ||
| 399 | } | ||
| 400 | return PCIBIOS_SUCCESSFUL; | ||
| 401 | } | ||
| 402 | |||
| 403 | static struct pci_ops u3_ht_pci_ops = | ||
| 404 | { | ||
| 405 | u3_ht_read_config, | ||
| 406 | u3_ht_write_config | ||
| 407 | }; | ||
| 408 | |||
| 409 | #endif /* CONFIG_POWER4 */ | ||
| 410 | |||
| 411 | /* | ||
| 412 | * For a bandit bridge, turn on cache coherency if necessary. | ||
| 413 | * N.B. we could clean this up using the hose ops directly. | ||
| 414 | */ | ||
| 415 | static void __init | ||
| 416 | init_bandit(struct pci_controller *bp) | ||
| 417 | { | ||
| 418 | unsigned int vendev, magic; | ||
| 419 | int rev; | ||
| 420 | |||
| 421 | /* read the word at offset 0 in config space for device 11 */ | ||
| 422 | out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); | ||
| 423 | udelay(2); | ||
| 424 | vendev = in_le32(bp->cfg_data); | ||
| 425 | if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + | ||
| 426 | PCI_VENDOR_ID_APPLE) { | ||
| 427 | /* read the revision id */ | ||
| 428 | out_le32(bp->cfg_addr, | ||
| 429 | (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); | ||
| 430 | udelay(2); | ||
| 431 | rev = in_8(bp->cfg_data); | ||
| 432 | if (rev != BANDIT_REVID) | ||
| 433 | printk(KERN_WARNING | ||
| 434 | "Unknown revision %d for bandit\n", rev); | ||
| 435 | } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { | ||
| 436 | printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); | ||
| 437 | return; | ||
| 438 | } | ||
| 439 | |||
| 440 | /* read the word at offset 0x50 */ | ||
| 441 | out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); | ||
| 442 | udelay(2); | ||
| 443 | magic = in_le32(bp->cfg_data); | ||
| 444 | if ((magic & BANDIT_COHERENT) != 0) | ||
| 445 | return; | ||
| 446 | magic |= BANDIT_COHERENT; | ||
| 447 | udelay(2); | ||
| 448 | out_le32(bp->cfg_data, magic); | ||
| 449 | printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n"); | ||
| 450 | } | ||
| 451 | |||
| 452 | |||
| 453 | /* | ||
| 454 | * Tweak the PCI-PCI bridge chip on the blue & white G3s. | ||
| 455 | */ | ||
| 456 | static void __init | ||
| 457 | init_p2pbridge(void) | ||
| 458 | { | ||
| 459 | struct device_node *p2pbridge; | ||
| 460 | struct pci_controller* hose; | ||
| 461 | u8 bus, devfn; | ||
| 462 | u16 val; | ||
| 463 | |||
| 464 | /* XXX it would be better here to identify the specific | ||
| 465 | PCI-PCI bridge chip we have. */ | ||
| 466 | if ((p2pbridge = find_devices("pci-bridge")) == 0 | ||
| 467 | || p2pbridge->parent == NULL | ||
| 468 | || strcmp(p2pbridge->parent->name, "pci") != 0) | ||
| 469 | return; | ||
| 470 | if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { | ||
| 471 | DBG("Can't find PCI infos for PCI<->PCI bridge\n"); | ||
| 472 | return; | ||
| 473 | } | ||
| 474 | /* Warning: At this point, we have not yet renumbered all busses. | ||
| 475 | * So we must use OF walking to find out hose | ||
| 476 | */ | ||
| 477 | hose = pci_find_hose_for_OF_device(p2pbridge); | ||
| 478 | if (!hose) { | ||
| 479 | DBG("Can't find hose for PCI<->PCI bridge\n"); | ||
| 480 | return; | ||
| 481 | } | ||
| 482 | if (early_read_config_word(hose, bus, devfn, | ||
| 483 | PCI_BRIDGE_CONTROL, &val) < 0) { | ||
| 484 | printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); | ||
| 485 | return; | ||
| 486 | } | ||
| 487 | val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; | ||
| 488 | early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); | ||
| 489 | } | ||
| 490 | |||
| 491 | /* | ||
| 492 | * Some Apple desktop machines have a NEC PD720100A USB2 controller | ||
| 493 | * on the motherboard. Open Firmware, on these, will disable the | ||
| 494 | * EHCI part of it so it behaves like a pair of OHCI's. This fixup | ||
| 495 | * code re-enables it ;) | ||
| 496 | */ | ||
| 497 | static void __init | ||
| 498 | fixup_nec_usb2(void) | ||
| 499 | { | ||
| 500 | struct device_node *nec; | ||
| 501 | |||
| 502 | for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { | ||
| 503 | struct pci_controller *hose; | ||
| 504 | u32 data, *prop; | ||
| 505 | u8 bus, devfn; | ||
| 506 | |||
| 507 | prop = (u32 *)get_property(nec, "vendor-id", NULL); | ||
| 508 | if (prop == NULL) | ||
| 509 | continue; | ||
| 510 | if (0x1033 != *prop) | ||
| 511 | continue; | ||
| 512 | prop = (u32 *)get_property(nec, "device-id", NULL); | ||
| 513 | if (prop == NULL) | ||
| 514 | continue; | ||
| 515 | if (0x0035 != *prop) | ||
| 516 | continue; | ||
| 517 | prop = (u32 *)get_property(nec, "reg", NULL); | ||
| 518 | if (prop == NULL) | ||
| 519 | continue; | ||
| 520 | devfn = (prop[0] >> 8) & 0xff; | ||
| 521 | bus = (prop[0] >> 16) & 0xff; | ||
| 522 | if (PCI_FUNC(devfn) != 0) | ||
| 523 | continue; | ||
| 524 | hose = pci_find_hose_for_OF_device(nec); | ||
| 525 | if (!hose) | ||
| 526 | continue; | ||
| 527 | early_read_config_dword(hose, bus, devfn, 0xe4, &data); | ||
| 528 | if (data & 1UL) { | ||
| 529 | printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n"); | ||
| 530 | data &= ~1UL; | ||
| 531 | early_write_config_dword(hose, bus, devfn, 0xe4, data); | ||
| 532 | early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE, | ||
| 533 | nec->intrs[0].line); | ||
| 534 | } | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | void __init | ||
| 539 | pmac_find_bridges(void) | ||
| 540 | { | ||
| 541 | struct device_node *np, *root; | ||
| 542 | struct device_node *ht = NULL; | ||
| 543 | |||
| 544 | root = of_find_node_by_path("/"); | ||
| 545 | if (root == NULL) { | ||
| 546 | printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); | ||
| 547 | return; | ||
| 548 | } | ||
| 549 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { | ||
| 550 | if (np->name == NULL) | ||
| 551 | continue; | ||
| 552 | if (strcmp(np->name, "bandit") == 0 | ||
| 553 | || strcmp(np->name, "chaos") == 0 | ||
| 554 | || strcmp(np->name, "pci") == 0) { | ||
| 555 | if (add_bridge(np) == 0) | ||
| 556 | of_node_get(np); | ||
| 557 | } | ||
| 558 | if (strcmp(np->name, "ht") == 0) { | ||
| 559 | of_node_get(np); | ||
| 560 | ht = np; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | of_node_put(root); | ||
| 564 | |||
| 565 | /* Probe HT last as it relies on the agp resources to be already | ||
| 566 | * setup | ||
| 567 | */ | ||
| 568 | if (ht && add_bridge(ht) != 0) | ||
| 569 | of_node_put(ht); | ||
| 570 | |||
| 571 | init_p2pbridge(); | ||
| 572 | fixup_nec_usb2(); | ||
| 573 | |||
| 574 | /* We are still having some issues with the Xserve G4, enabling | ||
| 575 | * some offset between bus number and domains for now when we | ||
| 576 | * assign all busses should help for now | ||
| 577 | */ | ||
| 578 | if (pci_assign_all_buses) | ||
| 579 | pcibios_assign_bus_offset = 0x10; | ||
| 580 | |||
| 581 | #ifdef CONFIG_POWER4 | ||
| 582 | /* There is something wrong with DMA on U3/HT. I haven't figured out | ||
| 583 | * the details yet, but if I set the cache line size to 128 bytes like | ||
| 584 | * it should, I'm getting memory corruption caused by devices like | ||
| 585 | * sungem (even without the MWI bit set, but maybe sungem doesn't | ||
| 586 | * care). Right now, it appears that setting up a 64 bytes line size | ||
| 587 | * works properly, 64 bytes beeing the max transfer size of HT, I | ||
| 588 | * suppose this is related the way HT/PCI are hooked together. I still | ||
| 589 | * need to dive into more specs though to be really sure of what's | ||
| 590 | * going on. --BenH. | ||
| 591 | * | ||
| 592 | * Ok, apparently, it's just that HT can't do more than 64 bytes | ||
| 593 | * transactions. MWI seem to be meaningless there as well, it may | ||
| 594 | * be worth nop'ing out pci_set_mwi too though I haven't done that | ||
| 595 | * yet. | ||
| 596 | * | ||
| 597 | * Note that it's a bit different for whatever is in the AGP slot. | ||
| 598 | * For now, I don't care, but this can become a real issue, we | ||
| 599 | * should probably hook pci_set_mwi anyway to make sure it sets | ||
| 600 | * the real cache line size in there. | ||
| 601 | */ | ||
| 602 | if (machine_is_compatible("MacRISC4")) | ||
| 603 | pci_cache_line_size = 16; /* 64 bytes */ | ||
| 604 | |||
| 605 | pmac_check_ht_link(); | ||
| 606 | #endif /* CONFIG_POWER4 */ | ||
| 607 | } | ||
| 608 | |||
| 609 | #define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ | ||
| 610 | | (((o) & ~3) << 24)) | ||
| 611 | |||
| 612 | #define GRACKLE_PICR1_STG 0x00000040 | ||
| 613 | #define GRACKLE_PICR1_LOOPSNOOP 0x00000010 | ||
| 614 | |||
| 615 | /* N.B. this is called before bridges is initialized, so we can't | ||
| 616 | use grackle_pcibios_{read,write}_config_dword. */ | ||
| 617 | static inline void grackle_set_stg(struct pci_controller* bp, int enable) | ||
| 618 | { | ||
| 619 | unsigned int val; | ||
| 620 | |||
| 621 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
| 622 | val = in_le32(bp->cfg_data); | ||
| 623 | val = enable? (val | GRACKLE_PICR1_STG) : | ||
| 624 | (val & ~GRACKLE_PICR1_STG); | ||
| 625 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
| 626 | out_le32(bp->cfg_data, val); | ||
| 627 | (void)in_le32(bp->cfg_data); | ||
| 628 | } | ||
| 629 | |||
| 630 | static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) | ||
| 631 | { | ||
| 632 | unsigned int val; | ||
| 633 | |||
| 634 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
| 635 | val = in_le32(bp->cfg_data); | ||
| 636 | val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) : | ||
| 637 | (val & ~GRACKLE_PICR1_LOOPSNOOP); | ||
| 638 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
| 639 | out_le32(bp->cfg_data, val); | ||
| 640 | (void)in_le32(bp->cfg_data); | ||
| 641 | } | ||
| 642 | |||
| 643 | static int __init | ||
| 644 | setup_uninorth(struct pci_controller* hose, struct reg_property* addr) | ||
| 645 | { | ||
| 646 | pci_assign_all_buses = 1; | ||
| 647 | has_uninorth = 1; | ||
| 648 | hose->ops = ¯isc_pci_ops; | ||
| 649 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
| 650 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
| 651 | /* We "know" that the bridge at f2000000 has the PCI slots. */ | ||
| 652 | return addr->address == 0xf2000000; | ||
| 653 | } | ||
| 654 | |||
| 655 | static void __init | ||
| 656 | setup_bandit(struct pci_controller* hose, struct reg_property* addr) | ||
| 657 | { | ||
| 658 | hose->ops = ¯isc_pci_ops; | ||
| 659 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
| 660 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
| 661 | init_bandit(hose); | ||
| 662 | } | ||
| 663 | |||
| 664 | static void __init | ||
| 665 | setup_chaos(struct pci_controller* hose, struct reg_property* addr) | ||
| 666 | { | ||
| 667 | /* assume a `chaos' bridge */ | ||
| 668 | hose->ops = &chaos_pci_ops; | ||
| 669 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
| 670 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
| 671 | } | ||
| 672 | |||
| 673 | #ifdef CONFIG_POWER4 | ||
| 674 | |||
| 675 | static void __init | ||
| 676 | setup_u3_agp(struct pci_controller* hose, struct reg_property* addr) | ||
| 677 | { | ||
| 678 | /* On G5, we move AGP up to high bus number so we don't need | ||
| 679 | * to reassign bus numbers for HT. If we ever have P2P bridges | ||
| 680 | * on AGP, we'll have to move pci_assign_all_buses to the | ||
| 681 | * pci_controller structure so we enable it for AGP and not for | ||
| 682 | * HT childs. | ||
| 683 | * We hard code the address because of the different size of | ||
| 684 | * the reg address cell, we shall fix that by killing struct | ||
| 685 | * reg_property and using some accessor functions instead | ||
| 686 | */ | ||
| 687 | hose->first_busno = 0xf0; | ||
| 688 | hose->last_busno = 0xff; | ||
| 689 | has_uninorth = 1; | ||
| 690 | hose->ops = ¯isc_pci_ops; | ||
| 691 | hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); | ||
| 692 | hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); | ||
| 693 | |||
| 694 | u3_agp = hose; | ||
| 695 | } | ||
| 696 | |||
| 697 | static void __init | ||
| 698 | setup_u3_ht(struct pci_controller* hose, struct reg_property *addr) | ||
| 699 | { | ||
| 700 | struct device_node *np = (struct device_node *)hose->arch_data; | ||
| 701 | int i, cur; | ||
| 702 | |||
| 703 | hose->ops = &u3_ht_pci_ops; | ||
| 704 | |||
| 705 | /* We hard code the address because of the different size of | ||
| 706 | * the reg address cell, we shall fix that by killing struct | ||
| 707 | * reg_property and using some accessor functions instead | ||
| 708 | */ | ||
| 709 | hose->cfg_data = ioremap(0xf2000000, 0x02000000); | ||
| 710 | |||
| 711 | /* | ||
| 712 | * /ht node doesn't expose a "ranges" property, so we "remove" regions that | ||
| 713 | * have been allocated to AGP. So far, this version of the code doesn't assign | ||
| 714 | * any of the 0xfxxxxxxx "fine" memory regions to /ht. | ||
| 715 | * We need to fix that sooner or later by either parsing all child "ranges" | ||
| 716 | * properties or figuring out the U3 address space decoding logic and | ||
| 717 | * then read its configuration register (if any). | ||
| 718 | */ | ||
| 719 | hose->io_base_phys = 0xf4000000; | ||
| 720 | hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); | ||
| 721 | isa_io_base = (unsigned long) hose->io_base_virt; | ||
| 722 | hose->io_resource.name = np->full_name; | ||
| 723 | hose->io_resource.start = 0; | ||
| 724 | hose->io_resource.end = 0x003fffff; | ||
| 725 | hose->io_resource.flags = IORESOURCE_IO; | ||
| 726 | hose->pci_mem_offset = 0; | ||
| 727 | hose->first_busno = 0; | ||
| 728 | hose->last_busno = 0xef; | ||
| 729 | hose->mem_resources[0].name = np->full_name; | ||
| 730 | hose->mem_resources[0].start = 0x80000000; | ||
| 731 | hose->mem_resources[0].end = 0xefffffff; | ||
| 732 | hose->mem_resources[0].flags = IORESOURCE_MEM; | ||
| 733 | |||
| 734 | if (u3_agp == NULL) { | ||
| 735 | DBG("U3 has no AGP, using full resource range\n"); | ||
| 736 | return; | ||
| 737 | } | ||
| 738 | |||
| 739 | /* We "remove" the AGP resources from the resources allocated to HT, that | ||
| 740 | * is we create "holes". However, that code does assumptions that so far | ||
| 741 | * happen to be true (cross fingers...), typically that resources in the | ||
| 742 | * AGP node are properly ordered | ||
| 743 | */ | ||
| 744 | cur = 0; | ||
| 745 | for (i=0; i<3; i++) { | ||
| 746 | struct resource *res = &u3_agp->mem_resources[i]; | ||
| 747 | if (res->flags != IORESOURCE_MEM) | ||
| 748 | continue; | ||
| 749 | /* We don't care about "fine" resources */ | ||
| 750 | if (res->start >= 0xf0000000) | ||
| 751 | continue; | ||
| 752 | /* Check if it's just a matter of "shrinking" us in one direction */ | ||
| 753 | if (hose->mem_resources[cur].start == res->start) { | ||
| 754 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", | ||
| 755 | cur, hose->mem_resources[cur].start, res->end + 1); | ||
| 756 | hose->mem_resources[cur].start = res->end + 1; | ||
| 757 | continue; | ||
| 758 | } | ||
| 759 | if (hose->mem_resources[cur].end == res->end) { | ||
| 760 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", | ||
| 761 | cur, hose->mem_resources[cur].end, res->start - 1); | ||
| 762 | hose->mem_resources[cur].end = res->start - 1; | ||
| 763 | continue; | ||
| 764 | } | ||
| 765 | /* No, it's not the case, we need a hole */ | ||
| 766 | if (cur == 2) { | ||
| 767 | /* not enough resources to make a hole, we drop part of the range */ | ||
| 768 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); | ||
| 769 | hose->mem_resources[cur].end = res->start - 1; | ||
| 770 | continue; | ||
| 771 | } | ||
| 772 | cur++; | ||
| 773 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", | ||
| 774 | cur-1, res->start - 1, cur, res->end + 1); | ||
| 775 | hose->mem_resources[cur].name = np->full_name; | ||
| 776 | hose->mem_resources[cur].flags = IORESOURCE_MEM; | ||
| 777 | hose->mem_resources[cur].start = res->end + 1; | ||
| 778 | hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; | ||
| 779 | hose->mem_resources[cur-1].end = res->start - 1; | ||
| 780 | } | ||
| 781 | } | ||
| 782 | |||
| 783 | #endif /* CONFIG_POWER4 */ | ||
| 784 | |||
| 785 | void __init | ||
| 786 | setup_grackle(struct pci_controller *hose) | ||
| 787 | { | ||
| 788 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | ||
| 789 | if (machine_is_compatible("AAPL,PowerBook1998")) | ||
| 790 | grackle_set_loop_snoop(hose, 1); | ||
| 791 | #if 0 /* Disabled for now, HW problems ??? */ | ||
| 792 | grackle_set_stg(hose, 1); | ||
| 793 | #endif | ||
| 794 | } | ||
| 795 | |||
| 796 | /* | ||
| 797 | * We assume that if we have a G3 powermac, we have one bridge called | ||
| 798 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, | ||
| 799 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. | ||
| 800 | */ | ||
| 801 | static int __init | ||
| 802 | add_bridge(struct device_node *dev) | ||
| 803 | { | ||
| 804 | int len; | ||
| 805 | struct pci_controller *hose; | ||
| 806 | struct reg_property *addr; | ||
| 807 | char* disp_name; | ||
| 808 | int *bus_range; | ||
| 809 | int primary = 1; | ||
| 810 | |||
| 811 | DBG("Adding PCI host bridge %s\n", dev->full_name); | ||
| 812 | |||
| 813 | addr = (struct reg_property *) get_property(dev, "reg", &len); | ||
| 814 | if (addr == NULL || len < sizeof(*addr)) { | ||
| 815 | printk(KERN_WARNING "Can't use %s: no address\n", | ||
| 816 | dev->full_name); | ||
| 817 | return -ENODEV; | ||
| 818 | } | ||
| 819 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
| 820 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
| 821 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | ||
| 822 | dev->full_name); | ||
| 823 | } | ||
| 824 | |||
| 825 | hose = pcibios_alloc_controller(); | ||
| 826 | if (!hose) | ||
| 827 | return -ENOMEM; | ||
| 828 | hose->arch_data = dev; | ||
| 829 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
| 830 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
| 831 | |||
| 832 | disp_name = NULL; | ||
| 833 | #ifdef CONFIG_POWER4 | ||
| 834 | if (device_is_compatible(dev, "u3-agp")) { | ||
| 835 | setup_u3_agp(hose, addr); | ||
| 836 | disp_name = "U3-AGP"; | ||
| 837 | primary = 0; | ||
| 838 | } else if (device_is_compatible(dev, "u3-ht")) { | ||
| 839 | setup_u3_ht(hose, addr); | ||
| 840 | disp_name = "U3-HT"; | ||
| 841 | primary = 1; | ||
| 842 | } else | ||
| 843 | #endif /* CONFIG_POWER4 */ | ||
| 844 | if (device_is_compatible(dev, "uni-north")) { | ||
| 845 | primary = setup_uninorth(hose, addr); | ||
| 846 | disp_name = "UniNorth"; | ||
| 847 | } else if (strcmp(dev->name, "pci") == 0) { | ||
| 848 | /* XXX assume this is a mpc106 (grackle) */ | ||
| 849 | setup_grackle(hose); | ||
| 850 | disp_name = "Grackle (MPC106)"; | ||
| 851 | } else if (strcmp(dev->name, "bandit") == 0) { | ||
| 852 | setup_bandit(hose, addr); | ||
| 853 | disp_name = "Bandit"; | ||
| 854 | } else if (strcmp(dev->name, "chaos") == 0) { | ||
| 855 | setup_chaos(hose, addr); | ||
| 856 | disp_name = "Chaos"; | ||
| 857 | primary = 0; | ||
| 858 | } | ||
| 859 | printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", | ||
| 860 | disp_name, addr->address, hose->first_busno, hose->last_busno); | ||
| 861 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
| 862 | hose, hose->cfg_addr, hose->cfg_data); | ||
| 863 | |||
| 864 | /* Interpret the "ranges" property */ | ||
| 865 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
| 866 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
| 867 | |||
| 868 | /* Fixup "bus-range" OF property */ | ||
| 869 | fixup_bus_range(dev); | ||
| 870 | |||
| 871 | return 0; | ||
| 872 | } | ||
| 873 | |||
| 874 | static void __init | ||
| 875 | pcibios_fixup_OF_interrupts(void) | ||
| 876 | { | ||
| 877 | struct pci_dev* dev = NULL; | ||
| 878 | |||
| 879 | /* | ||
| 880 | * Open Firmware often doesn't initialize the | ||
| 881 | * PCI_INTERRUPT_LINE config register properly, so we | ||
| 882 | * should find the device node and apply the interrupt | ||
| 883 | * obtained from the OF device-tree | ||
| 884 | */ | ||
| 885 | for_each_pci_dev(dev) { | ||
| 886 | struct device_node *node; | ||
| 887 | node = pci_device_to_OF_node(dev); | ||
| 888 | /* this is the node, see if it has interrupts */ | ||
| 889 | if (node && node->n_intrs > 0) | ||
| 890 | dev->irq = node->intrs[0].line; | ||
| 891 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
| 892 | } | ||
| 893 | } | ||
| 894 | |||
| 895 | void __init | ||
| 896 | pmac_pcibios_fixup(void) | ||
| 897 | { | ||
| 898 | /* Fixup interrupts according to OF tree */ | ||
| 899 | pcibios_fixup_OF_interrupts(); | ||
| 900 | } | ||
| 901 | |||
| 902 | int | ||
| 903 | pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) | ||
| 904 | { | ||
| 905 | struct device_node* node; | ||
| 906 | int updatecfg = 0; | ||
| 907 | int uninorth_child; | ||
| 908 | |||
| 909 | node = pci_device_to_OF_node(dev); | ||
| 910 | |||
| 911 | /* We don't want to enable USB controllers absent from the OF tree | ||
| 912 | * (iBook second controller) | ||
| 913 | */ | ||
| 914 | if (dev->vendor == PCI_VENDOR_ID_APPLE | ||
| 915 | && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) | ||
| 916 | && !node) { | ||
| 917 | printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n", | ||
| 918 | pci_name(dev)); | ||
| 919 | return -EINVAL; | ||
| 920 | } | ||
| 921 | |||
| 922 | if (!node) | ||
| 923 | return 0; | ||
| 924 | |||
| 925 | uninorth_child = node->parent && | ||
| 926 | device_is_compatible(node->parent, "uni-north"); | ||
| 927 | |||
| 928 | /* Firewire & GMAC were disabled after PCI probe, the driver is | ||
| 929 | * claiming them, we must re-enable them now. | ||
| 930 | */ | ||
| 931 | if (uninorth_child && !strcmp(node->name, "firewire") && | ||
| 932 | (device_is_compatible(node, "pci106b,18") || | ||
| 933 | device_is_compatible(node, "pci106b,30") || | ||
| 934 | device_is_compatible(node, "pci11c1,5811"))) { | ||
| 935 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); | ||
| 936 | pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); | ||
| 937 | updatecfg = 1; | ||
| 938 | } | ||
| 939 | if (uninorth_child && !strcmp(node->name, "ethernet") && | ||
| 940 | device_is_compatible(node, "gmac")) { | ||
| 941 | pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); | ||
| 942 | updatecfg = 1; | ||
| 943 | } | ||
| 944 | |||
| 945 | if (updatecfg) { | ||
| 946 | u16 cmd; | ||
| 947 | |||
| 948 | /* | ||
| 949 | * Make sure PCI is correctly configured | ||
| 950 | * | ||
| 951 | * We use old pci_bios versions of the function since, by | ||
| 952 | * default, gmac is not powered up, and so will be absent | ||
| 953 | * from the kernel initial PCI lookup. | ||
| 954 | * | ||
| 955 | * Should be replaced by 2.4 new PCI mechanisms and really | ||
| 956 | * register the device. | ||
| 957 | */ | ||
| 958 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 959 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; | ||
| 960 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 961 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); | ||
| 962 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); | ||
| 963 | } | ||
| 964 | |||
| 965 | return 0; | ||
| 966 | } | ||
| 967 | |||
| 968 | /* We power down some devices after they have been probed. They'll | ||
| 969 | * be powered back on later on | ||
| 970 | */ | ||
| 971 | void __init | ||
| 972 | pmac_pcibios_after_init(void) | ||
| 973 | { | ||
| 974 | struct device_node* nd; | ||
| 975 | |||
| 976 | #ifdef CONFIG_BLK_DEV_IDE | ||
| 977 | struct pci_dev *dev = NULL; | ||
| 978 | |||
| 979 | /* OF fails to initialize IDE controllers on macs | ||
| 980 | * (and maybe other machines) | ||
| 981 | * | ||
| 982 | * Ideally, this should be moved to the IDE layer, but we need | ||
| 983 | * to check specifically with Andre Hedrick how to do it cleanly | ||
| 984 | * since the common IDE code seem to care about the fact that the | ||
| 985 | * BIOS may have disabled a controller. | ||
| 986 | * | ||
| 987 | * -- BenH | ||
| 988 | */ | ||
| 989 | for_each_pci_dev(dev) { | ||
| 990 | if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) | ||
| 991 | pci_enable_device(dev); | ||
| 992 | } | ||
| 993 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
| 994 | |||
| 995 | nd = find_devices("firewire"); | ||
| 996 | while (nd) { | ||
| 997 | if (nd->parent && (device_is_compatible(nd, "pci106b,18") || | ||
| 998 | device_is_compatible(nd, "pci106b,30") || | ||
| 999 | device_is_compatible(nd, "pci11c1,5811")) | ||
| 1000 | && device_is_compatible(nd->parent, "uni-north")) { | ||
| 1001 | pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); | ||
| 1002 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); | ||
| 1003 | } | ||
| 1004 | nd = nd->next; | ||
| 1005 | } | ||
| 1006 | nd = find_devices("ethernet"); | ||
| 1007 | while (nd) { | ||
| 1008 | if (nd->parent && device_is_compatible(nd, "gmac") | ||
| 1009 | && device_is_compatible(nd->parent, "uni-north")) | ||
| 1010 | pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); | ||
| 1011 | nd = nd->next; | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | void pmac_pci_fixup_cardbus(struct pci_dev* dev) | ||
| 1016 | { | ||
| 1017 | if (_machine != _MACH_Pmac) | ||
| 1018 | return; | ||
| 1019 | /* | ||
| 1020 | * Fix the interrupt routing on the various cardbus bridges | ||
| 1021 | * used on powerbooks | ||
| 1022 | */ | ||
| 1023 | if (dev->vendor != PCI_VENDOR_ID_TI) | ||
| 1024 | return; | ||
| 1025 | if (dev->device == PCI_DEVICE_ID_TI_1130 || | ||
| 1026 | dev->device == PCI_DEVICE_ID_TI_1131) { | ||
| 1027 | u8 val; | ||
| 1028 | /* Enable PCI interrupt */ | ||
| 1029 | if (pci_read_config_byte(dev, 0x91, &val) == 0) | ||
| 1030 | pci_write_config_byte(dev, 0x91, val | 0x30); | ||
| 1031 | /* Disable ISA interrupt mode */ | ||
| 1032 | if (pci_read_config_byte(dev, 0x92, &val) == 0) | ||
| 1033 | pci_write_config_byte(dev, 0x92, val & ~0x06); | ||
| 1034 | } | ||
| 1035 | if (dev->device == PCI_DEVICE_ID_TI_1210 || | ||
| 1036 | dev->device == PCI_DEVICE_ID_TI_1211 || | ||
| 1037 | dev->device == PCI_DEVICE_ID_TI_1410 || | ||
| 1038 | dev->device == PCI_DEVICE_ID_TI_1510) { | ||
| 1039 | u8 val; | ||
| 1040 | /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA | ||
| 1041 | signal out the MFUNC0 pin */ | ||
| 1042 | if (pci_read_config_byte(dev, 0x8c, &val) == 0) | ||
| 1043 | pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2); | ||
| 1044 | /* Disable ISA interrupt mode */ | ||
| 1045 | if (pci_read_config_byte(dev, 0x92, &val) == 0) | ||
| 1046 | pci_write_config_byte(dev, 0x92, val & ~0x06); | ||
| 1047 | } | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus); | ||
| 1051 | |||
| 1052 | void pmac_pci_fixup_pciata(struct pci_dev* dev) | ||
| 1053 | { | ||
| 1054 | u8 progif = 0; | ||
| 1055 | |||
| 1056 | /* | ||
| 1057 | * On PowerMacs, we try to switch any PCI ATA controller to | ||
| 1058 | * fully native mode | ||
| 1059 | */ | ||
| 1060 | if (_machine != _MACH_Pmac) | ||
| 1061 | return; | ||
| 1062 | /* Some controllers don't have the class IDE */ | ||
| 1063 | if (dev->vendor == PCI_VENDOR_ID_PROMISE) | ||
| 1064 | switch(dev->device) { | ||
| 1065 | case PCI_DEVICE_ID_PROMISE_20246: | ||
| 1066 | case PCI_DEVICE_ID_PROMISE_20262: | ||
| 1067 | case PCI_DEVICE_ID_PROMISE_20263: | ||
| 1068 | case PCI_DEVICE_ID_PROMISE_20265: | ||
| 1069 | case PCI_DEVICE_ID_PROMISE_20267: | ||
| 1070 | case PCI_DEVICE_ID_PROMISE_20268: | ||
| 1071 | case PCI_DEVICE_ID_PROMISE_20269: | ||
| 1072 | case PCI_DEVICE_ID_PROMISE_20270: | ||
| 1073 | case PCI_DEVICE_ID_PROMISE_20271: | ||
| 1074 | case PCI_DEVICE_ID_PROMISE_20275: | ||
| 1075 | case PCI_DEVICE_ID_PROMISE_20276: | ||
| 1076 | case PCI_DEVICE_ID_PROMISE_20277: | ||
| 1077 | goto good; | ||
| 1078 | } | ||
| 1079 | /* Others, check PCI class */ | ||
| 1080 | if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) | ||
| 1081 | return; | ||
| 1082 | good: | ||
| 1083 | pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); | ||
| 1084 | if ((progif & 5) != 5) { | ||
| 1085 | printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev)); | ||
| 1086 | (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); | ||
| 1087 | if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || | ||
| 1088 | (progif & 5) != 5) | ||
| 1089 | printk(KERN_ERR "Rewrite of PROGIF failed !\n"); | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); | ||
| 1093 | |||
| 1094 | |||
| 1095 | /* | ||
| 1096 | * Disable second function on K2-SATA, it's broken | ||
| 1097 | * and disable IO BARs on first one | ||
| 1098 | */ | ||
| 1099 | void pmac_pci_fixup_k2_sata(struct pci_dev* dev) | ||
| 1100 | { | ||
| 1101 | int i; | ||
| 1102 | u16 cmd; | ||
| 1103 | |||
| 1104 | if (PCI_FUNC(dev->devfn) > 0) { | ||
| 1105 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 1106 | cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); | ||
| 1107 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 1108 | for (i = 0; i < 6; i++) { | ||
| 1109 | dev->resource[i].start = dev->resource[i].end = 0; | ||
| 1110 | dev->resource[i].flags = 0; | ||
| 1111 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); | ||
| 1112 | } | ||
| 1113 | } else { | ||
| 1114 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
| 1115 | cmd &= ~PCI_COMMAND_IO; | ||
| 1116 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
| 1117 | for (i = 0; i < 5; i++) { | ||
| 1118 | dev->resource[i].start = dev->resource[i].end = 0; | ||
| 1119 | dev->resource[i].flags = 0; | ||
| 1120 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); | ||
| 1121 | } | ||
| 1122 | } | ||
| 1123 | } | ||
| 1124 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata); | ||
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c deleted file mode 100644 index 4742bf609357..000000000000 --- a/arch/ppc/platforms/pmac_pic.c +++ /dev/null  | |||
| @@ -1,693 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support for the interrupt controllers found on Power Macintosh, | ||
| 3 | * currently Apple's "Grand Central" interrupt controller in all | ||
| 4 | * it's incarnations. OpenPIC support used on newer machines is | ||
| 5 | * in a separate file | ||
| 6 | * | ||
| 7 | * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) | ||
| 8 | * | ||
| 9 | * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version | ||
| 14 | * 2 of the License, or (at your option) any later version. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/config.h> | ||
| 19 | #include <linux/stddef.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/signal.h> | ||
| 23 | #include <linux/pci.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/sysdev.h> | ||
| 26 | #include <linux/adb.h> | ||
| 27 | #include <linux/pmu.h> | ||
| 28 | |||
| 29 | #include <asm/sections.h> | ||
| 30 | #include <asm/io.h> | ||
| 31 | #include <asm/smp.h> | ||
| 32 | #include <asm/prom.h> | ||
| 33 | #include <asm/pci-bridge.h> | ||
| 34 | #include <asm/time.h> | ||
| 35 | #include <asm/open_pic.h> | ||
| 36 | #include <asm/xmon.h> | ||
| 37 | #include <asm/pmac_feature.h> | ||
| 38 | #include <asm/machdep.h> | ||
| 39 | |||
| 40 | #include "pmac_pic.h" | ||
| 41 | |||
| 42 | /* | ||
| 43 | * XXX this should be in xmon.h, but putting it there means xmon.h | ||
| 44 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | ||
| 45 | * causes all sorts of problems. -- paulus | ||
| 46 | */ | ||
| 47 | extern irqreturn_t xmon_irq(int, void *, struct pt_regs *); | ||
| 48 | |||
| 49 | struct pmac_irq_hw { | ||
| 50 | unsigned int event; | ||
| 51 | unsigned int enable; | ||
| 52 | unsigned int ack; | ||
| 53 | unsigned int level; | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* Default addresses */ | ||
| 57 | static volatile struct pmac_irq_hw *pmac_irq_hw[4] = { | ||
| 58 | (struct pmac_irq_hw *) 0xf3000020, | ||
| 59 | (struct pmac_irq_hw *) 0xf3000010, | ||
| 60 | (struct pmac_irq_hw *) 0xf4000020, | ||
| 61 | (struct pmac_irq_hw *) 0xf4000010, | ||
| 62 | }; | ||
| 63 | |||
| 64 | #define GC_LEVEL_MASK 0x3ff00000 | ||
| 65 | #define OHARE_LEVEL_MASK 0x1ff00000 | ||
| 66 | #define HEATHROW_LEVEL_MASK 0x1ff00000 | ||
| 67 | |||
| 68 | static int max_irqs; | ||
| 69 | static int max_real_irqs; | ||
| 70 | static u32 level_mask[4]; | ||
| 71 | |||
| 72 | static DEFINE_SPINLOCK(pmac_pic_lock); | ||
| 73 | |||
| 74 | |||
| 75 | #define GATWICK_IRQ_POOL_SIZE 10 | ||
| 76 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | ||
| 77 | |||
| 78 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | ||
| 79 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | ||
| 80 | |||
| 81 | /* | ||
| 82 | * Mark an irq as "lost". This is only used on the pmac | ||
| 83 | * since it can lose interrupts (see pmac_set_irq_mask). | ||
| 84 | * -- Cort | ||
| 85 | */ | ||
| 86 | void | ||
| 87 | __set_lost(unsigned long irq_nr, int nokick) | ||
| 88 | { | ||
| 89 | if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { | ||
| 90 | atomic_inc(&ppc_n_lost_interrupts); | ||
| 91 | if (!nokick) | ||
| 92 | set_dec(1); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | static void | ||
| 97 | pmac_mask_and_ack_irq(unsigned int irq_nr) | ||
| 98 | { | ||
| 99 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
| 100 | int i = irq_nr >> 5; | ||
| 101 | unsigned long flags; | ||
| 102 | |||
| 103 | if ((unsigned)irq_nr >= max_irqs) | ||
| 104 | return; | ||
| 105 | |||
| 106 | clear_bit(irq_nr, ppc_cached_irq_mask); | ||
| 107 | if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) | ||
| 108 | atomic_dec(&ppc_n_lost_interrupts); | ||
| 109 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
| 110 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | ||
| 111 | out_le32(&pmac_irq_hw[i]->ack, bit); | ||
| 112 | do { | ||
| 113 | /* make sure ack gets to controller before we enable | ||
| 114 | interrupts */ | ||
| 115 | mb(); | ||
| 116 | } while((in_le32(&pmac_irq_hw[i]->enable) & bit) | ||
| 117 | != (ppc_cached_irq_mask[i] & bit)); | ||
| 118 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) | ||
| 122 | { | ||
| 123 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
| 124 | int i = irq_nr >> 5; | ||
| 125 | unsigned long flags; | ||
| 126 | |||
| 127 | if ((unsigned)irq_nr >= max_irqs) | ||
| 128 | return; | ||
| 129 | |||
| 130 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
| 131 | /* enable unmasked interrupts */ | ||
| 132 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | ||
| 133 | |||
| 134 | do { | ||
| 135 | /* make sure mask gets to controller before we | ||
| 136 | return to user */ | ||
| 137 | mb(); | ||
| 138 | } while((in_le32(&pmac_irq_hw[i]->enable) & bit) | ||
| 139 | != (ppc_cached_irq_mask[i] & bit)); | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Unfortunately, setting the bit in the enable register | ||
| 143 | * when the device interrupt is already on *doesn't* set | ||
| 144 | * the bit in the flag register or request another interrupt. | ||
| 145 | */ | ||
| 146 | if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) | ||
| 147 | __set_lost((ulong)irq_nr, nokicklost); | ||
| 148 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
| 149 | } | ||
| 150 | |||
| 151 | /* When an irq gets requested for the first client, if it's an | ||
| 152 | * edge interrupt, we clear any previous one on the controller | ||
| 153 | */ | ||
| 154 | static unsigned int pmac_startup_irq(unsigned int irq_nr) | ||
| 155 | { | ||
| 156 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
| 157 | int i = irq_nr >> 5; | ||
| 158 | |||
| 159 | if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) | ||
| 160 | out_le32(&pmac_irq_hw[i]->ack, bit); | ||
| 161 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
| 162 | pmac_set_irq_mask(irq_nr, 0); | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | static void pmac_mask_irq(unsigned int irq_nr) | ||
| 168 | { | ||
| 169 | clear_bit(irq_nr, ppc_cached_irq_mask); | ||
| 170 | pmac_set_irq_mask(irq_nr, 0); | ||
| 171 | mb(); | ||
| 172 | } | ||
| 173 | |||
| 174 | static void pmac_unmask_irq(unsigned int irq_nr) | ||
| 175 | { | ||
| 176 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
| 177 | pmac_set_irq_mask(irq_nr, 0); | ||
| 178 | } | ||
| 179 | |||
| 180 | static void pmac_end_irq(unsigned int irq_nr) | ||
| 181 | { | ||
| 182 | if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) | ||
| 183 | && irq_desc[irq_nr].action) { | ||
| 184 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
| 185 | pmac_set_irq_mask(irq_nr, 1); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | struct hw_interrupt_type pmac_pic = { | ||
| 191 | .typename = " PMAC-PIC ", | ||
| 192 | .startup = pmac_startup_irq, | ||
| 193 | .enable = pmac_unmask_irq, | ||
| 194 | .disable = pmac_mask_irq, | ||
| 195 | .ack = pmac_mask_and_ack_irq, | ||
| 196 | .end = pmac_end_irq, | ||
| 197 | }; | ||
| 198 | |||
| 199 | struct hw_interrupt_type gatwick_pic = { | ||
| 200 | .typename = " GATWICK ", | ||
| 201 | .startup = pmac_startup_irq, | ||
| 202 | .enable = pmac_unmask_irq, | ||
| 203 | .disable = pmac_mask_irq, | ||
| 204 | .ack = pmac_mask_and_ack_irq, | ||
| 205 | .end = pmac_end_irq, | ||
| 206 | }; | ||
| 207 | |||
| 208 | static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
| 209 | { | ||
| 210 | int irq, bits; | ||
| 211 | |||
| 212 | for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { | ||
| 213 | int i = irq >> 5; | ||
| 214 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | ||
| 215 | /* We must read level interrupts from the level register */ | ||
| 216 | bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); | ||
| 217 | bits &= ppc_cached_irq_mask[i]; | ||
| 218 | if (bits == 0) | ||
| 219 | continue; | ||
| 220 | irq += __ilog2(bits); | ||
| 221 | __do_IRQ(irq, regs); | ||
| 222 | return IRQ_HANDLED; | ||
| 223 | } | ||
| 224 | printk("gatwick irq not from gatwick pic\n"); | ||
| 225 | return IRQ_NONE; | ||
| 226 | } | ||
| 227 | |||
| 228 | int | ||
| 229 | pmac_get_irq(struct pt_regs *regs) | ||
| 230 | { | ||
| 231 | int irq; | ||
| 232 | unsigned long bits = 0; | ||
| 233 | |||
| 234 | #ifdef CONFIG_SMP | ||
| 235 | void psurge_smp_message_recv(struct pt_regs *); | ||
| 236 | |||
| 237 | /* IPI's are a hack on the powersurge -- Cort */ | ||
| 238 | if ( smp_processor_id() != 0 ) { | ||
| 239 | psurge_smp_message_recv(regs); | ||
| 240 | return -2; /* ignore, already handled */ | ||
| 241 | } | ||
| 242 | #endif /* CONFIG_SMP */ | ||
| 243 | for (irq = max_real_irqs; (irq -= 32) >= 0; ) { | ||
| 244 | int i = irq >> 5; | ||
| 245 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | ||
| 246 | /* We must read level interrupts from the level register */ | ||
| 247 | bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); | ||
| 248 | bits &= ppc_cached_irq_mask[i]; | ||
| 249 | if (bits == 0) | ||
| 250 | continue; | ||
| 251 | irq += __ilog2(bits); | ||
| 252 | break; | ||
| 253 | } | ||
| 254 | |||
| 255 | return irq; | ||
| 256 | } | ||
| 257 | |||
| 258 | /* This routine will fix some missing interrupt values in the device tree | ||
| 259 | * on the gatwick mac-io controller used by some PowerBooks | ||
| 260 | */ | ||
| 261 | static void __init | ||
| 262 | pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | ||
| 263 | { | ||
| 264 | struct device_node *node; | ||
| 265 | int count; | ||
| 266 | |||
| 267 | memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); | ||
| 268 | node = gw->child; | ||
| 269 | count = 0; | ||
| 270 | while(node) | ||
| 271 | { | ||
| 272 | /* Fix SCC */ | ||
| 273 | if (strcasecmp(node->name, "escc") == 0) | ||
| 274 | if (node->child) { | ||
| 275 | if (node->child->n_intrs < 3) { | ||
| 276 | node->child->intrs = &gatwick_int_pool[count]; | ||
| 277 | count += 3; | ||
| 278 | } | ||
| 279 | node->child->n_intrs = 3; | ||
| 280 | node->child->intrs[0].line = 15+irq_base; | ||
| 281 | node->child->intrs[1].line = 4+irq_base; | ||
| 282 | node->child->intrs[2].line = 5+irq_base; | ||
| 283 | printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", | ||
| 284 | node->child->intrs[0].line, | ||
| 285 | node->child->intrs[1].line, | ||
| 286 | node->child->intrs[2].line); | ||
| 287 | } | ||
| 288 | /* Fix media-bay & left SWIM */ | ||
| 289 | if (strcasecmp(node->name, "media-bay") == 0) { | ||
| 290 | struct device_node* ya_node; | ||
| 291 | |||
| 292 | if (node->n_intrs == 0) | ||
| 293 | node->intrs = &gatwick_int_pool[count++]; | ||
| 294 | node->n_intrs = 1; | ||
| 295 | node->intrs[0].line = 29+irq_base; | ||
| 296 | printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", | ||
| 297 | node->intrs[0].line); | ||
| 298 | |||
| 299 | ya_node = node->child; | ||
| 300 | while(ya_node) | ||
| 301 | { | ||
| 302 | if (strcasecmp(ya_node->name, "floppy") == 0) { | ||
| 303 | if (ya_node->n_intrs < 2) { | ||
| 304 | ya_node->intrs = &gatwick_int_pool[count]; | ||
| 305 | count += 2; | ||
| 306 | } | ||
| 307 | ya_node->n_intrs = 2; | ||
| 308 | ya_node->intrs[0].line = 19+irq_base; | ||
| 309 | ya_node->intrs[1].line = 1+irq_base; | ||
| 310 | printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", | ||
| 311 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
| 312 | } | ||
| 313 | if (strcasecmp(ya_node->name, "ata4") == 0) { | ||
| 314 | if (ya_node->n_intrs < 2) { | ||
| 315 | ya_node->intrs = &gatwick_int_pool[count]; | ||
| 316 | count += 2; | ||
| 317 | } | ||
| 318 | ya_node->n_intrs = 2; | ||
| 319 | ya_node->intrs[0].line = 14+irq_base; | ||
| 320 | ya_node->intrs[1].line = 3+irq_base; | ||
| 321 | printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", | ||
| 322 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
| 323 | } | ||
| 324 | ya_node = ya_node->sibling; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | node = node->sibling; | ||
| 328 | } | ||
| 329 | if (count > 10) { | ||
| 330 | printk("WARNING !! Gatwick interrupt pool overflow\n"); | ||
| 331 | printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); | ||
| 332 | printk(" requested = %d\n", count); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | /* | ||
| 337 | * The PowerBook 3400/2400/3500 can have a combo ethernet/modem | ||
| 338 | * card which includes an ohare chip that acts as a second interrupt | ||
| 339 | * controller. If we find this second ohare, set it up and fix the | ||
| 340 | * interrupt value in the device tree for the ethernet chip. | ||
| 341 | */ | ||
| 342 | static int __init enable_second_ohare(void) | ||
| 343 | { | ||
| 344 | unsigned char bus, devfn; | ||
| 345 | unsigned short cmd; | ||
| 346 | unsigned long addr; | ||
| 347 | struct device_node *irqctrler = find_devices("pci106b,7"); | ||
| 348 | struct device_node *ether; | ||
| 349 | |||
| 350 | if (irqctrler == NULL || irqctrler->n_addrs <= 0) | ||
| 351 | return -1; | ||
| 352 | addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); | ||
| 353 | pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); | ||
| 354 | max_irqs = 64; | ||
| 355 | if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { | ||
| 356 | struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); | ||
| 357 | if (!hose) | ||
| 358 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); | ||
| 359 | else { | ||
| 360 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | ||
| 361 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
| 362 | cmd &= ~PCI_COMMAND_IO; | ||
| 363 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | /* Fix interrupt for the modem/ethernet combo controller. The number | ||
| 368 | in the device tree (27) is bogus (correct for the ethernet-only | ||
| 369 | board but not the combo ethernet/modem board). | ||
| 370 | The real interrupt is 28 on the second controller -> 28+32 = 60. | ||
| 371 | */ | ||
| 372 | ether = find_devices("pci1011,14"); | ||
| 373 | if (ether && ether->n_intrs > 0) { | ||
| 374 | ether->intrs[0].line = 60; | ||
| 375 | printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", | ||
| 376 | ether->intrs[0].line); | ||
| 377 | } | ||
| 378 | |||
| 379 | /* Return the interrupt number of the cascade */ | ||
| 380 | return irqctrler->intrs[0].line; | ||
| 381 | } | ||
| 382 | |||
| 383 | #ifdef CONFIG_POWER4 | ||
| 384 | static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
| 385 | { | ||
| 386 | int irq; | ||
| 387 | |||
| 388 | irq = openpic2_get_irq(regs); | ||
| 389 | if (irq != -1) | ||
| 390 | __do_IRQ(irq, regs); | ||
| 391 | return IRQ_HANDLED; | ||
| 392 | } | ||
| 393 | |||
| 394 | static struct irqaction k2u3_cascade_action = { | ||
| 395 | .handler = k2u3_action, | ||
| 396 | .flags = 0, | ||
| 397 | .mask = CPU_MASK_NONE, | ||
| 398 | .name = "U3->K2 Cascade", | ||
| 399 | }; | ||
| 400 | #endif /* CONFIG_POWER4 */ | ||
| 401 | |||
| 402 | #ifdef CONFIG_XMON | ||
| 403 | static struct irqaction xmon_action = { | ||
| 404 | .handler = xmon_irq, | ||
| 405 | .flags = 0, | ||
| 406 | .mask = CPU_MASK_NONE, | ||
| 407 | .name = "NMI - XMON" | ||
| 408 | }; | ||
| 409 | #endif | ||
| 410 | |||
| 411 | static struct irqaction gatwick_cascade_action = { | ||
| 412 | .handler = gatwick_action, | ||
| 413 | .flags = SA_INTERRUPT, | ||
| 414 | .mask = CPU_MASK_NONE, | ||
| 415 | .name = "cascade", | ||
| 416 | }; | ||
| 417 | |||
| 418 | void __init pmac_pic_init(void) | ||
| 419 | { | ||
| 420 | int i; | ||
| 421 | struct device_node *irqctrler = NULL; | ||
| 422 | struct device_node *irqctrler2 = NULL; | ||
| 423 | struct device_node *np; | ||
| 424 | unsigned long addr; | ||
| 425 | int irq_cascade = -1; | ||
| 426 | |||
| 427 | /* We first try to detect Apple's new Core99 chipset, since mac-io | ||
| 428 | * is quite different on those machines and contains an IBM MPIC2. | ||
| 429 | */ | ||
| 430 | np = find_type_devices("open-pic"); | ||
| 431 | while(np) { | ||
| 432 | if (np->parent && !strcmp(np->parent->name, "u3")) | ||
| 433 | irqctrler2 = np; | ||
| 434 | else | ||
| 435 | irqctrler = np; | ||
| 436 | np = np->next; | ||
| 437 | } | ||
| 438 | if (irqctrler != NULL) | ||
| 439 | { | ||
| 440 | if (irqctrler->n_addrs > 0) | ||
| 441 | { | ||
| 442 | unsigned char senses[128]; | ||
| 443 | |||
| 444 | printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", | ||
| 445 | irqctrler->addrs[0].address); | ||
| 446 | |||
| 447 | prom_get_irq_senses(senses, 0, 128); | ||
| 448 | OpenPIC_InitSenses = senses; | ||
| 449 | OpenPIC_NumInitSenses = 128; | ||
| 450 | ppc_md.get_irq = openpic_get_irq; | ||
| 451 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0); | ||
| 452 | OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, | ||
| 453 | irqctrler->addrs[0].size); | ||
| 454 | openpic_init(0); | ||
| 455 | |||
| 456 | #ifdef CONFIG_POWER4 | ||
| 457 | if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && | ||
| 458 | irqctrler2->n_addrs > 0) { | ||
| 459 | printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", | ||
| 460 | irqctrler2->addrs[0].address, | ||
| 461 | irqctrler2->intrs[0].line); | ||
| 462 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); | ||
| 463 | OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, | ||
| 464 | irqctrler2->addrs[0].size); | ||
| 465 | prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET, | ||
| 466 | PMAC_OPENPIC2_OFFSET+128); | ||
| 467 | OpenPIC_InitSenses = senses; | ||
| 468 | OpenPIC_NumInitSenses = 128; | ||
| 469 | openpic2_init(PMAC_OPENPIC2_OFFSET); | ||
| 470 | |||
| 471 | if (setup_irq(irqctrler2->intrs[0].line, | ||
| 472 | &k2u3_cascade_action)) | ||
| 473 | printk("Unable to get OpenPIC IRQ for cascade\n"); | ||
| 474 | } | ||
| 475 | #endif /* CONFIG_POWER4 */ | ||
| 476 | |||
| 477 | #ifdef CONFIG_XMON | ||
| 478 | { | ||
| 479 | struct device_node* pswitch; | ||
| 480 | int nmi_irq; | ||
| 481 | |||
| 482 | pswitch = find_devices("programmer-switch"); | ||
| 483 | if (pswitch && pswitch->n_intrs) { | ||
| 484 | nmi_irq = pswitch->intrs[0].line; | ||
| 485 | openpic_init_nmi_irq(nmi_irq); | ||
| 486 | setup_irq(nmi_irq, &xmon_action); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | #endif /* CONFIG_XMON */ | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | irqctrler = NULL; | ||
| 493 | } | ||
| 494 | |||
| 495 | /* Get the level/edge settings, assume if it's not | ||
| 496 | * a Grand Central nor an OHare, then it's an Heathrow | ||
| 497 | * (or Paddington). | ||
| 498 | */ | ||
| 499 | if (find_devices("gc")) | ||
| 500 | level_mask[0] = GC_LEVEL_MASK; | ||
| 501 | else if (find_devices("ohare")) { | ||
| 502 | level_mask[0] = OHARE_LEVEL_MASK; | ||
| 503 | /* We might have a second cascaded ohare */ | ||
| 504 | level_mask[1] = OHARE_LEVEL_MASK; | ||
| 505 | } else { | ||
| 506 | level_mask[0] = HEATHROW_LEVEL_MASK; | ||
| 507 | level_mask[1] = 0; | ||
| 508 | /* We might have a second cascaded heathrow */ | ||
| 509 | level_mask[2] = HEATHROW_LEVEL_MASK; | ||
| 510 | level_mask[3] = 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | /* | ||
| 514 | * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts, | ||
| 515 | * 1998 G3 Series PowerBooks have 128, | ||
| 516 | * other powermacs have 32. | ||
| 517 | * The combo ethernet/modem card for the Powerstar powerbooks | ||
| 518 | * (2400/3400/3500, ohare based) has a second ohare chip | ||
| 519 | * effectively making a total of 64. | ||
| 520 | */ | ||
| 521 | max_irqs = max_real_irqs = 32; | ||
| 522 | irqctrler = find_devices("mac-io"); | ||
| 523 | if (irqctrler) | ||
| 524 | { | ||
| 525 | max_real_irqs = 64; | ||
| 526 | if (irqctrler->next) | ||
| 527 | max_irqs = 128; | ||
| 528 | else | ||
| 529 | max_irqs = 64; | ||
| 530 | } | ||
| 531 | for ( i = 0; i < max_real_irqs ; i++ ) | ||
| 532 | irq_desc[i].handler = &pmac_pic; | ||
| 533 | |||
| 534 | /* get addresses of first controller */ | ||
| 535 | if (irqctrler) { | ||
| 536 | if (irqctrler->n_addrs > 0) { | ||
| 537 | addr = (unsigned long) | ||
| 538 | ioremap(irqctrler->addrs[0].address, 0x40); | ||
| 539 | for (i = 0; i < 2; ++i) | ||
| 540 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | ||
| 541 | (addr + (2 - i) * 0x10); | ||
| 542 | } | ||
| 543 | |||
| 544 | /* get addresses of second controller */ | ||
| 545 | irqctrler = irqctrler->next; | ||
| 546 | if (irqctrler && irqctrler->n_addrs > 0) { | ||
| 547 | addr = (unsigned long) | ||
| 548 | ioremap(irqctrler->addrs[0].address, 0x40); | ||
| 549 | for (i = 2; i < 4; ++i) | ||
| 550 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | ||
| 551 | (addr + (4 - i) * 0x10); | ||
| 552 | irq_cascade = irqctrler->intrs[0].line; | ||
| 553 | if (device_is_compatible(irqctrler, "gatwick")) | ||
| 554 | pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); | ||
| 555 | } | ||
| 556 | } else { | ||
| 557 | /* older powermacs have a GC (grand central) or ohare at | ||
| 558 | f3000000, with interrupt control registers at f3000020. */ | ||
| 559 | addr = (unsigned long) ioremap(0xf3000000, 0x40); | ||
| 560 | pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20); | ||
| 561 | } | ||
| 562 | |||
| 563 | /* PowerBooks 3400 and 3500 can have a second controller in a second | ||
| 564 | ohare chip, on the combo ethernet/modem card */ | ||
| 565 | if (machine_is_compatible("AAPL,3400/2400") | ||
| 566 | || machine_is_compatible("AAPL,3500")) | ||
| 567 | irq_cascade = enable_second_ohare(); | ||
| 568 | |||
| 569 | /* disable all interrupts in all controllers */ | ||
| 570 | for (i = 0; i * 32 < max_irqs; ++i) | ||
| 571 | out_le32(&pmac_irq_hw[i]->enable, 0); | ||
| 572 | /* mark level interrupts */ | ||
| 573 | for (i = 0; i < max_irqs; i++) | ||
| 574 | if (level_mask[i >> 5] & (1UL << (i & 0x1f))) | ||
| 575 | irq_desc[i].status = IRQ_LEVEL; | ||
| 576 | |||
| 577 | /* get interrupt line of secondary interrupt controller */ | ||
| 578 | if (irq_cascade >= 0) { | ||
| 579 | printk(KERN_INFO "irq: secondary controller on irq %d\n", | ||
| 580 | (int)irq_cascade); | ||
| 581 | for ( i = max_real_irqs ; i < max_irqs ; i++ ) | ||
| 582 | irq_desc[i].handler = &gatwick_pic; | ||
| 583 | setup_irq(irq_cascade, &gatwick_cascade_action); | ||
| 584 | } | ||
| 585 | printk("System has %d possible interrupts\n", max_irqs); | ||
| 586 | if (max_irqs != max_real_irqs) | ||
| 587 | printk(KERN_DEBUG "%d interrupts on main controller\n", | ||
| 588 | max_real_irqs); | ||
| 589 | |||
| 590 | #ifdef CONFIG_XMON | ||
| 591 | setup_irq(20, &xmon_action); | ||
| 592 | #endif /* CONFIG_XMON */ | ||
| 593 | } | ||
| 594 | |||
| 595 | #ifdef CONFIG_PM | ||
| 596 | /* | ||
| 597 | * These procedures are used in implementing sleep on the powerbooks. | ||
| 598 | * sleep_save_intrs() saves the states of all interrupt enables | ||
| 599 | * and disables all interrupts except for the nominated one. | ||
| 600 | * sleep_restore_intrs() restores the states of all interrupt enables. | ||
| 601 | */ | ||
| 602 | unsigned long sleep_save_mask[2]; | ||
| 603 | |||
| 604 | /* This used to be passed by the PMU driver but that link got | ||
| 605 | * broken with the new driver model. We use this tweak for now... | ||
| 606 | */ | ||
| 607 | static int pmacpic_find_viaint(void) | ||
| 608 | { | ||
| 609 | int viaint = -1; | ||
| 610 | |||
| 611 | #ifdef CONFIG_ADB_PMU | ||
| 612 | struct device_node *np; | ||
| 613 | |||
| 614 | if (pmu_get_model() != PMU_OHARE_BASED) | ||
| 615 | goto not_found; | ||
| 616 | np = of_find_node_by_name(NULL, "via-pmu"); | ||
| 617 | if (np == NULL) | ||
| 618 | goto not_found; | ||
| 619 | viaint = np->intrs[0].line; | ||
| 620 | #endif /* CONFIG_ADB_PMU */ | ||
| 621 | |||
| 622 | not_found: | ||
| 623 | return viaint; | ||
| 624 | } | ||
| 625 | |||
| 626 | static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state) | ||
| 627 | { | ||
| 628 | int viaint = pmacpic_find_viaint(); | ||
| 629 | |||
| 630 | sleep_save_mask[0] = ppc_cached_irq_mask[0]; | ||
| 631 | sleep_save_mask[1] = ppc_cached_irq_mask[1]; | ||
| 632 | ppc_cached_irq_mask[0] = 0; | ||
| 633 | ppc_cached_irq_mask[1] = 0; | ||
| 634 | if (viaint > 0) | ||
| 635 | set_bit(viaint, ppc_cached_irq_mask); | ||
| 636 | out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); | ||
| 637 | if (max_real_irqs > 32) | ||
| 638 | out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); | ||
| 639 | (void)in_le32(&pmac_irq_hw[0]->event); | ||
| 640 | /* make sure mask gets to controller before we return to caller */ | ||
| 641 | mb(); | ||
| 642 | (void)in_le32(&pmac_irq_hw[0]->enable); | ||
| 643 | |||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | |||
| 647 | static int pmacpic_resume(struct sys_device *sysdev) | ||
| 648 | { | ||
| 649 | int i; | ||
| 650 | |||
| 651 | out_le32(&pmac_irq_hw[0]->enable, 0); | ||
| 652 | if (max_real_irqs > 32) | ||
| 653 | out_le32(&pmac_irq_hw[1]->enable, 0); | ||
| 654 | mb(); | ||
| 655 | for (i = 0; i < max_real_irqs; ++i) | ||
| 656 | if (test_bit(i, sleep_save_mask)) | ||
| 657 | pmac_unmask_irq(i); | ||
| 658 | |||
| 659 | return 0; | ||
| 660 | } | ||
| 661 | |||
| 662 | #endif /* CONFIG_PM */ | ||
| 663 | |||
| 664 | static struct sysdev_class pmacpic_sysclass = { | ||
| 665 | set_kset_name("pmac_pic"), | ||
| 666 | }; | ||
| 667 | |||
| 668 | static struct sys_device device_pmacpic = { | ||
| 669 | .id = 0, | ||
| 670 | .cls = &pmacpic_sysclass, | ||
| 671 | }; | ||
| 672 | |||
| 673 | static struct sysdev_driver driver_pmacpic = { | ||
| 674 | #ifdef CONFIG_PM | ||
| 675 | .suspend = &pmacpic_suspend, | ||
| 676 | .resume = &pmacpic_resume, | ||
| 677 | #endif /* CONFIG_PM */ | ||
| 678 | }; | ||
| 679 | |||
| 680 | static int __init init_pmacpic_sysfs(void) | ||
| 681 | { | ||
| 682 | if (max_irqs == 0) | ||
| 683 | return -ENODEV; | ||
| 684 | |||
| 685 | printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); | ||
| 686 | sysdev_class_register(&pmacpic_sysclass); | ||
| 687 | sysdev_register(&device_pmacpic); | ||
| 688 | sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); | ||
| 689 | return 0; | ||
| 690 | } | ||
| 691 | |||
| 692 | subsys_initcall(init_pmacpic_sysfs); | ||
| 693 | |||
diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h deleted file mode 100644 index 664103dfeef9..000000000000 --- a/arch/ppc/platforms/pmac_pic.h +++ /dev/null  | |||
| @@ -1,11 +0,0 @@ | |||
| 1 | #ifndef __PPC_PLATFORMS_PMAC_PIC_H | ||
| 2 | #define __PPC_PLATFORMS_PMAC_PIC_H | ||
| 3 | |||
| 4 | #include <linux/irq.h> | ||
| 5 | |||
| 6 | extern struct hw_interrupt_type pmac_pic; | ||
| 7 | |||
| 8 | void pmac_pic_init(void); | ||
| 9 | int pmac_get_irq(struct pt_regs *regs); | ||
| 10 | |||
| 11 | #endif /* __PPC_PLATFORMS_PMAC_PIC_H */ | ||
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c deleted file mode 100644 index 55d2beffe560..000000000000 --- a/arch/ppc/platforms/pmac_setup.c +++ /dev/null  | |||
| @@ -1,745 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/ppc/platforms/setup.c | ||
| 3 | * | ||
| 4 | * PowerPC version | ||
| 5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
| 6 | * | ||
| 7 | * Adapted for Power Macintosh by Paul Mackerras | ||
| 8 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | ||
| 9 | * | ||
| 10 | * Derived from "arch/alpha/kernel/setup.c" | ||
| 11 | * Copyright (C) 1995 Linus Torvalds | ||
| 12 | * | ||
| 13 | * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or | ||
| 16 | * modify it under the terms of the GNU General Public License | ||
| 17 | * as published by the Free Software Foundation; either version | ||
| 18 | * 2 of the License, or (at your option) any later version. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | /* | ||
| 23 | * bootup setup stuff.. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/config.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/errno.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/kernel.h> | ||
| 31 | #include <linux/mm.h> | ||
| 32 | #include <linux/stddef.h> | ||
| 33 | #include <linux/unistd.h> | ||
| 34 | #include <linux/ptrace.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | #include <linux/user.h> | ||
| 37 | #include <linux/a.out.h> | ||
| 38 | #include <linux/tty.h> | ||
| 39 | #include <linux/string.h> | ||
| 40 | #include <linux/delay.h> | ||
| 41 | #include <linux/ioport.h> | ||
| 42 | #include <linux/major.h> | ||
| 43 | #include <linux/initrd.h> | ||
| 44 | #include <linux/vt_kern.h> | ||
| 45 | #include <linux/console.h> | ||
| 46 | #include <linux/ide.h> | ||
| 47 | #include <linux/pci.h> | ||
| 48 | #include <linux/adb.h> | ||
| 49 | #include <linux/cuda.h> | ||
| 50 | #include <linux/pmu.h> | ||
| 51 | #include <linux/seq_file.h> | ||
| 52 | #include <linux/root_dev.h> | ||
| 53 | #include <linux/bitops.h> | ||
| 54 | #include <linux/suspend.h> | ||
| 55 | |||
| 56 | #include <asm/reg.h> | ||
| 57 | #include <asm/sections.h> | ||
| 58 | #include <asm/prom.h> | ||
| 59 | #include <asm/system.h> | ||
| 60 | #include <asm/pgtable.h> | ||
| 61 | #include <asm/io.h> | ||
| 62 | #include <asm/pci-bridge.h> | ||
| 63 | #include <asm/ohare.h> | ||
| 64 | #include <asm/mediabay.h> | ||
| 65 | #include <asm/machdep.h> | ||
| 66 | #include <asm/dma.h> | ||
| 67 | #include <asm/bootx.h> | ||
| 68 | #include <asm/cputable.h> | ||
| 69 | #include <asm/btext.h> | ||
| 70 | #include <asm/pmac_feature.h> | ||
| 71 | #include <asm/time.h> | ||
| 72 | #include <asm/of_device.h> | ||
| 73 | #include <asm/mmu_context.h> | ||
| 74 | |||
| 75 | #include "pmac_pic.h" | ||
| 76 | #include "mem_pieces.h" | ||
| 77 | |||
| 78 | #undef SHOW_GATWICK_IRQS | ||
| 79 | |||
| 80 | extern long pmac_time_init(void); | ||
| 81 | extern unsigned long pmac_get_rtc_time(void); | ||
| 82 | extern int pmac_set_rtc_time(unsigned long nowtime); | ||
| 83 | extern void pmac_read_rtc_time(void); | ||
| 84 | extern void pmac_calibrate_decr(void); | ||
| 85 | extern void pmac_pcibios_fixup(void); | ||
| 86 | extern void pmac_find_bridges(void); | ||
| 87 | extern unsigned long pmac_ide_get_base(int index); | ||
| 88 | extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, | ||
| 89 | unsigned long data_port, unsigned long ctrl_port, int *irq); | ||
| 90 | |||
| 91 | extern void pmac_nvram_update(void); | ||
| 92 | extern unsigned char pmac_nvram_read_byte(int addr); | ||
| 93 | extern void pmac_nvram_write_byte(int addr, unsigned char val); | ||
| 94 | extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); | ||
| 95 | extern void pmac_pcibios_after_init(void); | ||
| 96 | extern int of_show_percpuinfo(struct seq_file *m, int i); | ||
| 97 | |||
| 98 | struct device_node *memory_node; | ||
| 99 | |||
| 100 | unsigned char drive_info; | ||
| 101 | |||
| 102 | int ppc_override_l2cr = 0; | ||
| 103 | int ppc_override_l2cr_value; | ||
| 104 | int has_l2cache = 0; | ||
| 105 | |||
| 106 | static int current_root_goodness = -1; | ||
| 107 | |||
| 108 | extern int pmac_newworld; | ||
| 109 | |||
| 110 | #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ | ||
| 111 | |||
| 112 | extern void zs_kgdb_hook(int tty_num); | ||
| 113 | static void ohare_init(void); | ||
| 114 | #ifdef CONFIG_BOOTX_TEXT | ||
| 115 | static void pmac_progress(char *s, unsigned short hex); | ||
| 116 | #endif | ||
| 117 | |||
| 118 | sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; | ||
| 119 | |||
| 120 | #ifdef CONFIG_SMP | ||
| 121 | extern struct smp_ops_t psurge_smp_ops; | ||
| 122 | extern struct smp_ops_t core99_smp_ops; | ||
| 123 | #endif /* CONFIG_SMP */ | ||
| 124 | |||
| 125 | static int | ||
| 126 | pmac_show_cpuinfo(struct seq_file *m) | ||
| 127 | { | ||
| 128 | struct device_node *np; | ||
| 129 | char *pp; | ||
| 130 | int plen; | ||
| 131 | int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
| 132 | NULL, PMAC_MB_INFO_MODEL, 0); | ||
| 133 | unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
| 134 | NULL, PMAC_MB_INFO_FLAGS, 0); | ||
| 135 | char* mbname; | ||
| 136 | |||
| 137 | if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0) | ||
| 138 | mbname = "Unknown"; | ||
| 139 | |||
| 140 | /* find motherboard type */ | ||
| 141 | seq_printf(m, "machine\t\t: "); | ||
| 142 | np = find_devices("device-tree"); | ||
| 143 | if (np != NULL) { | ||
| 144 | pp = (char *) get_property(np, "model", NULL); | ||
| 145 | if (pp != NULL) | ||
| 146 | seq_printf(m, "%s\n", pp); | ||
| 147 | else | ||
| 148 | seq_printf(m, "PowerMac\n"); | ||
| 149 | pp = (char *) get_property(np, "compatible", &plen); | ||
| 150 | if (pp != NULL) { | ||
| 151 | seq_printf(m, "motherboard\t:"); | ||
| 152 | while (plen > 0) { | ||
| 153 | int l = strlen(pp) + 1; | ||
| 154 | seq_printf(m, " %s", pp); | ||
| 155 | plen -= l; | ||
| 156 | pp += l; | ||
| 157 | } | ||
| 158 | seq_printf(m, "\n"); | ||
| 159 | } | ||
| 160 | } else | ||
| 161 | seq_printf(m, "PowerMac\n"); | ||
| 162 | |||
| 163 | /* print parsed model */ | ||
| 164 | seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); | ||
| 165 | seq_printf(m, "pmac flags\t: %08x\n", mbflags); | ||
| 166 | |||
| 167 | /* find l2 cache info */ | ||
| 168 | np = find_devices("l2-cache"); | ||
| 169 | if (np == 0) | ||
| 170 | np = find_type_devices("cache"); | ||
| 171 | if (np != 0) { | ||
| 172 | unsigned int *ic = (unsigned int *) | ||
| 173 | get_property(np, "i-cache-size", NULL); | ||
| 174 | unsigned int *dc = (unsigned int *) | ||
| 175 | get_property(np, "d-cache-size", NULL); | ||
| 176 | seq_printf(m, "L2 cache\t:"); | ||
| 177 | has_l2cache = 1; | ||
| 178 | if (get_property(np, "cache-unified", NULL) != 0 && dc) { | ||
| 179 | seq_printf(m, " %dK unified", *dc / 1024); | ||
| 180 | } else { | ||
| 181 | if (ic) | ||
| 182 | seq_printf(m, " %dK instruction", *ic / 1024); | ||
| 183 | if (dc) | ||
| 184 | seq_printf(m, "%s %dK data", | ||
| 185 | (ic? " +": ""), *dc / 1024); | ||
| 186 | } | ||
| 187 | pp = get_property(np, "ram-type", NULL); | ||
| 188 | if (pp) | ||
| 189 | seq_printf(m, " %s", pp); | ||
| 190 | seq_printf(m, "\n"); | ||
| 191 | } | ||
| 192 | |||
| 193 | /* find ram info */ | ||
| 194 | np = find_devices("memory"); | ||
| 195 | if (np != 0) { | ||
| 196 | int n; | ||
| 197 | struct reg_property *reg = (struct reg_property *) | ||
| 198 | get_property(np, "reg", &n); | ||
| 199 | |||
| 200 | if (reg != 0) { | ||
| 201 | unsigned long total = 0; | ||
| 202 | |||
| 203 | for (n /= sizeof(struct reg_property); n > 0; --n) | ||
| 204 | total += (reg++)->size; | ||
| 205 | seq_printf(m, "memory\t\t: %luMB\n", total >> 20); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | /* Checks "l2cr-value" property in the registry */ | ||
| 210 | np = find_devices("cpus"); | ||
| 211 | if (np == 0) | ||
| 212 | np = find_type_devices("cpu"); | ||
| 213 | if (np != 0) { | ||
| 214 | unsigned int *l2cr = (unsigned int *) | ||
| 215 | get_property(np, "l2cr-value", NULL); | ||
| 216 | if (l2cr != 0) { | ||
| 217 | seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | /* Indicate newworld/oldworld */ | ||
| 222 | seq_printf(m, "pmac-generation\t: %s\n", | ||
| 223 | pmac_newworld ? "NewWorld" : "OldWorld"); | ||
| 224 | |||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int | ||
| 230 | pmac_show_percpuinfo(struct seq_file *m, int i) | ||
| 231 | { | ||
| 232 | #ifdef CONFIG_CPU_FREQ_PMAC | ||
| 233 | extern unsigned int pmac_get_one_cpufreq(int i); | ||
| 234 | unsigned int freq = pmac_get_one_cpufreq(i); | ||
| 235 | if (freq != 0) { | ||
| 236 | seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | #endif /* CONFIG_CPU_FREQ_PMAC */ | ||
| 240 | return of_show_percpuinfo(m, i); | ||
| 241 | } | ||
| 242 | |||
| 243 | static volatile u32 *sysctrl_regs; | ||
| 244 | |||
| 245 | void __init | ||
| 246 | pmac_setup_arch(void) | ||
| 247 | { | ||
| 248 | struct device_node *cpu; | ||
| 249 | int *fp; | ||
| 250 | unsigned long pvr; | ||
| 251 | |||
| 252 | pvr = PVR_VER(mfspr(SPRN_PVR)); | ||
| 253 | |||
| 254 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
| 255 | for use until calibrate_delay gets called. */ | ||
| 256 | cpu = find_type_devices("cpu"); | ||
| 257 | if (cpu != 0) { | ||
| 258 | fp = (int *) get_property(cpu, "clock-frequency", NULL); | ||
| 259 | if (fp != 0) { | ||
| 260 | if (pvr == 4 || pvr >= 8) | ||
| 261 | /* 604, G3, G4 etc. */ | ||
| 262 | loops_per_jiffy = *fp / HZ; | ||
| 263 | else | ||
| 264 | /* 601, 603, etc. */ | ||
| 265 | loops_per_jiffy = *fp / (2*HZ); | ||
| 266 | } else | ||
| 267 | loops_per_jiffy = 50000000 / HZ; | ||
| 268 | } | ||
| 269 | |||
| 270 | /* this area has the CPU identification register | ||
| 271 | and some registers used by smp boards */ | ||
| 272 | sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); | ||
| 273 | ohare_init(); | ||
| 274 | |||
| 275 | /* Lookup PCI hosts */ | ||
| 276 | pmac_find_bridges(); | ||
| 277 | |||
| 278 | /* Checks "l2cr-value" property in the registry */ | ||
| 279 | if (cpu_has_feature(CPU_FTR_L2CR)) { | ||
| 280 | struct device_node *np = find_devices("cpus"); | ||
| 281 | if (np == 0) | ||
| 282 | np = find_type_devices("cpu"); | ||
| 283 | if (np != 0) { | ||
| 284 | unsigned int *l2cr = (unsigned int *) | ||
| 285 | get_property(np, "l2cr-value", NULL); | ||
| 286 | if (l2cr != 0) { | ||
| 287 | ppc_override_l2cr = 1; | ||
| 288 | ppc_override_l2cr_value = *l2cr; | ||
| 289 | _set_L2CR(0); | ||
| 290 | _set_L2CR(ppc_override_l2cr_value); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | if (ppc_override_l2cr) | ||
| 296 | printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n", | ||
| 297 | ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) | ||
| 298 | ? "enabled" : "disabled"); | ||
| 299 | |||
| 300 | #ifdef CONFIG_KGDB | ||
| 301 | zs_kgdb_hook(0); | ||
| 302 | #endif | ||
| 303 | |||
| 304 | #ifdef CONFIG_ADB_CUDA | ||
| 305 | find_via_cuda(); | ||
| 306 | #else | ||
| 307 | if (find_devices("via-cuda")) { | ||
| 308 | printk("WARNING ! Your machine is Cuda based but your kernel\n"); | ||
| 309 | printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | #ifdef CONFIG_ADB_PMU | ||
| 313 | find_via_pmu(); | ||
| 314 | #else | ||
| 315 | if (find_devices("via-pmu")) { | ||
| 316 | printk("WARNING ! Your machine is PMU based but your kernel\n"); | ||
| 317 | printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); | ||
| 318 | } | ||
| 319 | #endif | ||
| 320 | #ifdef CONFIG_NVRAM | ||
| 321 | pmac_nvram_init(); | ||
| 322 | #endif | ||
| 323 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 324 | if (initrd_start) | ||
| 325 | ROOT_DEV = Root_RAM0; | ||
| 326 | else | ||
| 327 | #endif | ||
| 328 | ROOT_DEV = DEFAULT_ROOT_DEVICE; | ||
| 329 | |||
| 330 | #ifdef CONFIG_SMP | ||
| 331 | /* Check for Core99 */ | ||
| 332 | if (find_devices("uni-n") || find_devices("u3")) | ||
| 333 | smp_ops = &core99_smp_ops; | ||
| 334 | else | ||
| 335 | smp_ops = &psurge_smp_ops; | ||
| 336 | #endif /* CONFIG_SMP */ | ||
| 337 | |||
| 338 | pci_create_OF_bus_map(); | ||
| 339 | } | ||
| 340 | |||
| 341 | static void __init ohare_init(void) | ||
| 342 | { | ||
| 343 | /* | ||
| 344 | * Turn on the L2 cache. | ||
| 345 | * We assume that we have a PSX memory controller iff | ||
| 346 | * we have an ohare I/O controller. | ||
| 347 | */ | ||
| 348 | if (find_devices("ohare") != NULL) { | ||
| 349 | if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { | ||
| 350 | if (sysctrl_regs[4] & 0x10) | ||
| 351 | sysctrl_regs[4] |= 0x04000020; | ||
| 352 | else | ||
| 353 | sysctrl_regs[4] |= 0x04000000; | ||
| 354 | if(has_l2cache) | ||
| 355 | printk(KERN_INFO "Level 2 cache enabled\n"); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | extern char *bootpath; | ||
| 361 | extern char *bootdevice; | ||
| 362 | void *boot_host; | ||
| 363 | int boot_target; | ||
| 364 | int boot_part; | ||
| 365 | extern dev_t boot_dev; | ||
| 366 | |||
| 367 | #ifdef CONFIG_SCSI | ||
| 368 | void __init | ||
| 369 | note_scsi_host(struct device_node *node, void *host) | ||
| 370 | { | ||
| 371 | int l; | ||
| 372 | char *p; | ||
| 373 | |||
| 374 | l = strlen(node->full_name); | ||
| 375 | if (bootpath != NULL && bootdevice != NULL | ||
| 376 | && strncmp(node->full_name, bootdevice, l) == 0 | ||
| 377 | && (bootdevice[l] == '/' || bootdevice[l] == 0)) { | ||
| 378 | boot_host = host; | ||
| 379 | /* | ||
| 380 | * There's a bug in OF 1.0.5. (Why am I not surprised.) | ||
| 381 | * If you pass a path like scsi/sd@1:0 to canon, it returns | ||
| 382 | * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 | ||
| 383 | * That is, the scsi target number doesn't get preserved. | ||
| 384 | * So we pick the target number out of bootpath and use that. | ||
| 385 | */ | ||
| 386 | p = strstr(bootpath, "/sd@"); | ||
| 387 | if (p != NULL) { | ||
| 388 | p += 4; | ||
| 389 | boot_target = simple_strtoul(p, NULL, 10); | ||
| 390 | p = strchr(p, ':'); | ||
| 391 | if (p != NULL) | ||
| 392 | boot_part = simple_strtoul(p + 1, NULL, 10); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | } | ||
| 396 | #endif | ||
| 397 | |||
| 398 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
| 399 | static dev_t __init | ||
| 400 | find_ide_boot(void) | ||
| 401 | { | ||
| 402 | char *p; | ||
| 403 | int n; | ||
| 404 | dev_t __init pmac_find_ide_boot(char *bootdevice, int n); | ||
| 405 | |||
| 406 | if (bootdevice == NULL) | ||
| 407 | return 0; | ||
| 408 | p = strrchr(bootdevice, '/'); | ||
| 409 | if (p == NULL) | ||
| 410 | return 0; | ||
| 411 | n = p - bootdevice; | ||
| 412 | |||
| 413 | return pmac_find_ide_boot(bootdevice, n); | ||
| 414 | } | ||
| 415 | #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ | ||
| 416 | |||
| 417 | static void __init | ||
| 418 | find_boot_device(void) | ||
| 419 | { | ||
| 420 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
| 421 | boot_dev = find_ide_boot(); | ||
| 422 | #endif | ||
| 423 | } | ||
| 424 | |||
| 425 | static int initializing = 1; | ||
| 426 | /* TODO: Merge the suspend-to-ram with the common code !!! | ||
| 427 | * currently, this is a stub implementation for suspend-to-disk | ||
| 428 | * only | ||
| 429 | */ | ||
| 430 | |||
| 431 | #ifdef CONFIG_SOFTWARE_SUSPEND | ||
| 432 | |||
| 433 | static int pmac_pm_prepare(suspend_state_t state) | ||
| 434 | { | ||
| 435 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
| 436 | |||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 440 | static int pmac_pm_enter(suspend_state_t state) | ||
| 441 | { | ||
| 442 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
| 443 | |||
| 444 | /* Giveup the lazy FPU & vec so we don't have to back them | ||
| 445 | * up from the low level code | ||
| 446 | */ | ||
| 447 | enable_kernel_fp(); | ||
| 448 | |||
| 449 | #ifdef CONFIG_ALTIVEC | ||
| 450 | if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) | ||
| 451 | enable_kernel_altivec(); | ||
| 452 | #endif /* CONFIG_ALTIVEC */ | ||
| 453 | |||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 457 | static int pmac_pm_finish(suspend_state_t state) | ||
| 458 | { | ||
| 459 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
| 460 | |||
| 461 | /* Restore userland MMU context */ | ||
| 462 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | static struct pm_ops pmac_pm_ops = { | ||
| 468 | .pm_disk_mode = PM_DISK_SHUTDOWN, | ||
| 469 | .prepare = pmac_pm_prepare, | ||
| 470 | .enter = pmac_pm_enter, | ||
| 471 | .finish = pmac_pm_finish, | ||
| 472 | }; | ||
| 473 | |||
| 474 | #endif /* CONFIG_SOFTWARE_SUSPEND */ | ||
| 475 | |||
| 476 | static int pmac_late_init(void) | ||
| 477 | { | ||
| 478 | initializing = 0; | ||
| 479 | #ifdef CONFIG_SOFTWARE_SUSPEND | ||
| 480 | pm_set_ops(&pmac_pm_ops); | ||
| 481 | #endif /* CONFIG_SOFTWARE_SUSPEND */ | ||
| 482 | return 0; | ||
| 483 | } | ||
| 484 | |||
| 485 | late_initcall(pmac_late_init); | ||
| 486 | |||
| 487 | /* can't be __init - can be called whenever a disk is first accessed */ | ||
| 488 | void | ||
| 489 | note_bootable_part(dev_t dev, int part, int goodness) | ||
| 490 | { | ||
| 491 | static int found_boot = 0; | ||
| 492 | char *p; | ||
| 493 | |||
| 494 | if (!initializing) | ||
| 495 | return; | ||
| 496 | if ((goodness <= current_root_goodness) && | ||
| 497 | ROOT_DEV != DEFAULT_ROOT_DEVICE) | ||
| 498 | return; | ||
| 499 | p = strstr(saved_command_line, "root="); | ||
| 500 | if (p != NULL && (p == saved_command_line || p[-1] == ' ')) | ||
| 501 | return; | ||
| 502 | |||
| 503 | if (!found_boot) { | ||
| 504 | find_boot_device(); | ||
| 505 | found_boot = 1; | ||
| 506 | } | ||
| 507 | if (!boot_dev || dev == boot_dev) { | ||
| 508 | ROOT_DEV = dev + part; | ||
| 509 | boot_dev = 0; | ||
| 510 | current_root_goodness = goodness; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | static void | ||
| 515 | pmac_restart(char *cmd) | ||
| 516 | { | ||
| 517 | #ifdef CONFIG_ADB_CUDA | ||
| 518 | struct adb_request req; | ||
| 519 | #endif /* CONFIG_ADB_CUDA */ | ||
| 520 | |||
| 521 | switch (sys_ctrler) { | ||
| 522 | #ifdef CONFIG_ADB_CUDA | ||
| 523 | case SYS_CTRLER_CUDA: | ||
| 524 | cuda_request(&req, NULL, 2, CUDA_PACKET, | ||
| 525 | CUDA_RESET_SYSTEM); | ||
| 526 | for (;;) | ||
| 527 | cuda_poll(); | ||
| 528 | break; | ||
| 529 | #endif /* CONFIG_ADB_CUDA */ | ||
| 530 | #ifdef CONFIG_ADB_PMU | ||
| 531 | case SYS_CTRLER_PMU: | ||
| 532 | pmu_restart(); | ||
| 533 | break; | ||
| 534 | #endif /* CONFIG_ADB_PMU */ | ||
| 535 | default: ; | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | static void | ||
| 540 | pmac_power_off(void) | ||
| 541 | { | ||
| 542 | #ifdef CONFIG_ADB_CUDA | ||
| 543 | struct adb_request req; | ||
| 544 | #endif /* CONFIG_ADB_CUDA */ | ||
| 545 | |||
| 546 | switch (sys_ctrler) { | ||
| 547 | #ifdef CONFIG_ADB_CUDA | ||
| 548 | case SYS_CTRLER_CUDA: | ||
| 549 | cuda_request(&req, NULL, 2, CUDA_PACKET, | ||
| 550 | CUDA_POWERDOWN); | ||
| 551 | for (;;) | ||
| 552 | cuda_poll(); | ||
| 553 | break; | ||
| 554 | #endif /* CONFIG_ADB_CUDA */ | ||
| 555 | #ifdef CONFIG_ADB_PMU | ||
| 556 | case SYS_CTRLER_PMU: | ||
| 557 | pmu_shutdown(); | ||
| 558 | break; | ||
| 559 | #endif /* CONFIG_ADB_PMU */ | ||
| 560 | default: ; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | static void | ||
| 565 | pmac_halt(void) | ||
| 566 | { | ||
| 567 | pmac_power_off(); | ||
| 568 | } | ||
| 569 | |||
| 570 | /* | ||
| 571 | * Read in a property describing some pieces of memory. | ||
| 572 | */ | ||
| 573 | |||
| 574 | static int __init | ||
| 575 | get_mem_prop(char *name, struct mem_pieces *mp) | ||
| 576 | { | ||
| 577 | struct reg_property *rp; | ||
| 578 | int i, s; | ||
| 579 | unsigned int *ip; | ||
| 580 | int nac = prom_n_addr_cells(memory_node); | ||
| 581 | int nsc = prom_n_size_cells(memory_node); | ||
| 582 | |||
| 583 | ip = (unsigned int *) get_property(memory_node, name, &s); | ||
| 584 | if (ip == NULL) { | ||
| 585 | printk(KERN_ERR "error: couldn't get %s property on /memory\n", | ||
| 586 | name); | ||
| 587 | return 0; | ||
| 588 | } | ||
| 589 | s /= (nsc + nac) * 4; | ||
| 590 | rp = mp->regions; | ||
| 591 | for (i = 0; i < s; ++i, ip += nac+nsc) { | ||
| 592 | if (nac >= 2 && ip[nac-2] != 0) | ||
| 593 | continue; | ||
| 594 | rp->address = ip[nac-1]; | ||
| 595 | if (nsc >= 2 && ip[nac+nsc-2] != 0) | ||
| 596 | rp->size = ~0U; | ||
| 597 | else | ||
| 598 | rp->size = ip[nac+nsc-1]; | ||
| 599 | ++rp; | ||
| 600 | } | ||
| 601 | mp->n_regions = rp - mp->regions; | ||
| 602 | |||
| 603 | /* Make sure the pieces are sorted. */ | ||
| 604 | mem_pieces_sort(mp); | ||
| 605 | mem_pieces_coalesce(mp); | ||
| 606 | return 1; | ||
| 607 | } | ||
| 608 | |||
| 609 | /* | ||
| 610 | * On systems with Open Firmware, collect information about | ||
| 611 | * physical RAM and which pieces are already in use. | ||
| 612 | * At this point, we have (at least) the first 8MB mapped with a BAT. | ||
| 613 | * Our text, data, bss use something over 1MB, starting at 0. | ||
| 614 | * Open Firmware may be using 1MB at the 4MB point. | ||
| 615 | */ | ||
| 616 | unsigned long __init | ||
| 617 | pmac_find_end_of_memory(void) | ||
| 618 | { | ||
| 619 | unsigned long a, total; | ||
| 620 | struct mem_pieces phys_mem; | ||
| 621 | |||
| 622 | /* | ||
| 623 | * Find out where physical memory is, and check that it | ||
| 624 | * starts at 0 and is contiguous. It seems that RAM is | ||
| 625 | * always physically contiguous on Power Macintoshes. | ||
| 626 | * | ||
| 627 | * Supporting discontiguous physical memory isn't hard, | ||
| 628 | * it just makes the virtual <-> physical mapping functions | ||
| 629 | * more complicated (or else you end up wasting space | ||
| 630 | * in mem_map). | ||
| 631 | */ | ||
| 632 | memory_node = find_devices("memory"); | ||
| 633 | if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) | ||
| 634 | || phys_mem.n_regions == 0) | ||
| 635 | panic("No RAM??"); | ||
| 636 | a = phys_mem.regions[0].address; | ||
| 637 | if (a != 0) | ||
| 638 | panic("RAM doesn't start at physical address 0"); | ||
| 639 | total = phys_mem.regions[0].size; | ||
| 640 | |||
| 641 | if (phys_mem.n_regions > 1) { | ||
| 642 | printk("RAM starting at 0x%x is not contiguous\n", | ||
| 643 | phys_mem.regions[1].address); | ||
| 644 | printk("Using RAM from 0 to 0x%lx\n", total-1); | ||
| 645 | } | ||
| 646 | |||
| 647 | return total; | ||
| 648 | } | ||
| 649 | |||
| 650 | void __init | ||
| 651 | pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
| 652 | unsigned long r6, unsigned long r7) | ||
| 653 | { | ||
| 654 | /* isa_io_base gets set in pmac_find_bridges */ | ||
| 655 | isa_mem_base = PMAC_ISA_MEM_BASE; | ||
| 656 | pci_dram_offset = PMAC_PCI_DRAM_OFFSET; | ||
| 657 | ISA_DMA_THRESHOLD = ~0L; | ||
| 658 | DMA_MODE_READ = 1; | ||
| 659 | DMA_MODE_WRITE = 2; | ||
| 660 | |||
| 661 | ppc_md.setup_arch = pmac_setup_arch; | ||
| 662 | ppc_md.show_cpuinfo = pmac_show_cpuinfo; | ||
| 663 | ppc_md.show_percpuinfo = pmac_show_percpuinfo; | ||
| 664 | ppc_md.init_IRQ = pmac_pic_init; | ||
| 665 | ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ | ||
| 666 | |||
| 667 | ppc_md.pcibios_fixup = pmac_pcibios_fixup; | ||
| 668 | ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; | ||
| 669 | ppc_md.pcibios_after_init = pmac_pcibios_after_init; | ||
| 670 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | ||
| 671 | |||
| 672 | ppc_md.restart = pmac_restart; | ||
| 673 | ppc_md.power_off = pmac_power_off; | ||
| 674 | ppc_md.halt = pmac_halt; | ||
| 675 | |||
| 676 | ppc_md.time_init = pmac_time_init; | ||
| 677 | ppc_md.set_rtc_time = pmac_set_rtc_time; | ||
| 678 | ppc_md.get_rtc_time = pmac_get_rtc_time; | ||
| 679 | ppc_md.calibrate_decr = pmac_calibrate_decr; | ||
| 680 | |||
| 681 | ppc_md.find_end_of_memory = pmac_find_end_of_memory; | ||
| 682 | |||
| 683 | ppc_md.feature_call = pmac_do_feature_call; | ||
| 684 | |||
| 685 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
| 686 | #ifdef CONFIG_BLK_DEV_IDE_PMAC | ||
| 687 | ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; | ||
| 688 | ppc_ide_md.default_io_base = pmac_ide_get_base; | ||
| 689 | #endif /* CONFIG_BLK_DEV_IDE_PMAC */ | ||
| 690 | #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ | ||
| 691 | |||
| 692 | #ifdef CONFIG_BOOTX_TEXT | ||
| 693 | ppc_md.progress = pmac_progress; | ||
| 694 | #endif /* CONFIG_BOOTX_TEXT */ | ||
| 695 | |||
| 696 | if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); | ||
| 697 | |||
| 698 | } | ||
| 699 | |||
| 700 | #ifdef CONFIG_BOOTX_TEXT | ||
| 701 | static void __init | ||
| 702 | pmac_progress(char *s, unsigned short hex) | ||
| 703 | { | ||
| 704 | if (boot_text_mapped) { | ||
| 705 | btext_drawstring(s); | ||
| 706 | btext_drawchar('\n'); | ||
| 707 | } | ||
| 708 | } | ||
| 709 | #endif /* CONFIG_BOOTX_TEXT */ | ||
| 710 | |||
| 711 | static int __init | ||
| 712 | pmac_declare_of_platform_devices(void) | ||
| 713 | { | ||
| 714 | struct device_node *np; | ||
| 715 | |||
| 716 | np = find_devices("uni-n"); | ||
| 717 | if (np) { | ||
| 718 | for (np = np->child; np != NULL; np = np->sibling) | ||
| 719 | if (strncmp(np->name, "i2c", 3) == 0) { | ||
| 720 | of_platform_device_create(np, "uni-n-i2c", | ||
| 721 | NULL); | ||
| 722 | break; | ||
| 723 | } | ||
| 724 | } | ||
| 725 | np = find_devices("u3"); | ||
| 726 | if (np) { | ||
| 727 | for (np = np->child; np != NULL; np = np->sibling) | ||
| 728 | if (strncmp(np->name, "i2c", 3) == 0) { | ||
| 729 | of_platform_device_create(np, "u3-i2c", | ||
| 730 | NULL); | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | } | ||
| 734 | |||
| 735 | np = find_devices("valkyrie"); | ||
| 736 | if (np) | ||
| 737 | of_platform_device_create(np, "valkyrie", NULL); | ||
| 738 | np = find_devices("platinum"); | ||
| 739 | if (np) | ||
| 740 | of_platform_device_create(np, "platinum", NULL); | ||
| 741 | |||
| 742 | return 0; | ||
| 743 | } | ||
| 744 | |||
| 745 | device_initcall(pmac_declare_of_platform_devices); | ||
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S deleted file mode 100644 index 22b113d19b24..000000000000 --- a/arch/ppc/platforms/pmac_sleep.S +++ /dev/null  | |||
| @@ -1,396 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file contains sleep low-level functions for PowerBook G3. | ||
| 3 | * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
| 4 | * and Paul Mackerras (paulus@samba.org). | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/config.h> | ||
| 14 | #include <asm/processor.h> | ||
| 15 | #include <asm/page.h> | ||
| 16 | #include <asm/ppc_asm.h> | ||
| 17 | #include <asm/cputable.h> | ||
| 18 | #include <asm/cache.h> | ||
| 19 | #include <asm/thread_info.h> | ||
| 20 | #include <asm/asm-offsets.h> | ||
| 21 | |||
| 22 | #define MAGIC 0x4c617273 /* 'Lars' */ | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Structure for storing CPU registers on the stack. | ||
| 26 | */ | ||
| 27 | #define SL_SP 0 | ||
| 28 | #define SL_PC 4 | ||
| 29 | #define SL_MSR 8 | ||
| 30 | #define SL_SDR1 0xc | ||
| 31 | #define SL_SPRG0 0x10 /* 4 sprg's */ | ||
| 32 | #define SL_DBAT0 0x20 | ||
| 33 | #define SL_IBAT0 0x28 | ||
| 34 | #define SL_DBAT1 0x30 | ||
| 35 | #define SL_IBAT1 0x38 | ||
| 36 | #define SL_DBAT2 0x40 | ||
| 37 | #define SL_IBAT2 0x48 | ||
| 38 | #define SL_DBAT3 0x50 | ||
| 39 | #define SL_IBAT3 0x58 | ||
| 40 | #define SL_TB 0x60 | ||
| 41 | #define SL_R2 0x68 | ||
| 42 | #define SL_CR 0x6c | ||
| 43 | #define SL_R12 0x70 /* r12 to r31 */ | ||
| 44 | #define SL_SIZE (SL_R12 + 80) | ||
| 45 | |||
| 46 | .section .text | ||
| 47 | .align 5 | ||
| 48 | |||
| 49 | #if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) | ||
| 50 | |||
| 51 | /* This gets called by via-pmu.c late during the sleep process. | ||
| 52 | * The PMU was already send the sleep command and will shut us down | ||
| 53 | * soon. We need to save all that is needed and setup the wakeup | ||
| 54 | * vector that will be called by the ROM on wakeup | ||
| 55 | */ | ||
| 56 | _GLOBAL(low_sleep_handler) | ||
| 57 | #ifndef CONFIG_6xx | ||
| 58 | blr | ||
| 59 | #else | ||
| 60 | mflr r0 | ||
| 61 | stw r0,4(r1) | ||
| 62 | stwu r1,-SL_SIZE(r1) | ||
| 63 | mfcr r0 | ||
| 64 | stw r0,SL_CR(r1) | ||
| 65 | stw r2,SL_R2(r1) | ||
| 66 | stmw r12,SL_R12(r1) | ||
| 67 | |||
| 68 | /* Save MSR & SDR1 */ | ||
| 69 | mfmsr r4 | ||
| 70 | stw r4,SL_MSR(r1) | ||
| 71 | mfsdr1 r4 | ||
| 72 | stw r4,SL_SDR1(r1) | ||
| 73 | |||
| 74 | /* Get a stable timebase and save it */ | ||
| 75 | 1: mftbu r4 | ||
| 76 | stw r4,SL_TB(r1) | ||
| 77 | mftb r5 | ||
| 78 | stw r5,SL_TB+4(r1) | ||
| 79 | mftbu r3 | ||
| 80 | cmpw r3,r4 | ||
| 81 | bne 1b | ||
| 82 | |||
| 83 | /* Save SPRGs */ | ||
| 84 | mfsprg r4,0 | ||
| 85 | stw r4,SL_SPRG0(r1) | ||
| 86 | mfsprg r4,1 | ||
| 87 | stw r4,SL_SPRG0+4(r1) | ||
| 88 | mfsprg r4,2 | ||
| 89 | stw r4,SL_SPRG0+8(r1) | ||
| 90 | mfsprg r4,3 | ||
| 91 | stw r4,SL_SPRG0+12(r1) | ||
| 92 | |||
| 93 | /* Save BATs */ | ||
| 94 | mfdbatu r4,0 | ||
| 95 | stw r4,SL_DBAT0(r1) | ||
| 96 | mfdbatl r4,0 | ||
| 97 | stw r4,SL_DBAT0+4(r1) | ||
| 98 | mfdbatu r4,1 | ||
| 99 | stw r4,SL_DBAT1(r1) | ||
| 100 | mfdbatl r4,1 | ||
| 101 | stw r4,SL_DBAT1+4(r1) | ||
| 102 | mfdbatu r4,2 | ||
| 103 | stw r4,SL_DBAT2(r1) | ||
| 104 | mfdbatl r4,2 | ||
| 105 | stw r4,SL_DBAT2+4(r1) | ||
| 106 | mfdbatu r4,3 | ||
| 107 | stw r4,SL_DBAT3(r1) | ||
| 108 | mfdbatl r4,3 | ||
| 109 | stw r4,SL_DBAT3+4(r1) | ||
| 110 | mfibatu r4,0 | ||
| 111 | stw r4,SL_IBAT0(r1) | ||
| 112 | mfibatl r4,0 | ||
| 113 | stw r4,SL_IBAT0+4(r1) | ||
| 114 | mfibatu r4,1 | ||
| 115 | stw r4,SL_IBAT1(r1) | ||
| 116 | mfibatl r4,1 | ||
| 117 | stw r4,SL_IBAT1+4(r1) | ||
| 118 | mfibatu r4,2 | ||
| 119 | stw r4,SL_IBAT2(r1) | ||
| 120 | mfibatl r4,2 | ||
| 121 | stw r4,SL_IBAT2+4(r1) | ||
| 122 | mfibatu r4,3 | ||
| 123 | stw r4,SL_IBAT3(r1) | ||
| 124 | mfibatl r4,3 | ||
| 125 | stw r4,SL_IBAT3+4(r1) | ||
| 126 | |||
| 127 | /* Backup various CPU config stuffs */ | ||
| 128 | bl __save_cpu_setup | ||
| 129 | |||
| 130 | /* The ROM can wake us up via 2 different vectors: | ||
| 131 | * - On wallstreet & lombard, we must write a magic | ||
| 132 | * value 'Lars' at address 4 and a pointer to a | ||
| 133 | * memory location containing the PC to resume from | ||
| 134 | * at address 0. | ||
| 135 | * - On Core99, we must store the wakeup vector at | ||
| 136 | * address 0x80 and eventually it's parameters | ||
| 137 | * at address 0x84. I've have some trouble with those | ||
| 138 | * parameters however and I no longer use them. | ||
| 139 | */ | ||
| 140 | lis r5,grackle_wake_up@ha | ||
| 141 | addi r5,r5,grackle_wake_up@l | ||
| 142 | tophys(r5,r5) | ||
| 143 | stw r5,SL_PC(r1) | ||
| 144 | lis r4,KERNELBASE@h | ||
| 145 | tophys(r5,r1) | ||
| 146 | addi r5,r5,SL_PC | ||
| 147 | lis r6,MAGIC@ha | ||
| 148 | addi r6,r6,MAGIC@l | ||
| 149 | stw r5,0(r4) | ||
| 150 | stw r6,4(r4) | ||
| 151 | /* Setup stuffs at 0x80-0x84 for Core99 */ | ||
| 152 | lis r3,core99_wake_up@ha | ||
| 153 | addi r3,r3,core99_wake_up@l | ||
| 154 | tophys(r3,r3) | ||
| 155 | stw r3,0x80(r4) | ||
| 156 | stw r5,0x84(r4) | ||
| 157 | /* Store a pointer to our backup storage into | ||
| 158 | * a kernel global | ||
| 159 | */ | ||
| 160 | lis r3,sleep_storage@ha | ||
| 161 | addi r3,r3,sleep_storage@l | ||
| 162 | stw r5,0(r3) | ||
| 163 | |||
| 164 | .globl low_cpu_die | ||
| 165 | low_cpu_die: | ||
| 166 | /* Flush & disable all caches */ | ||
| 167 | bl flush_disable_caches | ||
| 168 | |||
| 169 | /* Turn off data relocation. */ | ||
| 170 | mfmsr r3 /* Save MSR in r7 */ | ||
| 171 | rlwinm r3,r3,0,28,26 /* Turn off DR bit */ | ||
| 172 | sync | ||
| 173 | mtmsr r3 | ||
| 174 | isync | ||
| 175 | |||
| 176 | BEGIN_FTR_SECTION | ||
| 177 | /* Flush any pending L2 data prefetches to work around HW bug */ | ||
| 178 | sync | ||
| 179 | lis r3,0xfff0 | ||
| 180 | lwz r0,0(r3) /* perform cache-inhibited load to ROM */ | ||
| 181 | sync /* (caches are disabled at this point) */ | ||
| 182 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
| 183 | |||
| 184 | /* | ||
| 185 | * Set the HID0 and MSR for sleep. | ||
| 186 | */ | ||
| 187 | mfspr r2,SPRN_HID0 | ||
| 188 | rlwinm r2,r2,0,10,7 /* clear doze, nap */ | ||
| 189 | oris r2,r2,HID0_SLEEP@h | ||
| 190 | sync | ||
| 191 | isync | ||
| 192 | mtspr SPRN_HID0,r2 | ||
| 193 | sync | ||
| 194 | |||
| 195 | /* This loop puts us back to sleep in case we have a spurrious | ||
| 196 | * wakeup so that the host bridge properly stays asleep. The | ||
| 197 | * CPU will be turned off, either after a known time (about 1 | ||
| 198 | * second) on wallstreet & lombard, or as soon as the CPU enters | ||
| 199 | * SLEEP mode on core99 | ||
| 200 | */ | ||
| 201 | mfmsr r2 | ||
| 202 | oris r2,r2,MSR_POW@h | ||
| 203 | 1: sync | ||
| 204 | mtmsr r2 | ||
| 205 | isync | ||
| 206 | b 1b | ||
| 207 | |||
| 208 | /* | ||
| 209 | * Here is the resume code. | ||
| 210 | */ | ||
| 211 | |||
| 212 | |||
| 213 | /* | ||
| 214 | * Core99 machines resume here | ||
| 215 | * r4 has the physical address of SL_PC(sp) (unused) | ||
| 216 | */ | ||
| 217 | _GLOBAL(core99_wake_up) | ||
| 218 | /* Make sure HID0 no longer contains any sleep bit and that data cache | ||
| 219 | * is disabled | ||
| 220 | */ | ||
| 221 | mfspr r3,SPRN_HID0 | ||
| 222 | rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ | ||
| 223 | rlwinm 3,r3,0,18,15 /* clear DCE, ICE */ | ||
| 224 | mtspr SPRN_HID0,r3 | ||
| 225 | sync | ||
| 226 | isync | ||
| 227 | |||
| 228 | /* sanitize MSR */ | ||
| 229 | mfmsr r3 | ||
| 230 | ori r3,r3,MSR_EE|MSR_IP | ||
| 231 | xori r3,r3,MSR_EE|MSR_IP | ||
| 232 | sync | ||
| 233 | isync | ||
| 234 | mtmsr r3 | ||
| 235 | sync | ||
| 236 | isync | ||
| 237 | |||
| 238 | /* Recover sleep storage */ | ||
| 239 | lis r3,sleep_storage@ha | ||
| 240 | addi r3,r3,sleep_storage@l | ||
| 241 | tophys(r3,r3) | ||
| 242 | lwz r1,0(r3) | ||
| 243 | |||
| 244 | /* Pass thru to older resume code ... */ | ||
| 245 | /* | ||
| 246 | * Here is the resume code for older machines. | ||
| 247 | * r1 has the physical address of SL_PC(sp). | ||
| 248 | */ | ||
| 249 | |||
| 250 | grackle_wake_up: | ||
| 251 | |||
| 252 | /* Restore the kernel's segment registers before | ||
| 253 | * we do any r1 memory access as we are not sure they | ||
| 254 | * are in a sane state above the first 256Mb region | ||
| 255 | */ | ||
| 256 | li r0,16 /* load up segment register values */ | ||
| 257 | mtctr r0 /* for context 0 */ | ||
| 258 | lis r3,0x2000 /* Ku = 1, VSID = 0 */ | ||
| 259 | li r4,0 | ||
| 260 | 3: mtsrin r3,r4 | ||
| 261 | addi r3,r3,0x111 /* increment VSID */ | ||
| 262 | addis r4,r4,0x1000 /* address of next segment */ | ||
| 263 | bdnz 3b | ||
| 264 | sync | ||
| 265 | isync | ||
| 266 | |||
| 267 | subi r1,r1,SL_PC | ||
| 268 | |||
| 269 | /* Restore various CPU config stuffs */ | ||
| 270 | bl __restore_cpu_setup | ||
| 271 | |||
| 272 | /* Make sure all FPRs have been initialized */ | ||
| 273 | bl reloc_offset | ||
| 274 | bl __init_fpu_registers | ||
| 275 | |||
| 276 | /* Invalidate & enable L1 cache, we don't care about | ||
| 277 | * whatever the ROM may have tried to write to memory | ||
| 278 | */ | ||
| 279 | bl __inval_enable_L1 | ||
| 280 | |||
| 281 | /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ | ||
| 282 | lwz r4,SL_SDR1(r1) | ||
| 283 | mtsdr1 r4 | ||
| 284 | lwz r4,SL_SPRG0(r1) | ||
| 285 | mtsprg 0,r4 | ||
| 286 | lwz r4,SL_SPRG0+4(r1) | ||
| 287 | mtsprg 1,r4 | ||
| 288 | lwz r4,SL_SPRG0+8(r1) | ||
| 289 | mtsprg 2,r4 | ||
| 290 | lwz r4,SL_SPRG0+12(r1) | ||
| 291 | mtsprg 3,r4 | ||
| 292 | |||
| 293 | lwz r4,SL_DBAT0(r1) | ||
| 294 | mtdbatu 0,r4 | ||
| 295 | lwz r4,SL_DBAT0+4(r1) | ||
| 296 | mtdbatl 0,r4 | ||
| 297 | lwz r4,SL_DBAT1(r1) | ||
| 298 | mtdbatu 1,r4 | ||
| 299 | lwz r4,SL_DBAT1+4(r1) | ||
| 300 | mtdbatl 1,r4 | ||
| 301 | lwz r4,SL_DBAT2(r1) | ||
| 302 | mtdbatu 2,r4 | ||
| 303 | lwz r4,SL_DBAT2+4(r1) | ||
| 304 | mtdbatl 2,r4 | ||
| 305 | lwz r4,SL_DBAT3(r1) | ||
| 306 | mtdbatu 3,r4 | ||
| 307 | lwz r4,SL_DBAT3+4(r1) | ||
| 308 | mtdbatl 3,r4 | ||
| 309 | lwz r4,SL_IBAT0(r1) | ||
| 310 | mtibatu 0,r4 | ||
| 311 | lwz r4,SL_IBAT0+4(r1) | ||
| 312 | mtibatl 0,r4 | ||
| 313 | lwz r4,SL_IBAT1(r1) | ||
| 314 | mtibatu 1,r4 | ||
| 315 | lwz r4,SL_IBAT1+4(r1) | ||
| 316 | mtibatl 1,r4 | ||
| 317 | lwz r4,SL_IBAT2(r1) | ||
| 318 | mtibatu 2,r4 | ||
| 319 | lwz r4,SL_IBAT2+4(r1) | ||
| 320 | mtibatl 2,r4 | ||
| 321 | lwz r4,SL_IBAT3(r1) | ||
| 322 | mtibatu 3,r4 | ||
| 323 | lwz r4,SL_IBAT3+4(r1) | ||
| 324 | mtibatl 3,r4 | ||
| 325 | |||
| 326 | BEGIN_FTR_SECTION | ||
| 327 | li r4,0 | ||
| 328 | mtspr SPRN_DBAT4U,r4 | ||
| 329 | mtspr SPRN_DBAT4L,r4 | ||
| 330 | mtspr SPRN_DBAT5U,r4 | ||
| 331 | mtspr SPRN_DBAT5L,r4 | ||
| 332 | mtspr SPRN_DBAT6U,r4 | ||
| 333 | mtspr SPRN_DBAT6L,r4 | ||
| 334 | mtspr SPRN_DBAT7U,r4 | ||
| 335 | mtspr SPRN_DBAT7L,r4 | ||
| 336 | mtspr SPRN_IBAT4U,r4 | ||
| 337 | mtspr SPRN_IBAT4L,r4 | ||
| 338 | mtspr SPRN_IBAT5U,r4 | ||
| 339 | mtspr SPRN_IBAT5L,r4 | ||
| 340 | mtspr SPRN_IBAT6U,r4 | ||
| 341 | mtspr SPRN_IBAT6L,r4 | ||
| 342 | mtspr SPRN_IBAT7U,r4 | ||
| 343 | mtspr SPRN_IBAT7L,r4 | ||
| 344 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) | ||
| 345 | |||
| 346 | /* Flush all TLBs */ | ||
| 347 | lis r4,0x1000 | ||
| 348 | 1: addic. r4,r4,-0x1000 | ||
| 349 | tlbie r4 | ||
| 350 | blt 1b | ||
| 351 | sync | ||
| 352 | |||
| 353 | /* restore the MSR and turn on the MMU */ | ||
| 354 | lwz r3,SL_MSR(r1) | ||
| 355 | bl turn_on_mmu | ||
| 356 | |||
| 357 | /* get back the stack pointer */ | ||
| 358 | tovirt(r1,r1) | ||
| 359 | |||
| 360 | /* Restore TB */ | ||
| 361 | li r3,0 | ||
| 362 | mttbl r3 | ||
| 363 | lwz r3,SL_TB(r1) | ||
| 364 | lwz r4,SL_TB+4(r1) | ||
| 365 | mttbu r3 | ||
| 366 | mttbl r4 | ||
| 367 | |||
| 368 | /* Restore the callee-saved registers and return */ | ||
| 369 | lwz r0,SL_CR(r1) | ||
| 370 | mtcr r0 | ||
| 371 | lwz r2,SL_R2(r1) | ||
| 372 | lmw r12,SL_R12(r1) | ||
| 373 | addi r1,r1,SL_SIZE | ||
| 374 | lwz r0,4(r1) | ||
| 375 | mtlr r0 | ||
| 376 | blr | ||
| 377 | |||
| 378 | turn_on_mmu: | ||
| 379 | mflr r4 | ||
| 380 | tovirt(r4,r4) | ||
| 381 | mtsrr0 r4 | ||
| 382 | mtsrr1 r3 | ||
| 383 | sync | ||
| 384 | isync | ||
| 385 | rfi | ||
| 386 | |||
| 387 | #endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */ | ||
| 388 | |||
| 389 | .section .data | ||
| 390 | .balign L1_CACHE_BYTES | ||
| 391 | sleep_storage: | ||
| 392 | .long 0 | ||
| 393 | .balign L1_CACHE_BYTES, 0 | ||
| 394 | |||
| 395 | #endif /* CONFIG_6xx */ | ||
| 396 | .section .text | ||
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c deleted file mode 100644 index 26ff26238f03..000000000000 --- a/arch/ppc/platforms/pmac_smp.c +++ /dev/null  | |||
| @@ -1,692 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SMP support for power macintosh. | ||
| 3 | * | ||
| 4 | * We support both the old "powersurge" SMP architecture | ||
| 5 | * and the current Core99 (G4 PowerMac) machines. | ||
| 6 | * | ||
| 7 | * Note that we don't support the very first rev. of | ||
| 8 | * Apple/DayStar 2 CPUs board, the one with the funky | ||
| 9 | * watchdog. Hopefully, none of these should be there except | ||
| 10 | * maybe internally to Apple. I should probably still add some | ||
| 11 | * code to detect this card though and disable SMP. --BenH. | ||
| 12 | * | ||
| 13 | * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) | ||
| 14 | * and Ben Herrenschmidt <benh@kernel.crashing.org>. | ||
| 15 | * | ||
| 16 | * Support for DayStar quad CPU cards | ||
| 17 | * Copyright (C) XLR8, Inc. 1994-2000 | ||
| 18 | * | ||
| 19 | * This program is free software; you can redistribute it and/or | ||
| 20 | * modify it under the terms of the GNU General Public License | ||
| 21 | * as published by the Free Software Foundation; either version | ||
| 22 | * 2 of the License, or (at your option) any later version. | ||
| 23 | */ | ||
| 24 | #include <linux/config.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | #include <linux/smp.h> | ||
| 28 | #include <linux/smp_lock.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/kernel_stat.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/spinlock.h> | ||
| 34 | #include <linux/errno.h> | ||
| 35 | #include <linux/hardirq.h> | ||
| 36 | #include <linux/cpu.h> | ||
| 37 | |||
| 38 | #include <asm/ptrace.h> | ||
| 39 | #include <asm/atomic.h> | ||
| 40 | #include <asm/irq.h> | ||
| 41 | #include <asm/page.h> | ||
| 42 | #include <asm/pgtable.h> | ||
| 43 | #include <asm/sections.h> | ||
| 44 | #include <asm/io.h> | ||
| 45 | #include <asm/prom.h> | ||
| 46 | #include <asm/smp.h> | ||
| 47 | #include <asm/residual.h> | ||
| 48 | #include <asm/machdep.h> | ||
| 49 | #include <asm/pmac_feature.h> | ||
| 50 | #include <asm/time.h> | ||
| 51 | #include <asm/open_pic.h> | ||
| 52 | #include <asm/cacheflush.h> | ||
| 53 | #include <asm/keylargo.h> | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Powersurge (old powermac SMP) support. | ||
| 57 | */ | ||
| 58 | |||
| 59 | extern void __secondary_start_pmac_0(void); | ||
| 60 | |||
| 61 | /* Addresses for powersurge registers */ | ||
| 62 | #define HAMMERHEAD_BASE 0xf8000000 | ||
| 63 | #define HHEAD_CONFIG 0x90 | ||
| 64 | #define HHEAD_SEC_INTR 0xc0 | ||
| 65 | |||
| 66 | /* register for interrupting the primary processor on the powersurge */ | ||
| 67 | /* N.B. this is actually the ethernet ROM! */ | ||
| 68 | #define PSURGE_PRI_INTR 0xf3019000 | ||
| 69 | |||
| 70 | /* register for storing the start address for the secondary processor */ | ||
| 71 | /* N.B. this is the PCI config space address register for the 1st bridge */ | ||
| 72 | #define PSURGE_START 0xf2800000 | ||
| 73 | |||
| 74 | /* Daystar/XLR8 4-CPU card */ | ||
| 75 | #define PSURGE_QUAD_REG_ADDR 0xf8800000 | ||
| 76 | |||
| 77 | #define PSURGE_QUAD_IRQ_SET 0 | ||
| 78 | #define PSURGE_QUAD_IRQ_CLR 1 | ||
| 79 | #define PSURGE_QUAD_IRQ_PRIMARY 2 | ||
| 80 | #define PSURGE_QUAD_CKSTOP_CTL 3 | ||
| 81 | #define PSURGE_QUAD_PRIMARY_ARB 4 | ||
| 82 | #define PSURGE_QUAD_BOARD_ID 6 | ||
| 83 | #define PSURGE_QUAD_WHICH_CPU 7 | ||
| 84 | #define PSURGE_QUAD_CKSTOP_RDBK 8 | ||
| 85 | #define PSURGE_QUAD_RESET_CTL 11 | ||
| 86 | |||
| 87 | #define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) | ||
| 88 | #define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) | ||
| 89 | #define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) | ||
| 90 | #define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) | ||
| 91 | |||
| 92 | /* virtual addresses for the above */ | ||
| 93 | static volatile u8 __iomem *hhead_base; | ||
| 94 | static volatile u8 __iomem *quad_base; | ||
| 95 | static volatile u32 __iomem *psurge_pri_intr; | ||
| 96 | static volatile u8 __iomem *psurge_sec_intr; | ||
| 97 | static volatile u32 __iomem *psurge_start; | ||
| 98 | |||
| 99 | /* values for psurge_type */ | ||
| 100 | #define PSURGE_NONE -1 | ||
| 101 | #define PSURGE_DUAL 0 | ||
| 102 | #define PSURGE_QUAD_OKEE 1 | ||
| 103 | #define PSURGE_QUAD_COTTON 2 | ||
| 104 | #define PSURGE_QUAD_ICEGRASS 3 | ||
| 105 | |||
| 106 | /* what sort of powersurge board we have */ | ||
| 107 | static int psurge_type = PSURGE_NONE; | ||
| 108 | |||
| 109 | /* L2 and L3 cache settings to pass from CPU0 to CPU1 */ | ||
| 110 | volatile static long int core99_l2_cache; | ||
| 111 | volatile static long int core99_l3_cache; | ||
| 112 | |||
| 113 | /* Timebase freeze GPIO */ | ||
| 114 | static unsigned int core99_tb_gpio; | ||
| 115 | |||
| 116 | /* Sync flag for HW tb sync */ | ||
| 117 | static volatile int sec_tb_reset = 0; | ||
| 118 | static unsigned int pri_tb_hi, pri_tb_lo; | ||
| 119 | static unsigned int pri_tb_stamp; | ||
| 120 | |||
| 121 | static void __devinit core99_init_caches(int cpu) | ||
| 122 | { | ||
| 123 | if (!cpu_has_feature(CPU_FTR_L2CR)) | ||
| 124 | return; | ||
| 125 | |||
| 126 | if (cpu == 0) { | ||
| 127 | core99_l2_cache = _get_L2CR(); | ||
| 128 | printk("CPU0: L2CR is %lx\n", core99_l2_cache); | ||
| 129 | } else { | ||
| 130 | printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR()); | ||
| 131 | _set_L2CR(0); | ||
| 132 | _set_L2CR(core99_l2_cache); | ||
| 133 | printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache); | ||
| 134 | } | ||
| 135 | |||
| 136 | if (!cpu_has_feature(CPU_FTR_L3CR)) | ||
| 137 | return; | ||
| 138 | |||
| 139 | if (cpu == 0){ | ||
| 140 | core99_l3_cache = _get_L3CR(); | ||
| 141 | printk("CPU0: L3CR is %lx\n", core99_l3_cache); | ||
| 142 | } else { | ||
| 143 | printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR()); | ||
| 144 | _set_L3CR(0); | ||
| 145 | _set_L3CR(core99_l3_cache); | ||
| 146 | printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Set and clear IPIs for powersurge. | ||
| 152 | */ | ||
| 153 | static inline void psurge_set_ipi(int cpu) | ||
| 154 | { | ||
| 155 | if (psurge_type == PSURGE_NONE) | ||
| 156 | return; | ||
| 157 | if (cpu == 0) | ||
| 158 | in_be32(psurge_pri_intr); | ||
| 159 | else if (psurge_type == PSURGE_DUAL) | ||
| 160 | out_8(psurge_sec_intr, 0); | ||
| 161 | else | ||
| 162 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); | ||
| 163 | } | ||
| 164 | |||
| 165 | static inline void psurge_clr_ipi(int cpu) | ||
| 166 | { | ||
| 167 | if (cpu > 0) { | ||
| 168 | switch(psurge_type) { | ||
| 169 | case PSURGE_DUAL: | ||
| 170 | out_8(psurge_sec_intr, ~0); | ||
| 171 | case PSURGE_NONE: | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | /* | ||
| 180 | * On powersurge (old SMP powermac architecture) we don't have | ||
| 181 | * separate IPIs for separate messages like openpic does. Instead | ||
| 182 | * we have a bitmap for each processor, where a 1 bit means that | ||
| 183 | * the corresponding message is pending for that processor. | ||
| 184 | * Ideally each cpu's entry would be in a different cache line. | ||
| 185 | * -- paulus. | ||
| 186 | */ | ||
| 187 | static unsigned long psurge_smp_message[NR_CPUS]; | ||
| 188 | |||
| 189 | void psurge_smp_message_recv(struct pt_regs *regs) | ||
| 190 | { | ||
| 191 | int cpu = smp_processor_id(); | ||
| 192 | int msg; | ||
| 193 | |||
| 194 | /* clear interrupt */ | ||
| 195 | psurge_clr_ipi(cpu); | ||
| 196 | |||
| 197 | if (num_online_cpus() < 2) | ||
| 198 | return; | ||
| 199 | |||
| 200 | /* make sure there is a message there */ | ||
| 201 | for (msg = 0; msg < 4; msg++) | ||
| 202 | if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) | ||
| 203 | smp_message_recv(msg, regs); | ||
| 204 | } | ||
| 205 | |||
| 206 | irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs) | ||
| 207 | { | ||
| 208 | psurge_smp_message_recv(regs); | ||
| 209 | return IRQ_HANDLED; | ||
| 210 | } | ||
| 211 | |||
| 212 | static void smp_psurge_message_pass(int target, int msg) | ||
| 213 | { | ||
| 214 | int i; | ||
| 215 | |||
| 216 | if (num_online_cpus() < 2) | ||
| 217 | return; | ||
| 218 | |||
| 219 | for (i = 0; i < NR_CPUS; i++) { | ||
| 220 | if (!cpu_online(i)) | ||
| 221 | continue; | ||
| 222 | if (target == MSG_ALL | ||
| 223 | || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) | ||
| 224 | || target == i) { | ||
| 225 | set_bit(msg, &psurge_smp_message[i]); | ||
| 226 | psurge_set_ipi(i); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | /* | ||
| 232 | * Determine a quad card presence. We read the board ID register, we | ||
| 233 | * force the data bus to change to something else, and we read it again. | ||
| 234 | * It it's stable, then the register probably exist (ugh !) | ||
| 235 | */ | ||
| 236 | static int __init psurge_quad_probe(void) | ||
| 237 | { | ||
| 238 | int type; | ||
| 239 | unsigned int i; | ||
| 240 | |||
| 241 | type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); | ||
| 242 | if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS | ||
| 243 | || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) | ||
| 244 | return PSURGE_DUAL; | ||
| 245 | |||
| 246 | /* looks OK, try a slightly more rigorous test */ | ||
| 247 | /* bogus is not necessarily cacheline-aligned, | ||
| 248 | though I don't suppose that really matters. -- paulus */ | ||
| 249 | for (i = 0; i < 100; i++) { | ||
| 250 | volatile u32 bogus[8]; | ||
| 251 | bogus[(0+i)%8] = 0x00000000; | ||
| 252 | bogus[(1+i)%8] = 0x55555555; | ||
| 253 | bogus[(2+i)%8] = 0xFFFFFFFF; | ||
| 254 | bogus[(3+i)%8] = 0xAAAAAAAA; | ||
| 255 | bogus[(4+i)%8] = 0x33333333; | ||
| 256 | bogus[(5+i)%8] = 0xCCCCCCCC; | ||
| 257 | bogus[(6+i)%8] = 0xCCCCCCCC; | ||
| 258 | bogus[(7+i)%8] = 0x33333333; | ||
| 259 | wmb(); | ||
| 260 | asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); | ||
| 261 | mb(); | ||
| 262 | if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) | ||
| 263 | return PSURGE_DUAL; | ||
| 264 | } | ||
| 265 | return type; | ||
| 266 | } | ||
| 267 | |||
| 268 | static void __init psurge_quad_init(void) | ||
| 269 | { | ||
| 270 | int procbits; | ||
| 271 | |||
| 272 | if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); | ||
| 273 | procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); | ||
| 274 | if (psurge_type == PSURGE_QUAD_ICEGRASS) | ||
| 275 | PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); | ||
| 276 | else | ||
| 277 | PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); | ||
| 278 | mdelay(33); | ||
| 279 | out_8(psurge_sec_intr, ~0); | ||
| 280 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); | ||
| 281 | PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); | ||
| 282 | if (psurge_type != PSURGE_QUAD_ICEGRASS) | ||
| 283 | PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); | ||
| 284 | PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); | ||
| 285 | mdelay(33); | ||
| 286 | PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); | ||
| 287 | mdelay(33); | ||
| 288 | PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); | ||
| 289 | mdelay(33); | ||
| 290 | } | ||
| 291 | |||
| 292 | static int __init smp_psurge_probe(void) | ||
| 293 | { | ||
| 294 | int i, ncpus; | ||
| 295 | |||
| 296 | /* We don't do SMP on the PPC601 -- paulus */ | ||
| 297 | if (PVR_VER(mfspr(SPRN_PVR)) == 1) | ||
| 298 | return 1; | ||
| 299 | |||
| 300 | /* | ||
| 301 | * The powersurge cpu board can be used in the generation | ||
| 302 | * of powermacs that have a socket for an upgradeable cpu card, | ||
| 303 | * including the 7500, 8500, 9500, 9600. | ||
| 304 | * The device tree doesn't tell you if you have 2 cpus because | ||
| 305 | * OF doesn't know anything about the 2nd processor. | ||
| 306 | * Instead we look for magic bits in magic registers, | ||
| 307 | * in the hammerhead memory controller in the case of the | ||
| 308 | * dual-cpu powersurge board. -- paulus. | ||
| 309 | */ | ||
| 310 | if (find_devices("hammerhead") == NULL) | ||
| 311 | return 1; | ||
| 312 | |||
| 313 | hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); | ||
| 314 | quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); | ||
| 315 | psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; | ||
| 316 | |||
| 317 | psurge_type = psurge_quad_probe(); | ||
| 318 | if (psurge_type != PSURGE_DUAL) { | ||
| 319 | psurge_quad_init(); | ||
| 320 | /* All released cards using this HW design have 4 CPUs */ | ||
| 321 | ncpus = 4; | ||
| 322 | } else { | ||
| 323 | iounmap(quad_base); | ||
| 324 | if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { | ||
| 325 | /* not a dual-cpu card */ | ||
| 326 | iounmap(hhead_base); | ||
| 327 | psurge_type = PSURGE_NONE; | ||
| 328 | return 1; | ||
| 329 | } | ||
| 330 | ncpus = 2; | ||
| 331 | } | ||
| 332 | |||
| 333 | psurge_start = ioremap(PSURGE_START, 4); | ||
| 334 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); | ||
| 335 | |||
| 336 | /* this is not actually strictly necessary -- paulus. */ | ||
| 337 | for (i = 1; i < ncpus; ++i) | ||
| 338 | smp_hw_index[i] = i; | ||
| 339 | |||
| 340 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); | ||
| 341 | |||
| 342 | return ncpus; | ||
| 343 | } | ||
| 344 | |||
| 345 | static void __init smp_psurge_kick_cpu(int nr) | ||
| 346 | { | ||
| 347 | unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; | ||
| 348 | unsigned long a; | ||
| 349 | |||
| 350 | /* may need to flush here if secondary bats aren't setup */ | ||
| 351 | for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) | ||
| 352 | asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); | ||
| 353 | asm volatile("sync"); | ||
| 354 | |||
| 355 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); | ||
| 356 | |||
| 357 | out_be32(psurge_start, start); | ||
| 358 | mb(); | ||
| 359 | |||
| 360 | psurge_set_ipi(nr); | ||
| 361 | udelay(10); | ||
| 362 | psurge_clr_ipi(nr); | ||
| 363 | |||
| 364 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); | ||
| 365 | } | ||
| 366 | |||
| 367 | /* | ||
| 368 | * With the dual-cpu powersurge board, the decrementers and timebases | ||
| 369 | * of both cpus are frozen after the secondary cpu is started up, | ||
| 370 | * until we give the secondary cpu another interrupt. This routine | ||
| 371 | * uses this to get the timebases synchronized. | ||
| 372 | * -- paulus. | ||
| 373 | */ | ||
| 374 | static void __init psurge_dual_sync_tb(int cpu_nr) | ||
| 375 | { | ||
| 376 | int t; | ||
| 377 | |||
| 378 | set_dec(tb_ticks_per_jiffy); | ||
| 379 | set_tb(0, 0); | ||
| 380 | last_jiffy_stamp(cpu_nr) = 0; | ||
| 381 | |||
| 382 | if (cpu_nr > 0) { | ||
| 383 | mb(); | ||
| 384 | sec_tb_reset = 1; | ||
| 385 | return; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* wait for the secondary to have reset its TB before proceeding */ | ||
| 389 | for (t = 10000000; t > 0 && !sec_tb_reset; --t) | ||
| 390 | ; | ||
| 391 | |||
| 392 | /* now interrupt the secondary, starting both TBs */ | ||
| 393 | psurge_set_ipi(1); | ||
| 394 | |||
| 395 | smp_tb_synchronized = 1; | ||
| 396 | } | ||
| 397 | |||
| 398 | static struct irqaction psurge_irqaction = { | ||
| 399 | .handler = psurge_primary_intr, | ||
| 400 | .flags = SA_INTERRUPT, | ||
| 401 | .mask = CPU_MASK_NONE, | ||
| 402 | .name = "primary IPI", | ||
| 403 | }; | ||
| 404 | |||
| 405 | static void __init smp_psurge_setup_cpu(int cpu_nr) | ||
| 406 | { | ||
| 407 | |||
| 408 | if (cpu_nr == 0) { | ||
| 409 | /* If we failed to start the second CPU, we should still | ||
| 410 | * send it an IPI to start the timebase & DEC or we might | ||
| 411 | * have them stuck. | ||
| 412 | */ | ||
| 413 | if (num_online_cpus() < 2) { | ||
| 414 | if (psurge_type == PSURGE_DUAL) | ||
| 415 | psurge_set_ipi(1); | ||
| 416 | return; | ||
| 417 | } | ||
| 418 | /* reset the entry point so if we get another intr we won't | ||
| 419 | * try to startup again */ | ||
| 420 | out_be32(psurge_start, 0x100); | ||
| 421 | if (setup_irq(30, &psurge_irqaction)) | ||
| 422 | printk(KERN_ERR "Couldn't get primary IPI interrupt"); | ||
| 423 | } | ||
| 424 | |||
| 425 | if (psurge_type == PSURGE_DUAL) | ||
| 426 | psurge_dual_sync_tb(cpu_nr); | ||
| 427 | } | ||
| 428 | |||
| 429 | void __init smp_psurge_take_timebase(void) | ||
| 430 | { | ||
| 431 | /* Dummy implementation */ | ||
| 432 | } | ||
| 433 | |||
| 434 | void __init smp_psurge_give_timebase(void) | ||
| 435 | { | ||
| 436 | /* Dummy implementation */ | ||
| 437 | } | ||
| 438 | |||
| 439 | static int __init smp_core99_probe(void) | ||
| 440 | { | ||
| 441 | #ifdef CONFIG_6xx | ||
| 442 | extern int powersave_nap; | ||
| 443 | #endif | ||
| 444 | struct device_node *cpus, *firstcpu; | ||
| 445 | int i, ncpus = 0, boot_cpu = -1; | ||
| 446 | u32 *tbprop = NULL; | ||
| 447 | |||
| 448 | if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); | ||
| 449 | cpus = firstcpu = find_type_devices("cpu"); | ||
| 450 | while(cpus != NULL) { | ||
| 451 | u32 *regprop = (u32 *)get_property(cpus, "reg", NULL); | ||
| 452 | char *stateprop = (char *)get_property(cpus, "state", NULL); | ||
| 453 | if (regprop != NULL && stateprop != NULL && | ||
| 454 | !strncmp(stateprop, "running", 7)) | ||
| 455 | boot_cpu = *regprop; | ||
| 456 | ++ncpus; | ||
| 457 | cpus = cpus->next; | ||
| 458 | } | ||
| 459 | if (boot_cpu == -1) | ||
| 460 | printk(KERN_WARNING "Couldn't detect boot CPU !\n"); | ||
| 461 | if (boot_cpu != 0) | ||
| 462 | printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu); | ||
| 463 | |||
| 464 | if (machine_is_compatible("MacRISC4")) { | ||
| 465 | extern struct smp_ops_t core99_smp_ops; | ||
| 466 | |||
| 467 | core99_smp_ops.take_timebase = smp_generic_take_timebase; | ||
| 468 | core99_smp_ops.give_timebase = smp_generic_give_timebase; | ||
| 469 | } else { | ||
| 470 | if (firstcpu != NULL) | ||
| 471 | tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL); | ||
| 472 | if (tbprop) | ||
| 473 | core99_tb_gpio = *tbprop; | ||
| 474 | else | ||
| 475 | core99_tb_gpio = KL_GPIO_TB_ENABLE; | ||
| 476 | } | ||
| 477 | |||
| 478 | if (ncpus > 1) { | ||
| 479 | openpic_request_IPIs(); | ||
| 480 | for (i = 1; i < ncpus; ++i) | ||
| 481 | smp_hw_index[i] = i; | ||
| 482 | #ifdef CONFIG_6xx | ||
| 483 | powersave_nap = 0; | ||
| 484 | #endif | ||
| 485 | core99_init_caches(0); | ||
| 486 | } | ||
| 487 | |||
| 488 | return ncpus; | ||
| 489 | } | ||
| 490 | |||
| 491 | static void __devinit smp_core99_kick_cpu(int nr) | ||
| 492 | { | ||
| 493 | unsigned long save_vector, new_vector; | ||
| 494 | unsigned long flags; | ||
| 495 | |||
| 496 | volatile unsigned long *vector | ||
| 497 | = ((volatile unsigned long *)(KERNELBASE+0x100)); | ||
| 498 | if (nr < 0 || nr > 3) | ||
| 499 | return; | ||
| 500 | if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); | ||
| 501 | |||
| 502 | local_irq_save(flags); | ||
| 503 | local_irq_disable(); | ||
| 504 | |||
| 505 | /* Save reset vector */ | ||
| 506 | save_vector = *vector; | ||
| 507 | |||
| 508 | /* Setup fake reset vector that does | ||
| 509 | * b __secondary_start_pmac_0 + nr*8 - KERNELBASE | ||
| 510 | */ | ||
| 511 | new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8; | ||
| 512 | *vector = 0x48000002 + new_vector - KERNELBASE; | ||
| 513 | |||
| 514 | /* flush data cache and inval instruction cache */ | ||
| 515 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); | ||
| 516 | |||
| 517 | /* Put some life in our friend */ | ||
| 518 | pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); | ||
| 519 | |||
| 520 | /* FIXME: We wait a bit for the CPU to take the exception, I should | ||
| 521 | * instead wait for the entry code to set something for me. Well, | ||
| 522 | * ideally, all that crap will be done in prom.c and the CPU left | ||
| 523 | * in a RAM-based wait loop like CHRP. | ||
| 524 | */ | ||
| 525 | mdelay(1); | ||
| 526 | |||
| 527 | /* Restore our exception vector */ | ||
| 528 | *vector = save_vector; | ||
| 529 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); | ||
| 530 | |||
| 531 | local_irq_restore(flags); | ||
| 532 | if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); | ||
| 533 | } | ||
| 534 | |||
| 535 | static void __devinit smp_core99_setup_cpu(int cpu_nr) | ||
| 536 | { | ||
| 537 | /* Setup L2/L3 */ | ||
| 538 | if (cpu_nr != 0) | ||
| 539 | core99_init_caches(cpu_nr); | ||
| 540 | |||
| 541 | /* Setup openpic */ | ||
| 542 | do_openpic_setup_cpu(); | ||
| 543 | |||
| 544 | if (cpu_nr == 0) { | ||
| 545 | #ifdef CONFIG_POWER4 | ||
| 546 | extern void g5_phy_disable_cpu1(void); | ||
| 547 | |||
| 548 | /* If we didn't start the second CPU, we must take | ||
| 549 | * it off the bus | ||
| 550 | */ | ||
| 551 | if (machine_is_compatible("MacRISC4") && | ||
| 552 | num_online_cpus() < 2) | ||
| 553 | g5_phy_disable_cpu1(); | ||
| 554 | #endif /* CONFIG_POWER4 */ | ||
| 555 | if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); | ||
| 556 | } | ||
| 557 | } | ||
| 558 | |||
| 559 | /* not __init, called in sleep/wakeup code */ | ||
| 560 | void smp_core99_take_timebase(void) | ||
| 561 | { | ||
| 562 | unsigned long flags; | ||
| 563 | |||
| 564 | /* tell the primary we're here */ | ||
| 565 | sec_tb_reset = 1; | ||
| 566 | mb(); | ||
| 567 | |||
| 568 | /* wait for the primary to set pri_tb_hi/lo */ | ||
| 569 | while (sec_tb_reset < 2) | ||
| 570 | mb(); | ||
| 571 | |||
| 572 | /* set our stuff the same as the primary */ | ||
| 573 | local_irq_save(flags); | ||
| 574 | set_dec(1); | ||
| 575 | set_tb(pri_tb_hi, pri_tb_lo); | ||
| 576 | last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp; | ||
| 577 | mb(); | ||
| 578 | |||
| 579 | /* tell the primary we're done */ | ||
| 580 | sec_tb_reset = 0; | ||
| 581 | mb(); | ||
| 582 | local_irq_restore(flags); | ||
| 583 | } | ||
| 584 | |||
| 585 | /* not __init, called in sleep/wakeup code */ | ||
| 586 | void smp_core99_give_timebase(void) | ||
| 587 | { | ||
| 588 | unsigned long flags; | ||
| 589 | unsigned int t; | ||
| 590 | |||
| 591 | /* wait for the secondary to be in take_timebase */ | ||
| 592 | for (t = 100000; t > 0 && !sec_tb_reset; --t) | ||
| 593 | udelay(10); | ||
| 594 | if (!sec_tb_reset) { | ||
| 595 | printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); | ||
| 596 | return; | ||
| 597 | } | ||
| 598 | |||
| 599 | /* freeze the timebase and read it */ | ||
| 600 | /* disable interrupts so the timebase is disabled for the | ||
| 601 | shortest possible time */ | ||
| 602 | local_irq_save(flags); | ||
| 603 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); | ||
| 604 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); | ||
| 605 | mb(); | ||
| 606 | pri_tb_hi = get_tbu(); | ||
| 607 | pri_tb_lo = get_tbl(); | ||
| 608 | pri_tb_stamp = last_jiffy_stamp(smp_processor_id()); | ||
| 609 | mb(); | ||
| 610 | |||
| 611 | /* tell the secondary we're ready */ | ||
| 612 | sec_tb_reset = 2; | ||
| 613 | mb(); | ||
| 614 | |||
| 615 | /* wait for the secondary to have taken it */ | ||
| 616 | for (t = 100000; t > 0 && sec_tb_reset; --t) | ||
| 617 | udelay(10); | ||
| 618 | if (sec_tb_reset) | ||
| 619 | printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n"); | ||
| 620 | else | ||
| 621 | smp_tb_synchronized = 1; | ||
| 622 | |||
| 623 | /* Now, restart the timebase by leaving the GPIO to an open collector */ | ||
| 624 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); | ||
| 625 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); | ||
| 626 | local_irq_restore(flags); | ||
| 627 | } | ||
| 628 | |||
| 629 | |||
| 630 | /* PowerSurge-style Macs */ | ||
| 631 | struct smp_ops_t psurge_smp_ops = { | ||
| 632 | .message_pass = smp_psurge_message_pass, | ||
| 633 | .probe = smp_psurge_probe, | ||
| 634 | .kick_cpu = smp_psurge_kick_cpu, | ||
| 635 | .setup_cpu = smp_psurge_setup_cpu, | ||
| 636 | .give_timebase = smp_psurge_give_timebase, | ||
| 637 | .take_timebase = smp_psurge_take_timebase, | ||
| 638 | }; | ||
| 639 | |||
| 640 | /* Core99 Macs (dual G4s) */ | ||
| 641 | struct smp_ops_t core99_smp_ops = { | ||
| 642 | .message_pass = smp_openpic_message_pass, | ||
| 643 | .probe = smp_core99_probe, | ||
| 644 | .kick_cpu = smp_core99_kick_cpu, | ||
| 645 | .setup_cpu = smp_core99_setup_cpu, | ||
| 646 | .give_timebase = smp_core99_give_timebase, | ||
| 647 | .take_timebase = smp_core99_take_timebase, | ||
| 648 | }; | ||
| 649 | |||
| 650 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 651 | |||
| 652 | int __cpu_disable(void) | ||
| 653 | { | ||
| 654 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
| 655 | |||
| 656 | /* XXX reset cpu affinity here */ | ||
| 657 | openpic_set_priority(0xf); | ||
| 658 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 659 | mb(); | ||
| 660 | udelay(20); | ||
| 661 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
| 662 | return 0; | ||
| 663 | } | ||
| 664 | |||
| 665 | extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */ | ||
| 666 | static int cpu_dead[NR_CPUS]; | ||
| 667 | |||
| 668 | void cpu_die(void) | ||
| 669 | { | ||
| 670 | local_irq_disable(); | ||
| 671 | cpu_dead[smp_processor_id()] = 1; | ||
| 672 | mb(); | ||
| 673 | low_cpu_die(); | ||
| 674 | } | ||
| 675 | |||
| 676 | void __cpu_die(unsigned int cpu) | ||
| 677 | { | ||
| 678 | int timeout; | ||
| 679 | |||
| 680 | timeout = 1000; | ||
| 681 | while (!cpu_dead[cpu]) { | ||
| 682 | if (--timeout == 0) { | ||
| 683 | printk("CPU %u refused to die!\n", cpu); | ||
| 684 | break; | ||
| 685 | } | ||
| 686 | msleep(1); | ||
| 687 | } | ||
| 688 | cpu_callin_map[cpu] = 0; | ||
| 689 | cpu_dead[cpu] = 0; | ||
| 690 | } | ||
| 691 | |||
| 692 | #endif | ||
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c deleted file mode 100644 index edb9fcc64790..000000000000 --- a/arch/ppc/platforms/pmac_time.c +++ /dev/null  | |||
| @@ -1,291 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Support for periodic interrupts (100 per second) and for getting | ||
| 3 | * the current time from the RTC on Power Macintoshes. | ||
| 4 | * | ||
| 5 | * We use the decrementer register for our periodic interrupts. | ||
| 6 | * | ||
| 7 | * Paul Mackerras August 1996. | ||
| 8 | * Copyright (C) 1996 Paul Mackerras. | ||
| 9 | */ | ||
| 10 | #include <linux/config.h> | ||
| 11 | #include <linux/errno.h> | ||
| 12 | #include <linux/sched.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/param.h> | ||
| 15 | #include <linux/string.h> | ||
| 16 | #include <linux/mm.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/time.h> | ||
| 19 | #include <linux/adb.h> | ||
| 20 | #include <linux/cuda.h> | ||
| 21 | #include <linux/pmu.h> | ||
| 22 | #include <linux/hardirq.h> | ||
| 23 | |||
| 24 | #include <asm/sections.h> | ||
| 25 | #include <asm/prom.h> | ||
| 26 | #include <asm/system.h> | ||
| 27 | #include <asm/io.h> | ||
| 28 | #include <asm/pgtable.h> | ||
| 29 | #include <asm/machdep.h> | ||
| 30 | #include <asm/time.h> | ||
| 31 | #include <asm/nvram.h> | ||
| 32 | |||
| 33 | /* Apparently the RTC stores seconds since 1 Jan 1904 */ | ||
| 34 | #define RTC_OFFSET 2082844800 | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Calibrate the decrementer frequency with the VIA timer 1. | ||
| 38 | */ | ||
| 39 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ | ||
| 40 | |||
| 41 | /* VIA registers */ | ||
| 42 | #define RS 0x200 /* skip between registers */ | ||
| 43 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
| 44 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
| 45 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
| 46 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
| 47 | #define ACR (11*RS) /* Auxiliary control register */ | ||
| 48 | #define IFR (13*RS) /* Interrupt flag register */ | ||
| 49 | |||
| 50 | /* Bits in ACR */ | ||
| 51 | #define T1MODE 0xc0 /* Timer 1 mode */ | ||
| 52 | #define T1MODE_CONT 0x40 /* continuous interrupts */ | ||
| 53 | |||
| 54 | /* Bits in IFR and IER */ | ||
| 55 | #define T1_INT 0x40 /* Timer 1 interrupt */ | ||
| 56 | |||
| 57 | extern struct timezone sys_tz; | ||
| 58 | |||
| 59 | long __init | ||
| 60 | pmac_time_init(void) | ||
| 61 | { | ||
| 62 | #ifdef CONFIG_NVRAM | ||
| 63 | s32 delta = 0; | ||
| 64 | int dst; | ||
| 65 | |||
| 66 | delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; | ||
| 67 | delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; | ||
| 68 | delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); | ||
| 69 | if (delta & 0x00800000UL) | ||
| 70 | delta |= 0xFF000000UL; | ||
| 71 | dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); | ||
| 72 | printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, | ||
| 73 | dst ? "on" : "off"); | ||
| 74 | return delta; | ||
| 75 | #else | ||
| 76 | return 0; | ||
| 77 | #endif | ||
| 78 | } | ||
| 79 | |||
| 80 | unsigned long | ||
| 81 | pmac_get_rtc_time(void) | ||
| 82 | { | ||
| 83 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) | ||
| 84 | struct adb_request req; | ||
| 85 | unsigned long now; | ||
| 86 | #endif | ||
| 87 | |||
| 88 | /* Get the time from the RTC */ | ||
| 89 | switch (sys_ctrler) { | ||
| 90 | #ifdef CONFIG_ADB_CUDA | ||
| 91 | case SYS_CTRLER_CUDA: | ||
| 92 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | ||
| 93 | return 0; | ||
| 94 | while (!req.complete) | ||
| 95 | cuda_poll(); | ||
| 96 | if (req.reply_len != 7) | ||
| 97 | printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", | ||
| 98 | req.reply_len); | ||
| 99 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | ||
| 100 | + (req.reply[5] << 8) + req.reply[6]; | ||
| 101 | return now - RTC_OFFSET; | ||
| 102 | #endif /* CONFIG_ADB_CUDA */ | ||
| 103 | #ifdef CONFIG_ADB_PMU | ||
| 104 | case SYS_CTRLER_PMU: | ||
| 105 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | ||
| 106 | return 0; | ||
| 107 | while (!req.complete) | ||
| 108 | pmu_poll(); | ||
| 109 | if (req.reply_len != 4) | ||
| 110 | printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", | ||
| 111 | req.reply_len); | ||
| 112 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | ||
| 113 | + (req.reply[2] << 8) + req.reply[3]; | ||
| 114 | return now - RTC_OFFSET; | ||
| 115 | #endif /* CONFIG_ADB_PMU */ | ||
| 116 | default: ; | ||
| 117 | } | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | int | ||
| 122 | pmac_set_rtc_time(unsigned long nowtime) | ||
| 123 | { | ||
| 124 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) | ||
| 125 | struct adb_request req; | ||
| 126 | #endif | ||
| 127 | |||
| 128 | nowtime += RTC_OFFSET; | ||
| 129 | |||
| 130 | switch (sys_ctrler) { | ||
| 131 | #ifdef CONFIG_ADB_CUDA | ||
| 132 | case SYS_CTRLER_CUDA: | ||
| 133 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | ||
| 134 | nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) | ||
| 135 | return 0; | ||
| 136 | while (!req.complete) | ||
| 137 | cuda_poll(); | ||
| 138 | if ((req.reply_len != 3) && (req.reply_len != 7)) | ||
| 139 | printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", | ||
| 140 | req.reply_len); | ||
| 141 | return 1; | ||
| 142 | #endif /* CONFIG_ADB_CUDA */ | ||
| 143 | #ifdef CONFIG_ADB_PMU | ||
| 144 | case SYS_CTRLER_PMU: | ||
| 145 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, | ||
| 146 | nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) | ||
| 147 | return 0; | ||
| 148 | while (!req.complete) | ||
| 149 | pmu_poll(); | ||
| 150 | if (req.reply_len != 0) | ||
| 151 | printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", | ||
| 152 | req.reply_len); | ||
| 153 | return 1; | ||
| 154 | #endif /* CONFIG_ADB_PMU */ | ||
| 155 | default: | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Calibrate the decrementer register using VIA timer 1. | ||
| 162 | * This is used both on powermacs and CHRP machines. | ||
| 163 | */ | ||
| 164 | int __init | ||
| 165 | via_calibrate_decr(void) | ||
| 166 | { | ||
| 167 | struct device_node *vias; | ||
| 168 | volatile unsigned char __iomem *via; | ||
| 169 | int count = VIA_TIMER_FREQ_6 / 100; | ||
| 170 | unsigned int dstart, dend; | ||
| 171 | |||
| 172 | vias = find_devices("via-cuda"); | ||
| 173 | if (vias == 0) | ||
| 174 | vias = find_devices("via-pmu"); | ||
| 175 | if (vias == 0) | ||
| 176 | vias = find_devices("via"); | ||
| 177 | if (vias == 0 || vias->n_addrs == 0) | ||
| 178 | return 0; | ||
| 179 | via = ioremap(vias->addrs[0].address, vias->addrs[0].size); | ||
| 180 | |||
| 181 | /* set timer 1 for continuous interrupts */ | ||
| 182 | out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); | ||
| 183 | /* set the counter to a small value */ | ||
| 184 | out_8(&via[T1CH], 2); | ||
| 185 | /* set the latch to `count' */ | ||
| 186 | out_8(&via[T1LL], count); | ||
| 187 | out_8(&via[T1LH], count >> 8); | ||
| 188 | /* wait until it hits 0 */ | ||
| 189 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
| 190 | ; | ||
| 191 | dstart = get_dec(); | ||
| 192 | /* clear the interrupt & wait until it hits 0 again */ | ||
| 193 | in_8(&via[T1CL]); | ||
| 194 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
| 195 | ; | ||
| 196 | dend = get_dec(); | ||
| 197 | |||
| 198 | tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100); | ||
| 199 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); | ||
| 200 | |||
| 201 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", | ||
| 202 | tb_ticks_per_jiffy, dstart - dend); | ||
| 203 | |||
| 204 | iounmap(via); | ||
| 205 | |||
| 206 | return 1; | ||
| 207 | } | ||
| 208 | |||
| 209 | #ifdef CONFIG_PM | ||
| 210 | /* | ||
| 211 | * Reset the time after a sleep. | ||
| 212 | */ | ||
| 213 | static int | ||
| 214 | time_sleep_notify(struct pmu_sleep_notifier *self, int when) | ||
| 215 | { | ||
| 216 | static unsigned long time_diff; | ||
| 217 | unsigned long flags; | ||
| 218 | unsigned long seq; | ||
| 219 | |||
| 220 | switch (when) { | ||
| 221 | case PBOOK_SLEEP_NOW: | ||
| 222 | do { | ||
| 223 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
| 224 | time_diff = xtime.tv_sec - pmac_get_rtc_time(); | ||
| 225 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
| 226 | break; | ||
| 227 | case PBOOK_WAKE: | ||
| 228 | write_seqlock_irqsave(&xtime_lock, flags); | ||
| 229 | xtime.tv_sec = pmac_get_rtc_time() + time_diff; | ||
| 230 | xtime.tv_nsec = 0; | ||
| 231 | last_rtc_update = xtime.tv_sec; | ||
| 232 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
| 233 | break; | ||
| 234 | } | ||
| 235 | return PBOOK_SLEEP_OK; | ||
| 236 | } | ||
| 237 | |||
| 238 | static struct pmu_sleep_notifier time_sleep_notifier = { | ||
| 239 | time_sleep_notify, SLEEP_LEVEL_MISC, | ||
| 240 | }; | ||
| 241 | #endif /* CONFIG_PM */ | ||
| 242 | |||
| 243 | /* | ||
| 244 | * Query the OF and get the decr frequency. | ||
| 245 | * This was taken from the pmac time_init() when merging the prep/pmac | ||
| 246 | * time functions. | ||
| 247 | */ | ||
| 248 | void __init | ||
| 249 | pmac_calibrate_decr(void) | ||
| 250 | { | ||
| 251 | struct device_node *cpu; | ||
| 252 | unsigned int freq, *fp; | ||
| 253 | |||
| 254 | #ifdef CONFIG_PM | ||
| 255 | pmu_register_sleep_notifier(&time_sleep_notifier); | ||
| 256 | #endif /* CONFIG_PM */ | ||
| 257 | |||
| 258 | /* We assume MacRISC2 machines have correct device-tree | ||
| 259 | * calibration. That's better since the VIA itself seems | ||
| 260 | * to be slightly off. --BenH | ||
| 261 | */ | ||
| 262 | if (!machine_is_compatible("MacRISC2") && | ||
| 263 | !machine_is_compatible("MacRISC3") && | ||
| 264 | !machine_is_compatible("MacRISC4")) | ||
| 265 | if (via_calibrate_decr()) | ||
| 266 | return; | ||
| 267 | |||
| 268 | /* Special case: QuickSilver G4s seem to have a badly calibrated | ||
| 269 | * timebase-frequency in OF, VIA is much better on these. We should | ||
| 270 | * probably implement calibration based on the KL timer on these | ||
| 271 | * machines anyway... -BenH | ||
| 272 | */ | ||
| 273 | if (machine_is_compatible("PowerMac3,5")) | ||
| 274 | if (via_calibrate_decr()) | ||
| 275 | return; | ||
| 276 | /* | ||
| 277 | * The cpu node should have a timebase-frequency property | ||
| 278 | * to tell us the rate at which the decrementer counts. | ||
| 279 | */ | ||
| 280 | cpu = find_type_devices("cpu"); | ||
| 281 | if (cpu == 0) | ||
| 282 | panic("can't find cpu node in time_init"); | ||
| 283 | fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); | ||
| 284 | if (fp == 0) | ||
| 285 | panic("can't get cpu timebase frequency"); | ||
| 286 | freq = *fp; | ||
| 287 | printk("time_init: decrementer frequency = %u.%.6u MHz\n", | ||
| 288 | freq/1000000, freq%1000000); | ||
| 289 | tb_ticks_per_jiffy = freq / HZ; | ||
| 290 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
| 291 | } | ||
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 84ef03018d0e..159dcd92a6d1 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile  | |||
| @@ -39,8 +39,6 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ | |||
| 39 | ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o | 39 | ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o | 
| 40 | obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o | 40 | obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o | 
| 41 | obj-$(CONFIG_PPC_OF) += prom_init.o prom.o | 41 | obj-$(CONFIG_PPC_OF) += prom_init.o prom.o | 
| 42 | obj-$(CONFIG_PPC_PMAC) += open_pic.o | ||
| 43 | obj-$(CONFIG_POWER4) += open_pic2.o | ||
| 44 | obj-$(CONFIG_PPC_CHRP) += open_pic.o | 42 | obj-$(CONFIG_PPC_CHRP) += open_pic.o | 
| 45 | obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o | 43 | obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o | 
| 46 | obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o | 44 | obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o | 
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index af4deace49e0..482f837fd373 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c  | |||
| @@ -70,8 +70,6 @@ int use_of_interrupt_tree; | |||
| 70 | struct device_node *dflt_interrupt_controller; | 70 | struct device_node *dflt_interrupt_controller; | 
| 71 | int num_interrupt_controllers; | 71 | int num_interrupt_controllers; | 
| 72 | 72 | ||
| 73 | int pmac_newworld; | ||
| 74 | |||
| 75 | extern unsigned int rtas_entry; /* physical pointer */ | 73 | extern unsigned int rtas_entry; /* physical pointer */ | 
| 76 | 74 | ||
| 77 | extern struct device_node *allnodes; | 75 | extern struct device_node *allnodes; | 
| @@ -123,22 +121,13 @@ finish_device_tree(void) | |||
| 123 | unsigned long mem = (unsigned long) klimit; | 121 | unsigned long mem = (unsigned long) klimit; | 
| 124 | struct device_node *np; | 122 | struct device_node *np; | 
| 125 | 123 | ||
| 126 | /* All newworld pmac machines and CHRPs now use the interrupt tree */ | 124 | /* All CHRPs now use the interrupt tree */ | 
| 127 | for (np = allnodes; np != NULL; np = np->allnext) { | 125 | for (np = allnodes; np != NULL; np = np->allnext) { | 
| 128 | if (get_property(np, "interrupt-parent", NULL)) { | 126 | if (get_property(np, "interrupt-parent", NULL)) { | 
| 129 | use_of_interrupt_tree = 1; | 127 | use_of_interrupt_tree = 1; | 
| 130 | break; | 128 | break; | 
| 131 | } | 129 | } | 
| 132 | } | 130 | } | 
| 133 | if (_machine == _MACH_Pmac && use_of_interrupt_tree) | ||
| 134 | pmac_newworld = 1; | ||
| 135 | |||
| 136 | #ifdef CONFIG_BOOTX_TEXT | ||
| 137 | if (boot_infos && pmac_newworld) { | ||
| 138 | prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n"); | ||
| 139 | prom_print(" You should use an Open Firmware bootloader\n"); | ||
| 140 | } | ||
| 141 | #endif /* CONFIG_BOOTX_TEXT */ | ||
| 142 | 131 | ||
| 143 | if (use_of_interrupt_tree) { | 132 | if (use_of_interrupt_tree) { | 
| 144 | /* | 133 | /* | 
| @@ -434,16 +423,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) | |||
| 434 | * those machines, we want to offset interrupts from the | 423 | * those machines, we want to offset interrupts from the | 
| 435 | * second openpic by 128 -- BenH | 424 | * second openpic by 128 -- BenH | 
| 436 | */ | 425 | */ | 
| 437 | if (_machine != _MACH_Pmac && num_interrupt_controllers > 1 | 426 | if (num_interrupt_controllers > 1 | 
| 438 | && ic != NULL | 427 | && ic != NULL | 
| 439 | && get_property(ic, "interrupt-parent", NULL) == NULL) | 428 | && get_property(ic, "interrupt-parent", NULL) == NULL) | 
| 440 | offset = 16; | 429 | offset = 16; | 
| 441 | else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1 | ||
| 442 | && ic != NULL && ic->parent != NULL) { | ||
| 443 | char *name = get_property(ic->parent, "name", NULL); | ||
| 444 | if (name && !strcmp(name, "u3")) | ||
| 445 | offset = 128; | ||
| 446 | } | ||
| 447 | 430 | ||
| 448 | np->intrs[i].line = irq[0] + offset; | 431 | np->intrs[i].line = irq[0] + offset; | 
| 449 | if (n > 1) | 432 | if (n > 1) | 
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index c80177f8ec04..4344cbe9b5c5 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c  | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include <asm/bootx.h> | 18 | #include <asm/bootx.h> | 
| 19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> | 
| 20 | #include <asm/errno.h> | 20 | #include <asm/errno.h> | 
| 21 | #include <asm/pmac_feature.h> | ||
| 22 | #include <asm/processor.h> | 21 | #include <asm/processor.h> | 
| 23 | #include <asm/delay.h> | 22 | #include <asm/delay.h> | 
| 24 | #include <asm/btext.h> | 23 | #include <asm/btext.h> | 
| @@ -27,11 +26,9 @@ static volatile unsigned char *sccc, *sccd; | |||
| 27 | unsigned int TXRDY, RXRDY, DLAB; | 26 | unsigned int TXRDY, RXRDY, DLAB; | 
| 28 | static int xmon_expect(const char *str, unsigned int timeout); | 27 | static int xmon_expect(const char *str, unsigned int timeout); | 
| 29 | 28 | ||
| 30 | static int use_serial; | ||
| 31 | static int use_screen; | 29 | static int use_screen; | 
| 32 | static int via_modem; | 30 | static int via_modem; | 
| 33 | static int xmon_use_sccb; | 31 | static int xmon_use_sccb; | 
| 34 | static struct device_node *channel_node; | ||
| 35 | 32 | ||
| 36 | #define TB_SPEED 25000000 | 33 | #define TB_SPEED 25000000 | 
| 37 | 34 | ||
| @@ -112,96 +109,21 @@ xmon_map_scc(void) | |||
| 112 | #ifdef CONFIG_PPC_MULTIPLATFORM | 109 | #ifdef CONFIG_PPC_MULTIPLATFORM | 
| 113 | volatile unsigned char *base; | 110 | volatile unsigned char *base; | 
| 114 | 111 | ||
| 115 | if (_machine == _MACH_Pmac) { | ||
| 116 | struct device_node *np; | ||
| 117 | unsigned long addr; | ||
| 118 | #ifdef CONFIG_BOOTX_TEXT | ||
| 119 | if (!use_screen && !use_serial | ||
| 120 | && !machine_is_compatible("iMac")) { | ||
| 121 | /* see if there is a keyboard in the device tree | ||
| 122 | with a parent of type "adb" */ | ||
| 123 | for (np = find_devices("keyboard"); np; np = np->next) | ||
| 124 | if (np->parent && np->parent->type | ||
| 125 | && strcmp(np->parent->type, "adb") == 0) | ||
| 126 | break; | ||
| 127 | |||
| 128 | /* needs to be hacked if xmon_printk is to be used | ||
| 129 | from within find_via_pmu() */ | ||
| 130 | #ifdef CONFIG_ADB_PMU | ||
| 131 | if (np != NULL && boot_text_mapped && find_via_pmu()) | ||
| 132 | use_screen = 1; | ||
| 133 | #endif | ||
| 134 | #ifdef CONFIG_ADB_CUDA | ||
| 135 | if (np != NULL && boot_text_mapped && find_via_cuda()) | ||
| 136 | use_screen = 1; | ||
| 137 | #endif | ||
| 138 | } | ||
| 139 | if (!use_screen && (np = find_devices("escc")) != NULL) { | ||
| 140 | /* | ||
| 141 | * look for the device node for the serial port | ||
| 142 | * we're using and see if it says it has a modem | ||
| 143 | */ | ||
| 144 | char *name = xmon_use_sccb? "ch-b": "ch-a"; | ||
| 145 | char *slots; | ||
| 146 | int l; | ||
| 147 | |||
| 148 | np = np->child; | ||
| 149 | while (np != NULL && strcmp(np->name, name) != 0) | ||
| 150 | np = np->sibling; | ||
| 151 | if (np != NULL) { | ||
| 152 | /* XXX should parse this properly */ | ||
| 153 | channel_node = np; | ||
| 154 | slots = get_property(np, "slot-names", &l); | ||
| 155 | if (slots != NULL && l >= 10 | ||
| 156 | && strcmp(slots+4, "Modem") == 0) | ||
| 157 | via_modem = 1; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | btext_drawstring("xmon uses "); | ||
| 161 | if (use_screen) | ||
| 162 | btext_drawstring("screen and keyboard\n"); | ||
| 163 | else { | ||
| 164 | if (via_modem) | ||
| 165 | btext_drawstring("modem on "); | ||
| 166 | btext_drawstring(xmon_use_sccb? "printer": "modem"); | ||
| 167 | btext_drawstring(" port\n"); | ||
| 168 | } | ||
| 169 | |||
| 170 | #endif /* CONFIG_BOOTX_TEXT */ | ||
| 171 | |||
| 172 | #ifdef CHRP_ESCC | ||
| 173 | addr = 0xc1013020; | ||
| 174 | #else | ||
| 175 | addr = 0xf3013020; | ||
| 176 | #endif | ||
| 177 | TXRDY = 4; | ||
| 178 | RXRDY = 1; | ||
| 179 | |||
| 180 | np = find_devices("mac-io"); | ||
| 181 | if (np && np->n_addrs) | ||
| 182 | addr = np->addrs[0].address + 0x13020; | ||
| 183 | base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE); | ||
| 184 | sccc = base + (addr & ~PAGE_MASK); | ||
| 185 | sccd = sccc + 0x10; | ||
| 186 | |||
| 187 | } | ||
| 188 | #ifdef CONFIG_PPC_CHRP | 112 | #ifdef CONFIG_PPC_CHRP | 
| 189 | else { | 113 | base = (volatile unsigned char *) isa_io_base; | 
| 190 | base = (volatile unsigned char *) isa_io_base; | 114 | if (_machine == _MACH_chrp) | 
| 191 | if (_machine == _MACH_chrp) | 115 | base = (volatile unsigned char *) | 
| 192 | base = (volatile unsigned char *) | 116 | ioremap(chrp_find_phys_io_base(), 0x1000); | 
| 193 | ioremap(chrp_find_phys_io_base(), 0x1000); | 117 | |
| 194 | 118 | sccc = base + 0x3fd; | |
| 195 | sccc = base + 0x3fd; | 119 | sccd = base + 0x3f8; | 
| 196 | sccd = base + 0x3f8; | 120 | if (xmon_use_sccb) { | 
| 197 | if (xmon_use_sccb) { | 121 | sccc -= 0x100; | 
| 198 | sccc -= 0x100; | 122 | sccd -= 0x100; | 
| 199 | sccd -= 0x100; | ||
| 200 | } | ||
| 201 | TXRDY = 0x20; | ||
| 202 | RXRDY = 1; | ||
| 203 | DLAB = 0x80; | ||
| 204 | } | 123 | } | 
| 124 | TXRDY = 0x20; | ||
| 125 | RXRDY = 1; | ||
| 126 | DLAB = 0x80; | ||
| 205 | #endif /* CONFIG_PPC_CHRP */ | 127 | #endif /* CONFIG_PPC_CHRP */ | 
| 206 | #elif defined(CONFIG_GEMINI) | 128 | #elif defined(CONFIG_GEMINI) | 
| 207 | /* should already be mapped by the kernel boot */ | 129 | /* should already be mapped by the kernel boot */ | 
| @@ -385,16 +307,6 @@ xmon_read_poll(void) | |||
| 385 | return *sccd; | 307 | return *sccd; | 
| 386 | } | 308 | } | 
| 387 | 309 | ||
| 388 | static unsigned char scc_inittab[] = { | ||
| 389 | 13, 0, /* set baud rate divisor */ | ||
| 390 | 12, 1, | ||
| 391 | 14, 1, /* baud rate gen enable, src=rtxc */ | ||
| 392 | 11, 0x50, /* clocks = br gen */ | ||
| 393 | 5, 0xea, /* tx 8 bits, assert DTR & RTS */ | ||
| 394 | 4, 0x46, /* x16 clock, 1 stop */ | ||
| 395 | 3, 0xc1, /* rx enable, 8 bits */ | ||
| 396 | }; | ||
| 397 | |||
| 398 | void | 310 | void | 
| 399 | xmon_init_scc(void) | 311 | xmon_init_scc(void) | 
| 400 | { | 312 | { | 
| @@ -407,43 +319,6 @@ xmon_init_scc(void) | |||
| 407 | sccd[3] = 3; eieio(); /* LCR = 8N1 */ | 319 | sccd[3] = 3; eieio(); /* LCR = 8N1 */ | 
| 408 | sccd[1] = 0; eieio(); /* IER = 0 */ | 320 | sccd[1] = 0; eieio(); /* IER = 0 */ | 
| 409 | } | 321 | } | 
| 410 | else if ( _machine == _MACH_Pmac ) | ||
| 411 | { | ||
| 412 | int i, x; | ||
| 413 | |||
| 414 | if (channel_node != 0) | ||
| 415 | pmac_call_feature( | ||
| 416 | PMAC_FTR_SCC_ENABLE, | ||
| 417 | channel_node, | ||
| 418 | PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); | ||
| 419 | printk(KERN_INFO "Serial port locked ON by debugger !\n"); | ||
| 420 | if (via_modem && channel_node != 0) { | ||
| 421 | unsigned int t0; | ||
| 422 | |||
| 423 | pmac_call_feature( | ||
| 424 | PMAC_FTR_MODEM_ENABLE, | ||
| 425 | channel_node, 0, 1); | ||
| 426 | printk(KERN_INFO "Modem powered up by debugger !\n"); | ||
| 427 | t0 = readtb(); | ||
| 428 | while (readtb() - t0 < 3*TB_SPEED) | ||
| 429 | eieio(); | ||
| 430 | } | ||
| 431 | /* use the B channel if requested */ | ||
| 432 | if (xmon_use_sccb) { | ||
| 433 | sccc = (volatile unsigned char *) | ||
| 434 | ((unsigned long)sccc & ~0x20); | ||
| 435 | sccd = sccc + 0x10; | ||
| 436 | } | ||
| 437 | for (i = 20000; i != 0; --i) { | ||
| 438 | x = *sccc; eieio(); | ||
| 439 | } | ||
| 440 | *sccc = 9; eieio(); /* reset A or B side */ | ||
| 441 | *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio(); | ||
| 442 | for (i = 0; i < sizeof(scc_inittab); ++i) { | ||
| 443 | *sccc = scc_inittab[i]; | ||
| 444 | eieio(); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | scc_initialized = 1; | 322 | scc_initialized = 1; | 
| 448 | if (via_modem) { | 323 | if (via_modem) { | 
| 449 | for (;;) { | 324 | for (;;) { | 
| @@ -632,19 +507,9 @@ xmon_fgets(char *str, int nb, void *f) | |||
| 632 | void | 507 | void | 
| 633 | xmon_enter(void) | 508 | xmon_enter(void) | 
| 634 | { | 509 | { | 
| 635 | #ifdef CONFIG_ADB_PMU | ||
| 636 | if (_machine == _MACH_Pmac) { | ||
| 637 | pmu_suspend(); | ||
| 638 | } | ||
| 639 | #endif | ||
| 640 | } | 510 | } | 
| 641 | 511 | ||
| 642 | void | 512 | void | 
| 643 | xmon_leave(void) | 513 | xmon_leave(void) | 
| 644 | { | 514 | { | 
| 645 | #ifdef CONFIG_ADB_PMU | ||
| 646 | if (_machine == _MACH_Pmac) { | ||
| 647 | pmu_resume(); | ||
| 648 | } | ||
| 649 | #endif | ||
| 650 | } | 515 | } | 
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 9075a7538e26..bdaf6597b4c2 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c  | |||
| @@ -16,9 +16,6 @@ | |||
| 16 | #include <asm/bootx.h> | 16 | #include <asm/bootx.h> | 
| 17 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> | 
| 18 | #include <asm/xmon.h> | 18 | #include <asm/xmon.h> | 
| 19 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 20 | #include <asm/backlight.h> | ||
| 21 | #endif | ||
| 22 | #include "nonstdio.h" | 19 | #include "nonstdio.h" | 
| 23 | #include "privinst.h" | 20 | #include "privinst.h" | 
| 24 | 21 | ||
| @@ -260,16 +257,6 @@ int xmon(struct pt_regs *excp) | |||
| 260 | */ | 257 | */ | 
| 261 | #endif /* CONFIG_SMP */ | 258 | #endif /* CONFIG_SMP */ | 
| 262 | remove_bpts(); | 259 | remove_bpts(); | 
| 263 | #ifdef CONFIG_PMAC_BACKLIGHT | ||
| 264 | if( setjmp(bus_error_jmp) == 0 ) { | ||
| 265 | debugger_fault_handler = handle_fault; | ||
| 266 | sync(); | ||
| 267 | set_backlight_enable(1); | ||
| 268 | set_backlight_level(BACKLIGHT_MAX); | ||
| 269 | sync(); | ||
| 270 | } | ||
| 271 | debugger_fault_handler = NULL; | ||
| 272 | #endif /* CONFIG_PMAC_BACKLIGHT */ | ||
| 273 | cmd = cmds(excp); | 260 | cmd = cmds(excp); | 
| 274 | if (cmd == 's') { | 261 | if (cmd == 's') { | 
| 275 | xmon_trace[smp_processor_id()] = SSTEP; | 262 | xmon_trace[smp_processor_id()] = SSTEP; | 
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c index fb88b4041dca..b474ea52d6e8 100644 --- a/drivers/char/watchdog/sa1100_wdt.c +++ b/drivers/char/watchdog/sa1100_wdt.c  | |||
| @@ -74,7 +74,7 @@ static int sa1100dog_release(struct inode *inode, struct file *file) | |||
| 74 | return 0; | 74 | return 0; | 
| 75 | } | 75 | } | 
| 76 | 76 | ||
| 77 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 77 | static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 
| 78 | { | 78 | { | 
| 79 | if (len) | 79 | if (len) | 
| 80 | /* Refresh OSMR3 timer. */ | 80 | /* Refresh OSMR3 timer. */ | 
| @@ -96,20 +96,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, | |||
| 96 | 96 | ||
| 97 | switch (cmd) { | 97 | switch (cmd) { | 
| 98 | case WDIOC_GETSUPPORT: | 98 | case WDIOC_GETSUPPORT: | 
| 99 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | 99 | ret = copy_to_user((struct watchdog_info __user *)arg, &ident, | 
| 100 | sizeof(ident)) ? -EFAULT : 0; | 100 | sizeof(ident)) ? -EFAULT : 0; | 
| 101 | break; | 101 | break; | 
| 102 | 102 | ||
| 103 | case WDIOC_GETSTATUS: | 103 | case WDIOC_GETSTATUS: | 
| 104 | ret = put_user(0, (int *)arg); | 104 | ret = put_user(0, (int __user *)arg); | 
| 105 | break; | 105 | break; | 
| 106 | 106 | ||
| 107 | case WDIOC_GETBOOTSTATUS: | 107 | case WDIOC_GETBOOTSTATUS: | 
| 108 | ret = put_user(boot_status, (int *)arg); | 108 | ret = put_user(boot_status, (int __user *)arg); | 
| 109 | break; | 109 | break; | 
| 110 | 110 | ||
| 111 | case WDIOC_SETTIMEOUT: | 111 | case WDIOC_SETTIMEOUT: | 
| 112 | ret = get_user(time, (int *)arg); | 112 | ret = get_user(time, (int __user *)arg); | 
| 113 | if (ret) | 113 | if (ret) | 
| 114 | break; | 114 | break; | 
| 115 | 115 | ||
| @@ -123,7 +123,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, | |||
| 123 | /*fall through*/ | 123 | /*fall through*/ | 
| 124 | 124 | ||
| 125 | case WDIOC_GETTIMEOUT: | 125 | case WDIOC_GETTIMEOUT: | 
| 126 | ret = put_user(pre_margin / OSCR_FREQ, (int *)arg); | 126 | ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg); | 
| 127 | break; | 127 | break; | 
| 128 | 128 | ||
| 129 | case WDIOC_KEEPALIVE: | 129 | case WDIOC_KEEPALIVE: | 
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c index ea3288661a34..246e67cd8b51 100644 --- a/drivers/media/video/zoran_card.c +++ b/drivers/media/video/zoran_card.c  | |||
| @@ -995,7 +995,7 @@ test_interrupts (struct zoran *zr) | |||
| 995 | static int __devinit | 995 | static int __devinit | 
| 996 | zr36057_init (struct zoran *zr) | 996 | zr36057_init (struct zoran *zr) | 
| 997 | { | 997 | { | 
| 998 | unsigned long mem; | 998 | u32 *mem; | 
| 999 | void *vdev; | 999 | void *vdev; | 
| 1000 | unsigned mem_needed; | 1000 | unsigned mem_needed; | 
| 1001 | int j; | 1001 | int j; | 
| @@ -1058,10 +1058,10 @@ zr36057_init (struct zoran *zr) | |||
| 1058 | "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", | 1058 | "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", | 
| 1059 | ZR_DEVNAME(zr)); | 1059 | ZR_DEVNAME(zr)); | 
| 1060 | kfree(vdev); | 1060 | kfree(vdev); | 
| 1061 | kfree((void *)mem); | 1061 | kfree(mem); | 
| 1062 | return -ENOMEM; | 1062 | return -ENOMEM; | 
| 1063 | } | 1063 | } | 
| 1064 | zr->stat_com = (u32 *) mem; | 1064 | zr->stat_com = mem; | 
| 1065 | for (j = 0; j < BUZ_NUM_STAT_COM; j++) { | 1065 | for (j = 0; j < BUZ_NUM_STAT_COM; j++) { | 
| 1066 | zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ | 1066 | zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ | 
| 1067 | } | 1067 | } | 
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 097d668c4fe5..556895e99645 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c  | |||
| @@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) | |||
| 2734 | * BIOS does tho. Right now, all this PM stuff is pmac-only for that | 2734 | * BIOS does tho. Right now, all this PM stuff is pmac-only for that | 
| 2735 | * reason. --BenH | 2735 | * reason. --BenH | 
| 2736 | */ | 2736 | */ | 
| 2737 | #if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) | 2737 | #if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) | 
| 2738 | if (_machine == _MACH_Pmac && rinfo->of_node) { | 2738 | if (_machine == _MACH_Pmac && rinfo->of_node) { | 
| 2739 | if (rinfo->is_mobility && rinfo->pm_reg && | 2739 | if (rinfo->is_mobility && rinfo->pm_reg && | 
| 2740 | rinfo->family <= CHIP_FAMILY_RV250) | 2740 | rinfo->family <= CHIP_FAMILY_RV250) | 
| @@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) | |||
| 2778 | OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); | 2778 | OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); | 
| 2779 | #endif | 2779 | #endif | 
| 2780 | } | 2780 | } | 
| 2781 | #endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */ | 2781 | #endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */ | 
| 2782 | } | 2782 | } | 
| 2783 | 2783 | ||
| 2784 | void radeonfb_pm_exit(struct radeonfb_info *rinfo) | 2784 | void radeonfb_pm_exit(struct radeonfb_info *rinfo) | 
| 2785 | { | 2785 | { | 
| 2786 | #if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) | 2786 | #if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) | 
| 2787 | if (rinfo->pm_mode != radeon_pm_none) | 2787 | if (rinfo->pm_mode != radeon_pm_none) | 
| 2788 | pmac_set_early_video_resume(NULL, NULL); | 2788 | pmac_set_early_video_resume(NULL, NULL); | 
| 2789 | #endif | 2789 | #endif | 
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 0fada8f16dc6..42a95d9a0641 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h  | |||
| @@ -35,7 +35,7 @@ static inline void atomic_long_set(atomic_long_t *l, long i) | |||
| 35 | { | 35 | { | 
| 36 | atomic64_t *v = (atomic64_t *)l; | 36 | atomic64_t *v = (atomic64_t *)l; | 
| 37 | 37 | ||
| 38 | atomic_set(v, i); | 38 | atomic64_set(v, i); | 
| 39 | } | 39 | } | 
| 40 | 40 | ||
| 41 | static inline void atomic_long_inc(atomic_long_t *l) | 41 | static inline void atomic_long_inc(atomic_long_t *l) | 
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index fffdf690b840..640a6459f2f4 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h  | |||
| @@ -31,12 +31,80 @@ | |||
| 31 | #define KEXEC_ARCH KEXEC_ARCH_PPC | 31 | #define KEXEC_ARCH KEXEC_ARCH_PPC | 
| 32 | #endif | 32 | #endif | 
| 33 | 33 | ||
| 34 | #define HAVE_ARCH_COPY_OLDMEM_PAGE | ||
| 35 | |||
| 36 | #ifndef __ASSEMBLY__ | ||
| 37 | |||
| 38 | #ifdef CONFIG_KEXEC | 34 | #ifdef CONFIG_KEXEC | 
| 39 | 35 | ||
| 36 | #ifdef __powerpc64__ | ||
| 37 | /* | ||
| 38 | * This function is responsible for capturing register states if coming | ||
| 39 | * via panic or invoking dump using sysrq-trigger. | ||
| 40 | */ | ||
| 41 | static inline void crash_setup_regs(struct pt_regs *newregs, | ||
| 42 | struct pt_regs *oldregs) | ||
| 43 | { | ||
| 44 | if (oldregs) | ||
| 45 | memcpy(newregs, oldregs, sizeof(*newregs)); | ||
| 46 | else { | ||
| 47 | /* FIXME Merge this with xmon_save_regs ?? */ | ||
| 48 | unsigned long tmp1, tmp2; | ||
| 49 | __asm__ __volatile__ ( | ||
| 50 | "std 0,0(%2)\n" | ||
| 51 | "std 1,8(%2)\n" | ||
| 52 | "std 2,16(%2)\n" | ||
| 53 | "std 3,24(%2)\n" | ||
| 54 | "std 4,32(%2)\n" | ||
| 55 | "std 5,40(%2)\n" | ||
| 56 | "std 6,48(%2)\n" | ||
| 57 | "std 7,56(%2)\n" | ||
| 58 | "std 8,64(%2)\n" | ||
| 59 | "std 9,72(%2)\n" | ||
| 60 | "std 10,80(%2)\n" | ||
| 61 | "std 11,88(%2)\n" | ||
| 62 | "std 12,96(%2)\n" | ||
| 63 | "std 13,104(%2)\n" | ||
| 64 | "std 14,112(%2)\n" | ||
| 65 | "std 15,120(%2)\n" | ||
| 66 | "std 16,128(%2)\n" | ||
| 67 | "std 17,136(%2)\n" | ||
| 68 | "std 18,144(%2)\n" | ||
| 69 | "std 19,152(%2)\n" | ||
| 70 | "std 20,160(%2)\n" | ||
| 71 | "std 21,168(%2)\n" | ||
| 72 | "std 22,176(%2)\n" | ||
| 73 | "std 23,184(%2)\n" | ||
| 74 | "std 24,192(%2)\n" | ||
| 75 | "std 25,200(%2)\n" | ||
| 76 | "std 26,208(%2)\n" | ||
| 77 | "std 27,216(%2)\n" | ||
| 78 | "std 28,224(%2)\n" | ||
| 79 | "std 29,232(%2)\n" | ||
| 80 | "std 30,240(%2)\n" | ||
| 81 | "std 31,248(%2)\n" | ||
| 82 | "mfmsr %0\n" | ||
| 83 | "std %0, 264(%2)\n" | ||
| 84 | "mfctr %0\n" | ||
| 85 | "std %0, 280(%2)\n" | ||
| 86 | "mflr %0\n" | ||
| 87 | "std %0, 288(%2)\n" | ||
| 88 | "bl 1f\n" | ||
| 89 | "1: mflr %1\n" | ||
| 90 | "std %1, 256(%2)\n" | ||
| 91 | "mtlr %0\n" | ||
| 92 | "mfxer %0\n" | ||
| 93 | "std %0, 296(%2)\n" | ||
| 94 | : "=&r" (tmp1), "=&r" (tmp2) | ||
| 95 | : "b" (newregs)); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | #else | ||
| 99 | /* | ||
| 100 | * Provide a dummy definition to avoid build failures. Will remain | ||
| 101 | * empty till crash dump support is enabled. | ||
| 102 | */ | ||
| 103 | static inline void crash_setup_regs(struct pt_regs *newregs, | ||
| 104 | struct pt_regs *oldregs) { } | ||
| 105 | #endif /* !__powerpc64 __ */ | ||
| 106 | |||
| 107 | #ifndef __ASSEMBLY__ | ||
| 40 | #define MAX_NOTE_BYTES 1024 | 108 | #define MAX_NOTE_BYTES 1024 | 
| 41 | 109 | ||
| 42 | #ifdef __powerpc64__ | 110 | #ifdef __powerpc64__ | 
| @@ -53,14 +121,7 @@ extern void default_machine_kexec(struct kimage *image); | |||
| 53 | extern int default_machine_kexec_prepare(struct kimage *image); | 121 | extern int default_machine_kexec_prepare(struct kimage *image); | 
| 54 | extern void default_machine_crash_shutdown(struct pt_regs *regs); | 122 | extern void default_machine_crash_shutdown(struct pt_regs *regs); | 
| 55 | 123 | ||
| 56 | #endif /* !CONFIG_KEXEC */ | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Provide a dummy definition to avoid build failures. Will remain | ||
| 60 | * empty till crash dump support is enabled. | ||
| 61 | */ | ||
| 62 | static inline void crash_setup_regs(struct pt_regs *newregs, | ||
| 63 | struct pt_regs *oldregs) { } | ||
| 64 | #endif /* ! __ASSEMBLY__ */ | 124 | #endif /* ! __ASSEMBLY__ */ | 
| 125 | #endif /* CONFIG_KEXEC */ | ||
| 65 | #endif /* __KERNEL__ */ | 126 | #endif /* __KERNEL__ */ | 
| 66 | #endif /* _ASM_POWERPC_KEXEC_H */ | 127 | #endif /* _ASM_POWERPC_KEXEC_H */ | 
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index eb317a0806e4..6d431d6fb022 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h  | |||
| @@ -167,6 +167,14 @@ extern int of_address_to_resource(struct device_node *dev, int index, | |||
| 167 | extern int of_pci_address_to_resource(struct device_node *dev, int bar, | 167 | extern int of_pci_address_to_resource(struct device_node *dev, int bar, | 
| 168 | struct resource *r); | 168 | struct resource *r); | 
| 169 | 169 | ||
| 170 | #ifndef CONFIG_PPC_OF | ||
| 171 | /* | ||
| 172 | * Fallback definitions for builds where we don't have prom.c included. | ||
| 173 | */ | ||
| 174 | #define machine_is_compatible(x) 0 | ||
| 175 | #define of_find_compatible_node(f, t, c) NULL | ||
| 176 | #define get_property(p, n, l) NULL | ||
| 177 | #endif | ||
| 170 | 178 | ||
| 171 | #endif /* _PPC_PROM_H */ | 179 | #endif /* _PPC_PROM_H */ | 
| 172 | #endif /* __KERNEL__ */ | 180 | #endif /* __KERNEL__ */ | 
