summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/ppc/Kconfig46
-rw-r--r--arch/ppc/kernel/Makefile2
-rw-r--r--arch/ppc/kernel/cpu_setup_6xx.S415
-rw-r--r--arch/ppc/kernel/head.S247
-rw-r--r--arch/ppc/kernel/misc.S115
-rw-r--r--arch/ppc/kernel/smp.c6
-rw-r--r--arch/ppc/platforms/Makefile6
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c345
-rw-r--r--arch/ppc/platforms/pmac_feature.c620
-rw-r--r--arch/ppc/platforms/pmac_setup.c16
-rw-r--r--arch/ppc/platforms/pmac_sleep.S (renamed from arch/ppc/platforms/sleep.S)113
-rw-r--r--arch/ppc/platforms/pmac_smp.c142
-rw-r--r--arch/ppc/platforms/pmac_time.c2
-rw-r--r--arch/ppc/platforms/spruce_setup.c4
-rw-r--r--arch/ppc/syslib/prom_init.c23
-rw-r--r--drivers/pcmcia/ds.c47
-rw-r--r--include/asm-ppc/keylargo.h117
-rw-r--r--include/asm-ppc/macio_asic.h80
-rw-r--r--include/asm-ppc/pgtable.h23
-rw-r--r--include/asm-ppc/pmac_feature.h77
-rw-r--r--include/asm-ppc/uninorth.h2
21 files changed, 1692 insertions, 756 deletions
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 84e94b319e68..db1097324b10 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -666,6 +666,52 @@ config MATH_EMULATION
here. Saying Y here will not hurt performance (on any machine) but
will increase the size of the kernel.
+config CPU_FREQ
+ bool "CPU Frequency scaling"
+ help
+ Clock scaling allows you to change the clock speed of CPUs on the
+ fly. This is a nice method to save battery power on notebooks,
+ because the lower the clock speed, the less power the CPU consumes.
+
+ For more information, take a look at linux/Documentation/cpufreq or
+ at <http://www.brodo.de/cpufreq/>
+
+ If in doubt, say N.
+
+config CPU_FREQ_PROC_INTF
+ bool "/proc/cpufreq interface (DEPRECATED)"
+ depends on CPU_FREQ && PROC_FS
+ help
+ This enables the /proc/cpufreq interface for controlling
+ CPUFreq. Please note that it is recommended to use the sysfs
+ interface instead (which is built automatically).
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say N.
+
+config CPU_FREQ_24_API
+ bool "/proc/sys/cpu/ interface (2.4. / OLD)"
+ depends on CPU_FREQ
+ help
+ This enables the /proc/sys/cpu/ sysctl interface for controlling
+ CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. 2.5
+ uses a sysfs interface instead. Please note that some drivers do
+ not work well with the 2.4. /proc/sys/cpu sysctl interface,
+ so if in doubt, say N here.
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say N.
+
+config CPU_FREQ_PMAC
+ bool "Support for Apple PowerBooks"
+ depends on CPU_FREQ && ADB_PMU
+ help
+ This adds support for frequency switching on Apple PowerBooks,
+ this currently includes some models of iBook & Titanium
+ PowerBook.
+
endmenu
menu "General setup"
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index fe53c9f39007..62a28abc7d6c 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -21,7 +21,7 @@ obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
process.o signal.o ptrace.o align.o \
semaphore.o syscalls.o setup.o \
cputable.o ppc_htab.o
-obj-$(CONFIG_6xx) += l2cr.o
+obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_PCI) += pci-dma.o
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
new file mode 100644
index 000000000000..cb0701cb24d0
--- /dev/null
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -0,0 +1,415 @@
+/*
+ * This file contains low level CPU setup functions.
+ * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+_GLOBAL(__setup_cpu_601)
+ blr
+_GLOBAL(__setup_cpu_603)
+ b setup_common_caches
+_GLOBAL(__setup_cpu_604)
+ mflr r4
+ bl setup_common_caches
+ bl setup_604_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750cx)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ bl setup_750cx
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_750fx)
+ mflr r4
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ bl setup_750fx
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7400)
+ mflr r4
+ bl setup_7400_workarounds
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7410)
+ mflr r4
+ bl setup_7410_workarounds
+ bl setup_common_caches
+ bl setup_750_7400_hid0
+ li r3,0
+ mtspr SPRN_L2CR2,r3
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7450)
+ mflr r4
+ bl setup_common_caches
+ bl setup_745x_specifics
+ mtlr r4
+ blr
+_GLOBAL(__setup_cpu_7455)
+ mflr r4
+ bl setup_common_caches
+ bl setup_745x_specifics
+ mtlr r4
+ blr
+
+/* Enable caches for 603's, 604, 750 & 7400 */
+setup_common_caches:
+ mfspr r11,HID0
+ andi. r0,r11,HID0_DCE
+#ifdef CONFIG_DCACHE_DISABLE
+ ori r11,r11,HID0_ICE
+#else
+ ori r11,r11,HID0_ICE|HID0_DCE
+#endif
+ ori r8,r11,HID0_ICFI
+ bne 1f /* don't invalidate the D-cache */
+ ori r8,r8,HID0_DCI /* unless it wasn't enabled */
+1: sync
+ mtspr HID0,r8 /* enable and invalidate caches */
+ sync
+ mtspr HID0,r11 /* enable caches */
+ sync
+ isync
+ blr
+
+/* 604, 604e, 604ev, ...
+ * Enable superscalar execution & branch history table
+ */
+setup_604_hid0:
+ mfspr r11,HID0
+ ori r11,r11,HID0_SIED|HID0_BHTE
+ ori r8,r11,HID0_BTCD
+ sync
+ mtspr HID0,r8 /* flush branch target address cache */
+ sync /* on 604e/604r */
+ mtspr HID0,r11
+ sync
+ isync
+ blr
+
+/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
+ * erratas we work around here.
+ * Moto MPC710CE.pdf describes them, those are errata
+ * #3, #4 and #5
+ * Note that we assume the firmware didn't choose to
+ * apply other workarounds (there are other ones documented
+ * in the .pdf). It appear that Apple firmware only works
+ * around #3 and with the same fix we use. We may want to
+ * check if the CPU is using 60x bus mode in which case
+ * the workaround for errata #4 is useless. Also, we may
+ * want to explicitely clear HID0_NOPDST as this is not
+ * needed once we have applied workaround #5 (though it's
+ * not set by Apple's firmware at least).
+ */
+setup_7400_workarounds:
+ mfpvr r3
+ rlwinm r3,r3,0,20,31
+ cmpwi 0,r3,0x0207
+ ble 1f
+ blr
+setup_7410_workarounds:
+ mfpvr r3
+ rlwinm r3,r3,0,20,31
+ cmpwi 0,r3,0x0100
+ bnelr
+1:
+ mfspr r11,SPRN_MSSSR0
+ /* Errata #3: Set L1OPQ_SIZE to 0x10 */
+ rlwinm r11,r11,0,9,6
+ oris r11,r11,0x0100
+ /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */
+ oris r11,r11,0x0002
+ /* Errata #5: Set DRLT_SIZE to 0x01 */
+ rlwinm r11,r11,0,5,2
+ oris r11,r11,0x0800
+ sync
+ mtspr SPRN_MSSSR0,r11
+ sync
+ isync
+ blr
+
+/* 740/750/7400/7410
+ * Enable Store Gathering (SGE), Address Brodcast (ABE),
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
+ * Dynamic Power Management (DPM), Speculative (SPD)
+ * Clear Instruction cache throttling (ICTC)
+ */
+setup_750_7400_hid0:
+ mfspr r11,HID0
+ ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+BEGIN_FTR_SECTION
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+ li r3,HID0_SPD
+ andc r11,r11,r3 /* clear SPD: enable speculative */
+ li r3,0
+ mtspr ICTC,r3 /* Instruction Cache Throttling off */
+ isync
+ mtspr HID0,r11
+ sync
+ isync
+ blr
+
+/* 750cx specific
+ * Looks like we have to disable NAP feature for some PLL settings...
+ * (waiting for confirmation)
+ */
+setup_750cx:
+ mfspr r10, SPRN_HID1
+ rlwinm r10,r10,4,28,31
+ cmpi cr0,r10,7
+ cmpi cr1,r10,9
+ cmpi cr2,r10,11
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
+ bnelr
+ lwz r6,CPU_SPEC_FEATURES(r5)
+ li r7,CPU_FTR_CAN_NAP
+ andc r6,r6,r7
+ stw r6,CPU_SPEC_FEATURES(r5)
+ blr
+
+/* 750fx specific
+ */
+setup_750fx:
+ blr
+
+/* MPC 745x
+ * Enable Store Gathering (SGE), Branch Folding (FOLD)
+ * Branch History Table (BHTE), Branch Target ICache (BTIC)
+ * Dynamic Power Management (DPM), Speculative (SPD)
+ * Ensure our data cache instructions really operate.
+ * Timebase has to be running or we wouldn't have made it here,
+ * just ensure we don't disable it.
+ * Clear Instruction cache throttling (ICTC)
+ * Enable L2 HW prefetch
+ */
+setup_745x_specifics:
+ /* We check for the presence of an L3 cache setup by
+ * the firmware. If any, we disable NAP capability as
+ * it's known to be bogus on rev 2.1 and earlier
+ */
+ mfspr r11,SPRN_L3CR
+ andis. r11,r11,L3CR_L3E@h
+ beq 1f
+ lwz r6,CPU_SPEC_FEATURES(r5)
+ andi. r0,r6,CPU_FTR_L3_DISABLE_NAP
+ beq 1f
+ li r7,CPU_FTR_CAN_NAP
+ andc r6,r6,r7
+ stw r6,CPU_SPEC_FEATURES(r5)
+1:
+ mfspr r11,HID0
+
+ /* All of the bits we have to set.....
+ */
+ ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC | HID0_LRSTK
+BEGIN_FTR_SECTION
+ oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
+END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+
+ /* All of the bits we have to clear....
+ */
+ li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI
+ andc r11,r11,r3 /* clear SPD: enable speculative */
+ li r3,0
+
+ mtspr ICTC,r3 /* Instruction Cache Throttling off */
+ isync
+ mtspr HID0,r11
+ sync
+ isync
+
+ /* Enable L2 HW prefetch
+ */
+ mfspr r3,SPRN_MSSCR0
+ ori r3,r3,3
+ sync
+ mtspr SPRN_MSSCR0,r3
+ sync
+ isync
+ blr
+
+/* Definitions for the table use to save CPU states */
+#define CS_HID0 0
+#define CS_HID1 4
+#define CS_MSSCR0 8
+#define CS_MSSSR0 12
+#define CS_ICTRL 16
+#define CS_LDSTCR 20
+#define CS_LDSTDB 24
+#define CS_SIZE 28
+
+ .data
+ .balign 4
+cpu_state_storage:
+ .space CS_SIZE
+ .text
+
+/* Called in normal context to backup CPU 0 state. This
+ * does not include cache settings. This function is also
+ * called for machine sleep. This does not include the MMU
+ * setup, BATs, etc... but rather the "special" registers
+ * like HID0, HID1, MSSCR0, etc...
+ */
+_GLOBAL(__save_cpu_setup)
+ /* Get storage ptr */
+ lis r5,cpu_state_storage@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* Save HID0 (common to all CONFIG_6xx cpus) */
+ mfspr r3,SPRN_HID0
+ stw r3,CS_HID0(r5)
+
+ /* Now deal with CPU type dependent registers */
+ mfspr r3,PVR
+ srwi r3,r3,16
+ cmpli cr0,r3,0x8000 /* 7450 */
+ cmpli cr1,r3,0x000c /* 7400 */
+ cmpli cr2,r3,0x800c /* 7410 */
+ cmpli cr3,r3,0x8001 /* 7455 */
+ cmpli cr4,r3,0x8002 /* 7457 */
+ cmpli cr5,r3,0x7000 /* 750FX */
+ /* cr1 is 7400 || 7410 */
+ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
+ /* cr0 is 74xx */
+ cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 1f
+ /* Backup 74xx specific regs */
+ mfspr r4,SPRN_MSSCR0
+ stw r4,CS_MSSCR0(r5)
+ mfspr r4,SPRN_MSSSR0
+ stw r4,CS_MSSSR0(r5)
+ beq cr1,1f
+ /* Backup 745x specific registers */
+ mfspr r4,SPRN_HID1
+ stw r4,CS_HID1(r5)
+ mfspr r4,SPRN_ICTRL
+ stw r4,CS_ICTRL(r5)
+ mfspr r4,SPRN_LDSTCR
+ stw r4,CS_LDSTCR(r5)
+ mfspr r4,SPRN_LDSTDB
+ stw r4,CS_LDSTDB(r5)
+1:
+ bne cr5,1f
+ /* Backup 750FX specific registers */
+ mfspr r4,SPRN_HID1
+ stw r4,CS_HID1(r5)
+1:
+ blr
+
+/* Called with no MMU context (typically MSR:IR/DR off) to
+ * restore CPU state as backed up by the previous
+ * function. This does not include cache setting
+ */
+_GLOBAL(__restore_cpu_setup)
+ /* Get storage ptr */
+ lis r5,(cpu_state_storage-KERNELBASE)@h
+ ori r5,r5,cpu_state_storage@l
+
+ /* Restore HID0 */
+ lwz r3,CS_HID0(r5)
+ sync
+ isync
+ mtspr SPRN_HID0,r3
+ sync
+ isync
+
+ /* Now deal with CPU type dependent registers */
+ mfspr r3,PVR
+ srwi r3,r3,16
+ cmpli cr0,r3,0x8000 /* 7450 */
+ cmpli cr1,r3,0x000c /* 7400 */
+ cmpli cr2,r3,0x800c /* 7410 */
+ cmpli cr3,r3,0x8001 /* 7455 */
+ cmpli cr4,r3,0x8002 /* 7457 */
+ cmpli cr5,r3,0x7000 /* 750FX */
+ /* cr1 is 7400 || 7410 */
+ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
+ /* cr0 is 74xx */
+ cror 4*cr0+eq,4*cr0+eq,4*cr3+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr4+eq
+ cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
+ bne 2f
+ /* Restore 74xx specific regs */
+ lwz r4,CS_MSSCR0(r5)
+ sync
+ mtspr SPRN_MSSCR0,r4
+ sync
+ isync
+ lwz r4,CS_MSSSR0(r5)
+ sync
+ mtspr SPRN_MSSSR0,r4
+ sync
+ isync
+ bne cr2,1f
+ /* Clear 7410 L2CR2 */
+ li r4,0
+ mtspr SPRN_L2CR2,r4
+1: beq cr1,2f
+ /* Restore 745x specific registers */
+ lwz r4,CS_HID1(r5)
+ sync
+ mtspr SPRN_HID1,r4
+ isync
+ sync
+ lwz r4,CS_ICTRL(r5)
+ sync
+ mtspr SPRN_ICTRL,r4
+ isync
+ sync
+ lwz r4,CS_LDSTCR(r5)
+ sync
+ mtspr SPRN_LDSTCR,r4
+ isync
+ sync
+ lwz r4,CS_LDSTDB(r5)
+ sync
+ mtspr SPRN_LDSTDB,r4
+ isync
+ sync
+2: bne cr5,1f
+ /* Restore 750FX specific registers
+ * that is restore PLL config & switch
+ * to PLL 0
+ */
+ lwz r4,CS_HID1(r5)
+ rlwinm r5,r4,0,16,14
+ mtspr SPRN_HID1,r5
+ /* Wait for PLL to stabilize */
+ mftbl r5
+3: mftbl r6
+ sub r6,r6,r5
+ cmpli cr0,r6,10000
+ ble 3b
+ /* Setup final PLL */
+ mtspr SPRN_HID1,r4
+1:
+ blr
+
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index ab323b477b97..68b4f262db4d 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -890,7 +890,7 @@ load_up_altivec:
*/
mfmsr r5
oris r5,r5,MSR_VEC@h
- mtmsr r5 /* enable use of AltiVec now */
+ MTMSRD(r5) /* enable use of AltiVec now */
isync
/*
* For SMP, we don't do lazy AltiVec switching because it just gets too
@@ -962,7 +962,7 @@ giveup_altivec:
mfmsr r5
oris r5,r5,MSR_VEC@h
SYNC
- mtmsr r5 /* enable use of AltiVec now */
+ MTMSRD(r5) /* enable use of AltiVec now */
isync
cmpi 0,r3,0
beqlr- /* if no previous owner, done */
@@ -999,7 +999,7 @@ giveup_fpu:
ori r5,r5,MSR_FP
SYNC_601
ISYNC_601
- mtmsr r5 /* enable use of fpu now */
+ MTMSRD(r5) /* enable use of fpu now */
SYNC_601
isync
cmpi 0,r3,0
@@ -1191,6 +1191,8 @@ __secondary_start:
MTMSRD(r0)
isync
#endif
+ /* Copy some CPU settings from CPU 0 */
+ bl __restore_cpu_setup
lis r3,-KERNELBASE@h
mr r4,r24
@@ -1236,248 +1238,21 @@ __secondary_start:
#endif /* CONFIG_SMP */
/*
- * Enable caches and 604-specific features if necessary.
+ * Those generic dummy functions are kept for CPUs not
+ * included in CONFIG_6xx
*/
-_GLOBAL(__setup_cpu_601)
- blr
-_GLOBAL(__setup_cpu_603)
- b setup_common_caches
-_GLOBAL(__setup_cpu_604)
- mflr r4
- bl setup_common_caches
- bl setup_604_hid0
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_750)
- mflr r4
- bl setup_common_caches
- bl setup_750_7400_hid0
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_750cx)
- mflr r4
- bl setup_common_caches
- bl setup_750_7400_hid0
- bl setup_750cx
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_750fx)
- mflr r4
- bl setup_common_caches
- bl setup_750_7400_hid0
- bl setup_750fx
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_7400)
- mflr r4
- bl setup_7400_workarounds
- bl setup_common_caches
- bl setup_750_7400_hid0
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_7410)
- mflr r4
- bl setup_7410_workarounds
- bl setup_common_caches
- bl setup_750_7400_hid0
- li r3,0
- mtspr SPRN_L2CR2,r3
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_7450)
- mflr r4
- bl setup_common_caches
- bl setup_745x_specifics
- mtlr r4
- blr
-_GLOBAL(__setup_cpu_7455)
- mflr r4
- bl setup_common_caches
- bl setup_745x_specifics
- mtlr r4
- blr
_GLOBAL(__setup_cpu_power3)
blr
_GLOBAL(__setup_cpu_generic)
blr
-/* Enable caches for 603's, 604, 750 & 7400 */
-setup_common_caches:
- mfspr r11,HID0
- andi. r0,r11,HID0_DCE
-#ifdef CONFIG_DCACHE_DISABLE
- ori r11,r11,HID0_ICE
-#else
- ori r11,r11,HID0_ICE|HID0_DCE
-#endif
- ori r8,r11,HID0_ICFI
- bne 1f /* don't invalidate the D-cache */
- ori r8,r8,HID0_DCI /* unless it wasn't enabled */
-1: sync
- mtspr HID0,r8 /* enable and invalidate caches */
- sync
- mtspr HID0,r11 /* enable caches */
- sync
- isync
- blr
-
-/* 604, 604e, 604ev, ...
- * Enable superscalar execution & branch history table
- */
-setup_604_hid0:
- mfspr r11,HID0
- ori r11,r11,HID0_SIED|HID0_BHTE
- ori r8,r11,HID0_BTCD
- sync
- mtspr HID0,r8 /* flush branch target address cache */
- sync /* on 604e/604r */
- mtspr HID0,r11
- sync
- isync
- blr
-
-/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
- * errata we work around here.
- * Moto MPC710CE.pdf describes them, those are errata
- * #3, #4 and #5
- * Note that we assume the firmware didn't choose to
- * apply other workarounds (there are other ones documented
- * in the .pdf). It appear that Apple firmware only works
- * around #3 and with the same fix we use. We may want to
- * check if the CPU is using 60x bus mode in which case
- * the workaround for errata #4 is useless. Also, we may
- * want to explicitely clear HID0_NOPDST as this is not
- * needed once we have applied workaround #5 (though it's
- * not set by Apple's firmware at least).
- */
-setup_7400_workarounds:
- mfpvr r3
- rlwinm r3,r3,0,20,31
- cmpwi 0,r3,0x0207
- ble 1f
- blr
-setup_7410_workarounds:
- mfpvr r3
- rlwinm r3,r3,0,20,31
- cmpwi 0,r3,0x0100
- bnelr
-1:
- mfspr r11,SPRN_MSSSR0
- /* Errata #3: Set L1OPQ_SIZE to 0x10 */
- rlwinm r11,r11,0,9,6
- oris r11,r11,0x0100
- /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */
- oris r11,r11,0x0002
- /* Errata #5: Set DRLT_SIZE to 0x01 */
- rlwinm r11,r11,0,5,2
- oris r11,r11,0x0800
- sync
- mtspr SPRN_MSSSR0,r11
- sync
- isync
- blr
-
-/* 740/750/7400/7410
- * Enable Store Gathering (SGE), Address Brodcast (ABE),
- * Branch History Table (BHTE), Branch Target ICache (BTIC)
- * Dynamic Power Management (DPM), Speculative (SPD)
- * Clear Instruction cache throttling (ICTC)
- */
-setup_750_7400_hid0:
- mfspr r11,HID0
- ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
-BEGIN_FTR_SECTION
- oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
- li r3,HID0_SPD
- andc r11,r11,r3 /* clear SPD: enable speculative */
- li r3,0
- mtspr ICTC,r3 /* Instruction Cache Throttling off */
- isync
- mtspr HID0,r11
- sync
- isync
- blr
-
-/* 750cx specific
- * Looks like we have to disable NAP feature for some PLL settings...
- * (waiting for confirmation)
- */
-setup_750cx:
- mfspr r10, SPRN_HID1
- rlwinm r10,r10,4,28,31
- cmpi cr0,r10,7
- cmpi cr1,r10,9
- cmpi cr2,r10,11
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
- bnelr
- lwz r6,CPU_SPEC_FEATURES(r5)
- li r7,CPU_FTR_CAN_NAP
- andc r6,r6,r7
- stw r6,CPU_SPEC_FEATURES(r5)
+#ifndef CONFIG_6xx
+_GLOBAL(__save_cpu_setup)
blr
-
-/* 750fx specific
- */
-setup_750fx:
+_GLOBAL(__restore_cpu_setup)
blr
+#endif /* CONFIG_6xx */
-/* MPC 745x
- * Enable Store Gathering (SGE), Branch Folding (FOLD)
- * Branch History Table (BHTE), Branch Target ICache (BTIC)
- * Dynamic Power Management (DPM), Speculative (SPD)
- * Ensure our data cache instructions really operate.
- * Timebase has to be running or we wouldn't have made it here,
- * just ensure we don't disable it.
- * Clear Instruction cache throttling (ICTC)
- * Enable L2 HW prefetch
- */
-setup_745x_specifics:
- /* We check for the presence of an L3 cache setup by
- * the firmware. If any, we disable NAP capability as
- * it's known to be bogus on rev 2.1 and earlier
- */
- mfspr r11,SPRN_L3CR
- andis. r11,r11,L3CR_L3E@h
- beq 1f
- lwz r6,CPU_SPEC_FEATURES(r5)
- andi. r0,r6,CPU_FTR_L3_DISABLE_NAP
- beq 1f
- li r7,CPU_FTR_CAN_NAP
- andc r6,r6,r7
- stw r6,CPU_SPEC_FEATURES(r5)
-1:
- mfspr r11,HID0
-
- /* All of the bits we have to set.....
- */
- ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC | HID0_LRSTK
-BEGIN_FTR_SECTION
- oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
-
- /* All of the bits we have to clear....
- */
- li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI
- andc r11,r11,r3 /* clear SPD: enable speculative */
- li r3,0
-
- mtspr ICTC,r3 /* Instruction Cache Throttling off */
- isync
- mtspr HID0,r11
- sync
- isync
-
- /* Enable L2 HW prefetch
- */
- mfspr r3,SPRN_MSSCR0
- ori r3,r3,3
- sync
- mtspr SPRN_MSSCR0,r3
- sync
- isync
- blr
/*
* Load stuff into the MMU. Intended to be called with
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 7d8e99cb83c2..d2d9e20bbfb0 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -201,6 +201,60 @@ _GLOBAL(call_setup_cpu)
mr r4,r24
bctr
+#ifdef CONFIG_CPU_FREQ_PMAC
+
+/* This gets called by via-pmu.c to switch the PLL selection
+ * on 750fx CPU. This function should really be moved to some
+ * other place (as most of the cpufreq code in via-pmu
+ */
+_GLOBAL(low_choose_750fx_pll)
+ /* Clear MSR:EE */
+ mfmsr r7
+ rlwinm r0,r7,0,17,15
+ mtmsr r0
+
+ /* If switching to PLL1, disable HID0:BTIC */
+ cmpli cr0,r3,0
+ beq 1f
+ mfspr r5,HID0
+ rlwinm r5,r5,0,27,25
+ sync
+ mtspr HID0,r5
+ isync
+ sync
+
+1:
+ /* Calc new HID1 value */
+ mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
+ rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
+ rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
+ or r4,r4,r5
+ mtspr SPRN_HID1,r4
+
+ /* Store new HID1 image */
+ rlwinm r6,r1,0,0,18
+ lwz r6,TI_CPU(r6)
+ slwi r6,r6,2
+ addis r6,r6,nap_save_hid1@ha
+ stw r4,nap_save_hid1@l(r6)
+
+ /* If switching to PLL0, enable HID0:BTIC */
+ cmpli cr0,r3,0
+ bne 1f
+ mfspr r5,HID0
+ ori r5,r5,HID0_BTIC
+ sync
+ mtspr HID0,r5
+ isync
+ sync
+
+1:
+ /* Return */
+ mtmsr r7
+ blr
+
+#endif /* CONFIG_CPU_FREQ_PMAC */
+
/* void local_save_flags_ptr(unsigned long *flags) */
_GLOBAL(local_save_flags_ptr)
mfmsr r4
@@ -351,7 +405,16 @@ _GLOBAL(_tlbia)
sync /* Flush to memory before changing mapping */
tlbia
isync /* Flush shadow TLB */
-#else /* ! defined(CONFIG_40x) */
+#elif defined(CONFIG_440)
+ lis r3,0
+ sync
+1:
+ tlbwe r3,r3,PPC440_TLB_PAGEID
+ addi r3,r3,1
+ cmpwi 0,r3,61
+ ble 1b
+ isync
+#else /* !(CONFIG_40x || CONFIG_440) */
#if defined(CONFIG_SMP)
rlwinm r8,r1,0,0,18
lwz r8,TI_CPU(r8)
@@ -392,7 +455,7 @@ _GLOBAL(_tlbia)
* Flush MMU TLB for a particular address
*/
_GLOBAL(_tlbie)
-#ifdef CONFIG_40x
+#if defined(CONFIG_40x)
tlbsx. r3, 0, r3
bne 10f
sync
@@ -402,7 +465,31 @@ _GLOBAL(_tlbie)
tlbwe r3, r3, TLB_TAG
isync
10:
-#else /* ! CONFIG_40x */
+#elif defined(CONFIG_440)
+ mfspr r4,SPRN_MMUCR /* Get MMUCR */
+ lis r5,PPC440_MMUCR_STS@h
+ ori r5,r5,PPC440_MMUCR_TID@l /* Create mask */
+ andc r4,r4,r5 /* Clear out TID/STS bits */
+ mfspr r5,SPRN_PID /* Get PID */
+ or r4,r4,r5 /* Set TID bits */
+ mfmsr r6 /* Get MSR */
+ andi. r6,r6,MSR_IS@l /* TS=1? */
+ beq 11f /* If not, leave STS=0 */
+ oris r4,r4,PPC440_MMUCR_STS@h /* Set STS=1 */
+11: mtspr SPRN_MMUCR, r4 /* Put MMUCR */
+
+ tlbsx. r3, 0, r3
+ bne 10f
+ sync
+ /* There are only 64 TLB entries, so r3 < 64,
+ * which means bit 22, is clear. Since 22 is
+ * the V bit in the TLB_PAGEID, loading this
+ * value will invalidate the TLB entry.
+ */
+ tlbwe r3, r3, PPC440_TLB_PAGEID
+ isync
+10:
+#else /* !(CONFIG_40x || CONFIG_440) */
#if defined(CONFIG_SMP)
rlwinm r8,r1,0,0,18
lwz r8,TI_CPU(r8)
@@ -569,22 +656,18 @@ _GLOBAL(invalidate_dcache_range)
blr
#ifdef CONFIG_NOT_COHERENT_CACHE
-/* This is a bad one....It is used by 'consistent_sync' functions when
- * there isn't any handle on the virtual address needed by the usual
- * cache flush instructions. On the MPC8xx, we can use the cache line
- * flush command, on others all we can do is read enough data to completely
- * reload the cache, flushing old data out.
- */
-
-/* Cache organization. The 4xx has a 8K (128 line) cache, and the 8xx
- * has 1, 2, 4, 8K variants. For now, cover worst case. When we can
- * deteremine actual size, we will use that later.
+/*
+ * 40x cores have 8K or 16K dcache and 32 byte line size.
+ * 440 has a 32K dcache and 32 byte line size.
+ * 8xx has 1, 2, 4, 8K variants.
+ * For now, cover the worst case of the 440.
+ * Must be called with external interrupts disabled.
*/
-#define CACHE_NWAYS 2
-#define CACHE_NLINES 128
+#define CACHE_NWAYS 64
+#define CACHE_NLINES 16
_GLOBAL(flush_dcache_all)
- li r4, (CACHE_NWAYS * CACHE_NLINES)
+ li r4, (2 * CACHE_NWAYS * CACHE_NLINES)
mtctr r4
lis r5, KERNELBASE@h
1: lwz r3, 0(r5) /* Load one word from every line */
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index 4291dabfe81a..e5094573c5c0 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -68,6 +68,9 @@ void smp_call_function_interrupt(void);
static int __smp_call_function(void (*func) (void *info), void *info,
int wait, int target);
+/* Low level assembly function used to backup CPU 0 state */
+extern void __save_cpu_setup(void);
+
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
* Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up
@@ -349,6 +352,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
num_cpus = smp_ops->probe();
cpu_possible_map = (1 << num_cpus)-1;
+ /* Backup CPU 0 state */
+ __save_cpu_setup();
+
if (smp_ops->space_timers)
smp_ops->space_timers(num_cpus);
}
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index a63cd434abc1..a04969d2ba8b 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -19,12 +19,14 @@ endif
obj-$(CONFIG_ALL_PPC) += pmac_pic.o pmac_setup.o pmac_time.o \
pmac_feature.o pmac_pci.o chrp_setup.o\
chrp_time.o chrp_pci.o prep_pci.o \
- prep_time.o prep_setup.o
+ prep_time.o prep_setup.o pmac_sleep.o
ifeq ($(CONFIG_ALL_PPC),y)
obj-$(CONFIG_NVRAM) += pmac_nvram.o
endif
obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
-obj-$(CONFIG_PMAC_PBOOK) += sleep.o
+ifeq ($(CONFIG_ALL_PPC),y)
+obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
+endif
obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
new file mode 100644
index 000000000000..26dc16846cc9
--- /dev/null
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -0,0 +1,345 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/init.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/hardirq.h>
+#include <asm/pmac_feature.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+
+#undef DEBUG_FREQ
+
+extern void low_choose_750fx_pll(int pll);
+extern void low_sleep_handler(void);
+extern void openpic_sleep_save_intrs(void);
+extern void openpic_sleep_restore_intrs(void);
+extern void enable_kernel_altivec(void);
+extern void enable_kernel_fp(void);
+
+static unsigned int low_freq;
+static unsigned int hi_freq;
+static unsigned int cur_freq;
+static int cpufreq_uses_pmu;
+
+#define PMAC_CPU_LOW_SPEED 1
+#define PMAC_CPU_HIGH_SPEED 0
+
+static inline void
+wakeup_decrementer(void)
+{
+ set_dec(tb_ticks_per_jiffy);
+ /* No currently-supported powerbook has a 601,
+ * so use get_tbl, not native
+ */
+ last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+}
+
+#ifdef DEBUG_FREQ
+static inline void
+debug_calc_bogomips(void)
+{
+ /* This will cause a recalc of bogomips and display the
+ * result. We backup/restore the value to avoid affecting the
+ * core cpufreq framework's own calculation.
+ */
+ extern void calibrate_delay(void);
+
+ unsigned long save_lpj = loops_per_jiffy;
+ calibrate_delay();
+ loops_per_jiffy = save_lpj;
+}
+#endif
+
+/* Switch CPU speed under 750FX CPU control
+ */
+static int __pmac
+cpu_750fx_cpu_speed(int low_speed)
+{
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+ low_choose_750fx_pll(low_speed);
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+ debug_calc_bogomips();
+#endif
+
+ return 0;
+}
+
+/* Switch CPU speed under PMU control
+ */
+static int __pmac
+pmu_set_cpu_speed(unsigned int low_speed)
+{
+ struct adb_request req;
+ unsigned long save_l2cr;
+ unsigned long save_l3cr;
+
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+#endif
+ /* Disable all interrupt sources on openpic */
+ openpic_sleep_save_intrs();
+
+ /* Make sure the PMU is idle */
+ pmu_suspend();
+
+ /* Make sure the decrementer won't interrupt us */
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ /* Make sure any pending DEC interrupt occuring while we did
+ * the above didn't re-enable the DEC */
+ mb();
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+ /* We can now disable MSR_EE */
+ local_irq_disable();
+
+ /* Giveup the FPU & vec */
+ enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+ enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+ /* Save & disable L2 and L3 caches */
+ save_l3cr = _get_L3CR(); /* (returns -1 if not available) */
+ save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
+ if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ _set_L3CR(save_l3cr & 0x7fffffff);
+ if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ _set_L2CR(save_l2cr & 0x7fffffff);
+
+ /* Send the new speed command. My assumption is that this command
+ * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
+ */
+ pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
+ while (!req.complete)
+ pmu_poll();
+
+ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
+
+ low_sleep_handler();
+
+ pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
+
+ /* Restore L2 cache */
+ if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ _set_L2CR(save_l2cr);
+ /* Restore L3 cache */
+ if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ _set_L3CR(save_l3cr);
+
+ /* Restore userland MMU context */
+ set_context(current->active_mm->context, current->active_mm->pgd);
+
+#ifdef DEBUG_FREQ
+ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+#endif
+
+ /* Restore decrementer */
+ wakeup_decrementer();
+
+ /* Restore interrupts */
+ openpic_sleep_restore_intrs();
+
+ pmu_resume();
+
+ /* Let interrupts flow again ... */
+ local_irq_enable();
+
+#ifdef DEBUG_FREQ
+ debug_calc_bogomips();
+#endif
+
+ return 0;
+}
+
+static int __pmac
+do_set_cpu_speed(int speed_mode)
+{
+ struct cpufreq_freqs freqs;
+ int rc;
+
+ freqs.old = cur_freq;
+ freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+ freqs.cpu = CPUFREQ_ALL_CPUS;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ if (cpufreq_uses_pmu)
+ rc = pmu_set_cpu_speed(speed_mode);
+ else
+ rc = cpu_750fx_cpu_speed(speed_mode);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+
+ return rc;
+}
+
+static int __pmac
+pmac_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ if (!policy)
+ return -EINVAL;
+
+ policy->cpu = 0; /* UP only */
+
+ cpufreq_verify_within_limits(policy, low_freq, hi_freq);
+
+ if ((policy->min > low_freq) &&
+ (policy->max < hi_freq))
+ policy->max = hi_freq;
+
+ return 0;
+}
+
+static int __pmac
+pmac_cpufreq_setpolicy(struct cpufreq_policy *policy)
+{
+ int rc;
+
+ if (!policy)
+ return -EINVAL;
+ if (policy->min > low_freq)
+ rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED);
+ else if (policy->max < hi_freq)
+ rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED);
+ else if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
+ rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED);
+ else
+ rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED);
+
+ return rc;
+}
+
+unsigned int __pmac
+pmac_get_one_cpufreq(int i)
+{
+ /* Supports only one CPU for now */
+ return (i == 0) ? cur_freq : 0;
+}
+
+
+/* Currently, we support the following machines:
+ *
+ * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
+ * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
+ * - iBook2 500 (PMU based, 400Mhz & 500Mhz)
+ * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
+ */
+static int __init
+pmac_cpufreq_setup(void)
+{
+ struct device_node *cpunode;
+ struct cpufreq_driver *driver;
+ u32 *value;
+ int has_freq_ctl = 0;
+ int rc;
+
+ memset(&driver, 0, sizeof(driver));
+
+ /* Assume only one CPU */
+ cpunode = find_type_devices("cpu");
+ if (!cpunode)
+ goto out;
+
+ /* Get current cpu clock freq */
+ value = (u32 *)get_property(cpunode, "clock-frequency", NULL);
+ if (!value)
+ goto out;
+ cur_freq = (*value) / 1000;
+
+ /* Check for tibook 800Mhz or 1Ghz */
+ if (machine_is_compatible("PowerBook3,4") || machine_is_compatible("PowerBook3,5")) {
+ value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
+ if (!value)
+ goto out;
+ low_freq = (*value) / 1000;
+
+ value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
+ if (!value)
+ goto out;
+ hi_freq = (*value) / 1000;
+ has_freq_ctl = 1;
+ cpufreq_uses_pmu = 1;
+ }
+ /* Else check for iBook2 500 */
+ else if (machine_is_compatible("PowerBook4,1")) {
+ /* We only know about 500Mhz model */
+ if (cur_freq < 450000 || cur_freq > 550000)
+ goto out;
+ hi_freq = cur_freq;
+ low_freq = 400000;
+ has_freq_ctl = 1;
+ cpufreq_uses_pmu = 1;
+ }
+ /* Else check for TiPb 500 */
+ else if (machine_is_compatible("PowerBook3,2")) {
+ /* We only know about 500Mhz model */
+ if (cur_freq < 450000 || cur_freq > 550000)
+ goto out;
+ hi_freq = cur_freq;
+ low_freq = 300000;
+ has_freq_ctl = 1;
+ cpufreq_uses_pmu = 1;
+ }
+ /* Else check for 750FX */
+ else if (PVR_VER(mfspr(PVR)) == 0x7000) {
+ if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
+ goto out;
+ hi_freq = cur_freq;
+ value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
+ if (!value)
+ goto out;
+ low_freq = (*value) / 1000;
+ cpufreq_uses_pmu = 0;
+ has_freq_ctl = 1;
+ }
+out:
+ if (!has_freq_ctl)
+ return -ENODEV;
+
+ /* initialization of main "cpufreq" code*/
+ driver = kmalloc(sizeof(struct cpufreq_driver) +
+ NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
+ if (!driver)
+ return -ENOMEM;
+
+ driver->policy = (struct cpufreq_policy *) (driver + 1);
+
+ driver->verify = &pmac_cpufreq_verify;
+ driver->setpolicy = &pmac_cpufreq_setpolicy;
+ driver->init = NULL;
+ driver->exit = NULL;
+ strncpy(driver->name, "powermac", CPUFREQ_NAME_LEN);
+
+ driver->policy[0].cpu = 0;
+ driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ driver->policy[0].cpuinfo.min_freq = low_freq;
+ driver->policy[0].min = low_freq;
+ driver->policy[0].max = cur_freq;
+ driver->policy[0].cpuinfo.max_freq = cur_freq;
+ driver->policy[0].policy = (cur_freq == low_freq) ?
+ CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
+
+ rc = cpufreq_register_driver(driver);
+ if (rc)
+ kfree(driver);
+ return rc;
+}
+
+__initcall(pmac_cpufreq_setup);
+
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index c36b8c34c405..518650988ed4 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -14,6 +14,8 @@
* - Replace mdelay with some schedule loop if possible
* - Shorten some obfuscated delays on some routines (like modem
* power)
+ * - Refcount some clocks (see darwin)
+ * - Split split split...
*
*/
#include <linux/config.h>
@@ -25,6 +27,8 @@
#include <linux/spinlock.h>
#include <linux/adb.h>
#include <linux/pmu.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
#include <asm/sections.h>
#include <asm/errno.h>
#include <asm/ohare.h>
@@ -34,8 +38,10 @@
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/macio_asic.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
+#include <asm/pci-bridge.h>
#undef DEBUG_FEATURE
@@ -46,7 +52,8 @@
#endif
/* Exported from arch/ppc/kernel/idle.c */
-extern unsigned long powersave_nap;
+extern int powersave_nap;
+extern int powersave_lowspeed;
/*
* We use a single global lock to protect accesses. Each driver has
@@ -57,53 +64,13 @@ static spinlock_t feature_lock __pmacdata = SPIN_LOCK_UNLOCKED;
#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
+
/*
- * Helper functions regarding the various flavors of mac-io
+ * Instance of some macio stuffs
*/
-
-#define MAX_MACIO_CHIPS 2
-
-enum {
- macio_unknown = 0,
- macio_grand_central,
- macio_ohare,
- macio_ohareII,
- macio_heathrow,
- macio_gatwick,
- macio_paddington,
- macio_keylargo,
- macio_pangea
-};
-
-static const char* macio_names[] __pmacdata =
-{
- "Unknown",
- "Grand Central",
- "OHare",
- "OHareII",
- "Heathrow",
- "Gatwick",
- "Paddington",
- "Keylargo",
- "Pangea"
-};
-
-static struct macio_chip
-{
- struct device_node* of_node;
- int type;
- int rev;
- volatile u32* base;
- unsigned long flags;
-} macio_chips[MAX_MACIO_CHIPS] __pmacdata;
+struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata;
-#define MACIO_FLAG_SCCA_ON 0x00000001
-#define MACIO_FLAG_SCCB_ON 0x00000002
-#define MACIO_FLAG_SCC_LOCKED 0x00000004
-#define MACIO_FLAG_AIRPORT_ON 0x00000010
-#define MACIO_FLAG_FW_SUPPORTED 0x00000020
-
-static struct macio_chip* __pmac
+struct macio_chip* __pmac
macio_find(struct device_node* child, int type)
{
while(child) {
@@ -118,15 +85,21 @@ macio_find(struct device_node* child, int type)
return NULL;
}
-#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
-#define MACIO_FCR8(macio, r) (((volatile u8*)((macio)->base)) + (r))
+static const char* macio_names[] __pmacdata =
+{
+ "Unknown",
+ "Grand Central",
+ "OHare",
+ "OHareII",
+ "Heathrow",
+ "Gatwick",
+ "Paddington",
+ "Keylargo",
+ "Pangea",
+ "Intrepid"
+};
+
-#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
-#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
-#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
-#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
-#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
-#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
/*
* Uninorth reg. access. Note that Uni-N regs are big endian
@@ -196,7 +169,7 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
unsigned long chan_mask;
unsigned long fcr;
unsigned long flags;
- int htw;
+ int htw, trans;
unsigned long rmask;
macio = macio_find(node, 0);
@@ -211,6 +184,9 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
htw = (macio->type == macio_heathrow || macio->type == macio_paddington
|| macio->type == macio_gatwick);
+ /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
+ trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+ pmac_mb.model_id != PMAC_TYPE_YIKES);
if (value) {
#ifdef CONFIG_ADB_PMU
if ((param & 0xfff) == PMAC_SCC_IRDA)
@@ -222,7 +198,13 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
if (!(fcr & OH_SCC_ENABLE)) {
fcr |= OH_SCC_ENABLE;
if (htw) {
- fcr &= ~HRW_SCC_TRANS_EN_N;
+ /* Side effect: this will also power up the
+ * modem, but it's too messy to figure out on which
+ * ports this controls the tranceiver and on which
+ * it controls the modem
+ */
+ if (trans)
+ fcr &= ~HRW_SCC_TRANS_EN_N;
MACIO_OUT32(OHARE_FCR, fcr);
fcr |= (rmask = HRW_RESET_SCC);
MACIO_OUT32(OHARE_FCR, fcr);
@@ -258,7 +240,7 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
MACIO_OUT32(OHARE_FCR, fcr);
if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
fcr &= ~OH_SCC_ENABLE;
- if (htw)
+ if (htw && trans)
fcr |= HRW_SCC_TRANS_EN_N;
MACIO_OUT32(OHARE_FCR, fcr);
}
@@ -330,9 +312,9 @@ ohare_sleep_state(struct device_node* node, int param, int value)
if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
return -EPERM;
- if (value) {
+ if (value == 1) {
MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
- } else {
+ } else if (value == 0) {
MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
}
@@ -522,7 +504,7 @@ heathrow_sound_enable(struct device_node* node, int param, int value)
return 0;
}
-static u32 save_fcr[5] __pmacdata;
+static u32 save_fcr[6] __pmacdata;
static u32 save_mbcr __pmacdata;
static u32 save_gpio_levels[2] __pmacdata;
static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
@@ -586,6 +568,7 @@ heathrow_sleep(struct macio_chip* macio, int secondary)
/* This seems to be necessary as well or the fan
* keeps coming up and battery drains fast */
MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+ MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
/* Make sure eth is down even if module or sleep
* won't work properly */
MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
@@ -750,7 +733,13 @@ core99_modem_enable(struct device_node* node, int param, int value)
struct macio_chip* macio;
u8 gpio;
unsigned long flags;
-
+
+ /* Hack for internal USB modem */
+ if (node == NULL) {
+ if (macio_chips[0].type != macio_keylargo)
+ return -ENODEV;
+ node = macio_chips[0].of_node;
+ }
macio = macio_find(node, 0);
if (!macio)
return -ENODEV;
@@ -791,8 +780,96 @@ core99_modem_enable(struct device_node* node, int param, int value)
}
static int __pmac
+pangea_modem_enable(struct device_node* node, int param, int value)
+{
+ struct macio_chip* macio;
+ u8 gpio;
+ unsigned long flags;
+
+ /* Hack for internal USB modem */
+ if (node == NULL) {
+ if (macio_chips[0].type != macio_pangea &&
+ macio_chips[0].type != macio_intrepid)
+ return -ENODEV;
+ node = macio_chips[0].of_node;
+ }
+ macio = macio_find(node, 0);
+ if (!macio)
+ return -ENODEV;
+ gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+ gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+ gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+
+ if (!value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ UNLOCK(flags);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ mdelay(250);
+ }
+ LOCK(flags);
+ if (value) {
+ MACIO_OUT8(KL_GPIO_MODEM_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE);
+ UNLOCK(flags);
+ (void)MACIO_IN32(KEYLARGO_FCR2);
+ mdelay(250);
+ } else {
+ MACIO_OUT8(KL_GPIO_MODEM_POWER,
+ KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+ UNLOCK(flags);
+ }
+ if (value) {
+ LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250); LOCK(flags);
+ MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+ (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+ UNLOCK(flags); mdelay(250);
+ }
+ return 0;
+}
+
+static int __pmac
+core99_ata100_enable(struct device_node* node, int value)
+{
+ unsigned long flags;
+ struct pci_dev *pdev = NULL;
+ u8 pbus, pid;
+
+ if (uninorth_rev < 0x24)
+ return -ENODEV;
+
+ LOCK(flags);
+ if (value)
+ UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+ else
+ UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
+ (void)UN_IN(UNI_N_CLOCK_CNTL);
+ UNLOCK(flags);
+ udelay(20);
+
+ if (value) {
+ if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
+ pdev = pci_find_slot(pbus, pid);
+ if (pdev == NULL)
+ return 0;
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ }
+ return 0;
+}
+
+static int __pmac
core99_ide_enable(struct device_node* node, int param, int value)
{
+ /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
+ * based ata-100
+ */
switch(param) {
case 0:
return simple_feature_tweak(node, macio_unknown,
@@ -803,6 +880,8 @@ core99_ide_enable(struct device_node* node, int param, int value)
case 2:
return simple_feature_tweak(node, macio_unknown,
KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
+ case 3:
+ return core99_ata100_enable(node, value);
default:
return -ENODEV;
}
@@ -850,7 +929,8 @@ core99_gmac_phy_reset(struct device_node* node, int param, int value)
struct macio_chip* macio;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
LOCK(flags);
@@ -987,27 +1067,40 @@ core99_airport_enable(struct device_node* node, int param, int value)
static int __pmac
core99_reset_cpu(struct device_node* node, int param, int value)
{
- const int reset_lines[] = { KL_GPIO_RESET_CPU0,
- KL_GPIO_RESET_CPU1,
- KL_GPIO_RESET_CPU2,
- KL_GPIO_RESET_CPU3 };
- int reset_io;
+ unsigned int reset_io = 0;
unsigned long flags;
struct macio_chip* macio;
+ struct device_node* np;
+ const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
+ KL_GPIO_RESET_CPU1,
+ KL_GPIO_RESET_CPU2,
+ KL_GPIO_RESET_CPU3 };
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo)
return -ENODEV;
- if (param > 3 || param < 0)
+
+ np = find_path_device("/cpus");
+ if (np == NULL)
return -ENODEV;
-
- reset_io = reset_lines[param];
+ for (np = np->child; np != NULL; np = np->sibling) {
+ u32* num = (u32 *)get_property(np, "reg", NULL);
+ u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
+ if (num == NULL || rst == NULL)
+ continue;
+ if (param == *num) {
+ reset_io = *rst;
+ break;
+ }
+ }
+ if (np == NULL || reset_io == 0)
+ reset_io = dflt_reset_lines[param];
LOCK(flags);
MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
(void)MACIO_IN8(reset_io);
udelay(1);
- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+ MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTOUT_DATA | KEYLARGO_GPIO_OUTPUT_ENABLE);
(void)MACIO_IN8(reset_io);
UNLOCK(flags);
@@ -1025,15 +1118,19 @@ core99_usb_enable(struct device_node* node, int param, int value)
u32 reg;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
-
+
+ /* XXX Fix handling of 3rd USB controller in Intrepid, move the
+ * port connect stuff (KL4_*) to the sleep code eventually
+ */
prop = (char *)get_property(node, "AAPL,clock-id", NULL);
if (!prop)
return -ENODEV;
- if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
+ if (strncmp(prop, "usb0u048", 8) == 0)
number = 0;
- else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
+ else if (strncmp(prop, "usb1u148", 8) == 0)
number = 2;
else
return -ENODEV;
@@ -1104,7 +1201,8 @@ core99_firewire_enable(struct device_node* node, int param, int value)
struct macio_chip* macio;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
return -ENODEV;
@@ -1133,7 +1231,8 @@ core99_firewire_cable_power(struct device_node* node, int param, int value)
if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
return -ENODEV;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
return -ENODEV;
@@ -1172,23 +1271,24 @@ core99_write_gpio(struct device_node* node, int param, int value)
}
static void __pmac
-keylargo_shutdown(struct macio_chip* macio, int restart)
+keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
{
u32 temp;
- mdelay(1);
- MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- mdelay(100);
+ if (sleep_mode) {
+ mdelay(1);
+ MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+ (void)MACIO_IN32(KEYLARGO_FCR0);
+ mdelay(1);
+ }
MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
KL0_SCC_CELL_ENABLE |
KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
KL0_IRDA_CLK19_ENABLE);
-
- (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+
MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
- (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+ MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
MACIO_BIC(KEYLARGO_FCR1,
KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
@@ -1199,27 +1299,33 @@ keylargo_shutdown(struct macio_chip* macio, int restart)
KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
KL1_UIDE_ENABLE);
- (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- udelay(10);
MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
- udelay(10);
+
temp = MACIO_IN32(KEYLARGO_FCR3);
- if (macio->rev >= 2)
- temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
-
+ if (macio->rev >= 2) {
+ temp |= KL3_SHUTDOWN_PLL2X;
+ if (sleep_mode)
+ temp |= KL3_SHUTDOWN_PLL_TOTAL;
+ }
+
temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
- KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
+ KL3_SHUTDOWN_PLLKW35;
+ if (sleep_mode)
+ temp |= KL3_SHUTDOWN_PLLKW12;
temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
- | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
- | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+ | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
MACIO_OUT32(KEYLARGO_FCR3, temp);
- (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
static void __pmac
-pangea_shutdown(struct macio_chip* macio, int restart)
+pangea_shutdown(struct macio_chip* macio, int sleep_mode)
{
u32 temp;
@@ -1227,10 +1333,6 @@ pangea_shutdown(struct macio_chip* macio, int restart)
KL0_SCC_CELL_ENABLE |
KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
- (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
- MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
- (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
-
MACIO_BIC(KEYLARGO_FCR1,
KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
@@ -1238,18 +1340,54 @@ pangea_shutdown(struct macio_chip* macio, int restart)
KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
KL1_UIDE_ENABLE);
- (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- udelay(10);
+
temp = MACIO_IN32(KEYLARGO_FCR3);
temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
KL3_SHUTDOWN_PLLKW35;
- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
- | KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
- | KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
+ | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
MACIO_OUT32(KEYLARGO_FCR3, temp);
- (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
+}
+
+static void __pmac
+intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
+{
+ u32 temp;
+
+ MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+ KL0_SCC_CELL_ENABLE |
+ KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+ MACIO_BIC(KEYLARGO_FCR1,
+ KL1_USB2_CELL_ENABLE |
+ KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+ KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+ KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
+ if (pmac_mb.board_flags & PMAC_MB_MOBILE)
+ MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
+
+ MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+
+ temp = MACIO_IN32(KEYLARGO_FCR3);
+ temp |= KL3_IT_SHUTDOWN_PLL1 | KL3_IT_SHUTDOWN_PLL2 |
+ KL3_IT_SHUTDOWN_PLL3;
+ temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
+ KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
+ if (sleep_mode)
+ temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
+ MACIO_OUT32(KEYLARGO_FCR3, temp);
+
+ /* Flush posted writes & wait a bit */
+ (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
static int __pmac
@@ -1259,7 +1397,8 @@ core99_sleep(void)
int i;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
/* We power off the wireless slot in case it was not done
@@ -1275,7 +1414,11 @@ core99_sleep(void)
}
/* We make sure int. modem is off (in case driver lost it) */
- core99_modem_enable(macio->of_node, 0, 0);
+ if (macio->type == macio_keylargo)
+ core99_modem_enable(macio->of_node, 0, 0);
+ else
+ pangea_modem_enable(macio->of_node, 0, 0);
+
/* We make sure the sound is off as well */
core99_sound_chip_enable(macio->of_node, 0, 0);
@@ -1292,12 +1435,15 @@ core99_sleep(void)
save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
/* Save the FCRs */
- save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
+ if (macio->type == macio_keylargo)
+ save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
+ if (macio->type == macio_pangea || macio->type == macio_intrepid)
+ save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
/* Save state & config of DBDMA channels */
dbdma_save(macio, save_dbdma);
@@ -1306,9 +1452,11 @@ core99_sleep(void)
* Turn off as much as we can
*/
if (macio->type == macio_pangea)
- pangea_shutdown(macio, 0);
+ pangea_shutdown(macio, 1);
+ else if (macio->type == macio_intrepid)
+ intrepid_shutdown(macio, 1);
else if (macio->type == macio_keylargo)
- keylargo_shutdown(macio, 0);
+ keylargo_shutdown(macio, 1);
/*
* Put the host bridge to sleep
@@ -1338,7 +1486,8 @@ core99_wake_up(void)
int i;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea)
+ if (macio->type != macio_keylargo && macio->type != macio_pangea &&
+ macio->type != macio_intrepid)
return -ENODEV;
/*
@@ -1352,9 +1501,11 @@ core99_wake_up(void)
/*
* Restore KeyLargo
*/
-
- MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
- (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+
+ if (macio->type == macio_keylargo) {
+ MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
+ (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+ }
MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
@@ -1365,6 +1516,10 @@ core99_wake_up(void)
(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
(void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
+ if (macio->type == macio_pangea || macio->type == macio_intrepid) {
+ MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
+ (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
+ }
dbdma_restore(macio, save_dbdma);
@@ -1390,6 +1545,21 @@ core99_wake_up(void)
static int __pmac
core99_sleep_state(struct device_node* node, int param, int value)
{
+ /* Param == 1 means to enter the "fake sleep" mode that is
+ * used for CPU speed switch
+ */
+ if (param == 1) {
+ if (value == 1) {
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
+ } else {
+ UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+ udelay(10);
+ UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+ udelay(10);
+ }
+ return 0;
+ }
if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
return -EPERM;
if (value == 1)
@@ -1400,55 +1570,6 @@ core99_sleep_state(struct device_node* node, int param, int value)
}
static int __pmac
-pangea_modem_enable(struct device_node* node, int param, int value)
-{
- struct macio_chip* macio;
- u8 gpio;
- unsigned long flags;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
- gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
- gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
-
- if (!value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- UNLOCK(flags);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- mdelay(250);
- }
- LOCK(flags);
- if (value) {
- MACIO_OUT8(KL_GPIO_MODEM_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE);
- UNLOCK(flags);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- mdelay(250);
- } else {
- MACIO_OUT8(KL_GPIO_MODEM_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- UNLOCK(flags);
- }
- if (value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250);
- }
- return 0;
-}
-
-
-static int __pmac
generic_get_mb_info(struct device_node* node, int param, int value)
{
switch(param) {
@@ -1561,6 +1682,26 @@ static struct feature_table_entry core99_features[] __pmacdata = {
{ 0, NULL }
};
+/* RackMac
+ */
+static struct feature_table_entry rackmac_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+#ifdef CONFIG_SMP
+ { PMAC_FTR_RESET_CPU, core99_reset_cpu },
+#endif /* CONFIG_SMP */
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
+
/* Pangea features
*/
static struct feature_table_entry pangea_features[] __pmacdata = {
@@ -1580,6 +1721,26 @@ static struct feature_table_entry pangea_features[] __pmacdata = {
{ PMAC_FTR_WRITE_GPIO, core99_write_gpio },
{ 0, NULL }
};
+
+/* Intrepid features
+ */
+static struct feature_table_entry intrepid_features[] __pmacdata = {
+ { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
+ { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
+ { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
+ { PMAC_FTR_IDE_RESET, core99_ide_reset },
+ { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
+ { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
+ { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
+ { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
+ { PMAC_FTR_USB_ENABLE, core99_usb_enable },
+ { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
+ { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+ { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+ { PMAC_FTR_READ_GPIO, core99_read_gpio },
+ { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
+ { 0, NULL }
+};
static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
/* Warning: ordering is important as some models may claim
@@ -1611,11 +1772,11 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "AAPL,3400/2400", "PowerBook 3400",
PMAC_TYPE_HOOPER, ohare_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "AAPL,3500", "PowerBook 3500",
PMAC_TYPE_KANGA, ohare_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
@@ -1627,11 +1788,11 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "AAPL,PowerBook1998", "PowerBook Wallstreet",
PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
- { "AAPL,PowerBook1,1", "PowerBook 101 (Lombard)",
+ { "PowerBook1,1", "PowerBook 101 (Lombard)",
PMAC_TYPE_101_PBOOK, paddington_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "iMac,1", "iMac (first generation)",
PMAC_TYPE_ORIG_IMAC, paddington_features,
@@ -1641,13 +1802,21 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_PANGEA_IMAC, pangea_features,
PMAC_MB_CAN_SLEEP
},
- { "PowerBook4,2", "iBook 2 with 14\" LCD",
+ { "PowerBook4,3", "iBook 2 rev. 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook4,2", "iBook 2",
PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook4,1", "iBook 2",
PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerMac4,4", "eMac",
+ PMAC_TYPE_EMAC, core99_features,
+ PMAC_MB_CAN_SLEEP
},
{ "PowerMac4,2", "Flat panel iMac",
PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
@@ -1663,34 +1832,35 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "PowerBook2,1", "iBook (first generation)",
PMAC_TYPE_ORIG_IBOOK, core99_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerMac3,1", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
- 0
+ PMAC_MB_OLD_CORE99
},
{ "PowerMac3,2", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
- 0
+ PMAC_MB_OLD_CORE99
},
{ "PowerMac3,3", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
- 0
+ PMAC_MB_OLD_CORE99
},
{ "PowerMac2,1", "iMac FireWire",
PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99
},
{ "PowerMac2,2", "iMac FireWire",
PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_CAN_SLEEP
+ PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99
},
{ "PowerBook2,2", "iBook FireWire",
PMAC_TYPE_FW_IBOOK, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerMac5,1", "PowerMac G4 Cube",
PMAC_TYPE_CUBE, core99_features,
+ PMAC_MB_OLD_CORE99
},
{ "PowerMac3,4", "PowerMac G4 Silver",
PMAC_TYPE_QUICKSILVER, core99_features,
@@ -1702,19 +1872,31 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "PowerBook3,1", "PowerBook Pismo",
PMAC_TYPE_PISMO, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerBook3,2", "PowerBook Titanium",
PMAC_TYPE_TITANIUM, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook3,3", "PowerBook Titanium II",
PMAC_TYPE_TITANIUM2, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook3,4", "PowerBook Titanium III",
PMAC_TYPE_TITANIUM3, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "PowerBook3,5", "PowerBook Titanium IV",
+ PMAC_TYPE_TITANIUM4, core99_features,
+ PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
+ },
+ { "RackMac1,1", "XServe",
+ PMAC_TYPE_RACKMAC, rackmac_features,
+ 0,
+ },
+ { "PowerMac3,6", "PowerMac G4 Windtunnel",
+ PMAC_TYPE_WINDTUNNEL, rackmac_features,
+ 0,
},
};
@@ -1758,8 +1940,22 @@ probe_motherboard(void)
{
int i;
struct macio_chip* macio = &macio_chips[0];
-
- /* Lookup known motherboard type in device-tree */
+ const char* model = NULL;
+ struct device_node *dt;
+
+ /* Lookup known motherboard type in device-tree. First try an
+ * exact match on the "model" property, then try a "compatible"
+ * match is none is found.
+ */
+ dt = find_devices("device-tree");
+ if (dt != NULL)
+ model = (const char *) get_property(dt, "model", NULL);
+ for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+ if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
+ pmac_mb = pmac_mb_defs[i];
+ goto found;
+ }
+ }
for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
pmac_mb = pmac_mb_defs[i];
@@ -1797,6 +1993,11 @@ probe_motherboard(void)
pmac_mb.model_name = "Unknown Pangea-based";
pmac_mb.features = pangea_features;
break;
+ case macio_intrepid:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
+ pmac_mb.model_name = "Unknown Pangea-based";
+ pmac_mb.features = intrepid_features;
+ break;
default:
return -ENODEV;
}
@@ -1815,6 +2016,7 @@ found:
iounmap(mach_id_ptr);
}
+#ifdef CONFIG_6xx
/* Set default value of powersave_nap on machines that support it.
* It appears that uninorth rev 3 has a problem with it, we don't
* enable it on those. In theory, the flush-on-lock property is
@@ -1823,7 +2025,6 @@ found:
*/
while (uninorth_base && uninorth_rev > 3) {
struct device_node* np = find_path_device("/cpus");
- u32 pvr = mfspr(PVR);
if (!np || !np->child) {
printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
break;
@@ -1835,14 +2036,23 @@ found:
/* Nap mode not supported if flush-on-lock property is present */
if (get_property(np, "flush-on-lock", NULL))
break;
- /* Some 7450 may have problem with NAP mode too ... */
- if (((pvr >> 16) == 0x8000) && ((pvr & 0xffff) < 0x0201))
- break;
powersave_nap = 1;
printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
break;
}
+ /* On CPUs that support it (750FX), lowspeed by default during
+ * NAP mode
+ */
+ powersave_lowspeed = 1;
+#endif /* CONFIG_6xx */
+
+ /* Check for "mobile" machine */
+ if (model && (strncmp(model, "PowerBook", 9) == 0
+ || strncmp(model, "iBook", 5) == 0))
+ pmac_mb.board_flags |= PMAC_MB_MOBILE;
+
+
printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
return 0;
}
@@ -1857,7 +2067,7 @@ probe_uninorth(void)
/* Locate core99 Uni-N */
uninorth_node = find_devices("uni-n");
if (uninorth_node && uninorth_node->n_addrs > 0) {
- uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x1000);
+ uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x4000);
uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
} else
uninorth_node = NULL;
@@ -1867,15 +2077,23 @@ probe_uninorth(void)
printk(KERN_INFO "Found Uninorth memory controller & host bridge, revision: %d\n",
uninorth_rev);
+ printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
/* Set the arbitrer QAck delay according to what Apple does
*/
- if (uninorth_rev < 0x10) {
+ if (uninorth_rev < 0x11) {
actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
UN_OUT(UNI_N_ARB_CTRL, actrl);
}
+
+ /* Some more magic as done by them in recent MacOS X on UniNorth
+ * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
+ * memory timeout
+ */
+ if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+ UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
}
static void __init
@@ -1917,11 +2135,14 @@ probe_one_macio(const char* name, const char* compat, int type)
u32* did = (u32 *)get_property(node, "device-id", NULL);
if (*did == 0x00000025)
type = macio_pangea;
+ if (*did == 0x0000003e)
+ type = macio_intrepid;
}
macio_chips[i].of_node = node;
macio_chips[i].type = type;
macio_chips[i].base = base;
macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+ macio_chips[i].name = macio_names[type];
revp = (u32 *)get_property(node, "revision-id", NULL);
if (revp)
macio_chips[i].rev = *revp;
@@ -2011,7 +2232,8 @@ set_initial_features(void)
}
if (macio_chips[0].type == macio_keylargo ||
- macio_chips[0].type == macio_pangea) {
+ macio_chips[0].type == macio_pangea ||
+ macio_chips[0].type == macio_intrepid) {
/* Enable GMAC for now for PCI probing. It will be disabled
* later on after PCI probe
*/
@@ -2042,6 +2264,17 @@ set_initial_features(void)
np = np->next;
}
+ /* Enable ATA-100 before PCI probe. */
+ np = find_devices("ata-6");
+ while(np) {
+ if (np->parent
+ && device_is_compatible(np->parent, "uni-north")
+ && device_is_compatible(np, "kauai-ata")) {
+ core99_ata100_enable(np, 1);
+ }
+ np = np->next;
+ }
+
/* Switch airport off */
np = find_devices("radio");
while(np) {
@@ -2079,9 +2312,6 @@ set_initial_features(void)
initial_serial_shutdown(np);
np = np->next;
}
-
- /* Let hardware settle down */
- mdelay(10);
}
void __init
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
index 0e78aa5e3c10..09162642a8fb 100644
--- a/arch/ppc/platforms/pmac_setup.c
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -225,6 +225,20 @@ pmac_show_cpuinfo(struct seq_file *m)
return 0;
}
+int __openfirmware
+pmac_show_percpuinfo(struct seq_file *m, int i)
+{
+#ifdef CONFIG_CPU_FREQ_PMAC
+ extern unsigned int pmac_get_one_cpufreq(int i);
+ unsigned int freq = pmac_get_one_cpufreq(i);
+ if (freq != 0) {
+ seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);
+ return 0;
+ }
+#endif /* CONFIG_CPU_FREQ_PMAC */
+ return of_show_percpuinfo(m, i);
+}
+
static volatile u32 *sysctrl_regs;
void __init
@@ -604,7 +618,7 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_arch = pmac_setup_arch;
ppc_md.show_cpuinfo = pmac_show_cpuinfo;
- ppc_md.show_percpuinfo = of_show_percpuinfo;
+ ppc_md.show_percpuinfo = pmac_show_percpuinfo;
ppc_md.irq_cannonicalize = NULL;
ppc_md.init_IRQ = pmac_pic_init;
ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
diff --git a/arch/ppc/platforms/sleep.S b/arch/ppc/platforms/pmac_sleep.S
index 6c2191f94ed5..4daebad932e7 100644
--- a/arch/ppc/platforms/sleep.S
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -10,10 +10,13 @@
*
*/
+#include <linux/config.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/offsets.h>
#define MAGIC 0x4c617273 /* 'Lars' */
@@ -34,21 +37,16 @@
#define SL_DBAT3 0x50
#define SL_IBAT3 0x58
#define SL_TB 0x60
-#define SL_HID0 0x68
-#define SL_HID1 0x6c
-#define SL_MSSCR0 0x70
-#define SL_MSSSR0 0x74
-#define SL_ICTRL 0x78
-#define SL_LDSTCR 0x7c
-#define SL_LDSTDB 0x80
-#define SL_R2 0x84
-#define SL_CR 0x88
-#define SL_R12 0x8c /* r12 to r31 */
+#define SL_R2 0x68
+#define SL_CR 0x6c
+#define SL_R12 0x70 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)
- .text
+ .section .text
.align 5
+#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC)
+
/* This gets called by via-pmu.c late during the sleep process.
* The PMU was already send the sleep command and will shut us down
* soon. We need to save all that is needed and setup the wakeup
@@ -122,34 +120,9 @@ _GLOBAL(low_sleep_handler)
mfibatl r4,3
stw r4,SL_IBAT3+4(r1)
- /* Save HID0 */
- mfspr r4,HID0
- stw r4,SL_HID0(r1)
-
- /* Save 7400/7410/7450 specific registers */
- mfspr r3,PVR
- srwi r3,r3,16
- cmpli cr0,r3,0x8000
- cmpli cr1,r3,0x000c
- cmpli cr2,r3,0x800c
- cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
- mfspr r4,SPRN_MSSCR0
- stw r4,SL_MSSCR0(r1)
- mfspr r4,SPRN_MSSSR0
- stw r4,SL_MSSSR0(r1)
- /* Save 7450 specific registers */
- beq cr1,1f
- mfspr r4,HID1
- stw r4,SL_HID1(r1)
- mfspr r4,SPRN_ICTRL
- stw r4,SL_ICTRL(r1)
- mfspr r4,SPRN_LDSTCR
- stw r4,SL_LDSTCR(r1)
- mfspr r4,SPRN_LDSTDB
- stw r4,SL_LDSTDB(r1)
-1:
+ /* Backup various CPU config stuffs */
+ bl __save_cpu_setup
+
/* The ROM can wake us up via 2 different vectors:
* - On wallstreet & lombard, we must write a magic
* value 'Lars' at address 4 and a pointer to a
@@ -184,6 +157,10 @@ _GLOBAL(low_sleep_handler)
addi r3,r3,sleep_storage@l
stw r5,0(r3)
+BEGIN_FTR_SECTION
+ DSSALL
+ sync
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
/*
* Flush the L1 data cache by reading the first 128kB of RAM
@@ -298,60 +275,11 @@ grackle_wake_up:
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
- /* Restore the remaining bits of the HID0 register. */
subi r1,r1,SL_PC
- lwz r3,SL_HID0(r1)
- sync
- isync
- mtspr HID0,r3
- sync
- isync
- /* Restore 7400/7410/7450 specific registers */
- mfspr r3,PVR
- srwi r3,r3,16
- cmpli cr0,r3,0x8000
- cmpli cr1,r3,0x000c
- cmpli cr2,r3,0x800c
- cror 4*cr1+eq,4*cr1+eq,4*cr2+eq
- cror 4*cr0+eq,4*cr0+eq,4*cr1+eq
- bne 1f
- lwz r4,SL_MSSCR0(r1)
- sync
- mtspr SPRN_MSSCR0,r4
- sync
- isync
- lwz r4,SL_MSSSR0(r1)
- sync
- mtspr SPRN_MSSSR0,r4
- sync
- isync
- bne cr2,1f
- li r4,0
- mtspr SPRN_L2CR2,r4
- /* Restore 7450 specific registers */
- beq cr1,1f
- lwz r4,SL_HID1(r1)
- sync
- mtspr HID1,r4
- isync
- sync
- lwz r4,SPRN_ICTRL(r1)
- sync
- mtspr SPRN_ICTRL,r4
- isync
- sync
- lwz r4,SPRN_LDSTCR(r1)
- sync
- mtspr SPRN_LDSTCR,r4
- isync
- sync
- lwz r4,SL_LDSTDB(r1)
- sync
- mtspr SPRN_LDSTDB,r4
- isync
- sync
-1:
+ /* Restore various CPU config stuffs */
+ bl __restore_cpu_setup
+
/* Restore the BATs, and SDR1. Then we can turn on the MMU. */
lwz r4,SL_SDR1(r1)
mtsdr1 r4
@@ -438,6 +366,9 @@ turn_on_mmu:
isync
rfi
+#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */
+
+
.data
.globl sleep_storage
sleep_storage:
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 5074392f0db2..6bbe4819de1a 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -106,14 +106,16 @@ volatile static long int core99_l2_cache;
volatile static long int core99_l3_cache;
static void __init
-core99_init_caches(void)
+core99_init_caches(int cpu)
{
- int cpu = smp_processor_id();
-
+ /* Check cache presence on cpu 0, we assume all CPUs have
+ * same features here. We also assume that if we don't have
+ * L2CR, we don't have L3CR neither
+ */
if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
return;
- if (cpu == 0){
+ if (cpu == 0) {
core99_l2_cache = _get_L2CR();
printk("CPU0: L2CR is %lx\n", core99_l2_cache);
} else {
@@ -137,106 +139,6 @@ core99_init_caches(void)
}
}
-/* Some CPU registers have to be saved from the first CPU and
- * applied to others. Note that we override what is setup by
- * the cputable intentionally.
- */
-
-#define reg_hid0 0
-#define reg_hid1 1
-#define reg_msscr0 2
-#define reg_msssr0 3
-#define reg_ictrl 4
-#define reg_ldstcr 5
-#define reg_ldstdb 6
-#define reg_count 7
-
-static unsigned long cpu_regs[reg_count];
-
-static void __pmac
-cpu_setup_grab(void)
-{
- unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
- /* Read cache setting of CPU 0 */
- core99_init_caches();
-
- /* 7400/7410/7450 */
- if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
- cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
- cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
- cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
- }
- /* 7450 only */
- if (pvers == 0x8000) {
- cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
- cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
- cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
- cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
- }
- flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
-}
-
-static void __pmac
-cpu_setup_apply(int cpu_nr)
-{
- unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
- /* Apply cache setting from CPU 0 */
- core99_init_caches();
-
- /* 7400/7410/7450 */
- if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "lwz %0,4*"stringify(reg_hid0)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_HID0)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_msscr0)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_MSSCR0)", %0\n"
- "isync;sync\n"
-// "lwz %0, "stringify(reg_msssr0)"(%1)\n"
-// "sync\n"
-// "mtspr "stringify(SPRN_MSSSR0)", %0\n"
-// "isync;sync\n"
- : "=&r" (tmp) : "r" (cpu_regs));
- }
- /* 7410 only */
- if (pvers == 0x800c) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "li %0, 0\n"
- "sync\n"
- "mtspr "stringify(SPRN_L2CR2)", %0\n"
- "isync;sync\n"
- : "=&r" (tmp));
- }
- /* 7450 only */
- if (pvers == 0x8000) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "lwz %0, 4*"stringify(reg_hid1)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_HID1)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ictrl)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_ICTRL)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ldstcr)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_LDSTCR)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ldstdb)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_LDSTDB)", %0\n"
- "isync;sync\n"
- : "=&r" (tmp) : "r" (cpu_regs));
- }
-}
-
/*
* Set and clear IPIs for powersurge.
*/
@@ -501,7 +403,7 @@ smp_psurge_setup_cpu(int cpu_nr)
/* reset the entry point so if we get another intr we won't
* try to startup again */
out_be32(psurge_start, 0x100);
- if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
+ if (request_irq(30, psurge_primary_intr, SA_INTERRUPT, "primary IPI", 0))
printk(KERN_ERR "Couldn't get primary IPI interrupt");
}
@@ -526,8 +428,10 @@ smp_core99_probe(void)
openpic_request_IPIs();
for (i = 1; i < ncpus; ++i)
smp_hw_index[i] = i;
+#ifdef CONFIG_6xx
powersave_nap = 0;
- cpu_setup_grab();
+#endif
+ core99_init_caches(0);
}
return ncpus;
@@ -593,7 +497,7 @@ smp_core99_setup_cpu(int cpu_nr)
{
/* Setup some registers */
if (cpu_nr != 0)
- cpu_setup_apply(cpu_nr);
+ core99_init_caches(cpu_nr);
/* Setup openpic */
do_openpic_setup_cpu();
@@ -605,20 +509,20 @@ smp_core99_setup_cpu(int cpu_nr)
/* PowerSurge-style Macs */
struct smp_ops_t psurge_smp_ops __pmacdata = {
- smp_psurge_message_pass,
- smp_psurge_probe,
- smp_psurge_kick_cpu,
- smp_psurge_setup_cpu,
- .give_timebase = smp_generic_give_timebase,
- .take_timebase = smp_generic_take_timebase,
+ .message_pass = smp_psurge_message_pass,
+ .probe = smp_psurge_probe,
+ .kick_cpu = smp_psurge_kick_cpu,
+ .setup_cpu = smp_psurge_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
/* Core99 Macs (dual G4s) */
struct smp_ops_t core99_smp_ops __pmacdata = {
- smp_openpic_message_pass,
- smp_core99_probe,
- smp_core99_kick_cpu,
- smp_core99_setup_cpu,
- .give_timebase = smp_generic_give_timebase,
- .take_timebase = smp_generic_take_timebase,
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_core99_probe,
+ .kick_cpu = smp_core99_kick_cpu,
+ .setup_cpu = smp_core99_setup_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
};
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
index 078c554145e2..70e7408e43df 100644
--- a/arch/ppc/platforms/pmac_time.c
+++ b/arch/ppc/platforms/pmac_time.c
@@ -202,6 +202,8 @@ via_calibrate_decr(void)
printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
tb_ticks_per_jiffy, dstart - dend);
+ iounmap((void*)via);
+
return 1;
}
diff --git a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c
index d2d5acd68660..bbd0fa92a933 100644
--- a/arch/ppc/platforms/spruce_setup.c
+++ b/arch/ppc/platforms/spruce_setup.c
@@ -133,8 +133,8 @@ spruce_setup_arch(void)
#endif
/* Identify the system */
- printk("System Identification: IBM Spruce\n");
- printk("IBM Spruce port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+ printk(KERN_INFO "System Identification: IBM Spruce\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
}
static void
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
index 127e4821e1d0..047e1bf54f96 100644
--- a/arch/ppc/syslib/prom_init.c
+++ b/arch/ppc/syslib/prom_init.c
@@ -275,7 +275,7 @@ check_display(unsigned long mem)
{
phandle node;
ihandle ih;
- int i;
+ int i, j;
char type[16], *path;
static unsigned char default_colors[] = {
0x00, 0x00, 0x00,
@@ -335,26 +335,23 @@ check_display(unsigned long mem)
break;
}
-try_again:
- /*
- * Open the first display and set its colormap.
- */
- if (prom_num_displays > 0) {
- path = prom_display_paths[0];
+ for (j=0; j<prom_num_displays; j++) {
+ path = prom_display_paths[j];
prom_print("opening display ");
prom_print(path);
ih = call_prom("open", 1, 1, path);
if (ih == 0 || ih == (ihandle) -1) {
prom_print("... failed\n");
- for (i=1; i<prom_num_displays; i++) {
+ for (i=j+1; i<prom_num_displays; i++) {
prom_display_paths[i-1] = prom_display_paths[i];
prom_display_nodes[i-1] = prom_display_nodes[i];
}
- if (--prom_num_displays > 0)
- prom_disp_node = prom_display_nodes[0];
- else
+ if (--prom_num_displays > 0) {
+ prom_disp_node = prom_display_nodes[j];
+ j--;
+ } else
prom_disp_node = NULL;
- goto try_again;
+ continue;
} else {
prom_print("... ok\n");
/*
@@ -369,7 +366,7 @@ try_again:
break;
#ifdef CONFIG_LOGO_LINUX_CLUT224
- clut = logo_linux_clut224.clut;
+ clut = PTRRELOC(logo_linux_clut224.clut);
for (i = 0; i < logo_linux_clut224.clutsize;
i++, clut += 3)
if (prom_set_color(ih, i + 32, clut[0],
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bbdb7466c267..09432fb60545 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -71,8 +71,6 @@ MODULE_LICENSE("Dual MPL/GPL");
#ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static const char *version =
-"ds.c 1.112 2001/10/13 00:08:28 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -188,35 +186,21 @@ int register_pccard_driver(dev_info_t *dev_info,
void (*detach)(dev_link_t *))
{
struct pcmcia_driver *driver;
- socket_bind_t *b;
- struct pcmcia_bus_socket *bus_sock;
DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
driver = get_pcmcia_driver(dev_info);
- if (!driver) {
- driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
- if (!driver) return -ENOMEM;
- memset(driver, 0, sizeof(struct pcmcia_driver));
- driver->drv.name = (char *)dev_info;
- pcmcia_register_driver(driver);
- }
+ if (driver)
+ return -EBUSY;
+
+ driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
+ if (!driver) return -ENOMEM;
+ memset(driver, 0, sizeof(struct pcmcia_driver));
+ driver->drv.name = (char *)dev_info;
+ pcmcia_register_driver(driver);
driver->attach = attach;
driver->detach = detach;
- if (driver->use_count == 0) return 0;
-
- /* Instantiate any already-bound devices */
- down_read(&bus_socket_list_rwsem);
- list_for_each_entry(bus_sock, &bus_socket_list, socket_list) {
- for (b = bus_sock->bind; b; b = b->next) {
- if (b->driver != driver) continue;
- b->instance = driver->attach();
- if (b->instance == NULL)
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", driver->drv.name);
- }
- }
- up_read(&bus_socket_list_rwsem);
+
return 0;
} /* register_pccard_driver */
@@ -411,16 +395,11 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
if (!s)
return -EINVAL;
- DEBUG(2, "bind_request(%d, '%s')\n", i,
+ DEBUG(2, "bind_request(%d, '%s')\n", s->socket_no,
(char *)bind_info->dev_info);
driver = get_pcmcia_driver(&bind_info->dev_info);
- if (driver == NULL) {
- driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
- if (!driver) return -ENOMEM;
- memset(driver, 0, sizeof(struct pcmcia_driver));
- driver->drv.name = bind_info->dev_info;
- pcmcia_register_driver(driver);
- }
+ if (!driver)
+ return -EINVAL;
for (b = s->bind; b; b = b->next)
if ((driver == b->driver) &&
@@ -543,7 +522,7 @@ static int unbind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
socket_bind_t **b, *c;
- DEBUG(2, "unbind_request(%d, '%s')\n", i,
+ DEBUG(2, "unbind_request(%d, '%s')\n", s->socket_no,
(char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next)
if ((strcmp((char *)(*b)->driver->drv.name,
diff --git a/include/asm-ppc/keylargo.h b/include/asm-ppc/keylargo.h
index 044337d31d3d..383b00df2c6b 100644
--- a/include/asm-ppc/keylargo.h
+++ b/include/asm-ppc/keylargo.h
@@ -10,12 +10,13 @@
#define KL_PANGEA_REV 0x100
/* offset from base for feature control registers */
-#define KEYLARGO_MBCR 0x34 /* Media bay control/status */
+#define KEYLARGO_MBCR 0x34 /* KL Only, Media bay control/status */
#define KEYLARGO_FCR0 0x38
#define KEYLARGO_FCR1 0x3c
#define KEYLARGO_FCR2 0x40
#define KEYLARGO_FCR3 0x44
#define KEYLARGO_FCR4 0x48
+#define KEYLARGO_FCR5 0x4c /* Pangea only */
/* GPIO registers */
#define KEYLARGO_GPIO_LEVELS0 0x50
@@ -85,76 +86,111 @@
#define KL_MBCR_MB1_DEV_RESET 0x02000000
#define KL_MBCR_MB1_ENABLE 0x01000000
-#define KL0_SCC_B_INTF_ENABLE 0x00000001
+#define KL0_SCC_B_INTF_ENABLE 0x00000001 /* (KL Only) */
#define KL0_SCC_A_INTF_ENABLE 0x00000002
#define KL0_SCC_SLOWPCLK 0x00000004
#define KL0_SCC_RESET 0x00000008
#define KL0_SCCA_ENABLE 0x00000010
#define KL0_SCCB_ENABLE 0x00000020
#define KL0_SCC_CELL_ENABLE 0x00000040
-#define KL0_IRDA_HIGH_BAND 0x00000100
-#define KL0_IRDA_SOURCE2_SEL 0x00000200
-#define KL0_IRDA_SOURCE1_SEL 0x00000400
-#define KL0_IRDA_RESET 0x00000800
-#define KL0_IRDA_DEFAULT1 0x00001000
-#define KL0_IRDA_DEFAULT0 0x00002000
-#define KL0_IRDA_FAST_CONNECT 0x00004000
-#define KL0_IRDA_ENABLE 0x00008000
-#define KL0_IRDA_CLK32_ENABLE 0x00010000
-#define KL0_IRDA_CLK19_ENABLE 0x00020000
+#define KL0_IRDA_HIGH_BAND 0x00000100 /* (KL Only) */
+#define KL0_IRDA_SOURCE2_SEL 0x00000200 /* (KL Only) */
+#define KL0_IRDA_SOURCE1_SEL 0x00000400 /* (KL Only) */
+#define KL0_PG_USB0_PMI_ENABLE 0x00000400 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_RESET 0x00000800 /* (KL Only) */
+#define KL0_PG_USB0_REF_SUSPEND_SEL 0x00000800 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_DEFAULT1 0x00001000 /* (KL Only) */
+#define KL0_PG_USB0_REF_SUSPEND 0x00001000 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_DEFAULT0 0x00002000 /* (KL Only) */
+#define KL0_PG_USB0_PAD_SUSPEND 0x00002000 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_FAST_CONNECT 0x00004000 /* (KL Only) */
+#define KL0_PG_USB1_PMI_ENABLE 0x00004000 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_ENABLE 0x00008000 /* (KL Only) */
+#define KL0_PG_USB1_REF_SUSPEND_SEL 0x00008000 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_CLK32_ENABLE 0x00010000 /* (KL Only) */
+#define KL0_PG_USB1_REF_SUSPEND 0x00010000 /* (Pangea/Intrepid Only) */
+#define KL0_IRDA_CLK19_ENABLE 0x00020000 /* (KL Only) */
+#define KL0_PG_USB1_PAD_SUSPEND 0x00020000 /* (Pangea/Intrepid Only) */
#define KL0_USB0_PAD_SUSPEND0 0x00040000
#define KL0_USB0_PAD_SUSPEND1 0x00080000
#define KL0_USB0_CELL_ENABLE 0x00100000
#define KL0_USB1_PAD_SUSPEND0 0x00400000
#define KL0_USB1_PAD_SUSPEND1 0x00800000
#define KL0_USB1_CELL_ENABLE 0x01000000
-#define KL0_USB_REF_SUSPEND 0x10000000
+#define KL0_USB_REF_SUSPEND 0x10000000 /* (KL Only) */
#define KL0_SERIAL_ENABLE (KL0_SCC_B_INTF_ENABLE | \
KL0_SCC_SLOWPCLK | \
KL0_SCC_CELL_ENABLE | KL0_SCCA_ENABLE)
-#define KL1_AUDIO_SEL_22MCLK 0x00000002
-#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008
-#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* Burgundy only ? */
-#define KL1_AUDIO_CELL_ENABLE 0x00000040
-#define KL1_AUDIO_CHOOSE 0x00000080 /* Burgundy only ? */
+#define KL1_USB2_PMI_ENABLE 0x00000001 /* Intrepid only */
+#define KL1_AUDIO_SEL_22MCLK 0x00000002 /* KL/Pangea only */
+#define KL1_USB2_REF_SUSPEND_SEL 0x00000002 /* Intrepid only */
+#define KL1_USB2_REF_SUSPEND 0x00000004 /* Intrepid only */
+#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008 /* KL/Pangea only */
+#define KL1_USB2_PAD_SUSPEND_SEL 0x00000008 /* Intrepid only */
+#define KL1_USB2_PAD_SUSPEND0 0x00000010 /* Intrepid only */
+#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* KL/Pangea only */
+#define KL1_USB2_PAD_SUSPEND1 0x00000020 /* Intrepid only */
+#define KL1_AUDIO_CELL_ENABLE 0x00000040 /* KL/Pangea only */
+#define KL1_USB2_CELL_ENABLE 0x00000040 /* Intrepid only */
+#define KL1_AUDIO_CHOOSE 0x00000080 /* KL/Pangea only */
+#define KL1_I2S0_CHOOSE 0x00000200 /* KL Only */
#define KL1_I2S0_CELL_ENABLE 0x00000400
#define KL1_I2S0_CLK_ENABLE_BIT 0x00001000
#define KL1_I2S0_ENABLE 0x00002000
#define KL1_I2S1_CELL_ENABLE 0x00020000
#define KL1_I2S1_CLK_ENABLE_BIT 0x00080000
#define KL1_I2S1_ENABLE 0x00100000
-#define KL1_EIDE0_ENABLE 0x00800000
-#define KL1_EIDE0_RESET_N 0x01000000
-#define KL1_EIDE1_ENABLE 0x04000000
-#define KL1_EIDE1_RESET_N 0x08000000
-#define KL1_UIDE_ENABLE 0x20000000
-#define KL1_UIDE_RESET_N 0x40000000
+#define KL1_EIDE0_ENABLE 0x00800000 /* KL/Intrepid Only */
+#define KL1_EIDE0_RESET_N 0x01000000 /* KL/Intrepid Only */
+#define KL1_EIDE1_ENABLE 0x04000000 /* KL Only */
+#define KL1_EIDE1_RESET_N 0x08000000 /* KL Only */
+#define KL1_UIDE_ENABLE 0x20000000 /* KL/Pangea Only */
+#define KL1_UIDE_RESET_N 0x40000000 /* KL/Pangea Only */
#define KL2_IOBUS_ENABLE 0x00000002
-#define KL2_SLEEP_STATE_BIT 0x00000100
+#define KL2_SLEEP_STATE_BIT 0x00000100 /* KL Only */
+#define KL2_PG_STOP_ALL_CLOCKS 0x00000100 /* Pangea Only */
#define KL2_MPIC_ENABLE 0x00020000
-#define KL2_ALT_DATA_OUT 0x02000000
+#define KL2_CARDSLOT_RESET 0x00040000 /* Pangea/Intrepid Only */
+#define KL2_ALT_DATA_OUT 0x02000000 /* KL Only ??? */
#define KL2_MEM_IS_BIG 0x04000000
#define KL2_CARDSEL_16 0x08000000
-#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001
-#define KL3_SHUTDOWN_PLLKW6 0x00000002
-#define KL3_SHUTDOWN_PLLKW4 0x00000004
-#define KL3_SHUTDOWN_PLLKW35 0x00000008
-#define KL3_SHUTDOWN_PLLKW12 0x00000010
-#define KL3_PLL_RESET 0x00000020
-#define KL3_SHUTDOWN_PLL2X 0x00000080
-#define KL3_CLK66_ENABLE 0x00000100
+#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001 /* KL/Pangea only */
+#define KL3_SHUTDOWN_PLLKW6 0x00000002 /* KL/Pangea only */
+#define KL3_IT_SHUTDOWN_PLL3 0x00000002 /* Intrepid only */
+#define KL3_SHUTDOWN_PLLKW4 0x00000004 /* KL/Pangea only */
+#define KL3_IT_SHUTDOWN_PLL2 0x00000004 /* Intrepid only */
+#define KL3_SHUTDOWN_PLLKW35 0x00000008 /* KL/Pangea only */
+#define KL3_IT_SHUTDOWN_PLL1 0x00000008 /* Intrepid only */
+#define KL3_SHUTDOWN_PLLKW12 0x00000010 /* KL Only */
+#define KL3_IT_ENABLE_PLL3_SHUTDOWN 0x00000010 /* Intrepid only */
+#define KL3_PLL_RESET 0x00000020 /* KL/Pangea only */
+#define KL3_IT_ENABLE_PLL2_SHUTDOWN 0x00000020 /* Intrepid only */
+#define KL3_IT_ENABLE_PLL1_SHUTDOWN 0x00000010 /* Intrepid only */
+#define KL3_SHUTDOWN_PLL2X 0x00000080 /* KL Only */
+#define KL3_CLK66_ENABLE 0x00000100 /* KL Only */
#define KL3_CLK49_ENABLE 0x00000200
#define KL3_CLK45_ENABLE 0x00000400
-#define KL3_CLK31_ENABLE 0x00000800
+#define KL3_CLK31_ENABLE 0x00000800 /* KL/Pangea only */
#define KL3_TIMER_CLK18_ENABLE 0x00001000
#define KL3_I2S1_CLK18_ENABLE 0x00002000
#define KL3_I2S0_CLK18_ENABLE 0x00004000
-#define KL3_VIA_CLK16_ENABLE 0x00008000
-#define KL3_STOPPING33_ENABLED 0x00080000
+#define KL3_VIA_CLK16_ENABLE 0x00008000 /* KL/Pangea only */
+#define KL3_IT_VIA_CLK32_ENABLE 0x00008000 /* Intrepid only */
+#define KL3_STOPPING33_ENABLED 0x00080000 /* KL Only */
+#define KL3_PG_PLL_ENABLE_TEST 0x00080000 /* Pangea Only */
+
+/* Intrepid USB bus 2, port 0,1 */
+#define KL3_IT_PORT_WAKEUP_ENABLE(p) (0x00080000 << ((p)<<3))
+#define KL3_IT_PORT_RESUME_WAKE_EN(p) (0x00040000 << ((p)<<3))
+#define KL3_IT_PORT_CONNECT_WAKE_EN(p) (0x00020000 << ((p)<<3))
+#define KL3_IT_PORT_DISCONNECT_WAKE_EN(p) (0x00010000 << ((p)<<3))
+#define KL3_IT_PORT_RESUME_STAT(p) (0x00300000 << ((p)<<3))
+#define KL3_IT_PORT_CONNECT_STAT(p) (0x00200000 << ((p)<<3))
+#define KL3_IT_PORT_DISCONNECT_STAT(p) (0x00100000 << ((p)<<3))
/* Port 0,1 : bus 0, port 2,3 : bus 1 */
#define KL4_PORT_WAKEUP_ENABLE(p) (0x00000008 << ((p)<<3))
@@ -165,3 +201,10 @@
#define KL4_PORT_CONNECT_STAT(p) (0x00000020 << ((p)<<3))
#define KL4_PORT_DISCONNECT_STAT(p) (0x00000010 << ((p)<<3))
+/* Pangea and Intrepid only */
+#define KL5_VIA_USE_CLK31 0x000000001 /* Pangea Only */
+#define KL5_SCC_USE_CLK31 0x000000002 /* Pangea Only */
+#define KL5_PWM_CLK32_EN 0x000000004
+#define KL5_CLK3_68_EN 0x000000010
+#define KL5_CLK32_EN 0x000000020
+
diff --git a/include/asm-ppc/macio_asic.h b/include/asm-ppc/macio_asic.h
new file mode 100644
index 000000000000..58d15c5b6c69
--- /dev/null
+++ b/include/asm-ppc/macio_asic.h
@@ -0,0 +1,80 @@
+#ifndef __MACIO_ASIC_H__
+#define __MACIO_ASIC_H__
+
+#include <linux/device.h>
+
+extern struct bus_type macio_bus_type;
+
+/* MacIO device driver is defined later */
+struct macio_driver;
+struct macio_chip;
+
+#define MACIO_DEV_COUNT_RESOURCE 8
+#define MACIO_DEV_COUNT_IRQS 8
+
+/*
+ * the macio_bus structure is used to describe a "virtual" bus
+ * within a MacIO ASIC. It's typically provided by a macio_pci_asic
+ * PCI device, but could be provided differently as well (nubus
+ * machines using a fake OF tree).
+ */
+struct macio_bus
+{
+ struct macio_chip *chip; /* macio_chip (private use) */
+ struct pci_dev *pdev; /* PCI device hosting this bus */
+ struct list_head devices; /* list of devices on this bus */
+};
+
+/*
+ * the macio_dev structure is used to describe a device
+ * within an Apple MacIO ASIC.
+ */
+struct macio_dev
+{
+ struct macio_bus *bus; /* virtual bus this device is on */
+
+ struct device_node *node; /* OF node */
+ struct macio_driver *driver; /* which driver allocated this device */
+ void *driver_data; /* placeholder for driver specific stuffs */
+ struct resource resources[MACIO_DEV_COUNT_RESOURCE]; /* I/O */
+ int irqs[MACIO_DEV_COUNT_IRQS];
+
+ struct device dev; /* Generic device interface */
+};
+#define to_macio_device(d) container_of(d, struct macio_dev, dev)
+
+/*
+ * Struct used for matching a device
+ */
+struct macio_match
+{
+ char *name;
+ char *type;
+ char *compatible;
+};
+#define MACIO_ANY_MATCH ((char *)-1L)
+
+/*
+ * A driver for a mac-io chip based device
+ */
+struct macio_driver
+{
+ struct list_head node;
+ char *name;
+ struct macio_match *match_table;
+
+ int (*probe)(struct macio_dev* dev, const struct macio_match *match);
+ int (*remove)(struct macio_dev* dev);
+
+ int (*suspend)(struct macio_dev* dev, u32 state, u32 level);
+ int (*resume)(struct macio_dev* dev, u32 level);
+ int (*shutdown)(struct macio_dev* dev);
+
+ struct device_driver driver;
+};
+#define to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
+
+extern int macio_register_driver(struct macio_driver *);
+extern void macio_unregister_driver(struct macio_driver *);
+
+#endif /* __MACIO_ASIC_H__ */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 4c3742d28256..c08041618042 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -152,6 +152,7 @@ extern unsigned long ioremap_bot, ioremap_base;
/* Definitions for 40x embedded chips. */
#define _PAGE_GUARDED 0x001 /* G: page is guarded from prefetch */
+#define _PAGE_FILE 0x001 /* when !present: nonlinear file mapping */
#define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */
#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */
#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */
@@ -172,6 +173,7 @@ extern unsigned long ioremap_bot, ioremap_base;
#elif defined(CONFIG_8xx)
/* Definitions for 8xx embedded chips. */
#define _PAGE_PRESENT 0x0001 /* Page is valid */
+#define _PAGE_FILE 0x0002 /* when !present: nonlinear file mapping */
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
@@ -210,6 +212,7 @@ extern unsigned long ioremap_bot, ioremap_base;
/* Definitions for 60x, 740/750, etc. */
#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
#define _PAGE_HASHPTE 0x002 /* hash_page has made an HPTE for this pte */
+#define _PAGE_FILE 0x004 /* when !present: nonlinear file mapping */
#define _PAGE_USER 0x004 /* usermode access allowed */
#define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */
#define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */
@@ -378,6 +381,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -523,14 +527,19 @@ extern void add_hash_page(unsigned context, unsigned long va,
/*
* Encode and decode a swap entry.
* Note that the bits we use in a PTE for representing a swap entry
- * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit
- * (if used). -- paulus
+ * must not include the _PAGE_PRESENT bit, the _PAGE_FILE bit, or the
+ *_PAGE_HASHPTE bit (if used). -- paulus
*/
-#define __swp_type(entry) ((entry).val & 0x3f)
-#define __swp_offset(entry) ((entry).val >> 6)
-#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 6) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 })
+#define __swp_type(entry) ((entry).val & 0x1f)
+#define __swp_offset(entry) ((entry).val >> 5)
+#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 5) })
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 })
+
+/* Encode and decode a nonlinear file mapping entry */
+#define PTE_FILE_MAX_BITS 29
+#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
+#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
/* CONFIG_APUS */
/* For virtual address to physical address conversion */
diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
index 712aea7aeef3..eace23e7d6ca 100644
--- a/include/asm-ppc/pmac_feature.h
+++ b/include/asm-ppc/pmac_feature.h
@@ -31,10 +31,16 @@
#ifndef __PPC_ASM_PMAC_FEATURE_H
#define __PPC_ASM_PMAC_FEATURE_H
+#include <asm/macio_asic.h>
+
/*
* Known Mac motherboard models
*
* Please, report any error here to benh@kernel.crashing.org, thanks !
+ *
+ * Note that I don't fully maintain this list for Core99 & MacRISC2
+ * and I'm considering removing all NewWorld entries from it and
+ * entirely rely on the model string.
*/
/* PowerSurge are the first generation of PCI Pmacs. This include
@@ -85,10 +91,16 @@
#define PMAC_TYPE_QUICKSILVER 0x45 /* QuickSilver G4s */
#define PMAC_TYPE_PISMO 0x46 /* Pismo PowerBook */
#define PMAC_TYPE_TITANIUM 0x47 /* Titanium PowerBook */
-#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook */
-#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3) */
+#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook (no L3, M6) */
+#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3 & M7) */
+#define PMAC_TYPE_TITANIUM4 0x50 /* Titanium IV PowerBook (with L3 & M9) */
+#define PMAC_TYPE_EMAC 0x50 /* eMac */
#define PMAC_TYPE_UNKNOWN_CORE99 0x5f
+/* MacRisc2 with UniNorth 2.0 */
+#define PMAC_TYPE_RACKMAC 0x80 /* XServe */
+#define PMAC_TYPE_WINDTUNNEL 0x81
+
/* MacRISC2 machines based on the Pangea chipset
*/
#define PMAC_TYPE_PANGEA_IMAC 0x100 /* Flower Power iMac */
@@ -96,12 +108,18 @@
#define PMAC_TYPE_FLAT_PANEL_IMAC 0x102 /* Flat panel iMac */
#define PMAC_TYPE_UNKNOWN_PANGEA 0x10f
+/* MacRISC2 machines based on the Intrepid chipset
+ */
+#define PMAC_TYPE_UNKNOWN_INTREPID 0x11f /* Generic */
+
/*
* Motherboard flags
*/
#define PMAC_MB_CAN_SLEEP 0x00000001
#define PMAC_MB_HAS_FW_POWER 0x00000002
+#define PMAC_MB_OLD_CORE99 0x00000004
+#define PMAC_MB_MOBILE 0x00000008
/*
* Feature calls supported on pmac
@@ -251,5 +269,60 @@ extern void pmac_feature_init(void);
#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
+
+/*
+ * The part below is for use by macio_asic.c only, do not rely
+ * on the data structures or constants below in a normal driver
+ *
+ */
+
+#define MAX_MACIO_CHIPS 2
+
+enum {
+ macio_unknown = 0,
+ macio_grand_central,
+ macio_ohare,
+ macio_ohareII,
+ macio_heathrow,
+ macio_gatwick,
+ macio_paddington,
+ macio_keylargo,
+ macio_pangea,
+ macio_intrepid,
+};
+
+struct macio_chip
+{
+ struct device_node *of_node;
+ int type;
+ const char *name;
+ int rev;
+ volatile u32 *base;
+ unsigned long flags;
+
+ /* For use by macio_asic PCI driver */
+ struct macio_bus lbus;
+};
+
+extern struct macio_chip macio_chips[MAX_MACIO_CHIPS];
+
+#define MACIO_FLAG_SCCA_ON 0x00000001
+#define MACIO_FLAG_SCCB_ON 0x00000002
+#define MACIO_FLAG_SCC_LOCKED 0x00000004
+#define MACIO_FLAG_AIRPORT_ON 0x00000010
+#define MACIO_FLAG_FW_SUPPORTED 0x00000020
+
+extern struct macio_chip* macio_find(struct device_node* child, int type);
+
+#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
+#define MACIO_FCR8(macio, r) (((volatile u8*)((macio)->base)) + (r))
+
+#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
+#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
+#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
+#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
+#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
+#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
+
#endif /* __PPC_ASM_PMAC_FEATURE_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
index b8e30135ea41..1d18c7983cd3 100644
--- a/include/asm-ppc/uninorth.h
+++ b/include/asm-ppc/uninorth.h
@@ -28,6 +28,7 @@
#define UNI_N_CFG_GART_INVAL 0x00000001
#define UNI_N_CFG_GART_ENABLE 0x00000100
#define UNI_N_CFG_GART_2xRESET 0x00010000
+#define UNI_N_CFG_GART_DISSBADET 0x00020000
/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
* revision 1.5 (x4 AGP) may need further changes.
@@ -94,6 +95,7 @@
#define UNI_N_CLOCK_CNTL_PCI 0x00000001 /* PCI2 clock control */
#define UNI_N_CLOCK_CNTL_GMAC 0x00000002 /* GMAC clock control */
#define UNI_N_CLOCK_CNTL_FW 0x00000004 /* FireWire clock control */
+#define UNI_N_CLOCK_CNTL_ATA100 0x00000010 /* ATA-100 clock control (U2) */
/* Power Management control */
#define UNI_N_POWER_MGT 0x0030