aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 12:02:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 12:02:42 -0400
commit6f73b3629f774c6cba589b15fd095112b25ca923 (patch)
tree50a60feae71cb5f40078f552b9b08468bc7b29c9
parent3a8580f82024e30b31c662aa49346adf7a3bcdb5 (diff)
parent2074b1d9d53ae696dd3f49482bad43254f40f01d (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Benjamin Herrenschmidt: "Here are the powerpc goodies for 3.5. Main highlights are: - Support for the NX crypto engine in Power7+ - A bunch of Anton goodness, including some micro optimization of our syscall entry on Power7 - I converted a pile of our thermal control drivers to the new i2c APIs (essentially turning the old therm_pm72 into a proper set of windfarm drivers). That's one more step toward removing the deprecated i2c APIs, there's still a few drivers to fix, but we are getting close - kexec/kdump support for 47x embedded cores The big missing thing here is no updates from Freescale. Not sure what's up here, but with Kumar not working for them anymore things are a bit in a state of flux in that area." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (71 commits) powerpc: Fix irq distribution Revert "powerpc/hw-breakpoint: Use generic hw-breakpoint interfaces for new PPC ptrace flags" powerpc: Fixing a cputhread code documentation powerpc/crypto: Enable the PFO-based encryption device powerpc/crypto: Build files for the nx device driver powerpc/crypto: debugfs routines and docs for the nx device driver powerpc/crypto: SHA512 hash routines for nx encryption powerpc/crypto: SHA256 hash routines for nx encryption powerpc/crypto: AES-XCBC mode routines for nx encryption powerpc/crypto: AES-GCM mode routines for nx encryption powerpc/crypto: AES-ECB mode routines for nx encryption powerpc/crypto: AES-CTR mode routines for nx encryption powerpc/crypto: AES-CCM mode routines for nx encryption powerpc/crypto: AES-CBC mode routines for nx encryption powerpc/crypto: nx driver code supporting nx encryption powerpc/pseries: Enable the PFO-based RNG accelerator powerpc/pseries/hwrng: PFO-based hwrng driver powerpc/pseries: Add PFO support to the VIO bus powerpc/pseries: Add pseries update notifier for OFDT prop changes powerpc/pseries: Add new hvcall constants to support PFO ...
-rw-r--r--Documentation/ABI/testing/debugfs-pfo-nx-crypto45
-rw-r--r--arch/powerpc/Kconfig4
-rw-r--r--arch/powerpc/Makefile49
-rw-r--r--arch/powerpc/boot/dts/bluestone.dts25
-rw-r--r--arch/powerpc/configs/g5_defconfig1
-rw-r--r--arch/powerpc/configs/maple_defconfig1
-rw-r--r--arch/powerpc/configs/pasemi_defconfig1
-rw-r--r--arch/powerpc/configs/ps3_defconfig6
-rw-r--r--arch/powerpc/include/asm/asm-compat.h11
-rw-r--r--arch/powerpc/include/asm/cputhreads.h2
-rw-r--r--arch/powerpc/include/asm/hvcall.h25
-rw-r--r--arch/powerpc/include/asm/lppaca.h196
-rw-r--r--arch/powerpc/include/asm/lv1call.h4
-rw-r--r--arch/powerpc/include/asm/pSeries_reconfig.h12
-rw-r--r--arch/powerpc/include/asm/ppc_asm.h10
-rw-r--r--arch/powerpc/include/asm/ptrace.h6
-rw-r--r--arch/powerpc/include/asm/switch_to.h6
-rw-r--r--arch/powerpc/include/asm/thread_info.h1
-rw-r--r--arch/powerpc/include/asm/vio.h46
-rw-r--r--arch/powerpc/kernel/asm-offsets.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S30
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S4
-rw-r--r--arch/powerpc/kernel/head_44x.S8
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S8
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/misc_32.S203
-rw-r--r--arch/powerpc/kernel/paca.c3
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/prom_init.c17
-rw-r--r--arch/powerpc/kernel/ptrace.c42
-rw-r--r--arch/powerpc/kernel/ptrace32.c32
-rw-r--r--arch/powerpc/kernel/vector.S10
-rw-r--r--arch/powerpc/kernel/vio.c273
-rw-r--r--arch/powerpc/lib/copyuser_64.S6
-rw-r--r--arch/powerpc/lib/mem_64.S6
-rw-r--r--arch/powerpc/lib/memcpy_64.S6
-rw-r--r--arch/powerpc/platforms/44x/Kconfig2
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype39
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c1
-rw-r--r--arch/powerpc/platforms/ps3/Kconfig22
-rw-r--r--arch/powerpc/platforms/ps3/mm.c77
-rw-r--r--arch/powerpc/platforms/ps3/platform.h16
-rw-r--r--arch/powerpc/platforms/ps3/repository.c198
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c2
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c7
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c42
-rw-r--r--drivers/char/hw_random/Kconfig13
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/pseries-rng.c96
-rw-r--r--drivers/crypto/Kconfig17
-rw-r--r--drivers/crypto/nx/Makefile11
-rw-r--r--drivers/crypto/nx/nx-aes-cbc.c141
-rw-r--r--drivers/crypto/nx/nx-aes-ccm.c468
-rw-r--r--drivers/crypto/nx/nx-aes-ctr.c178
-rw-r--r--drivers/crypto/nx/nx-aes-ecb.c139
-rw-r--r--drivers/crypto/nx/nx-aes-gcm.c353
-rw-r--r--drivers/crypto/nx/nx-aes-xcbc.c236
-rw-r--r--drivers/crypto/nx/nx-sha256.c246
-rw-r--r--drivers/crypto/nx/nx-sha512.c265
-rw-r--r--drivers/crypto/nx/nx.c716
-rw-r--r--drivers/crypto/nx/nx.h193
-rw-r--r--drivers/crypto/nx/nx_csbcpb.h205
-rw-r--r--drivers/crypto/nx/nx_debugfs.c103
-rw-r--r--drivers/i2c/busses/i2c-powermac.c98
-rw-r--r--drivers/macintosh/Kconfig23
-rw-r--r--drivers/macintosh/Makefile14
-rw-r--r--drivers/macintosh/ams/ams-i2c.c2
-rw-r--r--drivers/macintosh/therm_adt746x.c480
-rw-r--r--drivers/macintosh/windfarm.h51
-rw-r--r--drivers/macintosh/windfarm_ad7417_sensor.c347
-rw-r--r--drivers/macintosh/windfarm_core.c23
-rw-r--r--drivers/macintosh/windfarm_cpufreq_clamp.c6
-rw-r--r--drivers/macintosh/windfarm_fcu_controls.c613
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c135
-rw-r--r--drivers/macintosh/windfarm_lm87_sensor.c201
-rw-r--r--drivers/macintosh/windfarm_max6690_sensor.c109
-rw-r--r--drivers/macintosh/windfarm_mpu.h105
-rw-r--r--drivers/macintosh/windfarm_pm72.c847
-rw-r--r--drivers/macintosh/windfarm_pm81.c25
-rw-r--r--drivers/macintosh/windfarm_pm91.c33
-rw-r--r--drivers/macintosh/windfarm_rm31.c740
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c1
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c132
-rw-r--r--drivers/ps3/ps3av.c24
85 files changed, 7827 insertions, 1080 deletions
diff --git a/Documentation/ABI/testing/debugfs-pfo-nx-crypto b/Documentation/ABI/testing/debugfs-pfo-nx-crypto
new file mode 100644
index 000000000000..685d5a448423
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-pfo-nx-crypto
@@ -0,0 +1,45 @@
1What: /sys/kernel/debug/nx-crypto/*
2Date: March 2012
3KernelVersion: 3.4
4Contact: Kent Yoder <key@linux.vnet.ibm.com>
5Description:
6
7 These debugfs interfaces are built by the nx-crypto driver, built in
8arch/powerpc/crypto/nx.
9
10Error Detection
11===============
12
13errors:
14- A u32 providing a total count of errors since the driver was loaded. The
15only errors counted here are those returned from the hcall, H_COP_OP.
16
17last_error:
18- The most recent non-zero return code from the H_COP_OP hcall. -EBUSY is not
19recorded here (the hcall will retry until -EBUSY goes away).
20
21last_error_pid:
22- The process ID of the process who received the most recent error from the
23hcall.
24
25Device Use
26==========
27
28aes_bytes:
29- The total number of bytes encrypted using AES in any of the driver's
30supported modes.
31
32aes_ops:
33- The total number of AES operations submitted to the hardware.
34
35sha256_bytes:
36- The total number of bytes hashed by the hardware using SHA-256.
37
38sha256_ops:
39- The total number of SHA-256 operations submitted to the hardware.
40
41sha512_bytes:
42- The total number of bytes hashed by the hardware using SHA-512.
43
44sha512_ops:
45- The total number of SHA-512 operations submitted to the hardware.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8a01098eaaca..0a947bd9c076 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -350,7 +350,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
350 350
351config KEXEC 351config KEXEC
352 bool "kexec system call (EXPERIMENTAL)" 352 bool "kexec system call (EXPERIMENTAL)"
353 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL 353 depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) && EXPERIMENTAL
354 help 354 help
355 kexec is a system call that implements the ability to shutdown your 355 kexec is a system call that implements the ability to shutdown your
356 current kernel, and to start another kernel. It is like a reboot 356 current kernel, and to start another kernel. It is like a reboot
@@ -367,7 +367,7 @@ config KEXEC
367 367
368config CRASH_DUMP 368config CRASH_DUMP
369 bool "Build a kdump crash kernel" 369 bool "Build a kdump crash kernel"
370 depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP && !PPC_47x) 370 depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
371 select RELOCATABLE if PPC64 || 44x 371 select RELOCATABLE if PPC64 || 44x
372 select DYNAMIC_MEMSTART if FSL_BOOKE 372 select DYNAMIC_MEMSTART if FSL_BOOKE
373 help 373 help
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6524c6e21896..950d1f7a5a39 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -69,6 +69,16 @@ LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
69 69
70CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc 70CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc
71CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple 71CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
72
73CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
74CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
75CFLAGS-$(CONFIG_POWER4_CPU) += $(call cc-option,-mcpu=power4)
76CFLAGS-$(CONFIG_POWER5_CPU) += $(call cc-option,-mcpu=power5)
77CFLAGS-$(CONFIG_POWER6_CPU) += $(call cc-option,-mcpu=power6)
78CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7)
79
80CFLAGS-$(CONFIG_TUNE_CELL) += $(call cc-option,-mtune=cell)
81
72KBUILD_CPPFLAGS += -Iarch/$(ARCH) 82KBUILD_CPPFLAGS += -Iarch/$(ARCH)
73KBUILD_AFLAGS += -Iarch/$(ARCH) 83KBUILD_AFLAGS += -Iarch/$(ARCH)
74KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y) 84KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
@@ -76,32 +86,11 @@ CPP = $(CC) -E $(KBUILD_CFLAGS)
76 86
77CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__ 87CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
78 88
79ifeq ($(CONFIG_PPC64),y)
80GCC_BROKEN_VEC := $(call cc-ifversion, -lt, 0400, y)
81
82ifeq ($(CONFIG_POWER4_ONLY),y)
83ifeq ($(CONFIG_ALTIVEC),y)
84ifeq ($(GCC_BROKEN_VEC),y)
85 KBUILD_CFLAGS += $(call cc-option,-mcpu=970)
86else
87 KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
88endif
89else
90 KBUILD_CFLAGS += $(call cc-option,-mcpu=power4)
91endif
92else
93 KBUILD_CFLAGS += $(call cc-option,-mtune=power4)
94endif
95endif
96
97KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o 89KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
98 90
99ifeq ($(CONFIG_TUNE_CELL),y) 91# No AltiVec or VSX instructions when building kernel
100 KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
101endif
102
103# No AltiVec instruction when building kernel
104KBUILD_CFLAGS += $(call cc-option,-mno-altivec) 92KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
93KBUILD_CFLAGS += $(call cc-option,-mno-vsx)
105 94
106# No SPE instruction when building kernel 95# No SPE instruction when building kernel
107# (We use all available options to help semi-broken compilers) 96# (We use all available options to help semi-broken compilers)
@@ -160,6 +149,7 @@ core-$(CONFIG_KVM) += arch/powerpc/kvm/
160core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/ 149core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/
161 150
162drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ 151drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
152drivers-$(CONFIG_CRYPTO_DEV_NX) += drivers/crypto/nx/
163 153
164# Default to zImage, override when needed 154# Default to zImage, override when needed
165all: zImage 155all: zImage
@@ -234,10 +224,11 @@ archprepare: checkbin
234# Use the file '.tmp_gas_check' for binutils tests, as gas won't output 224# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
235# to stdout and these checks are run even on install targets. 225# to stdout and these checks are run even on install targets.
236TOUT := .tmp_gas_check 226TOUT := .tmp_gas_check
237# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
238# instructions.
239# gcc-3.4 and binutils-2.14 are a fatal combination.
240 227
228# Check gcc and binutils versions:
229# - gcc-3.4 and binutils-2.14 are a fatal combination
230# - Require gcc 4.0 or above on 64-bit
231# - gcc-4.2.0 has issues compiling modules on 64-bit
241checkbin: 232checkbin:
242 @if test "$(call cc-version)" = "0304" ; then \ 233 @if test "$(call cc-version)" = "0304" ; then \
243 if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ 234 if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
@@ -247,6 +238,12 @@ checkbin:
247 false; \ 238 false; \
248 fi ; \ 239 fi ; \
249 fi 240 fi
241 @if test "$(call cc-version)" -lt "0400" \
242 && test "x${CONFIG_PPC64}" = "xy" ; then \
243 echo -n "Sorry, GCC v4.0 or above is required to build " ; \
244 echo "the 64-bit powerpc kernel." ; \
245 false ; \
246 fi
250 @if test "$(call cc-fullversion)" = "040200" \ 247 @if test "$(call cc-fullversion)" = "040200" \
251 && test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \ 248 && test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \
252 echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \ 249 echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
index 7bda373f10ef..9d4917aebe6b 100644
--- a/arch/powerpc/boot/dts/bluestone.dts
+++ b/arch/powerpc/boot/dts/bluestone.dts
@@ -373,5 +373,30 @@
373 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */ 373 0x0 0x0 0x0 0x3 &UIC3 0xe 0x4 /* swizzled int C */
374 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>; 374 0x0 0x0 0x0 0x4 &UIC3 0xf 0x4 /* swizzled int D */>;
375 }; 375 };
376
377 MSI: ppc4xx-msi@C10000000 {
378 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
379 reg = < 0xC 0x10000000 0x100
380 0xC 0x10000000 0x100>;
381 sdr-base = <0x36C>;
382 msi-data = <0x00004440>;
383 msi-mask = <0x0000ffe0>;
384 interrupts =<0 1 2 3 4 5 6 7>;
385 interrupt-parent = <&MSI>;
386 #interrupt-cells = <1>;
387 #address-cells = <0>;
388 #size-cells = <0>;
389 msi-available-ranges = <0x0 0x100>;
390 interrupt-map = <
391 0 &UIC3 0x18 1
392 1 &UIC3 0x19 1
393 2 &UIC3 0x1A 1
394 3 &UIC3 0x1B 1
395 4 &UIC3 0x1C 1
396 5 &UIC3 0x1D 1
397 6 &UIC3 0x1E 1
398 7 &UIC3 0x1F 1
399 >;
400 };
376 }; 401 };
377}; 402};
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 1196c34163b7..07b7f2af2dca 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,5 +1,4 @@
1CONFIG_PPC64=y 1CONFIG_PPC64=y
2CONFIG_POWER4_ONLY=y
3CONFIG_ALTIVEC=y 2CONFIG_ALTIVEC=y
4CONFIG_SMP=y 3CONFIG_SMP=y
5CONFIG_NR_CPUS=4 4CONFIG_NR_CPUS=4
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 2244d370f24d..02ac96b679b8 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,5 +1,4 @@
1CONFIG_PPC64=y 1CONFIG_PPC64=y
2CONFIG_POWER4_ONLY=y
3CONFIG_SMP=y 2CONFIG_SMP=y
4CONFIG_NR_CPUS=4 3CONFIG_NR_CPUS=4
5CONFIG_EXPERIMENTAL=y 4CONFIG_EXPERIMENTAL=y
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index f4deb0b78cf0..840a2c2d0430 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,5 +1,4 @@
1CONFIG_PPC64=y 1CONFIG_PPC64=y
2CONFIG_POWER4_ONLY=y
3CONFIG_ALTIVEC=y 2CONFIG_ALTIVEC=y
4# CONFIG_VIRT_CPU_ACCOUNTING is not set 3# CONFIG_VIRT_CPU_ACCOUNTING is not set
5CONFIG_SMP=y 4CONFIG_SMP=y
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index ded867871e97..c2f4b4a86ece 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -6,7 +6,6 @@ CONFIG_NR_CPUS=2
6CONFIG_EXPERIMENTAL=y 6CONFIG_EXPERIMENTAL=y
7CONFIG_SYSVIPC=y 7CONFIG_SYSVIPC=y
8CONFIG_POSIX_MQUEUE=y 8CONFIG_POSIX_MQUEUE=y
9CONFIG_SPARSE_IRQ=y
10CONFIG_BLK_DEV_INITRD=y 9CONFIG_BLK_DEV_INITRD=y
11CONFIG_CC_OPTIMIZE_FOR_SIZE=y 10CONFIG_CC_OPTIMIZE_FOR_SIZE=y
12CONFIG_EMBEDDED=y 11CONFIG_EMBEDDED=y
@@ -25,7 +24,6 @@ CONFIG_PS3_DISK=y
25CONFIG_PS3_ROM=y 24CONFIG_PS3_ROM=y
26CONFIG_PS3_FLASH=y 25CONFIG_PS3_FLASH=y
27CONFIG_PS3_VRAM=m 26CONFIG_PS3_VRAM=m
28CONFIG_PS3_LPM=m
29# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set 27# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
30CONFIG_HIGH_RES_TIMERS=y 28CONFIG_HIGH_RES_TIMERS=y
31# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 29# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -53,8 +51,6 @@ CONFIG_IP_PNP_DHCP=y
53# CONFIG_INET_DIAG is not set 51# CONFIG_INET_DIAG is not set
54CONFIG_IPV6=y 52CONFIG_IPV6=y
55CONFIG_BT=m 53CONFIG_BT=m
56CONFIG_BT_L2CAP=y
57CONFIG_BT_SCO=y
58CONFIG_BT_RFCOMM=m 54CONFIG_BT_RFCOMM=m
59CONFIG_BT_RFCOMM_TTY=y 55CONFIG_BT_RFCOMM_TTY=y
60CONFIG_BT_BNEP=m 56CONFIG_BT_BNEP=m
@@ -63,7 +59,6 @@ CONFIG_BT_BNEP_PROTO_FILTER=y
63CONFIG_BT_HIDP=m 59CONFIG_BT_HIDP=m
64CONFIG_BT_HCIBTUSB=m 60CONFIG_BT_HCIBTUSB=m
65CONFIG_CFG80211=m 61CONFIG_CFG80211=m
66# CONFIG_WIRELESS_EXT_SYSFS is not set
67CONFIG_MAC80211=m 62CONFIG_MAC80211=m
68CONFIG_MAC80211_RC_PID=y 63CONFIG_MAC80211_RC_PID=y
69# CONFIG_MAC80211_RC_MINSTREL is not set 64# CONFIG_MAC80211_RC_MINSTREL is not set
@@ -181,7 +176,6 @@ CONFIG_DEBUG_INFO=y
181CONFIG_DEBUG_WRITECOUNT=y 176CONFIG_DEBUG_WRITECOUNT=y
182CONFIG_DEBUG_MEMORY_INIT=y 177CONFIG_DEBUG_MEMORY_INIT=y
183CONFIG_DEBUG_LIST=y 178CONFIG_DEBUG_LIST=y
184CONFIG_SYSCTL_SYSCALL_CHECK=y
185# CONFIG_FTRACE is not set 179# CONFIG_FTRACE is not set
186CONFIG_DEBUG_STACKOVERFLOW=y 180CONFIG_DEBUG_STACKOVERFLOW=y
187CONFIG_CRYPTO_CCM=m 181CONFIG_CRYPTO_CCM=m
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h
index decad950f11a..5d7fbe1950f9 100644
--- a/arch/powerpc/include/asm/asm-compat.h
+++ b/arch/powerpc/include/asm/asm-compat.h
@@ -29,18 +29,9 @@
29#define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh) 29#define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh)
30#define PPC_STLCX stringify_in_c(stdcx.) 30#define PPC_STLCX stringify_in_c(stdcx.)
31#define PPC_CNTLZL stringify_in_c(cntlzd) 31#define PPC_CNTLZL stringify_in_c(cntlzd)
32#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), (RS))
32#define PPC_LR_STKOFF 16 33#define PPC_LR_STKOFF 16
33#define PPC_MIN_STKFRM 112 34#define PPC_MIN_STKFRM 112
34
35/* Move to CR, single-entry optimized version. Only available
36 * on POWER4 and later.
37 */
38#ifdef CONFIG_POWER4_ONLY
39#define PPC_MTOCRF stringify_in_c(mtocrf)
40#else
41#define PPC_MTOCRF stringify_in_c(mtcrf)
42#endif
43
44#else /* 32-bit */ 35#else /* 32-bit */
45 36
46/* operations for longs and pointers */ 37/* operations for longs and pointers */
diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h
index ce516e5eb0d3..ac3eedb9b74a 100644
--- a/arch/powerpc/include/asm/cputhreads.h
+++ b/arch/powerpc/include/asm/cputhreads.h
@@ -9,7 +9,7 @@
9 * Note: This implementation is limited to a power of 2 number of 9 * Note: This implementation is limited to a power of 2 number of
10 * threads per core and the same number for each core in the system 10 * threads per core and the same number for each core in the system
11 * (though it would work if some processors had less threads as long 11 * (though it would work if some processors had less threads as long
12 * as the CPU numbers are still allocated, just not brought offline). 12 * as the CPU numbers are still allocated, just not brought online).
13 * 13 *
14 * However, the API allows for a different implementation in the future 14 * However, the API allows for a different implementation in the future
15 * if needed, as long as you only use the functions and not the variables 15 * if needed, as long as you only use the functions and not the variables
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 1c324ff55ea8..612252388190 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -77,8 +77,27 @@
77#define H_MR_CONDITION -43 77#define H_MR_CONDITION -43
78#define H_NOT_ENOUGH_RESOURCES -44 78#define H_NOT_ENOUGH_RESOURCES -44
79#define H_R_STATE -45 79#define H_R_STATE -45
80#define H_RESCINDEND -46 80#define H_RESCINDED -46
81#define H_MULTI_THREADS_ACTIVE -9005 81#define H_P2 -55
82#define H_P3 -56
83#define H_P4 -57
84#define H_P5 -58
85#define H_P6 -59
86#define H_P7 -60
87#define H_P8 -61
88#define H_P9 -62
89#define H_TOO_BIG -64
90#define H_OVERLAP -68
91#define H_INTERRUPT -69
92#define H_BAD_DATA -70
93#define H_NOT_ACTIVE -71
94#define H_SG_LIST -72
95#define H_OP_MODE -73
96#define H_COP_HW -74
97#define H_UNSUPPORTED_FLAG_START -256
98#define H_UNSUPPORTED_FLAG_END -511
99#define H_MULTI_THREADS_ACTIVE -9005
100#define H_OUTSTANDING_COP_OPS -9006
82 101
83 102
84/* Long Busy is a condition that can be returned by the firmware 103/* Long Busy is a condition that can be returned by the firmware
@@ -240,6 +259,8 @@
240#define H_GET_MPP 0x2D4 259#define H_GET_MPP 0x2D4
241#define H_HOME_NODE_ASSOCIATIVITY 0x2EC 260#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
242#define H_BEST_ENERGY 0x2F4 261#define H_BEST_ENERGY 0x2F4
262#define H_RANDOM 0x300
263#define H_COP 0x304
243#define H_GET_MPP_X 0x314 264#define H_GET_MPP_X 0x314
244#define MAX_HCALL_OPCODE H_GET_MPP_X 265#define MAX_HCALL_OPCODE H_GET_MPP_X
245 266
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index a76254af0aaa..531fe0c3108f 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -20,18 +20,16 @@
20#define _ASM_POWERPC_LPPACA_H 20#define _ASM_POWERPC_LPPACA_H
21#ifdef __KERNEL__ 21#ifdef __KERNEL__
22 22
23/* These definitions relate to hypervisors that only exist when using 23/*
24 * These definitions relate to hypervisors that only exist when using
24 * a server type processor 25 * a server type processor
25 */ 26 */
26#ifdef CONFIG_PPC_BOOK3S 27#ifdef CONFIG_PPC_BOOK3S
27 28
28//============================================================================= 29/*
29// 30 * This control block contains the data that is shared between the
30// This control block contains the data that is shared between the 31 * hypervisor and the OS.
31// hypervisor (PLIC) and the OS. 32 */
32//
33//
34//----------------------------------------------------------------------------
35#include <linux/cache.h> 33#include <linux/cache.h>
36#include <linux/threads.h> 34#include <linux/threads.h>
37#include <asm/types.h> 35#include <asm/types.h>
@@ -43,123 +41,65 @@
43 */ 41 */
44#define NR_LPPACAS 1 42#define NR_LPPACAS 1
45 43
46 44/*
47/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k 45 * The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
48 * alignment is sufficient to prevent this */ 46 * alignment is sufficient to prevent this
47 */
49struct lppaca { 48struct lppaca {
50//============================================================================= 49 /* cacheline 1 contains read-only data */
51// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data 50
52// NOTE: The xDynXyz fields are fields that will be dynamically changed by 51 u32 desc; /* Eye catcher 0xD397D781 */
53// PLIC when preparing to bring a processor online or when dispatching a 52 u16 size; /* Size of this struct */
54// virtual processor! 53 u16 reserved1;
55//============================================================================= 54 u16 reserved2:14;
56 u32 desc; // Eye catcher 0xD397D781 x00-x03 55 u8 shared_proc:1; /* Shared processor indicator */
57 u16 size; // Size of this struct x04-x05 56 u8 secondary_thread:1; /* Secondary thread indicator */
58 u16 reserved1; // Reserved x06-x07 57 u8 reserved3[14];
59 u16 reserved2:14; // Reserved x08-x09 58 volatile u32 dyn_hw_node_id; /* Dynamic hardware node id */
60 u8 shared_proc:1; // Shared processor indicator ... 59 volatile u32 dyn_hw_proc_id; /* Dynamic hardware proc id */
61 u8 secondary_thread:1; // Secondary thread indicator ... 60 u8 reserved4[56];
62 volatile u8 dyn_proc_status:8; // Dynamic Status of this proc x0A-x0A 61 volatile u8 vphn_assoc_counts[8]; /* Virtual processor home node */
63 u8 secondary_thread_count; // Secondary thread count x0B-x0B 62 /* associativity change counters */
64 volatile u16 dyn_hv_phys_proc_index;// Dynamic HV Physical Proc Index0C-x0D 63 u8 reserved5[32];
65 volatile u16 dyn_hv_log_proc_index;// Dynamic HV Logical Proc Indexx0E-x0F 64
66 u32 decr_val; // Value for Decr programming x10-x13 65 /* cacheline 2 contains local read-write data */
67 u32 pmc_val; // Value for PMC regs x14-x17 66
68 volatile u32 dyn_hw_node_id; // Dynamic Hardware Node id x18-x1B 67 u8 reserved6[48];
69 volatile u32 dyn_hw_proc_id; // Dynamic Hardware Proc Id x1C-x1F 68 u8 cede_latency_hint;
70 volatile u32 dyn_pir; // Dynamic ProcIdReg value x20-x23 69 u8 reserved7[7];
71 u32 dsei_data; // DSEI data x24-x27 70 u8 dtl_enable_mask; /* Dispatch Trace Log mask */
72 u64 sprg3; // SPRG3 value x28-x2F 71 u8 donate_dedicated_cpu; /* Donate dedicated CPU cycles */
73 u8 reserved3[40]; // Reserved x30-x57 72 u8 fpregs_in_use;
74 volatile u8 vphn_assoc_counts[8]; // Virtual processor home node 73 u8 pmcregs_in_use;
75 // associativity change counters x58-x5F 74 u8 reserved8[28];
76 u8 reserved4[32]; // Reserved x60-x7F 75 u64 wait_state_cycles; /* Wait cycles for this proc */
77 76 u8 reserved9[28];
78//============================================================================= 77 u16 slb_count; /* # of SLBs to maintain */
79// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data 78 u8 idle; /* Indicate OS is idle */
80//============================================================================= 79 u8 vmxregs_in_use;
81 // This Dword contains a byte for each type of interrupt that can occur. 80
82 // The IPI is a count while the others are just a binary 1 or 0. 81 /* cacheline 3 is shared with other processors */
83 union { 82
84 u64 any_int; 83 /*
85 struct { 84 * This is the yield_count. An "odd" value (low bit on) means that
86 u16 reserved; // Reserved - cleared by #mpasmbl 85 * the processor is yielded (either because of an OS yield or a
87 u8 xirr_int; // Indicates xXirrValue is valid or Immed IO 86 * hypervisor preempt). An even value implies that the processor is
88 u8 ipi_cnt; // IPI Count 87 * currently executing.
89 u8 decr_int; // DECR interrupt occurred 88 * NOTE: This value will ALWAYS be zero for dedicated processors and
90 u8 pdc_int; // PDC interrupt occurred 89 * will NEVER be zero for shared processors (ie, initialized to a 1).
91 u8 quantum_int; // Interrupt quantum reached 90 */
92 u8 old_plic_deferred_ext_int; // Old PLIC has a deferred XIRR pending 91 volatile u32 yield_count;
93 } fields; 92 volatile u32 dispersion_count; /* dispatch changed physical cpu */
94 } int_dword; 93 volatile u64 cmo_faults; /* CMO page fault count */
95 94 volatile u64 cmo_fault_time; /* CMO page fault time */
96 // Whenever any fields in this Dword are set then PLIC will defer the 95 u8 reserved10[104];
97 // processing of external interrupts. Note that PLIC will store the 96
98 // XIRR directly into the xXirrValue field so that another XIRR will 97 /* cacheline 4-5 */
99 // not be presented until this one clears. The layout of the low 98
100 // 4-bytes of this Dword is up to SLIC - PLIC just checks whether the 99 u32 page_ins; /* CMO Hint - # page ins by OS */
101 // entire Dword is zero or not. A non-zero value in the low order 100 u8 reserved11[148];
102 // 2-bytes will result in SLIC being granted the highest thread 101 volatile u64 dtl_idx; /* Dispatch Trace Log head index */
103 // priority upon return. A 0 will return to SLIC as medium priority. 102 u8 reserved12[96];
104 u64 plic_defer_ints_area; // Entire Dword
105
106 // Used to pass the real SRR0/1 from PLIC to SLIC as well as to
107 // pass the target SRR0/1 from SLIC to PLIC on a SetAsrAndRfid.
108 u64 saved_srr0; // Saved SRR0 x10-x17
109 u64 saved_srr1; // Saved SRR1 x18-x1F
110
111 // Used to pass parms from the OS to PLIC for SetAsrAndRfid
112 u64 saved_gpr3; // Saved GPR3 x20-x27
113 u64 saved_gpr4; // Saved GPR4 x28-x2F
114 union {
115 u64 saved_gpr5; /* Saved GPR5 x30-x37 */
116 struct {
117 u8 cede_latency_hint; /* x30 */
118 u8 reserved[7]; /* x31-x36 */
119 } fields;
120 } gpr5_dword;
121
122
123 u8 dtl_enable_mask; // Dispatch Trace Log mask x38-x38
124 u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39
125 u8 fpregs_in_use; // FP regs in use x3A-x3A
126 u8 pmcregs_in_use; // PMC regs in use x3B-x3B
127 volatile u32 saved_decr; // Saved Decr Value x3C-x3F
128 volatile u64 emulated_time_base;// Emulated TB for this thread x40-x47
129 volatile u64 cur_plic_latency; // Unaccounted PLIC latency x48-x4F
130 u64 tot_plic_latency; // Accumulated PLIC latency x50-x57
131 u64 wait_state_cycles; // Wait cycles for this proc x58-x5F
132 u64 end_of_quantum; // TB at end of quantum x60-x67
133 u64 pdc_saved_sprg1; // Saved SPRG1 for PMC int x68-x6F
134 u64 pdc_saved_srr0; // Saved SRR0 for PMC int x70-x77
135 volatile u32 virtual_decr; // Virtual DECR for shared procsx78-x7B
136 u16 slb_count; // # of SLBs to maintain x7C-x7D
137 u8 idle; // Indicate OS is idle x7E
138 u8 vmxregs_in_use; // VMX registers in use x7F
139
140
141//=============================================================================
142// CACHE_LINE_3 0x0100 - 0x017F: This line is shared with other processors
143//=============================================================================
144 // This is the yield_count. An "odd" value (low bit on) means that
145 // the processor is yielded (either because of an OS yield or a PLIC
146 // preempt). An even value implies that the processor is currently
147 // executing.
148 // NOTE: This value will ALWAYS be zero for dedicated processors and
149 // will NEVER be zero for shared processors (ie, initialized to a 1).
150 volatile u32 yield_count; // PLIC increments each dispatchx00-x03
151 volatile u32 dispersion_count; // dispatch changed phys cpu x04-x07
152 volatile u64 cmo_faults; // CMO page fault count x08-x0F
153 volatile u64 cmo_fault_time; // CMO page fault time x10-x17
154 u8 reserved7[104]; // Reserved x18-x7F
155
156//=============================================================================
157// CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
158//=============================================================================
159 u32 page_ins; // CMO Hint - # page ins by OS x00-x03
160 u8 reserved8[148]; // Reserved x04-x97
161 volatile u64 dtl_idx; // Dispatch Trace Log head idx x98-x9F
162 u8 reserved9[96]; // Reserved xA0-xFF
163} __attribute__((__aligned__(0x400))); 103} __attribute__((__aligned__(0x400)));
164 104
165extern struct lppaca lppaca[]; 105extern struct lppaca lppaca[];
@@ -172,13 +112,13 @@ extern struct lppaca lppaca[];
172 * ESID is stored in the lower 64bits, then the VSID. 112 * ESID is stored in the lower 64bits, then the VSID.
173 */ 113 */
174struct slb_shadow { 114struct slb_shadow {
175 u32 persistent; // Number of persistent SLBs x00-x03 115 u32 persistent; /* Number of persistent SLBs */
176 u32 buffer_length; // Total shadow buffer length x04-x07 116 u32 buffer_length; /* Total shadow buffer length */
177 u64 reserved; // Alignment x08-x0f 117 u64 reserved;
178 struct { 118 struct {
179 u64 esid; 119 u64 esid;
180 u64 vsid; 120 u64 vsid;
181 } save_area[SLB_NUM_BOLTED]; // x10-x40 121 } save_area[SLB_NUM_BOLTED];
182} ____cacheline_aligned; 122} ____cacheline_aligned;
183 123
184extern struct slb_shadow slb_shadow[]; 124extern struct slb_shadow slb_shadow[];
diff --git a/arch/powerpc/include/asm/lv1call.h b/arch/powerpc/include/asm/lv1call.h
index 233f9ecae761..f5117674bf92 100644
--- a/arch/powerpc/include/asm/lv1call.h
+++ b/arch/powerpc/include/asm/lv1call.h
@@ -265,8 +265,8 @@ LV1_CALL(get_spe_irq_outlet, 2, 1, 78 )
265LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 ) 265LV1_CALL(set_spe_privilege_state_area_1_register, 3, 0, 79 )
266LV1_CALL(create_repository_node, 6, 0, 90 ) 266LV1_CALL(create_repository_node, 6, 0, 90 )
267LV1_CALL(read_repository_node, 5, 2, 91 ) 267LV1_CALL(read_repository_node, 5, 2, 91 )
268LV1_CALL(modify_repository_node_value, 6, 0, 92 ) 268LV1_CALL(write_repository_node, 6, 0, 92 )
269LV1_CALL(remove_repository_node, 4, 0, 93 ) 269LV1_CALL(delete_repository_node, 4, 0, 93 )
270LV1_CALL(read_htab_entries, 2, 5, 95 ) 270LV1_CALL(read_htab_entries, 2, 5, 95 )
271LV1_CALL(set_dabr, 2, 0, 96 ) 271LV1_CALL(set_dabr, 2, 0, 96 )
272LV1_CALL(get_total_execution_time, 2, 1, 103 ) 272LV1_CALL(get_total_execution_time, 2, 1, 103 )
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
index 23cd6cc30bcf..c07edfe98b98 100644
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ b/arch/powerpc/include/asm/pSeries_reconfig.h
@@ -13,6 +13,18 @@
13#define PSERIES_RECONFIG_REMOVE 0x0002 13#define PSERIES_RECONFIG_REMOVE 0x0002
14#define PSERIES_DRCONF_MEM_ADD 0x0003 14#define PSERIES_DRCONF_MEM_ADD 0x0003
15#define PSERIES_DRCONF_MEM_REMOVE 0x0004 15#define PSERIES_DRCONF_MEM_REMOVE 0x0004
16#define PSERIES_UPDATE_PROPERTY 0x0005
17
18/**
19 * pSeries_reconfig_notify - Notifier value structure for OFDT property updates
20 *
21 * @node: Device tree node which owns the property being updated
22 * @property: Updated property
23 */
24struct pSeries_reconfig_prop_update {
25 struct device_node *node;
26 struct property *property;
27};
16 28
17#ifdef CONFIG_PPC_PSERIES 29#ifdef CONFIG_PPC_PSERIES
18extern int pSeries_reconfig_notifier_register(struct notifier_block *); 30extern int pSeries_reconfig_notifier_register(struct notifier_block *);
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 50f73aa2ba21..15444204a3a1 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -369,7 +369,15 @@ BEGIN_FTR_SECTION \
369END_FTR_SECTION_IFCLR(CPU_FTR_601) 369END_FTR_SECTION_IFCLR(CPU_FTR_601)
370#endif 370#endif
371 371
372 372#ifdef CONFIG_PPC64
373#define MTOCRF(FXM, RS) \
374 BEGIN_FTR_SECTION_NESTED(848); \
375 mtcrf (FXM), (RS); \
376 FTR_SECTION_ELSE_NESTED(848); \
377 mtocrf (FXM), (RS); \
378 ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_NOEXECUTE, 848)
379#endif
380
373/* 381/*
374 * This instruction is not implemented on the PPC 603 or 601; however, on 382 * This instruction is not implemented on the PPC 603 or 601; however, on
375 * the 403GCX and 405GP tlbia IS defined and tlbie is not. 383 * the 403GCX and 405GP tlbia IS defined and tlbie is not.
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 84cc7840cd18..9c21ed42aba6 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -354,12 +354,6 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
354#define PTRACE_GETREGS64 22 354#define PTRACE_GETREGS64 22
355#define PTRACE_SETREGS64 23 355#define PTRACE_SETREGS64 23
356 356
357/* (old) PTRACE requests with inverted arguments */
358#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */
359#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */
360#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */
361#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */
362
363/* Calls to trace a 64bit program from a 32bit program */ 357/* Calls to trace a 64bit program from a 32bit program */
364#define PPC_PTRACE_PEEKTEXT_3264 0x95 358#define PPC_PTRACE_PEEKTEXT_3264 0x95
365#define PPC_PTRACE_PEEKDATA_3264 0x94 359#define PPC_PTRACE_PEEKDATA_3264 0x94
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index caf82d0a00de..1a6320290d26 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -21,7 +21,6 @@ extern void disable_kernel_fp(void);
21extern void enable_kernel_fp(void); 21extern void enable_kernel_fp(void);
22extern void flush_fp_to_thread(struct task_struct *); 22extern void flush_fp_to_thread(struct task_struct *);
23extern void enable_kernel_altivec(void); 23extern void enable_kernel_altivec(void);
24extern void giveup_altivec(struct task_struct *);
25extern void load_up_altivec(struct task_struct *); 24extern void load_up_altivec(struct task_struct *);
26extern int emulate_altivec(struct pt_regs *); 25extern int emulate_altivec(struct pt_regs *);
27extern void __giveup_vsx(struct task_struct *); 26extern void __giveup_vsx(struct task_struct *);
@@ -40,10 +39,15 @@ static inline void discard_lazy_cpu_state(void)
40 39
41#ifdef CONFIG_ALTIVEC 40#ifdef CONFIG_ALTIVEC
42extern void flush_altivec_to_thread(struct task_struct *); 41extern void flush_altivec_to_thread(struct task_struct *);
42extern void giveup_altivec(struct task_struct *);
43extern void giveup_altivec_notask(void);
43#else 44#else
44static inline void flush_altivec_to_thread(struct task_struct *t) 45static inline void flush_altivec_to_thread(struct task_struct *t)
45{ 46{
46} 47}
48static inline void giveup_altivec(struct task_struct *t)
49{
50}
47#endif 51#endif
48 52
49#ifdef CONFIG_VSX 53#ifdef CONFIG_VSX
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 1a1bb00f061a..a556ccc16b58 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -113,7 +113,6 @@ static inline struct thread_info *current_thread_info(void)
113#define _TIF_NOERROR (1<<TIF_NOERROR) 113#define _TIF_NOERROR (1<<TIF_NOERROR)
114#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 114#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
115#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) 115#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
116#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
117#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ 116#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
118 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT) 117 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
119 118
diff --git a/arch/powerpc/include/asm/vio.h b/arch/powerpc/include/asm/vio.h
index 6bfd5ffe1d4f..b19adf751dd9 100644
--- a/arch/powerpc/include/asm/vio.h
+++ b/arch/powerpc/include/asm/vio.h
@@ -46,6 +46,48 @@
46 46
47struct iommu_table; 47struct iommu_table;
48 48
49/*
50 * Platform Facilities Option (PFO)-specific data
51 */
52
53/* Starting unit address for PFO devices on the VIO BUS */
54#define VIO_BASE_PFO_UA 0x50000000
55
56/**
57 * vio_pfo_op - PFO operation parameters
58 *
59 * @flags: h_call subfunctions and modifiers
60 * @in: Input data block logical real address
61 * @inlen: If non-negative, the length of the input data block. If negative,
62 * the length of the input data descriptor list in bytes.
63 * @out: Output data block logical real address
64 * @outlen: If non-negative, the length of the input data block. If negative,
65 * the length of the input data descriptor list in bytes.
66 * @csbcpb: Logical real address of the 4k naturally-aligned storage block
67 * containing the CSB & optional FC field specific CPB
68 * @timeout: # of milliseconds to retry h_call, 0 for no timeout.
69 * @hcall_err: pointer to return the h_call return value, else NULL
70 */
71struct vio_pfo_op {
72 u64 flags;
73 s64 in;
74 s64 inlen;
75 s64 out;
76 s64 outlen;
77 u64 csbcpb;
78 void *done;
79 unsigned long handle;
80 unsigned int timeout;
81 long hcall_err;
82};
83
84/* End PFO specific data */
85
86enum vio_dev_family {
87 VDEVICE, /* The OF node is a child of /vdevice */
88 PFO, /* The OF node is a child of /ibm,platform-facilities */
89};
90
49/** 91/**
50 * vio_dev - This structure is used to describe virtual I/O devices. 92 * vio_dev - This structure is used to describe virtual I/O devices.
51 * 93 *
@@ -58,6 +100,7 @@ struct vio_dev {
58 const char *name; 100 const char *name;
59 const char *type; 101 const char *type;
60 uint32_t unit_address; 102 uint32_t unit_address;
103 uint32_t resource_id;
61 unsigned int irq; 104 unsigned int irq;
62 struct { 105 struct {
63 size_t desired; 106 size_t desired;
@@ -65,6 +108,7 @@ struct vio_dev {
65 size_t allocated; 108 size_t allocated;
66 atomic_t allocs_failed; 109 atomic_t allocs_failed;
67 } cmo; 110 } cmo;
111 enum vio_dev_family family;
68 struct device dev; 112 struct device dev;
69}; 113};
70 114
@@ -95,6 +139,8 @@ extern void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired);
95 139
96extern void __devinit vio_unregister_device(struct vio_dev *dev); 140extern void __devinit vio_unregister_device(struct vio_dev *dev);
97 141
142extern int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op);
143
98struct device_node; 144struct device_node;
99 145
100extern struct vio_dev *vio_register_device_node( 146extern struct vio_dev *vio_register_device_node(
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 34b8afe94a50..4554dc2fe857 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -188,10 +188,6 @@ int main(void)
188 DEFINE(SLBSHADOW_STACKESID, 188 DEFINE(SLBSHADOW_STACKESID,
189 offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid)); 189 offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
190 DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area)); 190 DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
191 DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
192 DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
193 DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
194 DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
195 DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use)); 191 DEFINE(LPPACA_PMCINUSE, offsetof(struct lppaca, pmcregs_in_use));
196 DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx)); 192 DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx));
197 DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count)); 193 DEFINE(LPPACA_YIELDCOUNT, offsetof(struct lppaca, yield_count));
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index ef2074c3e906..ed1718feb9d9 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -63,15 +63,9 @@ system_call_common:
63 std r0,GPR0(r1) 63 std r0,GPR0(r1)
64 std r10,GPR1(r1) 64 std r10,GPR1(r1)
65 ACCOUNT_CPU_USER_ENTRY(r10, r11) 65 ACCOUNT_CPU_USER_ENTRY(r10, r11)
66 /*
67 * This "crclr so" clears CR0.SO, which is the error indication on
68 * return from this system call. There must be no cmp instruction
69 * between it and the "mfcr r9" below, otherwise if XER.SO is set,
70 * CR0.SO will get set, causing all system calls to appear to fail.
71 */
72 crclr so
73 std r2,GPR2(r1) 66 std r2,GPR2(r1)
74 std r3,GPR3(r1) 67 std r3,GPR3(r1)
68 mfcr r2
75 std r4,GPR4(r1) 69 std r4,GPR4(r1)
76 std r5,GPR5(r1) 70 std r5,GPR5(r1)
77 std r6,GPR6(r1) 71 std r6,GPR6(r1)
@@ -82,18 +76,20 @@ system_call_common:
82 std r11,GPR10(r1) 76 std r11,GPR10(r1)
83 std r11,GPR11(r1) 77 std r11,GPR11(r1)
84 std r11,GPR12(r1) 78 std r11,GPR12(r1)
79 std r11,_XER(r1)
80 std r11,_CTR(r1)
85 std r9,GPR13(r1) 81 std r9,GPR13(r1)
86 mfcr r9
87 mflr r10 82 mflr r10
83 /*
84 * This clears CR0.SO (bit 28), which is the error indication on
85 * return from this system call.
86 */
87 rldimi r2,r11,28,(63-28)
88 li r11,0xc01 88 li r11,0xc01
89 std r9,_CCR(r1)
90 std r10,_LINK(r1) 89 std r10,_LINK(r1)
91 std r11,_TRAP(r1) 90 std r11,_TRAP(r1)
92 mfxer r9
93 mfctr r10
94 std r9,_XER(r1)
95 std r10,_CTR(r1)
96 std r3,ORIG_GPR3(r1) 91 std r3,ORIG_GPR3(r1)
92 std r2,_CCR(r1)
97 ld r2,PACATOC(r13) 93 ld r2,PACATOC(r13)
98 addi r9,r1,STACK_FRAME_OVERHEAD 94 addi r9,r1,STACK_FRAME_OVERHEAD
99 ld r11,exception_marker@toc(r2) 95 ld r11,exception_marker@toc(r2)
@@ -154,7 +150,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
154 ld r10,TI_FLAGS(r11) 150 ld r10,TI_FLAGS(r11)
155 andi. r11,r10,_TIF_SYSCALL_T_OR_A 151 andi. r11,r10,_TIF_SYSCALL_T_OR_A
156 bne- syscall_dotrace 152 bne- syscall_dotrace
157syscall_dotrace_cont: 153.Lsyscall_dotrace_cont:
158 cmpldi 0,r0,NR_syscalls 154 cmpldi 0,r0,NR_syscalls
159 bge- syscall_enosys 155 bge- syscall_enosys
160 156
@@ -211,7 +207,7 @@ syscall_exit:
211 cmpld r3,r11 207 cmpld r3,r11
212 ld r5,_CCR(r1) 208 ld r5,_CCR(r1)
213 bge- syscall_error 209 bge- syscall_error
214syscall_error_cont: 210.Lsyscall_error_cont:
215 ld r7,_NIP(r1) 211 ld r7,_NIP(r1)
216BEGIN_FTR_SECTION 212BEGIN_FTR_SECTION
217 stdcx. r0,0,r1 /* to clear the reservation */ 213 stdcx. r0,0,r1 /* to clear the reservation */
@@ -246,7 +242,7 @@ syscall_error:
246 oris r5,r5,0x1000 /* Set SO bit in CR */ 242 oris r5,r5,0x1000 /* Set SO bit in CR */
247 neg r3,r3 243 neg r3,r3
248 std r5,_CCR(r1) 244 std r5,_CCR(r1)
249 b syscall_error_cont 245 b .Lsyscall_error_cont
250 246
251/* Traced system call support */ 247/* Traced system call support */
252syscall_dotrace: 248syscall_dotrace:
@@ -268,7 +264,7 @@ syscall_dotrace:
268 addi r9,r1,STACK_FRAME_OVERHEAD 264 addi r9,r1,STACK_FRAME_OVERHEAD
269 clrrdi r10,r1,THREAD_SHIFT 265 clrrdi r10,r1,THREAD_SHIFT
270 ld r10,TI_FLAGS(r10) 266 ld r10,TI_FLAGS(r10)
271 b syscall_dotrace_cont 267 b .Lsyscall_dotrace_cont
272 268
273syscall_enosys: 269syscall_enosys:
274 li r3,-ENOSYS 270 li r3,-ENOSYS
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 8f880bc77c56..f7bed44ee165 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -94,12 +94,10 @@ machine_check_pSeries_1:
94data_access_pSeries: 94data_access_pSeries:
95 HMT_MEDIUM 95 HMT_MEDIUM
96 SET_SCRATCH0(r13) 96 SET_SCRATCH0(r13)
97#ifndef CONFIG_POWER4_ONLY
98BEGIN_FTR_SECTION 97BEGIN_FTR_SECTION
99 b data_access_check_stab 98 b data_access_check_stab
100data_access_not_stab: 99data_access_not_stab:
101END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) 100END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
102#endif
103 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, 101 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD,
104 KVMTEST, 0x300) 102 KVMTEST, 0x300)
105 103
@@ -301,7 +299,6 @@ machine_check_fwnmi:
301 EXC_STD, KVMTEST, 0x200) 299 EXC_STD, KVMTEST, 0x200)
302 KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) 300 KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200)
303 301
304#ifndef CONFIG_POWER4_ONLY
305 /* moved from 0x300 */ 302 /* moved from 0x300 */
306data_access_check_stab: 303data_access_check_stab:
307 GET_PACA(r13) 304 GET_PACA(r13)
@@ -328,7 +325,6 @@ do_stab_bolted_pSeries:
328 GET_SCRATCH0(r10) 325 GET_SCRATCH0(r10)
329 std r10,PACA_EXSLB+EX_R13(r13) 326 std r10,PACA_EXSLB+EX_R13(r13)
330 EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD) 327 EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
331#endif /* CONFIG_POWER4_ONLY */
332 328
333 KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300) 329 KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
334 KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380) 330 KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 7dd2981bcc50..22d608e8bb7d 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -778,14 +778,6 @@ _GLOBAL(__fixup_440A_mcheck)
778 blr 778 blr
779 779
780/* 780/*
781 * extern void giveup_altivec(struct task_struct *prev)
782 *
783 * The 44x core does not have an AltiVec unit.
784 */
785_GLOBAL(giveup_altivec)
786 blr
787
788/*
789 * extern void giveup_fpu(struct task_struct *prev) 781 * extern void giveup_fpu(struct task_struct *prev)
790 * 782 *
791 * The 44x core does not have an FPU. 783 * The 44x core does not have an FPU.
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 28e62598d0e8..de80e0f9a2bd 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -874,14 +874,6 @@ _GLOBAL(__setup_e500mc_ivors)
874 sync 874 sync
875 blr 875 blr
876 876
877/*
878 * extern void giveup_altivec(struct task_struct *prev)
879 *
880 * The e500 core does not have an AltiVec unit.
881 */
882_GLOBAL(giveup_altivec)
883 blr
884
885#ifdef CONFIG_SPE 877#ifdef CONFIG_SPE
886/* 878/*
887 * extern void giveup_spe(struct task_struct *prev) 879 * extern void giveup_spe(struct task_struct *prev)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 641da9e868ce..7835a5e1ea5f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -587,7 +587,7 @@ int irq_choose_cpu(const struct cpumask *mask)
587{ 587{
588 int cpuid; 588 int cpuid;
589 589
590 if (cpumask_equal(mask, cpu_all_mask)) { 590 if (cpumask_equal(mask, cpu_online_mask)) {
591 static int irq_rover; 591 static int irq_rover;
592 static DEFINE_RAW_SPINLOCK(irq_rover_lock); 592 static DEFINE_RAW_SPINLOCK(irq_rover_lock);
593 unsigned long flags; 593 unsigned long flags;
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 7cd07b42ca1a..386d57f66f28 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -738,8 +738,23 @@ relocate_new_kernel:
738 mr r5, r31 738 mr r5, r31
739 739
740 li r0, 0 740 li r0, 0
741#elif defined(CONFIG_44x) && !defined(CONFIG_PPC_47x) 741#elif defined(CONFIG_44x)
742 742
743 /* Save our parameters */
744 mr r29, r3
745 mr r30, r4
746 mr r31, r5
747
748#ifdef CONFIG_PPC_47x
749 /* Check for 47x cores */
750 mfspr r3,SPRN_PVR
751 srwi r3,r3,16
752 cmplwi cr0,r3,PVR_476@h
753 beq setup_map_47x
754 cmplwi cr0,r3,PVR_476_ISS@h
755 beq setup_map_47x
756#endif /* CONFIG_PPC_47x */
757
743/* 758/*
744 * Code for setting up 1:1 mapping for PPC440x for KEXEC 759 * Code for setting up 1:1 mapping for PPC440x for KEXEC
745 * 760 *
@@ -753,16 +768,15 @@ relocate_new_kernel:
753 * 5) Invalidate the tmp mapping. 768 * 5) Invalidate the tmp mapping.
754 * 769 *
755 * - Based on the kexec support code for FSL BookE 770 * - Based on the kexec support code for FSL BookE
756 * - Doesn't support 47x yet.
757 * 771 *
758 */ 772 */
759 /* Save our parameters */
760 mr r29, r3
761 mr r30, r4
762 mr r31, r5
763 773
764 /* Load our MSR_IS and TID to MMUCR for TLB search */ 774 /*
765 mfspr r3,SPRN_PID 775 * Load the PID with kernel PID (0).
776 * Also load our MSR_IS and TID to MMUCR for TLB search.
777 */
778 li r3, 0
779 mtspr SPRN_PID, r3
766 mfmsr r4 780 mfmsr r4
767 andi. r4,r4,MSR_IS@l 781 andi. r4,r4,MSR_IS@l
768 beq wmmucr 782 beq wmmucr
@@ -900,6 +914,179 @@ next_tlb:
900 li r3, 0 914 li r3, 0
901 tlbwe r3, r24, PPC44x_TLB_PAGEID 915 tlbwe r3, r24, PPC44x_TLB_PAGEID
902 sync 916 sync
917 b ppc44x_map_done
918
919#ifdef CONFIG_PPC_47x
920
921 /* 1:1 mapping for 47x */
922
923setup_map_47x:
924
925 /*
926 * Load the kernel pid (0) to PID and also to MMUCR[TID].
927 * Also set the MSR IS->MMUCR STS
928 */
929 li r3, 0
930 mtspr SPRN_PID, r3 /* Set PID */
931 mfmsr r4 /* Get MSR */
932 andi. r4, r4, MSR_IS@l /* TS=1? */
933 beq 1f /* If not, leave STS=0 */
934 oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
9351: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
936 sync
937
938 /* Find the entry we are running from */
939 bl 2f
9402: mflr r23
941 tlbsx r23, 0, r23
942 tlbre r24, r23, 0 /* TLB Word 0 */
943 tlbre r25, r23, 1 /* TLB Word 1 */
944 tlbre r26, r23, 2 /* TLB Word 2 */
945
946
947 /*
948 * Invalidates all the tlb entries by writing to 256 RPNs(r4)
949 * of 4k page size in all 4 ways (0-3 in r3).
950 * This would invalidate the entire UTLB including the one we are
951 * running from. However the shadow TLB entries would help us
952 * to continue the execution, until we flush them (rfi/isync).
953 */
954 addis r3, 0, 0x8000 /* specify the way */
955 addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
956 addi r5, 0, 0
957 b clear_utlb_entry
958
959 /* Align the loop to speed things up. from head_44x.S */
960 .align 6
961
962clear_utlb_entry:
963
964 tlbwe r4, r3, 0
965 tlbwe r5, r3, 1
966 tlbwe r5, r3, 2
967 addis r3, r3, 0x2000 /* Increment the way */
968 cmpwi r3, 0
969 bne clear_utlb_entry
970 addis r3, 0, 0x8000
971 addis r4, r4, 0x100 /* Increment the EPN */
972 cmpwi r4, 0
973 bne clear_utlb_entry
974
975 /* Create the entries in the other address space */
976 mfmsr r5
977 rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
978 xori r7, r7, 1 /* r7 = !TS */
979
980 insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
981
982 /*
983 * write out the TLB entries for the tmp mapping
984 * Use way '0' so that we could easily invalidate it later.
985 */
986 lis r3, 0x8000 /* Way '0' */
987
988 tlbwe r24, r3, 0
989 tlbwe r25, r3, 1
990 tlbwe r26, r3, 2
991
992 /* Update the msr to the new TS */
993 insrwi r5, r7, 1, 26
994
995 bl 1f
9961: mflr r6
997 addi r6, r6, (2f-1b)
998
999 mtspr SPRN_SRR0, r6
1000 mtspr SPRN_SRR1, r5
1001 rfi
1002
1003 /*
1004 * Now we are in the tmp address space.
1005 * Create a 1:1 mapping for 0-2GiB in the original TS.
1006 */
10072:
1008 li r3, 0
1009 li r4, 0 /* TLB Word 0 */
1010 li r5, 0 /* TLB Word 1 */
1011 li r6, 0
1012 ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
1013
1014 li r8, 0 /* PageIndex */
1015
1016 xori r7, r7, 1 /* revert back to original TS */
1017
1018write_utlb:
1019 rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
1020 /* ERPN = 0 as we don't use memory above 2G */
1021
1022 mr r4, r5 /* EPN = RPN */
1023 ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
1024 insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
1025
1026 tlbwe r4, r3, 0 /* Write out the entries */
1027 tlbwe r5, r3, 1
1028 tlbwe r6, r3, 2
1029 addi r8, r8, 1
1030 cmpwi r8, 8 /* Have we completed ? */
1031 bne write_utlb
1032
1033 /* make sure we complete the TLB write up */
1034 isync
1035
1036 /*
1037 * Prepare to jump to the 1:1 mapping.
1038 * 1) Extract page size of the tmp mapping
1039 * DSIZ = TLB_Word0[22:27]
1040 * 2) Calculate the physical address of the address
1041 * to jump to.
1042 */
1043 rlwinm r10, r24, 0, 22, 27
1044
1045 cmpwi r10, PPC47x_TLB0_4K
1046 bne 0f
1047 li r10, 0x1000 /* r10 = 4k */
1048 bl 1f
1049
10500:
1051 /* Defaults to 256M */
1052 lis r10, 0x1000
1053
1054 bl 1f
10551: mflr r4
1056 addi r4, r4, (2f-1b) /* virtual address of 2f */
1057
1058 subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
1059 not r10, r11 /* Pagemask = ~(offsetmask) */
1060
1061 and r5, r25, r10 /* Physical page */
1062 and r6, r4, r11 /* offset within the current page */
1063
1064 or r5, r5, r6 /* Physical address for 2f */
1065
1066 /* Switch the TS in MSR to the original one */
1067 mfmsr r8
1068 insrwi r8, r7, 1, 26
1069
1070 mtspr SPRN_SRR1, r8
1071 mtspr SPRN_SRR0, r5
1072 rfi
1073
10742:
1075 /* Invalidate the tmp mapping */
1076 lis r3, 0x8000 /* Way '0' */
1077
1078 clrrwi r24, r24, 12 /* Clear the valid bit */
1079 tlbwe r24, r3, 0
1080 tlbwe r25, r3, 1
1081 tlbwe r26, r3, 2
1082
1083 /* Make sure we complete the TLB write and flush the shadow TLB */
1084 isync
1085
1086#endif
1087
1088ppc44x_map_done:
1089
903 1090
904 /* Restore the parameters */ 1091 /* Restore the parameters */
905 mr r3, r29 1092 mr r3, r29
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 0bb1f98613ba..fbe1a12dc7f1 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -36,10 +36,7 @@ struct lppaca lppaca[] = {
36 [0 ... (NR_LPPACAS-1)] = { 36 [0 ... (NR_LPPACAS-1)] = {
37 .desc = 0xd397d781, /* "LpPa" */ 37 .desc = 0xd397d781, /* "LpPa" */
38 .size = sizeof(struct lppaca), 38 .size = sizeof(struct lppaca),
39 .dyn_proc_status = 2,
40 .decr_val = 0x00ff0000,
41 .fpregs_in_use = 1, 39 .fpregs_in_use = 1,
42 .end_of_quantum = 0xfffffffffffffffful,
43 .slb_count = 64, 40 .slb_count = 64,
44 .vmxregs_in_use = 0, 41 .vmxregs_in_use = 0,
45 .page_ins = 0, 42 .page_ins = 0,
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index aa05935b6947..7f8ec1de0ace 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -124,7 +124,7 @@ void enable_kernel_altivec(void)
124 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) 124 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
125 giveup_altivec(current); 125 giveup_altivec(current);
126 else 126 else
127 giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ 127 giveup_altivec_notask();
128#else 128#else
129 giveup_altivec(last_task_used_altivec); 129 giveup_altivec(last_task_used_altivec);
130#endif /* CONFIG_SMP */ 130#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 99860273211b..1b488e5305c5 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -680,6 +680,9 @@ static void __init early_cmdline_parse(void)
680#define OV3_VMX 0x40 /* VMX/Altivec */ 680#define OV3_VMX 0x40 /* VMX/Altivec */
681#define OV3_DFP 0x20 /* decimal FP */ 681#define OV3_DFP 0x20 /* decimal FP */
682 682
683/* Option vector 4: IBM PAPR implementation */
684#define OV4_MIN_ENT_CAP 0x01 /* minimum VP entitled capacity */
685
683/* Option vector 5: PAPR/OF options supported */ 686/* Option vector 5: PAPR/OF options supported */
684#define OV5_LPAR 0x80 /* logical partitioning supported */ 687#define OV5_LPAR 0x80 /* logical partitioning supported */
685#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */ 688#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
@@ -701,6 +704,8 @@ static void __init early_cmdline_parse(void)
701#define OV5_XCMO 0x00 704#define OV5_XCMO 0x00
702#endif 705#endif
703#define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */ 706#define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */
707#define OV5_PFO_HW_RNG 0x80 /* PFO Random Number Generator */
708#define OV5_PFO_HW_ENCR 0x20 /* PFO Encryption Accelerator */
704 709
705/* Option Vector 6: IBM PAPR hints */ 710/* Option Vector 6: IBM PAPR hints */
706#define OV6_LINUX 0x02 /* Linux is our OS */ 711#define OV6_LINUX 0x02 /* Linux is our OS */
@@ -744,11 +749,12 @@ static unsigned char ibm_architecture_vec[] = {
744 OV3_FP | OV3_VMX | OV3_DFP, 749 OV3_FP | OV3_VMX | OV3_DFP,
745 750
746 /* option vector 4: IBM PAPR implementation */ 751 /* option vector 4: IBM PAPR implementation */
747 2 - 2, /* length */ 752 3 - 2, /* length */
748 0, /* don't halt */ 753 0, /* don't halt */
754 OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
749 755
750 /* option vector 5: PAPR/OF options */ 756 /* option vector 5: PAPR/OF options */
751 13 - 2, /* length */ 757 18 - 2, /* length */
752 0, /* don't ignore, don't halt */ 758 0, /* don't ignore, don't halt */
753 OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | 759 OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY |
754 OV5_DONATE_DEDICATE_CPU | OV5_MSI, 760 OV5_DONATE_DEDICATE_CPU | OV5_MSI,
@@ -762,8 +768,13 @@ static unsigned char ibm_architecture_vec[] = {
762 * must match by the macro below. Update the definition if 768 * must match by the macro below. Update the definition if
763 * the structure layout changes. 769 * the structure layout changes.
764 */ 770 */
765#define IBM_ARCH_VEC_NRCORES_OFFSET 100 771#define IBM_ARCH_VEC_NRCORES_OFFSET 101
766 W(NR_CPUS), /* number of cores supported */ 772 W(NR_CPUS), /* number of cores supported */
773 0,
774 0,
775 0,
776 0,
777 OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR,
767 778
768 /* option vector 6: IBM PAPR hints */ 779 /* option vector 6: IBM PAPR hints */
769 4 - 2, /* length */ 780 4 - 2, /* length */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index dd5e214cdf21..c10fc28b9092 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1432,40 +1432,6 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
1432#endif 1432#endif
1433} 1433}
1434 1434
1435/*
1436 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
1437 * we mark them as obsolete now, they will be removed in a future version
1438 */
1439static long arch_ptrace_old(struct task_struct *child, long request,
1440 unsigned long addr, unsigned long data)
1441{
1442 void __user *datavp = (void __user *) data;
1443
1444 switch (request) {
1445 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
1446 return copy_regset_to_user(child, &user_ppc_native_view,
1447 REGSET_GPR, 0, 32 * sizeof(long),
1448 datavp);
1449
1450 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
1451 return copy_regset_from_user(child, &user_ppc_native_view,
1452 REGSET_GPR, 0, 32 * sizeof(long),
1453 datavp);
1454
1455 case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
1456 return copy_regset_to_user(child, &user_ppc_native_view,
1457 REGSET_FPR, 0, 32 * sizeof(double),
1458 datavp);
1459
1460 case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */
1461 return copy_regset_from_user(child, &user_ppc_native_view,
1462 REGSET_FPR, 0, 32 * sizeof(double),
1463 datavp);
1464 }
1465
1466 return -EPERM;
1467}
1468
1469long arch_ptrace(struct task_struct *child, long request, 1435long arch_ptrace(struct task_struct *child, long request,
1470 unsigned long addr, unsigned long data) 1436 unsigned long addr, unsigned long data)
1471{ 1437{
@@ -1687,14 +1653,6 @@ long arch_ptrace(struct task_struct *child, long request,
1687 datavp); 1653 datavp);
1688#endif 1654#endif
1689 1655
1690 /* Old reverse args ptrace callss */
1691 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
1692 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
1693 case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
1694 case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */
1695 ret = arch_ptrace_old(child, request, addr, data);
1696 break;
1697
1698 default: 1656 default:
1699 ret = ptrace_request(child, request, addr, data); 1657 ret = ptrace_request(child, request, addr, data);
1700 break; 1658 break;
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 469349d14a97..8c21658719d9 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -39,30 +39,6 @@
39 * in exit.c or in signal.c. 39 * in exit.c or in signal.c.
40 */ 40 */
41 41
42/*
43 * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
44 * we mark them as obsolete now, they will be removed in a future version
45 */
46static long compat_ptrace_old(struct task_struct *child, long request,
47 long addr, long data)
48{
49 switch (request) {
50 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
51 return copy_regset_to_user(child,
52 task_user_regset_view(current), 0,
53 0, 32 * sizeof(compat_long_t),
54 compat_ptr(data));
55
56 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
57 return copy_regset_from_user(child,
58 task_user_regset_view(current), 0,
59 0, 32 * sizeof(compat_long_t),
60 compat_ptr(data));
61 }
62
63 return -EPERM;
64}
65
66/* Macros to workout the correct index for the FPR in the thread struct */ 42/* Macros to workout the correct index for the FPR in the thread struct */
67#define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) 43#define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
68#define FPRHALF(i) (((i) - PT_FPR0) & 1) 44#define FPRHALF(i) (((i) - PT_FPR0) & 1)
@@ -308,8 +284,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
308 case PTRACE_SETVSRREGS: 284 case PTRACE_SETVSRREGS:
309 case PTRACE_GETREGS64: 285 case PTRACE_GETREGS64:
310 case PTRACE_SETREGS64: 286 case PTRACE_SETREGS64:
311 case PPC_PTRACE_GETFPREGS:
312 case PPC_PTRACE_SETFPREGS:
313 case PTRACE_KILL: 287 case PTRACE_KILL:
314 case PTRACE_SINGLESTEP: 288 case PTRACE_SINGLESTEP:
315 case PTRACE_DETACH: 289 case PTRACE_DETACH:
@@ -322,12 +296,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
322 ret = arch_ptrace(child, request, addr, data); 296 ret = arch_ptrace(child, request, addr, data);
323 break; 297 break;
324 298
325 /* Old reverse args ptrace callss */
326 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
327 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
328 ret = compat_ptrace_old(child, request, addr, data);
329 break;
330
331 default: 299 default:
332 ret = compat_ptrace_request(child, request, addr, data); 300 ret = compat_ptrace_request(child, request, addr, data);
333 break; 301 break;
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 4d5a3edff49e..e830289d2e48 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -89,6 +89,16 @@ _GLOBAL(load_up_altivec)
89 /* restore registers and return */ 89 /* restore registers and return */
90 blr 90 blr
91 91
92_GLOBAL(giveup_altivec_notask)
93 mfmsr r3
94 andis. r4,r3,MSR_VEC@h
95 bnelr /* Already enabled? */
96 oris r3,r3,MSR_VEC@h
97 SYNC
98 MTMSRD(r3) /* enable use of VMX now */
99 isync
100 blr
101
92/* 102/*
93 * giveup_altivec(tsk) 103 * giveup_altivec(tsk)
94 * Disable VMX for the task given as the argument, 104 * Disable VMX for the task given as the argument,
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index a3a99901c8ec..cb87301ccd55 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -14,7 +14,9 @@
14 * 2 of the License, or (at your option) any later version. 14 * 2 of the License, or (at your option) any later version.
15 */ 15 */
16 16
17#include <linux/cpu.h>
17#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/delay.h>
18#include <linux/stat.h> 20#include <linux/stat.h>
19#include <linux/device.h> 21#include <linux/device.h>
20#include <linux/init.h> 22#include <linux/init.h>
@@ -709,13 +711,26 @@ static int vio_cmo_bus_probe(struct vio_dev *viodev)
709 struct vio_driver *viodrv = to_vio_driver(dev->driver); 711 struct vio_driver *viodrv = to_vio_driver(dev->driver);
710 unsigned long flags; 712 unsigned long flags;
711 size_t size; 713 size_t size;
714 bool dma_capable = false;
715
716 /* A device requires entitlement if it has a DMA window property */
717 switch (viodev->family) {
718 case VDEVICE:
719 if (of_get_property(viodev->dev.of_node,
720 "ibm,my-dma-window", NULL))
721 dma_capable = true;
722 break;
723 case PFO:
724 dma_capable = false;
725 break;
726 default:
727 dev_warn(dev, "unknown device family: %d\n", viodev->family);
728 BUG();
729 break;
730 }
712 731
713 /* 732 /* Configure entitlement for the device. */
714 * Check to see that device has a DMA window and configure 733 if (dma_capable) {
715 * entitlement for the device.
716 */
717 if (of_get_property(viodev->dev.of_node,
718 "ibm,my-dma-window", NULL)) {
719 /* Check that the driver is CMO enabled and get desired DMA */ 734 /* Check that the driver is CMO enabled and get desired DMA */
720 if (!viodrv->get_desired_dma) { 735 if (!viodrv->get_desired_dma) {
721 dev_err(dev, "%s: device driver does not support CMO\n", 736 dev_err(dev, "%s: device driver does not support CMO\n",
@@ -1050,6 +1065,94 @@ static void vio_cmo_sysfs_init(void) { }
1050EXPORT_SYMBOL(vio_cmo_entitlement_update); 1065EXPORT_SYMBOL(vio_cmo_entitlement_update);
1051EXPORT_SYMBOL(vio_cmo_set_dev_desired); 1066EXPORT_SYMBOL(vio_cmo_set_dev_desired);
1052 1067
1068
1069/*
1070 * Platform Facilities Option (PFO) support
1071 */
1072
1073/**
1074 * vio_h_cop_sync - Perform a synchronous PFO co-processor operation
1075 *
1076 * @vdev - Pointer to a struct vio_dev for device
1077 * @op - Pointer to a struct vio_pfo_op for the operation parameters
1078 *
1079 * Calls the hypervisor to synchronously perform the PFO operation
1080 * described in @op. In the case of a busy response from the hypervisor,
1081 * the operation will be re-submitted indefinitely unless a non-zero timeout
1082 * is specified or an error occurs. The timeout places a limit on when to
1083 * stop re-submitting a operation, the total time can be exceeded if an
1084 * operation is in progress.
1085 *
1086 * If op->hcall_ret is not NULL, this will be set to the return from the
1087 * last h_cop_op call or it will be 0 if an error not involving the h_call
1088 * was encountered.
1089 *
1090 * Returns:
1091 * 0 on success,
1092 * -EINVAL if the h_call fails due to an invalid parameter,
1093 * -E2BIG if the h_call can not be performed synchronously,
1094 * -EBUSY if a timeout is specified and has elapsed,
1095 * -EACCES if the memory area for data/status has been rescinded, or
1096 * -EPERM if a hardware fault has been indicated
1097 */
1098int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op)
1099{
1100 struct device *dev = &vdev->dev;
1101 unsigned long deadline = 0;
1102 long hret = 0;
1103 int ret = 0;
1104
1105 if (op->timeout)
1106 deadline = jiffies + msecs_to_jiffies(op->timeout);
1107
1108 while (true) {
1109 hret = plpar_hcall_norets(H_COP, op->flags,
1110 vdev->resource_id,
1111 op->in, op->inlen, op->out,
1112 op->outlen, op->csbcpb);
1113
1114 if (hret == H_SUCCESS ||
1115 (hret != H_NOT_ENOUGH_RESOURCES &&
1116 hret != H_BUSY && hret != H_RESOURCE) ||
1117 (op->timeout && time_after(deadline, jiffies)))
1118 break;
1119
1120 dev_dbg(dev, "%s: hcall ret(%ld), retrying.\n", __func__, hret);
1121 }
1122
1123 switch (hret) {
1124 case H_SUCCESS:
1125 ret = 0;
1126 break;
1127 case H_OP_MODE:
1128 case H_TOO_BIG:
1129 ret = -E2BIG;
1130 break;
1131 case H_RESCINDED:
1132 ret = -EACCES;
1133 break;
1134 case H_HARDWARE:
1135 ret = -EPERM;
1136 break;
1137 case H_NOT_ENOUGH_RESOURCES:
1138 case H_RESOURCE:
1139 case H_BUSY:
1140 ret = -EBUSY;
1141 break;
1142 default:
1143 ret = -EINVAL;
1144 break;
1145 }
1146
1147 if (ret)
1148 dev_dbg(dev, "%s: Sync h_cop_op failure (ret:%d) (hret:%ld)\n",
1149 __func__, ret, hret);
1150
1151 op->hcall_err = hret;
1152 return ret;
1153}
1154EXPORT_SYMBOL(vio_h_cop_sync);
1155
1053static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) 1156static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
1054{ 1157{
1055 const unsigned char *dma_window; 1158 const unsigned char *dma_window;
@@ -1211,35 +1314,87 @@ static void __devinit vio_dev_release(struct device *dev)
1211struct vio_dev *vio_register_device_node(struct device_node *of_node) 1314struct vio_dev *vio_register_device_node(struct device_node *of_node)
1212{ 1315{
1213 struct vio_dev *viodev; 1316 struct vio_dev *viodev;
1317 struct device_node *parent_node;
1214 const unsigned int *unit_address; 1318 const unsigned int *unit_address;
1319 const unsigned int *pfo_resid = NULL;
1320 enum vio_dev_family family;
1321 const char *of_node_name = of_node->name ? of_node->name : "<unknown>";
1215 1322
1216 /* we need the 'device_type' property, in order to match with drivers */ 1323 /*
1217 if (of_node->type == NULL) { 1324 * Determine if this node is a under the /vdevice node or under the
1218 printk(KERN_WARNING "%s: node %s missing 'device_type'\n", 1325 * /ibm,platform-facilities node. This decides the device's family.
1219 __func__, 1326 */
1220 of_node->name ? of_node->name : "<unknown>"); 1327 parent_node = of_get_parent(of_node);
1328 if (parent_node) {
1329 if (!strcmp(parent_node->full_name, "/ibm,platform-facilities"))
1330 family = PFO;
1331 else if (!strcmp(parent_node->full_name, "/vdevice"))
1332 family = VDEVICE;
1333 else {
1334 pr_warn("%s: parent(%s) of %s not recognized.\n",
1335 __func__,
1336 parent_node->full_name,
1337 of_node_name);
1338 of_node_put(parent_node);
1339 return NULL;
1340 }
1341 of_node_put(parent_node);
1342 } else {
1343 pr_warn("%s: could not determine the parent of node %s.\n",
1344 __func__, of_node_name);
1221 return NULL; 1345 return NULL;
1222 } 1346 }
1223 1347
1224 unit_address = of_get_property(of_node, "reg", NULL); 1348 if (family == PFO) {
1225 if (unit_address == NULL) { 1349 if (of_get_property(of_node, "interrupt-controller", NULL)) {
1226 printk(KERN_WARNING "%s: node %s missing 'reg'\n", 1350 pr_debug("%s: Skipping the interrupt controller %s.\n",
1227 __func__, 1351 __func__, of_node_name);
1228 of_node->name ? of_node->name : "<unknown>"); 1352 return NULL;
1229 return NULL; 1353 }
1230 } 1354 }
1231 1355
1232 /* allocate a vio_dev for this node */ 1356 /* allocate a vio_dev for this node */
1233 viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL); 1357 viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
1234 if (viodev == NULL) 1358 if (viodev == NULL) {
1359 pr_warn("%s: allocation failure for VIO device.\n", __func__);
1235 return NULL; 1360 return NULL;
1361 }
1236 1362
1237 viodev->irq = irq_of_parse_and_map(of_node, 0); 1363 /* we need the 'device_type' property, in order to match with drivers */
1364 viodev->family = family;
1365 if (viodev->family == VDEVICE) {
1366 if (of_node->type != NULL)
1367 viodev->type = of_node->type;
1368 else {
1369 pr_warn("%s: node %s is missing the 'device_type' "
1370 "property.\n", __func__, of_node_name);
1371 goto out;
1372 }
1373
1374 unit_address = of_get_property(of_node, "reg", NULL);
1375 if (unit_address == NULL) {
1376 pr_warn("%s: node %s missing 'reg'\n",
1377 __func__, of_node_name);
1378 goto out;
1379 }
1380 dev_set_name(&viodev->dev, "%x", *unit_address);
1381 viodev->irq = irq_of_parse_and_map(of_node, 0);
1382 viodev->unit_address = *unit_address;
1383 } else {
1384 /* PFO devices need their resource_id for submitting COP_OPs
1385 * This is an optional field for devices, but is required when
1386 * performing synchronous ops */
1387 pfo_resid = of_get_property(of_node, "ibm,resource-id", NULL);
1388 if (pfo_resid != NULL)
1389 viodev->resource_id = *pfo_resid;
1390
1391 unit_address = NULL;
1392 dev_set_name(&viodev->dev, "%s", of_node_name);
1393 viodev->type = of_node_name;
1394 viodev->irq = 0;
1395 }
1238 1396
1239 dev_set_name(&viodev->dev, "%x", *unit_address);
1240 viodev->name = of_node->name; 1397 viodev->name = of_node->name;
1241 viodev->type = of_node->type;
1242 viodev->unit_address = *unit_address;
1243 viodev->dev.of_node = of_node_get(of_node); 1398 viodev->dev.of_node = of_node_get(of_node);
1244 1399
1245 if (firmware_has_feature(FW_FEATURE_CMO)) 1400 if (firmware_has_feature(FW_FEATURE_CMO))
@@ -1267,16 +1422,51 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
1267 } 1422 }
1268 1423
1269 return viodev; 1424 return viodev;
1425
1426out: /* Use this exit point for any return prior to device_register */
1427 kfree(viodev);
1428
1429 return NULL;
1270} 1430}
1271EXPORT_SYMBOL(vio_register_device_node); 1431EXPORT_SYMBOL(vio_register_device_node);
1272 1432
1433/*
1434 * vio_bus_scan_for_devices - Scan OF and register each child device
1435 * @root_name - OF node name for the root of the subtree to search.
1436 * This must be non-NULL
1437 *
1438 * Starting from the root node provide, register the device node for
1439 * each child beneath the root.
1440 */
1441static void vio_bus_scan_register_devices(char *root_name)
1442{
1443 struct device_node *node_root, *node_child;
1444
1445 if (!root_name)
1446 return;
1447
1448 node_root = of_find_node_by_name(NULL, root_name);
1449 if (node_root) {
1450
1451 /*
1452 * Create struct vio_devices for each virtual device in
1453 * the device tree. Drivers will associate with them later.
1454 */
1455 node_child = of_get_next_child(node_root, NULL);
1456 while (node_child) {
1457 vio_register_device_node(node_child);
1458 node_child = of_get_next_child(node_root, node_child);
1459 }
1460 of_node_put(node_root);
1461 }
1462}
1463
1273/** 1464/**
1274 * vio_bus_init: - Initialize the virtual IO bus 1465 * vio_bus_init: - Initialize the virtual IO bus
1275 */ 1466 */
1276static int __init vio_bus_init(void) 1467static int __init vio_bus_init(void)
1277{ 1468{
1278 int err; 1469 int err;
1279 struct device_node *node_vroot;
1280 1470
1281 if (firmware_has_feature(FW_FEATURE_CMO)) 1471 if (firmware_has_feature(FW_FEATURE_CMO))
1282 vio_cmo_sysfs_init(); 1472 vio_cmo_sysfs_init();
@@ -1301,19 +1491,8 @@ static int __init vio_bus_init(void)
1301 if (firmware_has_feature(FW_FEATURE_CMO)) 1491 if (firmware_has_feature(FW_FEATURE_CMO))
1302 vio_cmo_bus_init(); 1492 vio_cmo_bus_init();
1303 1493
1304 node_vroot = of_find_node_by_name(NULL, "vdevice"); 1494 vio_bus_scan_register_devices("vdevice");
1305 if (node_vroot) { 1495 vio_bus_scan_register_devices("ibm,platform-facilities");
1306 struct device_node *of_node;
1307
1308 /*
1309 * Create struct vio_devices for each virtual device in
1310 * the device tree. Drivers will associate with them later.
1311 */
1312 for (of_node = node_vroot->child; of_node != NULL;
1313 of_node = of_node->sibling)
1314 vio_register_device_node(of_node);
1315 of_node_put(node_vroot);
1316 }
1317 1496
1318 return 0; 1497 return 0;
1319} 1498}
@@ -1436,12 +1615,28 @@ struct vio_dev *vio_find_node(struct device_node *vnode)
1436{ 1615{
1437 const uint32_t *unit_address; 1616 const uint32_t *unit_address;
1438 char kobj_name[20]; 1617 char kobj_name[20];
1618 struct device_node *vnode_parent;
1619 const char *dev_type;
1620
1621 vnode_parent = of_get_parent(vnode);
1622 if (!vnode_parent)
1623 return NULL;
1624
1625 dev_type = of_get_property(vnode_parent, "device_type", NULL);
1626 of_node_put(vnode_parent);
1627 if (!dev_type)
1628 return NULL;
1439 1629
1440 /* construct the kobject name from the device node */ 1630 /* construct the kobject name from the device node */
1441 unit_address = of_get_property(vnode, "reg", NULL); 1631 if (!strcmp(dev_type, "vdevice")) {
1442 if (!unit_address) 1632 unit_address = of_get_property(vnode, "reg", NULL);
1633 if (!unit_address)
1634 return NULL;
1635 snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address);
1636 } else if (!strcmp(dev_type, "ibm,platform-facilities"))
1637 snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name);
1638 else
1443 return NULL; 1639 return NULL;
1444 snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address);
1445 1640
1446 return vio_find_name(kobj_name); 1641 return vio_find_name(kobj_name);
1447} 1642}
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
index 773d38f90aaa..d73a59014900 100644
--- a/arch/powerpc/lib/copyuser_64.S
+++ b/arch/powerpc/lib/copyuser_64.S
@@ -30,7 +30,7 @@ _GLOBAL(__copy_tofrom_user_base)
30 dcbt 0,r4 30 dcbt 0,r4
31 beq .Lcopy_page_4K 31 beq .Lcopy_page_4K
32 andi. r6,r6,7 32 andi. r6,r6,7
33 PPC_MTOCRF 0x01,r5 33 PPC_MTOCRF(0x01,r5)
34 blt cr1,.Lshort_copy 34 blt cr1,.Lshort_copy
35/* Below we want to nop out the bne if we're on a CPU that has the 35/* Below we want to nop out the bne if we're on a CPU that has the
36 * CPU_FTR_UNALIGNED_LD_STD bit set and the CPU_FTR_CP_USE_DCBTZ bit 36 * CPU_FTR_UNALIGNED_LD_STD bit set and the CPU_FTR_CP_USE_DCBTZ bit
@@ -186,7 +186,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
186 blr 186 blr
187 187
188.Ldst_unaligned: 188.Ldst_unaligned:
189 PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */ 189 PPC_MTOCRF(0x01,r6) /* put #bytes to 8B bdry into cr7 */
190 subf r5,r6,r5 190 subf r5,r6,r5
191 li r7,0 191 li r7,0
192 cmpldi cr1,r5,16 192 cmpldi cr1,r5,16
@@ -201,7 +201,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
2012: bf cr7*4+1,3f 2012: bf cr7*4+1,3f
20237: lwzx r0,r7,r4 20237: lwzx r0,r7,r4
20383: stwx r0,r7,r3 20383: stwx r0,r7,r3
2043: PPC_MTOCRF 0x01,r5 2043: PPC_MTOCRF(0x01,r5)
205 add r4,r6,r4 205 add r4,r6,r4
206 add r3,r6,r3 206 add r3,r6,r3
207 b .Ldst_aligned 207 b .Ldst_aligned
diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S
index 11ce045e21fd..f4fcb0bc6563 100644
--- a/arch/powerpc/lib/mem_64.S
+++ b/arch/powerpc/lib/mem_64.S
@@ -19,7 +19,7 @@ _GLOBAL(memset)
19 rlwimi r4,r4,16,0,15 19 rlwimi r4,r4,16,0,15
20 cmplw cr1,r5,r0 /* do we get that far? */ 20 cmplw cr1,r5,r0 /* do we get that far? */
21 rldimi r4,r4,32,0 21 rldimi r4,r4,32,0
22 PPC_MTOCRF 1,r0 22 PPC_MTOCRF(1,r0)
23 mr r6,r3 23 mr r6,r3
24 blt cr1,8f 24 blt cr1,8f
25 beq+ 3f /* if already 8-byte aligned */ 25 beq+ 3f /* if already 8-byte aligned */
@@ -49,7 +49,7 @@ _GLOBAL(memset)
49 bdnz 4b 49 bdnz 4b
505: srwi. r0,r5,3 505: srwi. r0,r5,3
51 clrlwi r5,r5,29 51 clrlwi r5,r5,29
52 PPC_MTOCRF 1,r0 52 PPC_MTOCRF(1,r0)
53 beq 8f 53 beq 8f
54 bf 29,6f 54 bf 29,6f
55 std r4,0(r6) 55 std r4,0(r6)
@@ -65,7 +65,7 @@ _GLOBAL(memset)
65 std r4,0(r6) 65 std r4,0(r6)
66 addi r6,r6,8 66 addi r6,r6,8
678: cmpwi r5,0 678: cmpwi r5,0
68 PPC_MTOCRF 1,r5 68 PPC_MTOCRF(1,r5)
69 beqlr+ 69 beqlr+
70 bf 29,9f 70 bf 29,9f
71 stw r4,0(r6) 71 stw r4,0(r6)
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
index e178922b2c21..82fea3963e15 100644
--- a/arch/powerpc/lib/memcpy_64.S
+++ b/arch/powerpc/lib/memcpy_64.S
@@ -12,7 +12,7 @@
12 .align 7 12 .align 7
13_GLOBAL(memcpy) 13_GLOBAL(memcpy)
14 std r3,48(r1) /* save destination pointer for return value */ 14 std r3,48(r1) /* save destination pointer for return value */
15 PPC_MTOCRF 0x01,r5 15 PPC_MTOCRF(0x01,r5)
16 cmpldi cr1,r5,16 16 cmpldi cr1,r5,16
17 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry 17 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
18 andi. r6,r6,7 18 andi. r6,r6,7
@@ -154,7 +154,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
154 blr 154 blr
155 155
156.Ldst_unaligned: 156.Ldst_unaligned:
157 PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7 157 PPC_MTOCRF(0x01,r6) # put #bytes to 8B bdry into cr7
158 subf r5,r6,r5 158 subf r5,r6,r5
159 li r7,0 159 li r7,0
160 cmpldi cr1,r5,16 160 cmpldi cr1,r5,16
@@ -169,7 +169,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
1692: bf cr7*4+1,3f 1692: bf cr7*4+1,3f
170 lwzx r0,r7,r4 170 lwzx r0,r7,r4
171 stwx r0,r7,r3 171 stwx r0,r7,r3
1723: PPC_MTOCRF 0x01,r5 1723: PPC_MTOCRF(0x01,r5)
173 add r4,r6,r4 173 add r4,r6,r4
174 add r3,r6,r3 174 add r3,r6,r3
175 b .Ldst_aligned 175 b .Ldst_aligned
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 2e4e64abfab4..8abf6fb8f410 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -23,6 +23,8 @@ config BLUESTONE
23 default n 23 default n
24 select PPC44x_SIMPLE 24 select PPC44x_SIMPLE
25 select APM821xx 25 select APM821xx
26 select PCI_MSI
27 select PPC4xx_MSI
26 select PPC4xx_PCI_EXPRESS 28 select PPC4xx_PCI_EXPRESS
27 select IBM_EMAC_RGMII 29 select IBM_EMAC_RGMII
28 help 30 help
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 9c80fc07384a..61c9550819a2 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -78,6 +78,36 @@ config PPC_BOOK3E_64
78 78
79endchoice 79endchoice
80 80
81choice
82 prompt "CPU selection"
83 depends on PPC64
84 default GENERIC_CPU
85 help
86 This will create a kernel which is optimised for a particular CPU.
87 The resulting kernel may not run on other CPUs, so use this with care.
88
89 If unsure, select Generic.
90
91config GENERIC_CPU
92 bool "Generic"
93
94config CELL_CPU
95 bool "Cell Broadband Engine"
96
97config POWER4_CPU
98 bool "POWER4"
99
100config POWER5_CPU
101 bool "POWER5"
102
103config POWER6_CPU
104 bool "POWER6"
105
106config POWER7_CPU
107 bool "POWER7"
108
109endchoice
110
81config PPC_BOOK3S 111config PPC_BOOK3S
82 def_bool y 112 def_bool y
83 depends on PPC_BOOK3S_32 || PPC_BOOK3S_64 113 depends on PPC_BOOK3S_32 || PPC_BOOK3S_64
@@ -86,15 +116,6 @@ config PPC_BOOK3E
86 def_bool y 116 def_bool y
87 depends on PPC_BOOK3E_64 117 depends on PPC_BOOK3E_64
88 118
89config POWER4_ONLY
90 bool "Optimize for POWER4"
91 depends on PPC64 && PPC_BOOK3S
92 default n
93 ---help---
94 Cause the compiler to optimize for POWER4/POWER5/PPC970 processors.
95 The resulting binary will not work on POWER3 or RS64 processors
96 when compiled with binutils 2.15 or later.
97
98config 6xx 119config 6xx
99 def_bool y 120 def_bool y
100 depends on PPC32 && PPC_BOOK3S 121 depends on PPC32 && PPC_BOOK3S
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 03685a329d7d..fc536f2971c0 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1503,6 +1503,7 @@ static int __init pmac_i2c_create_platform_devices(void)
1503 if (bus->platform_dev == NULL) 1503 if (bus->platform_dev == NULL)
1504 return -ENOMEM; 1504 return -ENOMEM;
1505 bus->platform_dev->dev.platform_data = bus; 1505 bus->platform_dev->dev.platform_data = bus;
1506 bus->platform_dev->dev.of_node = bus->busnode;
1506 platform_device_add(bus->platform_dev); 1507 platform_device_add(bus->platform_dev);
1507 } 1508 }
1508 1509
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index 476d9d9b2405..46b7f0232523 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -7,7 +7,6 @@ config PPC_PS3
7 select USB_OHCI_BIG_ENDIAN_MMIO 7 select USB_OHCI_BIG_ENDIAN_MMIO
8 select USB_ARCH_HAS_EHCI 8 select USB_ARCH_HAS_EHCI
9 select USB_EHCI_BIG_ENDIAN_MMIO 9 select USB_EHCI_BIG_ENDIAN_MMIO
10 select MEMORY_HOTPLUG
11 select PPC_PCI_CHOICE 10 select PPC_PCI_CHOICE
12 help 11 help
13 This option enables support for the Sony PS3 game console 12 This option enables support for the Sony PS3 game console
@@ -74,7 +73,7 @@ config PS3_PS3AV
74 help 73 help
75 Include support for the PS3 AV Settings driver. 74 Include support for the PS3 AV Settings driver.
76 75
77 This support is required for graphics and sound. In 76 This support is required for PS3 graphics and sound. In
78 general, all users will say Y or M. 77 general, all users will say Y or M.
79 78
80config PS3_SYS_MANAGER 79config PS3_SYS_MANAGER
@@ -85,9 +84,22 @@ config PS3_SYS_MANAGER
85 help 84 help
86 Include support for the PS3 System Manager. 85 Include support for the PS3 System Manager.
87 86
88 This support is required for system control. In 87 This support is required for PS3 system control. In
89 general, all users will say Y or M. 88 general, all users will say Y or M.
90 89
90config PS3_REPOSITORY_WRITE
91 bool "PS3 Repository write support" if PS3_ADVANCED
92 depends on PPC_PS3
93 default n
94 help
95 Enables support for writing to the PS3 System Repository.
96
97 This support is intended for bootloaders that need to store data
98 in the repository for later boot stages.
99
100 If in doubt, say N here and reduce the size of the kernel by a
101 small amount.
102
91config PS3_STORAGE 103config PS3_STORAGE
92 depends on PPC_PS3 104 depends on PPC_PS3
93 tristate 105 tristate
@@ -122,7 +134,7 @@ config PS3_FLASH
122 134
123 This support is required to access the PS3 FLASH ROM, which 135 This support is required to access the PS3 FLASH ROM, which
124 contains the boot loader and some boot options. 136 contains the boot loader and some boot options.
125 In general, all users will say Y or M. 137 In general, PS3 OtherOS users will say Y or M.
126 138
127 As this driver needs a fixed buffer of 256 KiB of memory, it can 139 As this driver needs a fixed buffer of 256 KiB of memory, it can
128 be disabled on the kernel command line using "ps3flash=off", to 140 be disabled on the kernel command line using "ps3flash=off", to
@@ -156,7 +168,7 @@ config PS3GELIC_UDBG
156 via the Ethernet port (UDP port number 18194). 168 via the Ethernet port (UDP port number 18194).
157 169
158 This driver uses a trivial implementation and is independent 170 This driver uses a trivial implementation and is independent
159 from the main network driver. 171 from the main PS3 gelic network driver.
160 172
161 If in doubt, say N here. 173 If in doubt, say N here.
162 174
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index de2aea421707..0c9f643d9e2a 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -20,7 +20,6 @@
20 20
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/export.h> 22#include <linux/export.h>
23#include <linux/memory_hotplug.h>
24#include <linux/memblock.h> 23#include <linux/memblock.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
26 25
@@ -79,12 +78,14 @@ enum {
79 * @base: base address 78 * @base: base address
80 * @size: size in bytes 79 * @size: size in bytes
81 * @offset: difference between base and rm.size 80 * @offset: difference between base and rm.size
81 * @destroy: flag if region should be destroyed upon shutdown
82 */ 82 */
83 83
84struct mem_region { 84struct mem_region {
85 u64 base; 85 u64 base;
86 u64 size; 86 u64 size;
87 unsigned long offset; 87 unsigned long offset;
88 int destroy;
88}; 89};
89 90
90/** 91/**
@@ -96,7 +97,7 @@ struct mem_region {
96 * The HV virtual address space (vas) allows for hotplug memory regions. 97 * The HV virtual address space (vas) allows for hotplug memory regions.
97 * Memory regions can be created and destroyed in the vas at runtime. 98 * Memory regions can be created and destroyed in the vas at runtime.
98 * @rm: real mode (bootmem) region 99 * @rm: real mode (bootmem) region
99 * @r1: hotplug memory region(s) 100 * @r1: highmem region(s)
100 * 101 *
101 * ps3 addresses 102 * ps3 addresses
102 * virt_addr: a cpu 'translated' effective address 103 * virt_addr: a cpu 'translated' effective address
@@ -222,10 +223,6 @@ void ps3_mm_vas_destroy(void)
222 } 223 }
223} 224}
224 225
225/*============================================================================*/
226/* memory hotplug routines */
227/*============================================================================*/
228
229/** 226/**
230 * ps3_mm_region_create - create a memory region in the vas 227 * ps3_mm_region_create - create a memory region in the vas
231 * @r: pointer to a struct mem_region to accept initialized values 228 * @r: pointer to a struct mem_region to accept initialized values
@@ -262,6 +259,7 @@ static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
262 goto zero_region; 259 goto zero_region;
263 } 260 }
264 261
262 r->destroy = 1;
265 r->offset = r->base - map.rm.size; 263 r->offset = r->base - map.rm.size;
266 return result; 264 return result;
267 265
@@ -279,7 +277,14 @@ static void ps3_mm_region_destroy(struct mem_region *r)
279{ 277{
280 int result; 278 int result;
281 279
280 if (!r->destroy) {
281 pr_info("%s:%d: Not destroying high region: %llxh %llxh\n",
282 __func__, __LINE__, r->base, r->size);
283 return;
284 }
285
282 DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base); 286 DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
287
283 if (r->base) { 288 if (r->base) {
284 result = lv1_release_memory(r->base); 289 result = lv1_release_memory(r->base);
285 BUG_ON(result); 290 BUG_ON(result);
@@ -288,50 +293,36 @@ static void ps3_mm_region_destroy(struct mem_region *r)
288 } 293 }
289} 294}
290 295
291/** 296static int ps3_mm_get_repository_highmem(struct mem_region *r)
292 * ps3_mm_add_memory - hot add memory
293 */
294
295static int __init ps3_mm_add_memory(void)
296{ 297{
297 int result; 298 int result;
298 unsigned long start_addr;
299 unsigned long start_pfn;
300 unsigned long nr_pages;
301
302 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
303 return -ENODEV;
304 299
305 BUG_ON(!mem_init_done); 300 /* Assume a single highmem region. */
306 301
307 start_addr = map.rm.size; 302 result = ps3_repository_read_highmem_info(0, &r->base, &r->size);
308 start_pfn = start_addr >> PAGE_SHIFT;
309 nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
310 303
311 DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n", 304 if (result)
312 __func__, __LINE__, start_addr, start_pfn, nr_pages); 305 goto zero_region;
313
314 result = add_memory(0, start_addr, map.r1.size);
315 306
316 if (result) { 307 if (!r->base || !r->size) {
317 pr_err("%s:%d: add_memory failed: (%d)\n", 308 result = -1;
318 __func__, __LINE__, result); 309 goto zero_region;
319 return result;
320 } 310 }
321 311
322 memblock_add(start_addr, map.r1.size); 312 r->offset = r->base - map.rm.size;
323 313
324 result = online_pages(start_pfn, nr_pages); 314 DBG("%s:%d: Found high region in repository: %llxh %llxh\n",
315 __func__, __LINE__, r->base, r->size);
325 316
326 if (result) 317 return 0;
327 pr_err("%s:%d: online_pages failed: (%d)\n",
328 __func__, __LINE__, result);
329 318
319zero_region:
320 DBG("%s:%d: No high region in repository.\n", __func__, __LINE__);
321
322 r->size = r->base = r->offset = 0;
330 return result; 323 return result;
331} 324}
332 325
333device_initcall(ps3_mm_add_memory);
334
335/*============================================================================*/ 326/*============================================================================*/
336/* dma routines */ 327/* dma routines */
337/*============================================================================*/ 328/*============================================================================*/
@@ -1217,13 +1208,23 @@ void __init ps3_mm_init(void)
1217 BUG_ON(map.rm.base); 1208 BUG_ON(map.rm.base);
1218 BUG_ON(!map.rm.size); 1209 BUG_ON(!map.rm.size);
1219 1210
1211 /* Check if we got the highmem region from an earlier boot step */
1220 1212
1221 /* arrange to do this in ps3_mm_add_memory */ 1213 if (ps3_mm_get_repository_highmem(&map.r1))
1222 ps3_mm_region_create(&map.r1, map.total - map.rm.size); 1214 ps3_mm_region_create(&map.r1, map.total - map.rm.size);
1223 1215
1224 /* correct map.total for the real total amount of memory we use */ 1216 /* correct map.total for the real total amount of memory we use */
1225 map.total = map.rm.size + map.r1.size; 1217 map.total = map.rm.size + map.r1.size;
1226 1218
1219 if (!map.r1.size) {
1220 DBG("%s:%d: No highmem region found\n", __func__, __LINE__);
1221 } else {
1222 DBG("%s:%d: Adding highmem region: %llxh %llxh\n",
1223 __func__, __LINE__, map.rm.size,
1224 map.total - map.rm.size);
1225 memblock_add(map.rm.size, map.total - map.rm.size);
1226 }
1227
1227 DBG(" <- %s:%d\n", __func__, __LINE__); 1228 DBG(" <- %s:%d\n", __func__, __LINE__);
1228} 1229}
1229 1230
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 1a633ed0fe98..d71329a8e325 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -188,6 +188,22 @@ int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size);
188int ps3_repository_read_region_total(u64 *region_total); 188int ps3_repository_read_region_total(u64 *region_total);
189int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, 189int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size,
190 u64 *region_total); 190 u64 *region_total);
191int ps3_repository_read_highmem_region_count(unsigned int *region_count);
192int ps3_repository_read_highmem_base(unsigned int region_index,
193 u64 *highmem_base);
194int ps3_repository_read_highmem_size(unsigned int region_index,
195 u64 *highmem_size);
196int ps3_repository_read_highmem_info(unsigned int region_index,
197 u64 *highmem_base, u64 *highmem_size);
198
199int ps3_repository_write_highmem_region_count(unsigned int region_count);
200int ps3_repository_write_highmem_base(unsigned int region_index,
201 u64 highmem_base);
202int ps3_repository_write_highmem_size(unsigned int region_index,
203 u64 highmem_size);
204int ps3_repository_write_highmem_info(unsigned int region_index,
205 u64 highmem_base, u64 highmem_size);
206int ps3_repository_delete_highmem_info(unsigned int region_index);
191 207
192/* repository pme info */ 208/* repository pme info */
193 209
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index 7bdfea336f5e..9b47ba7a5de7 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -779,6 +779,72 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
779} 779}
780 780
781/** 781/**
782 * ps3_repository_read_highmem_region_count - Read the number of highmem regions
783 *
784 * Bootloaders must arrange the repository nodes such that regions are indexed
785 * with a region_index from 0 to region_count-1.
786 */
787
788int ps3_repository_read_highmem_region_count(unsigned int *region_count)
789{
790 int result;
791 u64 v1 = 0;
792
793 result = read_node(PS3_LPAR_ID_CURRENT,
794 make_first_field("highmem", 0),
795 make_field("region", 0),
796 make_field("count", 0),
797 0,
798 &v1, NULL);
799 *region_count = v1;
800 return result;
801}
802
803
804int ps3_repository_read_highmem_base(unsigned int region_index,
805 u64 *highmem_base)
806{
807 return read_node(PS3_LPAR_ID_CURRENT,
808 make_first_field("highmem", 0),
809 make_field("region", region_index),
810 make_field("base", 0),
811 0,
812 highmem_base, NULL);
813}
814
815int ps3_repository_read_highmem_size(unsigned int region_index,
816 u64 *highmem_size)
817{
818 return read_node(PS3_LPAR_ID_CURRENT,
819 make_first_field("highmem", 0),
820 make_field("region", region_index),
821 make_field("size", 0),
822 0,
823 highmem_size, NULL);
824}
825
826/**
827 * ps3_repository_read_highmem_info - Read high memory region info
828 * @region_index: Region index, {0,..,region_count-1}.
829 * @highmem_base: High memory base address.
830 * @highmem_size: High memory size.
831 *
832 * Bootloaders that preallocate highmem regions must place the
833 * region info into the repository at these well known nodes.
834 */
835
836int ps3_repository_read_highmem_info(unsigned int region_index,
837 u64 *highmem_base, u64 *highmem_size)
838{
839 int result;
840
841 *highmem_base = 0;
842 result = ps3_repository_read_highmem_base(region_index, highmem_base);
843 return result ? result
844 : ps3_repository_read_highmem_size(region_index, highmem_size);
845}
846
847/**
782 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. 848 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved.
783 * @num_spu: Number of physical spus. 849 * @num_spu: Number of physical spus.
784 */ 850 */
@@ -1002,6 +1068,138 @@ int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar,
1002 lpar, rights); 1068 lpar, rights);
1003} 1069}
1004 1070
1071#if defined(CONFIG_PS3_REPOSITORY_WRITE)
1072
1073static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1074{
1075 int result;
1076
1077 dump_node(0, n1, n2, n3, n4, v1, v2);
1078
1079 result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2);
1080
1081 if (result) {
1082 pr_devel("%s:%d: lv1_create_repository_node failed: %s\n",
1083 __func__, __LINE__, ps3_result(result));
1084 return -ENOENT;
1085 }
1086
1087 return 0;
1088}
1089
1090static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4)
1091{
1092 int result;
1093
1094 dump_node(0, n1, n2, n3, n4, 0, 0);
1095
1096 result = lv1_delete_repository_node(n1, n2, n3, n4);
1097
1098 if (result) {
1099 pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n",
1100 __func__, __LINE__, ps3_result(result));
1101 return -ENOENT;
1102 }
1103
1104 return 0;
1105}
1106
1107static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2)
1108{
1109 int result;
1110
1111 result = create_node(n1, n2, n3, n4, v1, v2);
1112
1113 if (!result)
1114 return 0;
1115
1116 result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2);
1117
1118 if (result) {
1119 pr_devel("%s:%d: lv1_write_repository_node failed: %s\n",
1120 __func__, __LINE__, ps3_result(result));
1121 return -ENOENT;
1122 }
1123
1124 return 0;
1125}
1126
1127int ps3_repository_write_highmem_region_count(unsigned int region_count)
1128{
1129 int result;
1130 u64 v1 = (u64)region_count;
1131
1132 result = write_node(
1133 make_first_field("highmem", 0),
1134 make_field("region", 0),
1135 make_field("count", 0),
1136 0,
1137 v1, 0);
1138 return result;
1139}
1140
1141int ps3_repository_write_highmem_base(unsigned int region_index,
1142 u64 highmem_base)
1143{
1144 return write_node(
1145 make_first_field("highmem", 0),
1146 make_field("region", region_index),
1147 make_field("base", 0),
1148 0,
1149 highmem_base, 0);
1150}
1151
1152int ps3_repository_write_highmem_size(unsigned int region_index,
1153 u64 highmem_size)
1154{
1155 return write_node(
1156 make_first_field("highmem", 0),
1157 make_field("region", region_index),
1158 make_field("size", 0),
1159 0,
1160 highmem_size, 0);
1161}
1162
1163int ps3_repository_write_highmem_info(unsigned int region_index,
1164 u64 highmem_base, u64 highmem_size)
1165{
1166 int result;
1167
1168 result = ps3_repository_write_highmem_base(region_index, highmem_base);
1169 return result ? result
1170 : ps3_repository_write_highmem_size(region_index, highmem_size);
1171}
1172
1173static int ps3_repository_delete_highmem_base(unsigned int region_index)
1174{
1175 return delete_node(
1176 make_first_field("highmem", 0),
1177 make_field("region", region_index),
1178 make_field("base", 0),
1179 0);
1180}
1181
1182static int ps3_repository_delete_highmem_size(unsigned int region_index)
1183{
1184 return delete_node(
1185 make_first_field("highmem", 0),
1186 make_field("region", region_index),
1187 make_field("size", 0),
1188 0);
1189}
1190
1191int ps3_repository_delete_highmem_info(unsigned int region_index)
1192{
1193 int result;
1194
1195 result = ps3_repository_delete_highmem_base(region_index);
1196 result += ps3_repository_delete_highmem_size(region_index);
1197
1198 return result ? -1 : 0;
1199}
1200
1201#endif /* defined(CONFIG_PS3_WRITE_REPOSITORY) */
1202
1005#if defined(DEBUG) 1203#if defined(DEBUG)
1006 1204
1007int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) 1205int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo)
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index a75e37dc41aa..ecd394cf34e6 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -489,7 +489,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
489 * a stack trace will help the device-driver authors figure 489 * a stack trace will help the device-driver authors figure
490 * out what happened. So print that out. 490 * out what happened. So print that out.
491 */ 491 */
492 dump_stack(); 492 WARN(1, "EEH: failure detected\n");
493 return 1; 493 return 1;
494 494
495dn_unlock: 495dn_unlock:
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 342797fc0f9c..13e8cc43adf7 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -22,12 +22,12 @@ static inline long poll_pending(void)
22 22
23static inline u8 get_cede_latency_hint(void) 23static inline u8 get_cede_latency_hint(void)
24{ 24{
25 return get_lppaca()->gpr5_dword.fields.cede_latency_hint; 25 return get_lppaca()->cede_latency_hint;
26} 26}
27 27
28static inline void set_cede_latency_hint(u8 latency_hint) 28static inline void set_cede_latency_hint(u8 latency_hint)
29{ 29{
30 get_lppaca()->gpr5_dword.fields.cede_latency_hint = latency_hint; 30 get_lppaca()->cede_latency_hint = latency_hint;
31} 31}
32 32
33static inline long cede_processor(void) 33static inline long cede_processor(void)
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 168651acdd83..7b3bf76ef834 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -103,11 +103,13 @@ int pSeries_reconfig_notifier_register(struct notifier_block *nb)
103{ 103{
104 return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); 104 return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
105} 105}
106EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
106 107
107void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) 108void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
108{ 109{
109 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); 110 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
110} 111}
112EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
111 113
112int pSeries_reconfig_notify(unsigned long action, void *p) 114int pSeries_reconfig_notify(unsigned long action, void *p)
113{ 115{
@@ -426,6 +428,7 @@ static int do_remove_property(char *buf, size_t bufsize)
426static int do_update_property(char *buf, size_t bufsize) 428static int do_update_property(char *buf, size_t bufsize)
427{ 429{
428 struct device_node *np; 430 struct device_node *np;
431 struct pSeries_reconfig_prop_update upd_value;
429 unsigned char *value; 432 unsigned char *value;
430 char *name, *end, *next_prop; 433 char *name, *end, *next_prop;
431 int rc, length; 434 int rc, length;
@@ -454,6 +457,10 @@ static int do_update_property(char *buf, size_t bufsize)
454 return -ENODEV; 457 return -ENODEV;
455 } 458 }
456 459
460 upd_value.node = np;
461 upd_value.property = newprop;
462 pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
463
457 rc = prom_update_property(np, newprop, oldprop); 464 rc = prom_update_property(np, newprop, oldprop);
458 if (rc) 465 if (rc)
459 return rc; 466 return rc;
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
index 1c2d7af17bbe..82c6702dcbab 100644
--- a/arch/powerpc/sysdev/ppc4xx_msi.c
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -28,10 +28,11 @@
28#include <linux/of_platform.h> 28#include <linux/of_platform.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/export.h> 30#include <linux/export.h>
31#include <linux/kernel.h>
31#include <asm/prom.h> 32#include <asm/prom.h>
32#include <asm/hw_irq.h> 33#include <asm/hw_irq.h>
33#include <asm/ppc-pci.h> 34#include <asm/ppc-pci.h>
34#include <boot/dcr.h> 35#include <asm/dcr.h>
35#include <asm/dcr-regs.h> 36#include <asm/dcr-regs.h>
36#include <asm/msi_bitmap.h> 37#include <asm/msi_bitmap.h>
37 38
@@ -43,13 +44,14 @@
43#define PEIH_FLUSH0 0x30 44#define PEIH_FLUSH0 0x30
44#define PEIH_FLUSH1 0x38 45#define PEIH_FLUSH1 0x38
45#define PEIH_CNTRST 0x48 46#define PEIH_CNTRST 0x48
46#define NR_MSI_IRQS 4 47
48static int msi_irqs;
47 49
48struct ppc4xx_msi { 50struct ppc4xx_msi {
49 u32 msi_addr_lo; 51 u32 msi_addr_lo;
50 u32 msi_addr_hi; 52 u32 msi_addr_hi;
51 void __iomem *msi_regs; 53 void __iomem *msi_regs;
52 int msi_virqs[NR_MSI_IRQS]; 54 int *msi_virqs;
53 struct msi_bitmap bitmap; 55 struct msi_bitmap bitmap;
54 struct device_node *msi_dev; 56 struct device_node *msi_dev;
55}; 57};
@@ -61,7 +63,7 @@ static int ppc4xx_msi_init_allocator(struct platform_device *dev,
61{ 63{
62 int err; 64 int err;
63 65
64 err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, 66 err = msi_bitmap_alloc(&msi_data->bitmap, msi_irqs,
65 dev->dev.of_node); 67 dev->dev.of_node);
66 if (err) 68 if (err)
67 return err; 69 return err;
@@ -83,6 +85,11 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
83 struct msi_desc *entry; 85 struct msi_desc *entry;
84 struct ppc4xx_msi *msi_data = &ppc4xx_msi; 86 struct ppc4xx_msi *msi_data = &ppc4xx_msi;
85 87
88 msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int),
89 GFP_KERNEL);
90 if (!msi_data->msi_virqs)
91 return -ENOMEM;
92
86 list_for_each_entry(entry, &dev->msi_list, list) { 93 list_for_each_entry(entry, &dev->msi_list, list) {
87 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); 94 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
88 if (int_no >= 0) 95 if (int_no >= 0)
@@ -150,12 +157,11 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
150 if (!sdr_addr) 157 if (!sdr_addr)
151 return -1; 158 return -1;
152 159
153 SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */ 160 mtdcri(SDR0, *sdr_addr, upper_32_bits(res.start)); /*HIGH addr */
154 SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */ 161 mtdcri(SDR0, *sdr_addr + 1, lower_32_bits(res.start)); /* Low addr */
155
156 162
157 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi"); 163 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
158 if (msi->msi_dev) 164 if (!msi->msi_dev)
159 return -ENODEV; 165 return -ENODEV;
160 166
161 msi->msi_regs = of_iomap(msi->msi_dev, 0); 167 msi->msi_regs = of_iomap(msi->msi_dev, 0);
@@ -167,9 +173,12 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
167 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs)); 173 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
168 174
169 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL); 175 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
170 msi->msi_addr_hi = 0x0; 176 if (!msi_virt)
171 msi->msi_addr_lo = (u32) msi_phys; 177 return -ENOMEM;
172 dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo); 178 msi->msi_addr_hi = upper_32_bits(msi_phys);
179 msi->msi_addr_lo = lower_32_bits(msi_phys & 0xffffffff);
180 dev_dbg(&dev->dev, "PCIE-MSI: msi address high 0x%x, low 0x%x\n",
181 msi->msi_addr_hi, msi->msi_addr_lo);
173 182
174 /* Progam the Interrupt handler Termination addr registers */ 183 /* Progam the Interrupt handler Termination addr registers */
175 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi); 184 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
@@ -185,6 +194,8 @@ static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
185 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data); 194 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
186 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask); 195 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
187 196
197 dma_free_coherent(&dev->dev, 64, msi_virt, msi_phys);
198
188 return 0; 199 return 0;
189} 200}
190 201
@@ -194,7 +205,7 @@ static int ppc4xx_of_msi_remove(struct platform_device *dev)
194 int i; 205 int i;
195 int virq; 206 int virq;
196 207
197 for (i = 0; i < NR_MSI_IRQS; i++) { 208 for (i = 0; i < msi_irqs; i++) {
198 virq = msi->msi_virqs[i]; 209 virq = msi->msi_virqs[i];
199 if (virq != NO_IRQ) 210 if (virq != NO_IRQ)
200 irq_dispose_mapping(virq); 211 irq_dispose_mapping(virq);
@@ -215,8 +226,6 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
215 struct resource res; 226 struct resource res;
216 int err = 0; 227 int err = 0;
217 228
218 msi = &ppc4xx_msi;/*keep the msi data for further use*/
219
220 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n"); 229 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
221 230
222 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL); 231 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
@@ -234,6 +243,10 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
234 goto error_out; 243 goto error_out;
235 } 244 }
236 245
246 msi_irqs = of_irq_count(dev->dev.of_node);
247 if (!msi_irqs)
248 return -ENODEV;
249
237 if (ppc4xx_setup_pcieh_hw(dev, res, msi)) 250 if (ppc4xx_setup_pcieh_hw(dev, res, msi))
238 goto error_out; 251 goto error_out;
239 252
@@ -242,6 +255,7 @@ static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
242 dev_err(&dev->dev, "Error allocating MSI bitmap\n"); 255 dev_err(&dev->dev, "Error allocating MSI bitmap\n");
243 goto error_out; 256 goto error_out;
244 } 257 }
258 ppc4xx_msi = *msi;
245 259
246 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs; 260 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
247 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs; 261 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index b2402eb076c7..c225314468ee 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -250,3 +250,16 @@ config UML_RANDOM
250 (check your distro, or download from 250 (check your distro, or download from
251 http://sourceforge.net/projects/gkernel/). rngd periodically reads 251 http://sourceforge.net/projects/gkernel/). rngd periodically reads
252 /dev/hwrng and injects the entropy into /dev/random. 252 /dev/hwrng and injects the entropy into /dev/random.
253
254config HW_RANDOM_PSERIES
255 tristate "pSeries HW Random Number Generator support"
256 depends on HW_RANDOM && PPC64 && IBMVIO
257 default HW_RANDOM
258 ---help---
259 This driver provides kernel-side support for the Random Number
260 Generator hardware found on POWER7+ machines and above
261
262 To compile this driver as a module, choose M here: the
263 module will be called pseries-rng.
264
265 If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b2ff5265a996..d901dfa30321 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
22obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o 22obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
23obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o 23obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
24obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o 24obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
25obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
new file mode 100644
index 000000000000..5f1197929f0c
--- /dev/null
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2010 Michael Neuling IBM Corporation
3 *
4 * Driver for the pseries hardware RNG for POWER7+ and above
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/hw_random.h>
22#include <asm/vio.h>
23
24#define MODULE_NAME "pseries-rng"
25
26static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
27{
28 if (plpar_hcall(H_RANDOM, (unsigned long *)data) != H_SUCCESS) {
29 printk(KERN_ERR "pseries rng hcall error\n");
30 return 0;
31 }
32 return 8;
33}
34
35/**
36 * pseries_rng_get_desired_dma - Return desired DMA allocate for CMO operations
37 *
38 * This is a required function for a driver to operate in a CMO environment
39 * but this device does not make use of DMA allocations, return 0.
40 *
41 * Return value:
42 * Number of bytes of IO data the driver will need to perform well -> 0
43 */
44static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev)
45{
46 return 0;
47};
48
49static struct hwrng pseries_rng = {
50 .name = MODULE_NAME,
51 .data_read = pseries_rng_data_read,
52};
53
54static int __init pseries_rng_probe(struct vio_dev *dev,
55 const struct vio_device_id *id)
56{
57 return hwrng_register(&pseries_rng);
58}
59
60static int __exit pseries_rng_remove(struct vio_dev *dev)
61{
62 hwrng_unregister(&pseries_rng);
63 return 0;
64}
65
66static struct vio_device_id pseries_rng_driver_ids[] = {
67 { "ibm,random-v1", "ibm,random"},
68 { "", "" }
69};
70MODULE_DEVICE_TABLE(vio, pseries_rng_driver_ids);
71
72static struct vio_driver pseries_rng_driver = {
73 .name = MODULE_NAME,
74 .probe = pseries_rng_probe,
75 .remove = pseries_rng_remove,
76 .get_desired_dma = pseries_rng_get_desired_dma,
77 .id_table = pseries_rng_driver_ids
78};
79
80static int __init rng_init(void)
81{
82 printk(KERN_INFO "Registering IBM pSeries RNG driver\n");
83 return vio_register_driver(&pseries_rng_driver);
84}
85
86module_init(rng_init);
87
88static void __exit rng_exit(void)
89{
90 vio_unregister_driver(&pseries_rng_driver);
91}
92module_exit(rng_exit);
93
94MODULE_LICENSE("GPL");
95MODULE_AUTHOR("Michael Neuling <mikey@neuling.org>");
96MODULE_DESCRIPTION("H/W RNG driver for IBM pSeries processors");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 371f13cc38eb..6373fa0ddb65 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -297,4 +297,21 @@ config CRYPTO_DEV_TEGRA_AES
297 To compile this driver as a module, choose M here: the module 297 To compile this driver as a module, choose M here: the module
298 will be called tegra-aes. 298 will be called tegra-aes.
299 299
300config CRYPTO_DEV_NX
301 tristate "Support for Power7+ in-Nest cryptographic accleration"
302 depends on PPC64 && IBMVIO
303 select CRYPTO_AES
304 select CRYPTO_CBC
305 select CRYPTO_ECB
306 select CRYPTO_CCM
307 select CRYPTO_GCM
308 select CRYPTO_AUTHENC
309 select CRYPTO_XCBC
310 select CRYPTO_SHA256
311 select CRYPTO_SHA512
312 help
313 Support for Power7+ in-Nest cryptographic acceleration. This
314 module supports acceleration for AES and SHA2 algorithms. If you
315 choose 'M' here, this module will be called nx_crypto.
316
300endif # CRYPTO_HW 317endif # CRYPTO_HW
diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
new file mode 100644
index 000000000000..411ce59c80d1
--- /dev/null
+++ b/drivers/crypto/nx/Makefile
@@ -0,0 +1,11 @@
1obj-$(CONFIG_CRYPTO_DEV_NX) += nx-crypto.o
2nx-crypto-objs := nx.o \
3 nx_debugfs.o \
4 nx-aes-cbc.o \
5 nx-aes-ecb.o \
6 nx-aes-gcm.o \
7 nx-aes-ccm.o \
8 nx-aes-ctr.o \
9 nx-aes-xcbc.o \
10 nx-sha256.o \
11 nx-sha512.o
diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c
new file mode 100644
index 000000000000..69ed796ee327
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-cbc.c
@@ -0,0 +1,141 @@
1/**
2 * AES CBC routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/aes.h>
23#include <crypto/algapi.h>
24#include <linux/module.h>
25#include <linux/types.h>
26#include <linux/crypto.h>
27#include <asm/vio.h>
28
29#include "nx_csbcpb.h"
30#include "nx.h"
31
32
33static int cbc_aes_nx_set_key(struct crypto_tfm *tfm,
34 const u8 *in_key,
35 unsigned int key_len)
36{
37 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
38 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
39
40 nx_ctx_init(nx_ctx, HCOP_FC_AES);
41
42 switch (key_len) {
43 case AES_KEYSIZE_128:
44 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
45 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
46 break;
47 case AES_KEYSIZE_192:
48 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
49 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
50 break;
51 case AES_KEYSIZE_256:
52 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
53 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
54 break;
55 default:
56 return -EINVAL;
57 }
58
59 csbcpb->cpb.hdr.mode = NX_MODE_AES_CBC;
60 memcpy(csbcpb->cpb.aes_cbc.key, in_key, key_len);
61
62 return 0;
63}
64
65static int cbc_aes_nx_crypt(struct blkcipher_desc *desc,
66 struct scatterlist *dst,
67 struct scatterlist *src,
68 unsigned int nbytes,
69 int enc)
70{
71 struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
72 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
73 int rc;
74
75 if (nbytes > nx_ctx->ap->databytelen)
76 return -EINVAL;
77
78 if (enc)
79 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
80 else
81 NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
82
83 rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
84 csbcpb->cpb.aes_cbc.iv);
85 if (rc)
86 goto out;
87
88 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
89 rc = -EINVAL;
90 goto out;
91 }
92
93 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
94 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
95 if (rc)
96 goto out;
97
98 atomic_inc(&(nx_ctx->stats->aes_ops));
99 atomic64_add(csbcpb->csb.processed_byte_count,
100 &(nx_ctx->stats->aes_bytes));
101out:
102 return rc;
103}
104
105static int cbc_aes_nx_encrypt(struct blkcipher_desc *desc,
106 struct scatterlist *dst,
107 struct scatterlist *src,
108 unsigned int nbytes)
109{
110 return cbc_aes_nx_crypt(desc, dst, src, nbytes, 1);
111}
112
113static int cbc_aes_nx_decrypt(struct blkcipher_desc *desc,
114 struct scatterlist *dst,
115 struct scatterlist *src,
116 unsigned int nbytes)
117{
118 return cbc_aes_nx_crypt(desc, dst, src, nbytes, 0);
119}
120
121struct crypto_alg nx_cbc_aes_alg = {
122 .cra_name = "cbc(aes)",
123 .cra_driver_name = "cbc-aes-nx",
124 .cra_priority = 300,
125 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
126 .cra_blocksize = AES_BLOCK_SIZE,
127 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
128 .cra_type = &crypto_blkcipher_type,
129 .cra_module = THIS_MODULE,
130 .cra_list = LIST_HEAD_INIT(nx_cbc_aes_alg.cra_list),
131 .cra_init = nx_crypto_ctx_aes_cbc_init,
132 .cra_exit = nx_crypto_ctx_exit,
133 .cra_blkcipher = {
134 .min_keysize = AES_MIN_KEY_SIZE,
135 .max_keysize = AES_MAX_KEY_SIZE,
136 .ivsize = AES_BLOCK_SIZE,
137 .setkey = cbc_aes_nx_set_key,
138 .encrypt = cbc_aes_nx_encrypt,
139 .decrypt = cbc_aes_nx_decrypt,
140 }
141};
diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
new file mode 100644
index 000000000000..7aeac678b9c0
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -0,0 +1,468 @@
1/**
2 * AES CCM routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/aead.h>
23#include <crypto/aes.h>
24#include <crypto/algapi.h>
25#include <crypto/scatterwalk.h>
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/crypto.h>
29#include <asm/vio.h>
30
31#include "nx_csbcpb.h"
32#include "nx.h"
33
34
35static int ccm_aes_nx_set_key(struct crypto_aead *tfm,
36 const u8 *in_key,
37 unsigned int key_len)
38{
39 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
40 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
41 struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
42
43 nx_ctx_init(nx_ctx, HCOP_FC_AES);
44
45 switch (key_len) {
46 case AES_KEYSIZE_128:
47 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
48 NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
49 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
50 break;
51 default:
52 return -EINVAL;
53 }
54
55 csbcpb->cpb.hdr.mode = NX_MODE_AES_CCM;
56 memcpy(csbcpb->cpb.aes_ccm.key, in_key, key_len);
57
58 csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_CCA;
59 memcpy(csbcpb_aead->cpb.aes_cca.key, in_key, key_len);
60
61 return 0;
62
63}
64
65static int ccm4309_aes_nx_set_key(struct crypto_aead *tfm,
66 const u8 *in_key,
67 unsigned int key_len)
68{
69 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
70
71 if (key_len < 3)
72 return -EINVAL;
73
74 key_len -= 3;
75
76 memcpy(nx_ctx->priv.ccm.nonce, in_key + key_len, 3);
77
78 return ccm_aes_nx_set_key(tfm, in_key, key_len);
79}
80
81static int ccm_aes_nx_setauthsize(struct crypto_aead *tfm,
82 unsigned int authsize)
83{
84 switch (authsize) {
85 case 4:
86 case 6:
87 case 8:
88 case 10:
89 case 12:
90 case 14:
91 case 16:
92 break;
93 default:
94 return -EINVAL;
95 }
96
97 crypto_aead_crt(tfm)->authsize = authsize;
98
99 return 0;
100}
101
102static int ccm4309_aes_nx_setauthsize(struct crypto_aead *tfm,
103 unsigned int authsize)
104{
105 switch (authsize) {
106 case 8:
107 case 12:
108 case 16:
109 break;
110 default:
111 return -EINVAL;
112 }
113
114 crypto_aead_crt(tfm)->authsize = authsize;
115
116 return 0;
117}
118
119/* taken from crypto/ccm.c */
120static int set_msg_len(u8 *block, unsigned int msglen, int csize)
121{
122 __be32 data;
123
124 memset(block, 0, csize);
125 block += csize;
126
127 if (csize >= 4)
128 csize = 4;
129 else if (msglen > (unsigned int)(1 << (8 * csize)))
130 return -EOVERFLOW;
131
132 data = cpu_to_be32(msglen);
133 memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
134
135 return 0;
136}
137
138/* taken from crypto/ccm.c */
139static inline int crypto_ccm_check_iv(const u8 *iv)
140{
141 /* 2 <= L <= 8, so 1 <= L' <= 7. */
142 if (1 > iv[0] || iv[0] > 7)
143 return -EINVAL;
144
145 return 0;
146}
147
148/* based on code from crypto/ccm.c */
149static int generate_b0(u8 *iv, unsigned int assoclen, unsigned int authsize,
150 unsigned int cryptlen, u8 *b0)
151{
152 unsigned int l, lp, m = authsize;
153 int rc;
154
155 memcpy(b0, iv, 16);
156
157 lp = b0[0];
158 l = lp + 1;
159
160 /* set m, bits 3-5 */
161 *b0 |= (8 * ((m - 2) / 2));
162
163 /* set adata, bit 6, if associated data is used */
164 if (assoclen)
165 *b0 |= 64;
166
167 rc = set_msg_len(b0 + 16 - l, cryptlen, l);
168
169 return rc;
170}
171
172static int generate_pat(u8 *iv,
173 struct aead_request *req,
174 struct nx_crypto_ctx *nx_ctx,
175 unsigned int authsize,
176 unsigned int nbytes,
177 u8 *out)
178{
179 struct nx_sg *nx_insg = nx_ctx->in_sg;
180 struct nx_sg *nx_outsg = nx_ctx->out_sg;
181 unsigned int iauth_len = 0;
182 struct vio_pfo_op *op = NULL;
183 u8 tmp[16], *b1 = NULL, *b0 = NULL, *result = NULL;
184 int rc;
185
186 /* zero the ctr value */
187 memset(iv + 15 - iv[0], 0, iv[0] + 1);
188
189 if (!req->assoclen) {
190 b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
191 } else if (req->assoclen <= 14) {
192 /* if associated data is 14 bytes or less, we do 1 GCM
193 * operation on 2 AES blocks, B0 (stored in the csbcpb) and B1,
194 * which is fed in through the source buffers here */
195 b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
196 b1 = nx_ctx->priv.ccm.iauth_tag;
197 iauth_len = req->assoclen;
198
199 nx_insg = nx_build_sg_list(nx_insg, b1, 16, nx_ctx->ap->sglen);
200 nx_outsg = nx_build_sg_list(nx_outsg, tmp, 16,
201 nx_ctx->ap->sglen);
202
203 /* inlen should be negative, indicating to phyp that its a
204 * pointer to an sg list */
205 nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) *
206 sizeof(struct nx_sg);
207 nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) *
208 sizeof(struct nx_sg);
209
210 NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_ENDE_ENCRYPT;
211 NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_INTERMEDIATE;
212
213 op = &nx_ctx->op;
214 result = nx_ctx->csbcpb->cpb.aes_ccm.out_pat_or_mac;
215 } else if (req->assoclen <= 65280) {
216 /* if associated data is less than (2^16 - 2^8), we construct
217 * B1 differently and feed in the associated data to a CCA
218 * operation */
219 b0 = nx_ctx->csbcpb_aead->cpb.aes_cca.b0;
220 b1 = nx_ctx->csbcpb_aead->cpb.aes_cca.b1;
221 iauth_len = 14;
222
223 /* remaining assoc data must have scatterlist built for it */
224 nx_insg = nx_walk_and_build(nx_insg, nx_ctx->ap->sglen,
225 req->assoc, iauth_len,
226 req->assoclen - iauth_len);
227 nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_insg) *
228 sizeof(struct nx_sg);
229
230 op = &nx_ctx->op_aead;
231 result = nx_ctx->csbcpb_aead->cpb.aes_cca.out_pat_or_b0;
232 } else {
233 /* if associated data is less than (2^32), we construct B1
234 * differently yet again and feed in the associated data to a
235 * CCA operation */
236 pr_err("associated data len is %u bytes (returning -EINVAL)\n",
237 req->assoclen);
238 rc = -EINVAL;
239 }
240
241 rc = generate_b0(iv, req->assoclen, authsize, nbytes, b0);
242 if (rc)
243 goto done;
244
245 if (b1) {
246 memset(b1, 0, 16);
247 *(u16 *)b1 = (u16)req->assoclen;
248
249 scatterwalk_map_and_copy(b1 + 2, req->assoc, 0,
250 iauth_len, SCATTERWALK_FROM_SG);
251
252 rc = nx_hcall_sync(nx_ctx, op,
253 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
254 if (rc)
255 goto done;
256
257 atomic_inc(&(nx_ctx->stats->aes_ops));
258 atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
259
260 memcpy(out, result, AES_BLOCK_SIZE);
261 }
262done:
263 return rc;
264}
265
266static int ccm_nx_decrypt(struct aead_request *req,
267 struct blkcipher_desc *desc)
268{
269 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
270 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
271 unsigned int nbytes = req->cryptlen;
272 unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
273 struct nx_ccm_priv *priv = &nx_ctx->priv.ccm;
274 int rc = -1;
275
276 if (nbytes > nx_ctx->ap->databytelen)
277 return -EINVAL;
278
279 nbytes -= authsize;
280
281 /* copy out the auth tag to compare with later */
282 scatterwalk_map_and_copy(priv->oauth_tag,
283 req->src, nbytes, authsize,
284 SCATTERWALK_FROM_SG);
285
286 rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
287 csbcpb->cpb.aes_ccm.in_pat_or_b0);
288 if (rc)
289 goto out;
290
291 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
292 csbcpb->cpb.aes_ccm.iv_or_ctr);
293 if (rc)
294 goto out;
295
296 NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
297 NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_INTERMEDIATE;
298
299 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
300 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
301 if (rc)
302 goto out;
303
304 atomic_inc(&(nx_ctx->stats->aes_ops));
305 atomic64_add(csbcpb->csb.processed_byte_count,
306 &(nx_ctx->stats->aes_bytes));
307
308 rc = memcmp(csbcpb->cpb.aes_ccm.out_pat_or_mac, priv->oauth_tag,
309 authsize) ? -EBADMSG : 0;
310out:
311 return rc;
312}
313
314static int ccm_nx_encrypt(struct aead_request *req,
315 struct blkcipher_desc *desc)
316{
317 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
318 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
319 unsigned int nbytes = req->cryptlen;
320 unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
321 int rc = -1;
322
323 if (nbytes > nx_ctx->ap->databytelen)
324 return -EINVAL;
325
326 rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
327 csbcpb->cpb.aes_ccm.in_pat_or_b0);
328 if (rc)
329 goto out;
330
331 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
332 csbcpb->cpb.aes_ccm.iv_or_ctr);
333 if (rc)
334 goto out;
335
336 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
337 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
338
339 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
340 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
341 if (rc)
342 goto out;
343
344 atomic_inc(&(nx_ctx->stats->aes_ops));
345 atomic64_add(csbcpb->csb.processed_byte_count,
346 &(nx_ctx->stats->aes_bytes));
347
348 /* copy out the auth tag */
349 scatterwalk_map_and_copy(csbcpb->cpb.aes_ccm.out_pat_or_mac,
350 req->dst, nbytes, authsize,
351 SCATTERWALK_TO_SG);
352out:
353 return rc;
354}
355
356static int ccm4309_aes_nx_encrypt(struct aead_request *req)
357{
358 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
359 struct blkcipher_desc desc;
360 u8 *iv = nx_ctx->priv.ccm.iv;
361
362 iv[0] = 3;
363 memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
364 memcpy(iv + 4, req->iv, 8);
365
366 desc.info = iv;
367 desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
368
369 return ccm_nx_encrypt(req, &desc);
370}
371
372static int ccm_aes_nx_encrypt(struct aead_request *req)
373{
374 struct blkcipher_desc desc;
375 int rc;
376
377 desc.info = req->iv;
378 desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
379
380 rc = crypto_ccm_check_iv(desc.info);
381 if (rc)
382 return rc;
383
384 return ccm_nx_encrypt(req, &desc);
385}
386
387static int ccm4309_aes_nx_decrypt(struct aead_request *req)
388{
389 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
390 struct blkcipher_desc desc;
391 u8 *iv = nx_ctx->priv.ccm.iv;
392
393 iv[0] = 3;
394 memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
395 memcpy(iv + 4, req->iv, 8);
396
397 desc.info = iv;
398 desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
399
400 return ccm_nx_decrypt(req, &desc);
401}
402
403static int ccm_aes_nx_decrypt(struct aead_request *req)
404{
405 struct blkcipher_desc desc;
406 int rc;
407
408 desc.info = req->iv;
409 desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
410
411 rc = crypto_ccm_check_iv(desc.info);
412 if (rc)
413 return rc;
414
415 return ccm_nx_decrypt(req, &desc);
416}
417
418/* tell the block cipher walk routines that this is a stream cipher by
419 * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
420 * during encrypt/decrypt doesn't solve this problem, because it calls
421 * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
422 * but instead uses this tfm->blocksize. */
423struct crypto_alg nx_ccm_aes_alg = {
424 .cra_name = "ccm(aes)",
425 .cra_driver_name = "ccm-aes-nx",
426 .cra_priority = 300,
427 .cra_flags = CRYPTO_ALG_TYPE_AEAD |
428 CRYPTO_ALG_NEED_FALLBACK,
429 .cra_blocksize = 1,
430 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
431 .cra_type = &crypto_aead_type,
432 .cra_module = THIS_MODULE,
433 .cra_list = LIST_HEAD_INIT(nx_ccm_aes_alg.cra_list),
434 .cra_init = nx_crypto_ctx_aes_ccm_init,
435 .cra_exit = nx_crypto_ctx_exit,
436 .cra_aead = {
437 .ivsize = AES_BLOCK_SIZE,
438 .maxauthsize = AES_BLOCK_SIZE,
439 .setkey = ccm_aes_nx_set_key,
440 .setauthsize = ccm_aes_nx_setauthsize,
441 .encrypt = ccm_aes_nx_encrypt,
442 .decrypt = ccm_aes_nx_decrypt,
443 }
444};
445
446struct crypto_alg nx_ccm4309_aes_alg = {
447 .cra_name = "rfc4309(ccm(aes))",
448 .cra_driver_name = "rfc4309-ccm-aes-nx",
449 .cra_priority = 300,
450 .cra_flags = CRYPTO_ALG_TYPE_AEAD |
451 CRYPTO_ALG_NEED_FALLBACK,
452 .cra_blocksize = 1,
453 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
454 .cra_type = &crypto_nivaead_type,
455 .cra_module = THIS_MODULE,
456 .cra_list = LIST_HEAD_INIT(nx_ccm4309_aes_alg.cra_list),
457 .cra_init = nx_crypto_ctx_aes_ccm_init,
458 .cra_exit = nx_crypto_ctx_exit,
459 .cra_aead = {
460 .ivsize = 8,
461 .maxauthsize = AES_BLOCK_SIZE,
462 .setkey = ccm4309_aes_nx_set_key,
463 .setauthsize = ccm4309_aes_nx_setauthsize,
464 .encrypt = ccm4309_aes_nx_encrypt,
465 .decrypt = ccm4309_aes_nx_decrypt,
466 .geniv = "seqiv",
467 }
468};
diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
new file mode 100644
index 000000000000..52d4eb05e8f7
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ctr.c
@@ -0,0 +1,178 @@
1/**
2 * AES CTR routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/aes.h>
23#include <crypto/ctr.h>
24#include <crypto/algapi.h>
25#include <linux/module.h>
26#include <linux/types.h>
27#include <linux/crypto.h>
28#include <asm/vio.h>
29
30#include "nx_csbcpb.h"
31#include "nx.h"
32
33
34static int ctr_aes_nx_set_key(struct crypto_tfm *tfm,
35 const u8 *in_key,
36 unsigned int key_len)
37{
38 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
39 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
40
41 nx_ctx_init(nx_ctx, HCOP_FC_AES);
42
43 switch (key_len) {
44 case AES_KEYSIZE_128:
45 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
46 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
47 break;
48 case AES_KEYSIZE_192:
49 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
50 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
51 break;
52 case AES_KEYSIZE_256:
53 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
54 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
55 break;
56 default:
57 return -EINVAL;
58 }
59
60 csbcpb->cpb.hdr.mode = NX_MODE_AES_CTR;
61 memcpy(csbcpb->cpb.aes_ctr.key, in_key, key_len);
62
63 return 0;
64}
65
66static int ctr3686_aes_nx_set_key(struct crypto_tfm *tfm,
67 const u8 *in_key,
68 unsigned int key_len)
69{
70 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
71
72 if (key_len < CTR_RFC3686_NONCE_SIZE)
73 return -EINVAL;
74
75 memcpy(nx_ctx->priv.ctr.iv,
76 in_key + key_len - CTR_RFC3686_NONCE_SIZE,
77 CTR_RFC3686_NONCE_SIZE);
78
79 key_len -= CTR_RFC3686_NONCE_SIZE;
80
81 return ctr_aes_nx_set_key(tfm, in_key, key_len);
82}
83
84static int ctr_aes_nx_crypt(struct blkcipher_desc *desc,
85 struct scatterlist *dst,
86 struct scatterlist *src,
87 unsigned int nbytes)
88{
89 struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
90 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
91 int rc;
92
93 if (nbytes > nx_ctx->ap->databytelen)
94 return -EINVAL;
95
96 rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
97 csbcpb->cpb.aes_ctr.iv);
98 if (rc)
99 goto out;
100
101 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
102 rc = -EINVAL;
103 goto out;
104 }
105
106 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
107 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
108 if (rc)
109 goto out;
110
111 atomic_inc(&(nx_ctx->stats->aes_ops));
112 atomic64_add(csbcpb->csb.processed_byte_count,
113 &(nx_ctx->stats->aes_bytes));
114out:
115 return rc;
116}
117
118static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc,
119 struct scatterlist *dst,
120 struct scatterlist *src,
121 unsigned int nbytes)
122{
123 struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
124 u8 *iv = nx_ctx->priv.ctr.iv;
125
126 memcpy(iv + CTR_RFC3686_NONCE_SIZE,
127 desc->info, CTR_RFC3686_IV_SIZE);
128 iv[15] = 1;
129
130 desc->info = nx_ctx->priv.ctr.iv;
131
132 return ctr_aes_nx_crypt(desc, dst, src, nbytes);
133}
134
135struct crypto_alg nx_ctr_aes_alg = {
136 .cra_name = "ctr(aes)",
137 .cra_driver_name = "ctr-aes-nx",
138 .cra_priority = 300,
139 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
140 .cra_blocksize = 1,
141 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
142 .cra_type = &crypto_blkcipher_type,
143 .cra_module = THIS_MODULE,
144 .cra_list = LIST_HEAD_INIT(nx_ctr_aes_alg.cra_list),
145 .cra_init = nx_crypto_ctx_aes_ctr_init,
146 .cra_exit = nx_crypto_ctx_exit,
147 .cra_blkcipher = {
148 .min_keysize = AES_MIN_KEY_SIZE,
149 .max_keysize = AES_MAX_KEY_SIZE,
150 .ivsize = AES_BLOCK_SIZE,
151 .setkey = ctr_aes_nx_set_key,
152 .encrypt = ctr_aes_nx_crypt,
153 .decrypt = ctr_aes_nx_crypt,
154 }
155};
156
157struct crypto_alg nx_ctr3686_aes_alg = {
158 .cra_name = "rfc3686(ctr(aes))",
159 .cra_driver_name = "rfc3686-ctr-aes-nx",
160 .cra_priority = 300,
161 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
162 .cra_blocksize = 1,
163 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
164 .cra_type = &crypto_blkcipher_type,
165 .cra_module = THIS_MODULE,
166 .cra_list = LIST_HEAD_INIT(nx_ctr3686_aes_alg.cra_list),
167 .cra_init = nx_crypto_ctx_aes_ctr_init,
168 .cra_exit = nx_crypto_ctx_exit,
169 .cra_blkcipher = {
170 .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
171 .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
172 .ivsize = CTR_RFC3686_IV_SIZE,
173 .geniv = "seqiv",
174 .setkey = ctr3686_aes_nx_set_key,
175 .encrypt = ctr3686_aes_nx_crypt,
176 .decrypt = ctr3686_aes_nx_crypt,
177 }
178};
diff --git a/drivers/crypto/nx/nx-aes-ecb.c b/drivers/crypto/nx/nx-aes-ecb.c
new file mode 100644
index 000000000000..7b77bc2d1df4
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ecb.c
@@ -0,0 +1,139 @@
1/**
2 * AES ECB routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/aes.h>
23#include <crypto/algapi.h>
24#include <linux/module.h>
25#include <linux/types.h>
26#include <linux/crypto.h>
27#include <asm/vio.h>
28
29#include "nx_csbcpb.h"
30#include "nx.h"
31
32
33static int ecb_aes_nx_set_key(struct crypto_tfm *tfm,
34 const u8 *in_key,
35 unsigned int key_len)
36{
37 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
38 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
39
40 nx_ctx_init(nx_ctx, HCOP_FC_AES);
41
42 switch (key_len) {
43 case AES_KEYSIZE_128:
44 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
45 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
46 break;
47 case AES_KEYSIZE_192:
48 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
49 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
50 break;
51 case AES_KEYSIZE_256:
52 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
53 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
54 break;
55 default:
56 return -EINVAL;
57 }
58
59 csbcpb->cpb.hdr.mode = NX_MODE_AES_ECB;
60 memcpy(csbcpb->cpb.aes_ecb.key, in_key, key_len);
61
62 return 0;
63}
64
65static int ecb_aes_nx_crypt(struct blkcipher_desc *desc,
66 struct scatterlist *dst,
67 struct scatterlist *src,
68 unsigned int nbytes,
69 int enc)
70{
71 struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
72 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
73 int rc;
74
75 if (nbytes > nx_ctx->ap->databytelen)
76 return -EINVAL;
77
78 if (enc)
79 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
80 else
81 NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
82
83 rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes, NULL);
84 if (rc)
85 goto out;
86
87 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
88 rc = -EINVAL;
89 goto out;
90 }
91
92 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
93 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
94 if (rc)
95 goto out;
96
97 atomic_inc(&(nx_ctx->stats->aes_ops));
98 atomic64_add(csbcpb->csb.processed_byte_count,
99 &(nx_ctx->stats->aes_bytes));
100out:
101 return rc;
102}
103
104static int ecb_aes_nx_encrypt(struct blkcipher_desc *desc,
105 struct scatterlist *dst,
106 struct scatterlist *src,
107 unsigned int nbytes)
108{
109 return ecb_aes_nx_crypt(desc, dst, src, nbytes, 1);
110}
111
112static int ecb_aes_nx_decrypt(struct blkcipher_desc *desc,
113 struct scatterlist *dst,
114 struct scatterlist *src,
115 unsigned int nbytes)
116{
117 return ecb_aes_nx_crypt(desc, dst, src, nbytes, 0);
118}
119
120struct crypto_alg nx_ecb_aes_alg = {
121 .cra_name = "ecb(aes)",
122 .cra_driver_name = "ecb-aes-nx",
123 .cra_priority = 300,
124 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
125 .cra_blocksize = AES_BLOCK_SIZE,
126 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
127 .cra_type = &crypto_blkcipher_type,
128 .cra_module = THIS_MODULE,
129 .cra_list = LIST_HEAD_INIT(nx_ecb_aes_alg.cra_list),
130 .cra_init = nx_crypto_ctx_aes_ecb_init,
131 .cra_exit = nx_crypto_ctx_exit,
132 .cra_blkcipher = {
133 .min_keysize = AES_MIN_KEY_SIZE,
134 .max_keysize = AES_MAX_KEY_SIZE,
135 .setkey = ecb_aes_nx_set_key,
136 .encrypt = ecb_aes_nx_encrypt,
137 .decrypt = ecb_aes_nx_decrypt,
138 }
139};
diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
new file mode 100644
index 000000000000..9ab1c7341dac
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -0,0 +1,353 @@
1/**
2 * AES GCM routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/aead.h>
23#include <crypto/aes.h>
24#include <crypto/algapi.h>
25#include <crypto/scatterwalk.h>
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/crypto.h>
29#include <asm/vio.h>
30
31#include "nx_csbcpb.h"
32#include "nx.h"
33
34
35static int gcm_aes_nx_set_key(struct crypto_aead *tfm,
36 const u8 *in_key,
37 unsigned int key_len)
38{
39 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
40 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
41 struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
42
43 nx_ctx_init(nx_ctx, HCOP_FC_AES);
44
45 switch (key_len) {
46 case AES_KEYSIZE_128:
47 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
48 NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
49 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
50 break;
51 case AES_KEYSIZE_192:
52 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
53 NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_192);
54 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
55 break;
56 case AES_KEYSIZE_256:
57 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
58 NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_256);
59 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
60 break;
61 default:
62 return -EINVAL;
63 }
64
65 csbcpb->cpb.hdr.mode = NX_MODE_AES_GCM;
66 memcpy(csbcpb->cpb.aes_gcm.key, in_key, key_len);
67
68 csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_GCA;
69 memcpy(csbcpb_aead->cpb.aes_gca.key, in_key, key_len);
70
71 return 0;
72}
73
74static int gcm4106_aes_nx_set_key(struct crypto_aead *tfm,
75 const u8 *in_key,
76 unsigned int key_len)
77{
78 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
79 char *nonce = nx_ctx->priv.gcm.nonce;
80 int rc;
81
82 if (key_len < 4)
83 return -EINVAL;
84
85 key_len -= 4;
86
87 rc = gcm_aes_nx_set_key(tfm, in_key, key_len);
88 if (rc)
89 goto out;
90
91 memcpy(nonce, in_key + key_len, 4);
92out:
93 return rc;
94}
95
96static int gcm_aes_nx_setauthsize(struct crypto_aead *tfm,
97 unsigned int authsize)
98{
99 if (authsize > crypto_aead_alg(tfm)->maxauthsize)
100 return -EINVAL;
101
102 crypto_aead_crt(tfm)->authsize = authsize;
103
104 return 0;
105}
106
107static int gcm4106_aes_nx_setauthsize(struct crypto_aead *tfm,
108 unsigned int authsize)
109{
110 switch (authsize) {
111 case 8:
112 case 12:
113 case 16:
114 break;
115 default:
116 return -EINVAL;
117 }
118
119 crypto_aead_crt(tfm)->authsize = authsize;
120
121 return 0;
122}
123
124static int nx_gca(struct nx_crypto_ctx *nx_ctx,
125 struct aead_request *req,
126 u8 *out)
127{
128 struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
129 int rc = -EINVAL;
130 struct scatter_walk walk;
131 struct nx_sg *nx_sg = nx_ctx->in_sg;
132
133 if (req->assoclen > nx_ctx->ap->databytelen)
134 goto out;
135
136 if (req->assoclen <= AES_BLOCK_SIZE) {
137 scatterwalk_start(&walk, req->assoc);
138 scatterwalk_copychunks(out, &walk, req->assoclen,
139 SCATTERWALK_FROM_SG);
140 scatterwalk_done(&walk, SCATTERWALK_FROM_SG, 0);
141
142 rc = 0;
143 goto out;
144 }
145
146 nx_sg = nx_walk_and_build(nx_sg, nx_ctx->ap->sglen, req->assoc, 0,
147 req->assoclen);
148 nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_sg) * sizeof(struct nx_sg);
149
150 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op_aead,
151 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
152 if (rc)
153 goto out;
154
155 atomic_inc(&(nx_ctx->stats->aes_ops));
156 atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
157
158 memcpy(out, csbcpb_aead->cpb.aes_gca.out_pat, AES_BLOCK_SIZE);
159out:
160 return rc;
161}
162
163static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
164{
165 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
166 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
167 struct blkcipher_desc desc;
168 unsigned int nbytes = req->cryptlen;
169 int rc = -EINVAL;
170
171 if (nbytes > nx_ctx->ap->databytelen)
172 goto out;
173
174 desc.info = nx_ctx->priv.gcm.iv;
175 /* initialize the counter */
176 *(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
177
178 /* For scenarios where the input message is zero length, AES CTR mode
179 * may be used. Set the source data to be a single block (16B) of all
180 * zeros, and set the input IV value to be the same as the GMAC IV
181 * value. - nx_wb 4.8.1.3 */
182 if (nbytes == 0) {
183 char src[AES_BLOCK_SIZE] = {};
184 struct scatterlist sg;
185
186 desc.tfm = crypto_alloc_blkcipher("ctr(aes)", 0, 0);
187 if (IS_ERR(desc.tfm)) {
188 rc = -ENOMEM;
189 goto out;
190 }
191
192 crypto_blkcipher_setkey(desc.tfm, csbcpb->cpb.aes_gcm.key,
193 NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_128 ? 16 :
194 NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_192 ? 24 : 32);
195
196 sg_init_one(&sg, src, AES_BLOCK_SIZE);
197 if (enc)
198 crypto_blkcipher_encrypt_iv(&desc, req->dst, &sg,
199 AES_BLOCK_SIZE);
200 else
201 crypto_blkcipher_decrypt_iv(&desc, req->dst, &sg,
202 AES_BLOCK_SIZE);
203 crypto_free_blkcipher(desc.tfm);
204
205 rc = 0;
206 goto out;
207 }
208
209 desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
210
211 csbcpb->cpb.aes_gcm.bit_length_aad = req->assoclen * 8;
212
213 if (req->assoclen) {
214 rc = nx_gca(nx_ctx, req, csbcpb->cpb.aes_gcm.in_pat_or_aad);
215 if (rc)
216 goto out;
217 }
218
219 if (enc)
220 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
221 else
222 nbytes -= AES_BLOCK_SIZE;
223
224 csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8;
225
226 rc = nx_build_sg_lists(nx_ctx, &desc, req->dst, req->src, nbytes,
227 csbcpb->cpb.aes_gcm.iv_or_cnt);
228 if (rc)
229 goto out;
230
231 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
232 req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP);
233 if (rc)
234 goto out;
235
236 atomic_inc(&(nx_ctx->stats->aes_ops));
237 atomic64_add(csbcpb->csb.processed_byte_count,
238 &(nx_ctx->stats->aes_bytes));
239
240 if (enc) {
241 /* copy out the auth tag */
242 scatterwalk_map_and_copy(csbcpb->cpb.aes_gcm.out_pat_or_mac,
243 req->dst, nbytes,
244 crypto_aead_authsize(crypto_aead_reqtfm(req)),
245 SCATTERWALK_TO_SG);
246 } else if (req->assoclen) {
247 u8 *itag = nx_ctx->priv.gcm.iauth_tag;
248 u8 *otag = csbcpb->cpb.aes_gcm.out_pat_or_mac;
249
250 scatterwalk_map_and_copy(itag, req->dst, nbytes,
251 crypto_aead_authsize(crypto_aead_reqtfm(req)),
252 SCATTERWALK_FROM_SG);
253 rc = memcmp(itag, otag,
254 crypto_aead_authsize(crypto_aead_reqtfm(req))) ?
255 -EBADMSG : 0;
256 }
257out:
258 return rc;
259}
260
261static int gcm_aes_nx_encrypt(struct aead_request *req)
262{
263 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
264 char *iv = nx_ctx->priv.gcm.iv;
265
266 memcpy(iv, req->iv, 12);
267
268 return gcm_aes_nx_crypt(req, 1);
269}
270
271static int gcm_aes_nx_decrypt(struct aead_request *req)
272{
273 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
274 char *iv = nx_ctx->priv.gcm.iv;
275
276 memcpy(iv, req->iv, 12);
277
278 return gcm_aes_nx_crypt(req, 0);
279}
280
281static int gcm4106_aes_nx_encrypt(struct aead_request *req)
282{
283 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
284 char *iv = nx_ctx->priv.gcm.iv;
285 char *nonce = nx_ctx->priv.gcm.nonce;
286
287 memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
288 memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
289
290 return gcm_aes_nx_crypt(req, 1);
291}
292
293static int gcm4106_aes_nx_decrypt(struct aead_request *req)
294{
295 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
296 char *iv = nx_ctx->priv.gcm.iv;
297 char *nonce = nx_ctx->priv.gcm.nonce;
298
299 memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
300 memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
301
302 return gcm_aes_nx_crypt(req, 0);
303}
304
305/* tell the block cipher walk routines that this is a stream cipher by
306 * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
307 * during encrypt/decrypt doesn't solve this problem, because it calls
308 * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
309 * but instead uses this tfm->blocksize. */
310struct crypto_alg nx_gcm_aes_alg = {
311 .cra_name = "gcm(aes)",
312 .cra_driver_name = "gcm-aes-nx",
313 .cra_priority = 300,
314 .cra_flags = CRYPTO_ALG_TYPE_AEAD,
315 .cra_blocksize = 1,
316 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
317 .cra_type = &crypto_aead_type,
318 .cra_module = THIS_MODULE,
319 .cra_list = LIST_HEAD_INIT(nx_gcm_aes_alg.cra_list),
320 .cra_init = nx_crypto_ctx_aes_gcm_init,
321 .cra_exit = nx_crypto_ctx_exit,
322 .cra_aead = {
323 .ivsize = AES_BLOCK_SIZE,
324 .maxauthsize = AES_BLOCK_SIZE,
325 .setkey = gcm_aes_nx_set_key,
326 .setauthsize = gcm_aes_nx_setauthsize,
327 .encrypt = gcm_aes_nx_encrypt,
328 .decrypt = gcm_aes_nx_decrypt,
329 }
330};
331
332struct crypto_alg nx_gcm4106_aes_alg = {
333 .cra_name = "rfc4106(gcm(aes))",
334 .cra_driver_name = "rfc4106-gcm-aes-nx",
335 .cra_priority = 300,
336 .cra_flags = CRYPTO_ALG_TYPE_AEAD,
337 .cra_blocksize = 1,
338 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
339 .cra_type = &crypto_nivaead_type,
340 .cra_module = THIS_MODULE,
341 .cra_list = LIST_HEAD_INIT(nx_gcm4106_aes_alg.cra_list),
342 .cra_init = nx_crypto_ctx_aes_gcm_init,
343 .cra_exit = nx_crypto_ctx_exit,
344 .cra_aead = {
345 .ivsize = 8,
346 .maxauthsize = AES_BLOCK_SIZE,
347 .geniv = "seqiv",
348 .setkey = gcm4106_aes_nx_set_key,
349 .setauthsize = gcm4106_aes_nx_setauthsize,
350 .encrypt = gcm4106_aes_nx_encrypt,
351 .decrypt = gcm4106_aes_nx_decrypt,
352 }
353};
diff --git a/drivers/crypto/nx/nx-aes-xcbc.c b/drivers/crypto/nx/nx-aes-xcbc.c
new file mode 100644
index 000000000000..93923e4628c0
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-xcbc.c
@@ -0,0 +1,236 @@
1/**
2 * AES XCBC routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/hash.h>
23#include <crypto/aes.h>
24#include <crypto/algapi.h>
25#include <linux/module.h>
26#include <linux/types.h>
27#include <linux/crypto.h>
28#include <asm/vio.h>
29
30#include "nx_csbcpb.h"
31#include "nx.h"
32
33
34struct xcbc_state {
35 u8 state[AES_BLOCK_SIZE];
36 unsigned int count;
37 u8 buffer[AES_BLOCK_SIZE];
38};
39
40static int nx_xcbc_set_key(struct crypto_shash *desc,
41 const u8 *in_key,
42 unsigned int key_len)
43{
44 struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc);
45
46 switch (key_len) {
47 case AES_KEYSIZE_128:
48 nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
49 break;
50 default:
51 return -EINVAL;
52 }
53
54 memcpy(nx_ctx->priv.xcbc.key, in_key, key_len);
55
56 return 0;
57}
58
59static int nx_xcbc_init(struct shash_desc *desc)
60{
61 struct xcbc_state *sctx = shash_desc_ctx(desc);
62 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
63 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
64 struct nx_sg *out_sg;
65
66 nx_ctx_init(nx_ctx, HCOP_FC_AES);
67
68 memset(sctx, 0, sizeof *sctx);
69
70 NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
71 csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
72
73 memcpy(csbcpb->cpb.aes_xcbc.key, nx_ctx->priv.xcbc.key, AES_BLOCK_SIZE);
74 memset(nx_ctx->priv.xcbc.key, 0, sizeof *nx_ctx->priv.xcbc.key);
75
76 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
77 AES_BLOCK_SIZE, nx_ctx->ap->sglen);
78 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
79
80 return 0;
81}
82
83static int nx_xcbc_update(struct shash_desc *desc,
84 const u8 *data,
85 unsigned int len)
86{
87 struct xcbc_state *sctx = shash_desc_ctx(desc);
88 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
89 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
90 struct nx_sg *in_sg;
91 u32 to_process, leftover;
92 int rc = 0;
93
94 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
95 /* we've hit the nx chip previously and we're updating again,
96 * so copy over the partial digest */
97 memcpy(csbcpb->cpb.aes_xcbc.cv,
98 csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
99 }
100
101 /* 2 cases for total data len:
102 * 1: <= AES_BLOCK_SIZE: copy into state, return 0
103 * 2: > AES_BLOCK_SIZE: process X blocks, copy in leftover
104 */
105 if (len + sctx->count <= AES_BLOCK_SIZE) {
106 memcpy(sctx->buffer + sctx->count, data, len);
107 sctx->count += len;
108 goto out;
109 }
110
111 /* to_process: the AES_BLOCK_SIZE data chunk to process in this
112 * update */
113 to_process = (sctx->count + len) & ~(AES_BLOCK_SIZE - 1);
114 leftover = (sctx->count + len) & (AES_BLOCK_SIZE - 1);
115
116 /* the hardware will not accept a 0 byte operation for this algorithm
117 * and the operation MUST be finalized to be correct. So if we happen
118 * to get an update that falls on a block sized boundary, we must
119 * save off the last block to finalize with later. */
120 if (!leftover) {
121 to_process -= AES_BLOCK_SIZE;
122 leftover = AES_BLOCK_SIZE;
123 }
124
125 if (sctx->count) {
126 in_sg = nx_build_sg_list(nx_ctx->in_sg, sctx->buffer,
127 sctx->count, nx_ctx->ap->sglen);
128 in_sg = nx_build_sg_list(in_sg, (u8 *)data,
129 to_process - sctx->count,
130 nx_ctx->ap->sglen);
131 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
132 sizeof(struct nx_sg);
133 } else {
134 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data, to_process,
135 nx_ctx->ap->sglen);
136 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
137 sizeof(struct nx_sg);
138 }
139
140 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
141
142 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
143 rc = -EINVAL;
144 goto out;
145 }
146
147 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
148 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
149 if (rc)
150 goto out;
151
152 atomic_inc(&(nx_ctx->stats->aes_ops));
153
154 /* copy the leftover back into the state struct */
155 memcpy(sctx->buffer, data + len - leftover, leftover);
156 sctx->count = leftover;
157
158 /* everything after the first update is continuation */
159 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
160out:
161 return rc;
162}
163
164static int nx_xcbc_final(struct shash_desc *desc, u8 *out)
165{
166 struct xcbc_state *sctx = shash_desc_ctx(desc);
167 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
168 struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
169 struct nx_sg *in_sg, *out_sg;
170 int rc = 0;
171
172 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
173 /* we've hit the nx chip previously, now we're finalizing,
174 * so copy over the partial digest */
175 memcpy(csbcpb->cpb.aes_xcbc.cv,
176 csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
177 } else if (sctx->count == 0) {
178 /* we've never seen an update, so this is a 0 byte op. The
179 * hardware cannot handle a 0 byte op, so just copy out the
180 * known 0 byte result. This is cheaper than allocating a
181 * software context to do a 0 byte op */
182 u8 data[] = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c,
183 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 };
184 memcpy(out, data, sizeof(data));
185 goto out;
186 }
187
188 /* final is represented by continuing the operation and indicating that
189 * this is not an intermediate operation */
190 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
191
192 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer,
193 sctx->count, nx_ctx->ap->sglen);
194 out_sg = nx_build_sg_list(nx_ctx->out_sg, out, AES_BLOCK_SIZE,
195 nx_ctx->ap->sglen);
196
197 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
198 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
199
200 if (!nx_ctx->op.outlen) {
201 rc = -EINVAL;
202 goto out;
203 }
204
205 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
206 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
207 if (rc)
208 goto out;
209
210 atomic_inc(&(nx_ctx->stats->aes_ops));
211
212 memcpy(out, csbcpb->cpb.aes_xcbc.out_cv_mac, AES_BLOCK_SIZE);
213out:
214 return rc;
215}
216
217struct shash_alg nx_shash_aes_xcbc_alg = {
218 .digestsize = AES_BLOCK_SIZE,
219 .init = nx_xcbc_init,
220 .update = nx_xcbc_update,
221 .final = nx_xcbc_final,
222 .setkey = nx_xcbc_set_key,
223 .descsize = sizeof(struct xcbc_state),
224 .statesize = sizeof(struct xcbc_state),
225 .base = {
226 .cra_name = "xcbc(aes)",
227 .cra_driver_name = "xcbc-aes-nx",
228 .cra_priority = 300,
229 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
230 .cra_blocksize = AES_BLOCK_SIZE,
231 .cra_module = THIS_MODULE,
232 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
233 .cra_init = nx_crypto_ctx_aes_xcbc_init,
234 .cra_exit = nx_crypto_ctx_exit,
235 }
236};
diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
new file mode 100644
index 000000000000..9767315f8c0b
--- /dev/null
+++ b/drivers/crypto/nx/nx-sha256.c
@@ -0,0 +1,246 @@
1/**
2 * SHA-256 routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/hash.h>
23#include <crypto/sha.h>
24#include <linux/module.h>
25#include <asm/vio.h>
26
27#include "nx_csbcpb.h"
28#include "nx.h"
29
30
31static int nx_sha256_init(struct shash_desc *desc)
32{
33 struct sha256_state *sctx = shash_desc_ctx(desc);
34 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
35 struct nx_sg *out_sg;
36
37 nx_ctx_init(nx_ctx, HCOP_FC_SHA);
38
39 memset(sctx, 0, sizeof *sctx);
40
41 nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA256];
42
43 NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA256);
44 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
45 SHA256_DIGEST_SIZE, nx_ctx->ap->sglen);
46 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
47
48 return 0;
49}
50
51static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
52 unsigned int len)
53{
54 struct sha256_state *sctx = shash_desc_ctx(desc);
55 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
56 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
57 struct nx_sg *in_sg;
58 u64 to_process, leftover;
59 int rc = 0;
60
61 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
62 /* we've hit the nx chip previously and we're updating again,
63 * so copy over the partial digest */
64 memcpy(csbcpb->cpb.sha256.input_partial_digest,
65 csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
66 }
67
68 /* 2 cases for total data len:
69 * 1: <= SHA256_BLOCK_SIZE: copy into state, return 0
70 * 2: > SHA256_BLOCK_SIZE: process X blocks, copy in leftover
71 */
72 if (len + sctx->count <= SHA256_BLOCK_SIZE) {
73 memcpy(sctx->buf + sctx->count, data, len);
74 sctx->count += len;
75 goto out;
76 }
77
78 /* to_process: the SHA256_BLOCK_SIZE data chunk to process in this
79 * update */
80 to_process = (sctx->count + len) & ~(SHA256_BLOCK_SIZE - 1);
81 leftover = (sctx->count + len) & (SHA256_BLOCK_SIZE - 1);
82
83 if (sctx->count) {
84 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
85 sctx->count, nx_ctx->ap->sglen);
86 in_sg = nx_build_sg_list(in_sg, (u8 *)data,
87 to_process - sctx->count,
88 nx_ctx->ap->sglen);
89 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
90 sizeof(struct nx_sg);
91 } else {
92 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data,
93 to_process, nx_ctx->ap->sglen);
94 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
95 sizeof(struct nx_sg);
96 }
97
98 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
99
100 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
101 rc = -EINVAL;
102 goto out;
103 }
104
105 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
106 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
107 if (rc)
108 goto out;
109
110 atomic_inc(&(nx_ctx->stats->sha256_ops));
111
112 /* copy the leftover back into the state struct */
113 memcpy(sctx->buf, data + len - leftover, leftover);
114 sctx->count = leftover;
115
116 csbcpb->cpb.sha256.message_bit_length += (u64)
117 (csbcpb->cpb.sha256.spbc * 8);
118
119 /* everything after the first update is continuation */
120 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
121out:
122 return rc;
123}
124
125static int nx_sha256_final(struct shash_desc *desc, u8 *out)
126{
127 struct sha256_state *sctx = shash_desc_ctx(desc);
128 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
129 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
130 struct nx_sg *in_sg, *out_sg;
131 int rc;
132
133 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
134 /* we've hit the nx chip previously, now we're finalizing,
135 * so copy over the partial digest */
136 memcpy(csbcpb->cpb.sha256.input_partial_digest,
137 csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
138 }
139
140 /* final is represented by continuing the operation and indicating that
141 * this is not an intermediate operation */
142 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
143
144 csbcpb->cpb.sha256.message_bit_length += (u64)(sctx->count * 8);
145
146 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
147 sctx->count, nx_ctx->ap->sglen);
148 out_sg = nx_build_sg_list(nx_ctx->out_sg, out, SHA256_DIGEST_SIZE,
149 nx_ctx->ap->sglen);
150 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
151 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
152
153 if (!nx_ctx->op.outlen) {
154 rc = -EINVAL;
155 goto out;
156 }
157
158 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
159 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
160 if (rc)
161 goto out;
162
163 atomic_inc(&(nx_ctx->stats->sha256_ops));
164
165 atomic64_add(csbcpb->cpb.sha256.message_bit_length,
166 &(nx_ctx->stats->sha256_bytes));
167 memcpy(out, csbcpb->cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
168out:
169 return rc;
170}
171
172static int nx_sha256_export(struct shash_desc *desc, void *out)
173{
174 struct sha256_state *sctx = shash_desc_ctx(desc);
175 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
176 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
177 struct sha256_state *octx = out;
178
179 octx->count = sctx->count +
180 (csbcpb->cpb.sha256.message_bit_length / 8);
181 memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
182
183 /* if no data has been processed yet, we need to export SHA256's
184 * initial data, in case this context gets imported into a software
185 * context */
186 if (csbcpb->cpb.sha256.message_bit_length)
187 memcpy(octx->state, csbcpb->cpb.sha256.message_digest,
188 SHA256_DIGEST_SIZE);
189 else {
190 octx->state[0] = SHA256_H0;
191 octx->state[1] = SHA256_H1;
192 octx->state[2] = SHA256_H2;
193 octx->state[3] = SHA256_H3;
194 octx->state[4] = SHA256_H4;
195 octx->state[5] = SHA256_H5;
196 octx->state[6] = SHA256_H6;
197 octx->state[7] = SHA256_H7;
198 }
199
200 return 0;
201}
202
203static int nx_sha256_import(struct shash_desc *desc, const void *in)
204{
205 struct sha256_state *sctx = shash_desc_ctx(desc);
206 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
207 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
208 const struct sha256_state *ictx = in;
209
210 memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
211
212 sctx->count = ictx->count & 0x3f;
213 csbcpb->cpb.sha256.message_bit_length = (ictx->count & ~0x3f) * 8;
214
215 if (csbcpb->cpb.sha256.message_bit_length) {
216 memcpy(csbcpb->cpb.sha256.message_digest, ictx->state,
217 SHA256_DIGEST_SIZE);
218
219 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
220 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
221 }
222
223 return 0;
224}
225
226struct shash_alg nx_shash_sha256_alg = {
227 .digestsize = SHA256_DIGEST_SIZE,
228 .init = nx_sha256_init,
229 .update = nx_sha256_update,
230 .final = nx_sha256_final,
231 .export = nx_sha256_export,
232 .import = nx_sha256_import,
233 .descsize = sizeof(struct sha256_state),
234 .statesize = sizeof(struct sha256_state),
235 .base = {
236 .cra_name = "sha256",
237 .cra_driver_name = "sha256-nx",
238 .cra_priority = 300,
239 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
240 .cra_blocksize = SHA256_BLOCK_SIZE,
241 .cra_module = THIS_MODULE,
242 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
243 .cra_init = nx_crypto_ctx_sha_init,
244 .cra_exit = nx_crypto_ctx_exit,
245 }
246};
diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c
new file mode 100644
index 000000000000..3177b8c3d5f1
--- /dev/null
+++ b/drivers/crypto/nx/nx-sha512.c
@@ -0,0 +1,265 @@
1/**
2 * SHA-512 routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/hash.h>
23#include <crypto/sha.h>
24#include <linux/module.h>
25#include <asm/vio.h>
26
27#include "nx_csbcpb.h"
28#include "nx.h"
29
30
31static int nx_sha512_init(struct shash_desc *desc)
32{
33 struct sha512_state *sctx = shash_desc_ctx(desc);
34 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
35 struct nx_sg *out_sg;
36
37 nx_ctx_init(nx_ctx, HCOP_FC_SHA);
38
39 memset(sctx, 0, sizeof *sctx);
40
41 nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA512];
42
43 NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA512);
44 out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
45 SHA512_DIGEST_SIZE, nx_ctx->ap->sglen);
46 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
47
48 return 0;
49}
50
51static int nx_sha512_update(struct shash_desc *desc, const u8 *data,
52 unsigned int len)
53{
54 struct sha512_state *sctx = shash_desc_ctx(desc);
55 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
56 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
57 struct nx_sg *in_sg;
58 u64 to_process, leftover, spbc_bits;
59 int rc = 0;
60
61 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
62 /* we've hit the nx chip previously and we're updating again,
63 * so copy over the partial digest */
64 memcpy(csbcpb->cpb.sha512.input_partial_digest,
65 csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
66 }
67
68 /* 2 cases for total data len:
69 * 1: <= SHA512_BLOCK_SIZE: copy into state, return 0
70 * 2: > SHA512_BLOCK_SIZE: process X blocks, copy in leftover
71 */
72 if ((u64)len + sctx->count[0] <= SHA512_BLOCK_SIZE) {
73 memcpy(sctx->buf + sctx->count[0], data, len);
74 sctx->count[0] += len;
75 goto out;
76 }
77
78 /* to_process: the SHA512_BLOCK_SIZE data chunk to process in this
79 * update */
80 to_process = (sctx->count[0] + len) & ~(SHA512_BLOCK_SIZE - 1);
81 leftover = (sctx->count[0] + len) & (SHA512_BLOCK_SIZE - 1);
82
83 if (sctx->count[0]) {
84 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buf,
85 sctx->count[0], nx_ctx->ap->sglen);
86 in_sg = nx_build_sg_list(in_sg, (u8 *)data,
87 to_process - sctx->count[0],
88 nx_ctx->ap->sglen);
89 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
90 sizeof(struct nx_sg);
91 } else {
92 in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)data,
93 to_process, nx_ctx->ap->sglen);
94 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
95 sizeof(struct nx_sg);
96 }
97
98 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
99
100 if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
101 rc = -EINVAL;
102 goto out;
103 }
104
105 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
106 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
107 if (rc)
108 goto out;
109
110 atomic_inc(&(nx_ctx->stats->sha512_ops));
111
112 /* copy the leftover back into the state struct */
113 memcpy(sctx->buf, data + len - leftover, leftover);
114 sctx->count[0] = leftover;
115
116 spbc_bits = csbcpb->cpb.sha512.spbc * 8;
117 csbcpb->cpb.sha512.message_bit_length_lo += spbc_bits;
118 if (csbcpb->cpb.sha512.message_bit_length_lo < spbc_bits)
119 csbcpb->cpb.sha512.message_bit_length_hi++;
120
121 /* everything after the first update is continuation */
122 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
123out:
124 return rc;
125}
126
127static int nx_sha512_final(struct shash_desc *desc, u8 *out)
128{
129 struct sha512_state *sctx = shash_desc_ctx(desc);
130 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
131 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
132 struct nx_sg *in_sg, *out_sg;
133 u64 count0;
134 int rc;
135
136 if (NX_CPB_FDM(csbcpb) & NX_FDM_CONTINUATION) {
137 /* we've hit the nx chip previously, now we're finalizing,
138 * so copy over the partial digest */
139 memcpy(csbcpb->cpb.sha512.input_partial_digest,
140 csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
141 }
142
143 /* final is represented by continuing the operation and indicating that
144 * this is not an intermediate operation */
145 NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
146
147 count0 = sctx->count[0] * 8;
148
149 csbcpb->cpb.sha512.message_bit_length_lo += count0;
150 if (csbcpb->cpb.sha512.message_bit_length_lo < count0)
151 csbcpb->cpb.sha512.message_bit_length_hi++;
152
153 in_sg = nx_build_sg_list(nx_ctx->in_sg, sctx->buf, sctx->count[0],
154 nx_ctx->ap->sglen);
155 out_sg = nx_build_sg_list(nx_ctx->out_sg, out, SHA512_DIGEST_SIZE,
156 nx_ctx->ap->sglen);
157 nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
158 nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
159
160 if (!nx_ctx->op.outlen) {
161 rc = -EINVAL;
162 goto out;
163 }
164
165 rc = nx_hcall_sync(nx_ctx, &nx_ctx->op,
166 desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP);
167 if (rc)
168 goto out;
169
170 atomic_inc(&(nx_ctx->stats->sha512_ops));
171 atomic64_add(csbcpb->cpb.sha512.message_bit_length_lo,
172 &(nx_ctx->stats->sha512_bytes));
173
174 memcpy(out, csbcpb->cpb.sha512.message_digest, SHA512_DIGEST_SIZE);
175out:
176 return rc;
177}
178
179static int nx_sha512_export(struct shash_desc *desc, void *out)
180{
181 struct sha512_state *sctx = shash_desc_ctx(desc);
182 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
183 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
184 struct sha512_state *octx = out;
185
186 /* move message_bit_length (128 bits) into count and convert its value
187 * to bytes */
188 octx->count[0] = csbcpb->cpb.sha512.message_bit_length_lo >> 3 |
189 ((csbcpb->cpb.sha512.message_bit_length_hi & 7) << 61);
190 octx->count[1] = csbcpb->cpb.sha512.message_bit_length_hi >> 3;
191
192 octx->count[0] += sctx->count[0];
193 if (octx->count[0] < sctx->count[0])
194 octx->count[1]++;
195
196 memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
197
198 /* if no data has been processed yet, we need to export SHA512's
199 * initial data, in case this context gets imported into a software
200 * context */
201 if (csbcpb->cpb.sha512.message_bit_length_hi ||
202 csbcpb->cpb.sha512.message_bit_length_lo)
203 memcpy(octx->state, csbcpb->cpb.sha512.message_digest,
204 SHA512_DIGEST_SIZE);
205 else {
206 octx->state[0] = SHA512_H0;
207 octx->state[1] = SHA512_H1;
208 octx->state[2] = SHA512_H2;
209 octx->state[3] = SHA512_H3;
210 octx->state[4] = SHA512_H4;
211 octx->state[5] = SHA512_H5;
212 octx->state[6] = SHA512_H6;
213 octx->state[7] = SHA512_H7;
214 }
215
216 return 0;
217}
218
219static int nx_sha512_import(struct shash_desc *desc, const void *in)
220{
221 struct sha512_state *sctx = shash_desc_ctx(desc);
222 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
223 struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
224 const struct sha512_state *ictx = in;
225
226 memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
227 sctx->count[0] = ictx->count[0] & 0x3f;
228 csbcpb->cpb.sha512.message_bit_length_lo = (ictx->count[0] & ~0x3f)
229 << 3;
230 csbcpb->cpb.sha512.message_bit_length_hi = ictx->count[1] << 3 |
231 ictx->count[0] >> 61;
232
233 if (csbcpb->cpb.sha512.message_bit_length_hi ||
234 csbcpb->cpb.sha512.message_bit_length_lo) {
235 memcpy(csbcpb->cpb.sha512.message_digest, ictx->state,
236 SHA512_DIGEST_SIZE);
237
238 NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
239 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
240 }
241
242 return 0;
243}
244
245struct shash_alg nx_shash_sha512_alg = {
246 .digestsize = SHA512_DIGEST_SIZE,
247 .init = nx_sha512_init,
248 .update = nx_sha512_update,
249 .final = nx_sha512_final,
250 .export = nx_sha512_export,
251 .import = nx_sha512_import,
252 .descsize = sizeof(struct sha512_state),
253 .statesize = sizeof(struct sha512_state),
254 .base = {
255 .cra_name = "sha512",
256 .cra_driver_name = "sha512-nx",
257 .cra_priority = 300,
258 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
259 .cra_blocksize = SHA512_BLOCK_SIZE,
260 .cra_module = THIS_MODULE,
261 .cra_ctxsize = sizeof(struct nx_crypto_ctx),
262 .cra_init = nx_crypto_ctx_sha_init,
263 .cra_exit = nx_crypto_ctx_exit,
264 }
265};
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
new file mode 100644
index 000000000000..d7f179cc2e98
--- /dev/null
+++ b/drivers/crypto/nx/nx.c
@@ -0,0 +1,716 @@
1/**
2 * Routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <crypto/internal/hash.h>
23#include <crypto/hash.h>
24#include <crypto/aes.h>
25#include <crypto/sha.h>
26#include <crypto/algapi.h>
27#include <crypto/scatterwalk.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
30#include <linux/types.h>
31#include <linux/mm.h>
32#include <linux/crypto.h>
33#include <linux/scatterlist.h>
34#include <linux/device.h>
35#include <linux/of.h>
36#include <asm/pSeries_reconfig.h>
37#include <asm/abs_addr.h>
38#include <asm/hvcall.h>
39#include <asm/vio.h>
40
41#include "nx_csbcpb.h"
42#include "nx.h"
43
44
45/**
46 * nx_hcall_sync - make an H_COP_OP hcall for the passed in op structure
47 *
48 * @nx_ctx: the crypto context handle
49 * @op: PFO operation struct to pass in
50 * @may_sleep: flag indicating the request can sleep
51 *
52 * Make the hcall, retrying while the hardware is busy. If we cannot yield
53 * the thread, limit the number of retries to 10 here.
54 */
55int nx_hcall_sync(struct nx_crypto_ctx *nx_ctx,
56 struct vio_pfo_op *op,
57 u32 may_sleep)
58{
59 int rc, retries = 10;
60 struct vio_dev *viodev = nx_driver.viodev;
61
62 atomic_inc(&(nx_ctx->stats->sync_ops));
63
64 do {
65 rc = vio_h_cop_sync(viodev, op);
66 } while ((rc == -EBUSY && !may_sleep && retries--) ||
67 (rc == -EBUSY && may_sleep && cond_resched()));
68
69 if (rc) {
70 dev_dbg(&viodev->dev, "vio_h_cop_sync failed: rc: %d "
71 "hcall rc: %ld\n", rc, op->hcall_err);
72 atomic_inc(&(nx_ctx->stats->errors));
73 atomic_set(&(nx_ctx->stats->last_error), op->hcall_err);
74 atomic_set(&(nx_ctx->stats->last_error_pid), current->pid);
75 }
76
77 return rc;
78}
79
80/**
81 * nx_build_sg_list - build an NX scatter list describing a single buffer
82 *
83 * @sg_head: pointer to the first scatter list element to build
84 * @start_addr: pointer to the linear buffer
85 * @len: length of the data at @start_addr
86 * @sgmax: the largest number of scatter list elements we're allowed to create
87 *
88 * This function will start writing nx_sg elements at @sg_head and keep
89 * writing them until all of the data from @start_addr is described or
90 * until sgmax elements have been written. Scatter list elements will be
91 * created such that none of the elements describes a buffer that crosses a 4K
92 * boundary.
93 */
94struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
95 u8 *start_addr,
96 unsigned int len,
97 u32 sgmax)
98{
99 unsigned int sg_len = 0;
100 struct nx_sg *sg;
101 u64 sg_addr = (u64)start_addr;
102 u64 end_addr;
103
104 /* determine the start and end for this address range - slightly
105 * different if this is in VMALLOC_REGION */
106 if (is_vmalloc_addr(start_addr))
107 sg_addr = phys_to_abs(page_to_phys(vmalloc_to_page(start_addr)))
108 + offset_in_page(sg_addr);
109 else
110 sg_addr = virt_to_abs(sg_addr);
111
112 end_addr = sg_addr + len;
113
114 /* each iteration will write one struct nx_sg element and add the
115 * length of data described by that element to sg_len. Once @len bytes
116 * have been described (or @sgmax elements have been written), the
117 * loop ends. min_t is used to ensure @end_addr falls on the same page
118 * as sg_addr, if not, we need to create another nx_sg element for the
119 * data on the next page */
120 for (sg = sg_head; sg_len < len; sg++) {
121 sg->addr = sg_addr;
122 sg_addr = min_t(u64, NX_PAGE_NUM(sg_addr + NX_PAGE_SIZE), end_addr);
123 sg->len = sg_addr - sg->addr;
124 sg_len += sg->len;
125
126 if ((sg - sg_head) == sgmax) {
127 pr_err("nx: scatter/gather list overflow, pid: %d\n",
128 current->pid);
129 return NULL;
130 }
131 }
132
133 /* return the moved sg_head pointer */
134 return sg;
135}
136
137/**
138 * nx_walk_and_build - walk a linux scatterlist and build an nx scatterlist
139 *
140 * @nx_dst: pointer to the first nx_sg element to write
141 * @sglen: max number of nx_sg entries we're allowed to write
142 * @sg_src: pointer to the source linux scatterlist to walk
143 * @start: number of bytes to fast-forward past at the beginning of @sg_src
144 * @src_len: number of bytes to walk in @sg_src
145 */
146struct nx_sg *nx_walk_and_build(struct nx_sg *nx_dst,
147 unsigned int sglen,
148 struct scatterlist *sg_src,
149 unsigned int start,
150 unsigned int src_len)
151{
152 struct scatter_walk walk;
153 struct nx_sg *nx_sg = nx_dst;
154 unsigned int n, offset = 0, len = src_len;
155 char *dst;
156
157 /* we need to fast forward through @start bytes first */
158 for (;;) {
159 scatterwalk_start(&walk, sg_src);
160
161 if (start < offset + sg_src->length)
162 break;
163
164 offset += sg_src->length;
165 sg_src = scatterwalk_sg_next(sg_src);
166 }
167
168 /* start - offset is the number of bytes to advance in the scatterlist
169 * element we're currently looking at */
170 scatterwalk_advance(&walk, start - offset);
171
172 while (len && nx_sg) {
173 n = scatterwalk_clamp(&walk, len);
174 if (!n) {
175 scatterwalk_start(&walk, sg_next(walk.sg));
176 n = scatterwalk_clamp(&walk, len);
177 }
178 dst = scatterwalk_map(&walk);
179
180 nx_sg = nx_build_sg_list(nx_sg, dst, n, sglen);
181 len -= n;
182
183 scatterwalk_unmap(dst);
184 scatterwalk_advance(&walk, n);
185 scatterwalk_done(&walk, SCATTERWALK_FROM_SG, len);
186 }
187
188 /* return the moved destination pointer */
189 return nx_sg;
190}
191
192/**
193 * nx_build_sg_lists - walk the input scatterlists and build arrays of NX
194 * scatterlists based on them.
195 *
196 * @nx_ctx: NX crypto context for the lists we're building
197 * @desc: the block cipher descriptor for the operation
198 * @dst: destination scatterlist
199 * @src: source scatterlist
200 * @nbytes: length of data described in the scatterlists
201 * @iv: destination for the iv data, if the algorithm requires it
202 *
203 * This is common code shared by all the AES algorithms. It uses the block
204 * cipher walk routines to traverse input and output scatterlists, building
205 * corresponding NX scatterlists
206 */
207int nx_build_sg_lists(struct nx_crypto_ctx *nx_ctx,
208 struct blkcipher_desc *desc,
209 struct scatterlist *dst,
210 struct scatterlist *src,
211 unsigned int nbytes,
212 u8 *iv)
213{
214 struct nx_sg *nx_insg = nx_ctx->in_sg;
215 struct nx_sg *nx_outsg = nx_ctx->out_sg;
216 struct blkcipher_walk walk;
217 int rc;
218
219 blkcipher_walk_init(&walk, dst, src, nbytes);
220 rc = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
221 if (rc)
222 goto out;
223
224 if (iv)
225 memcpy(iv, walk.iv, AES_BLOCK_SIZE);
226
227 while (walk.nbytes) {
228 nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
229 walk.nbytes, nx_ctx->ap->sglen);
230 nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
231 walk.nbytes, nx_ctx->ap->sglen);
232
233 rc = blkcipher_walk_done(desc, &walk, 0);
234 if (rc)
235 break;
236 }
237
238 if (walk.nbytes) {
239 nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
240 walk.nbytes, nx_ctx->ap->sglen);
241 nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
242 walk.nbytes, nx_ctx->ap->sglen);
243
244 rc = 0;
245 }
246
247 /* these lengths should be negative, which will indicate to phyp that
248 * the input and output parameters are scatterlists, not linear
249 * buffers */
250 nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) * sizeof(struct nx_sg);
251 nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) * sizeof(struct nx_sg);
252out:
253 return rc;
254}
255
256/**
257 * nx_ctx_init - initialize an nx_ctx's vio_pfo_op struct
258 *
259 * @nx_ctx: the nx context to initialize
260 * @function: the function code for the op
261 */
262void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
263{
264 memset(nx_ctx->kmem, 0, nx_ctx->kmem_len);
265 nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
266
267 nx_ctx->op.flags = function;
268 nx_ctx->op.csbcpb = virt_to_abs(nx_ctx->csbcpb);
269 nx_ctx->op.in = virt_to_abs(nx_ctx->in_sg);
270 nx_ctx->op.out = virt_to_abs(nx_ctx->out_sg);
271
272 if (nx_ctx->csbcpb_aead) {
273 nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
274
275 nx_ctx->op_aead.flags = function;
276 nx_ctx->op_aead.csbcpb = virt_to_abs(nx_ctx->csbcpb_aead);
277 nx_ctx->op_aead.in = virt_to_abs(nx_ctx->in_sg);
278 nx_ctx->op_aead.out = virt_to_abs(nx_ctx->out_sg);
279 }
280}
281
282static void nx_of_update_status(struct device *dev,
283 struct property *p,
284 struct nx_of *props)
285{
286 if (!strncmp(p->value, "okay", p->length)) {
287 props->status = NX_WAITING;
288 props->flags |= NX_OF_FLAG_STATUS_SET;
289 } else {
290 dev_info(dev, "%s: status '%s' is not 'okay'\n", __func__,
291 (char *)p->value);
292 }
293}
294
295static void nx_of_update_sglen(struct device *dev,
296 struct property *p,
297 struct nx_of *props)
298{
299 if (p->length != sizeof(props->max_sg_len)) {
300 dev_err(dev, "%s: unexpected format for "
301 "ibm,max-sg-len property\n", __func__);
302 dev_dbg(dev, "%s: ibm,max-sg-len is %d bytes "
303 "long, expected %zd bytes\n", __func__,
304 p->length, sizeof(props->max_sg_len));
305 return;
306 }
307
308 props->max_sg_len = *(u32 *)p->value;
309 props->flags |= NX_OF_FLAG_MAXSGLEN_SET;
310}
311
312static void nx_of_update_msc(struct device *dev,
313 struct property *p,
314 struct nx_of *props)
315{
316 struct msc_triplet *trip;
317 struct max_sync_cop *msc;
318 unsigned int bytes_so_far, i, lenp;
319
320 msc = (struct max_sync_cop *)p->value;
321 lenp = p->length;
322
323 /* You can't tell if the data read in for this property is sane by its
324 * size alone. This is because there are sizes embedded in the data
325 * structure. The best we can do is check lengths as we parse and bail
326 * as soon as a length error is detected. */
327 bytes_so_far = 0;
328
329 while ((bytes_so_far + sizeof(struct max_sync_cop)) <= lenp) {
330 bytes_so_far += sizeof(struct max_sync_cop);
331
332 trip = msc->trip;
333
334 for (i = 0;
335 ((bytes_so_far + sizeof(struct msc_triplet)) <= lenp) &&
336 i < msc->triplets;
337 i++) {
338 if (msc->fc > NX_MAX_FC || msc->mode > NX_MAX_MODE) {
339 dev_err(dev, "unknown function code/mode "
340 "combo: %d/%d (ignored)\n", msc->fc,
341 msc->mode);
342 goto next_loop;
343 }
344
345 switch (trip->keybitlen) {
346 case 128:
347 case 160:
348 props->ap[msc->fc][msc->mode][0].databytelen =
349 trip->databytelen;
350 props->ap[msc->fc][msc->mode][0].sglen =
351 trip->sglen;
352 break;
353 case 192:
354 props->ap[msc->fc][msc->mode][1].databytelen =
355 trip->databytelen;
356 props->ap[msc->fc][msc->mode][1].sglen =
357 trip->sglen;
358 break;
359 case 256:
360 if (msc->fc == NX_FC_AES) {
361 props->ap[msc->fc][msc->mode][2].
362 databytelen = trip->databytelen;
363 props->ap[msc->fc][msc->mode][2].sglen =
364 trip->sglen;
365 } else if (msc->fc == NX_FC_AES_HMAC ||
366 msc->fc == NX_FC_SHA) {
367 props->ap[msc->fc][msc->mode][1].
368 databytelen = trip->databytelen;
369 props->ap[msc->fc][msc->mode][1].sglen =
370 trip->sglen;
371 } else {
372 dev_warn(dev, "unknown function "
373 "code/key bit len combo"
374 ": (%u/256)\n", msc->fc);
375 }
376 break;
377 case 512:
378 props->ap[msc->fc][msc->mode][2].databytelen =
379 trip->databytelen;
380 props->ap[msc->fc][msc->mode][2].sglen =
381 trip->sglen;
382 break;
383 default:
384 dev_warn(dev, "unknown function code/key bit "
385 "len combo: (%u/%u)\n", msc->fc,
386 trip->keybitlen);
387 break;
388 }
389next_loop:
390 bytes_so_far += sizeof(struct msc_triplet);
391 trip++;
392 }
393
394 msc = (struct max_sync_cop *)trip;
395 }
396
397 props->flags |= NX_OF_FLAG_MAXSYNCCOP_SET;
398}
399
400/**
401 * nx_of_init - read openFirmware values from the device tree
402 *
403 * @dev: device handle
404 * @props: pointer to struct to hold the properties values
405 *
406 * Called once at driver probe time, this function will read out the
407 * openFirmware properties we use at runtime. If all the OF properties are
408 * acceptable, when we exit this function props->flags will indicate that
409 * we're ready to register our crypto algorithms.
410 */
411static void nx_of_init(struct device *dev, struct nx_of *props)
412{
413 struct device_node *base_node = dev->of_node;
414 struct property *p;
415
416 p = of_find_property(base_node, "status", NULL);
417 if (!p)
418 dev_info(dev, "%s: property 'status' not found\n", __func__);
419 else
420 nx_of_update_status(dev, p, props);
421
422 p = of_find_property(base_node, "ibm,max-sg-len", NULL);
423 if (!p)
424 dev_info(dev, "%s: property 'ibm,max-sg-len' not found\n",
425 __func__);
426 else
427 nx_of_update_sglen(dev, p, props);
428
429 p = of_find_property(base_node, "ibm,max-sync-cop", NULL);
430 if (!p)
431 dev_info(dev, "%s: property 'ibm,max-sync-cop' not found\n",
432 __func__);
433 else
434 nx_of_update_msc(dev, p, props);
435}
436
437/**
438 * nx_register_algs - register algorithms with the crypto API
439 *
440 * Called from nx_probe()
441 *
442 * If all OF properties are in an acceptable state, the driver flags will
443 * indicate that we're ready and we'll create our debugfs files and register
444 * out crypto algorithms.
445 */
446static int nx_register_algs(void)
447{
448 int rc = -1;
449
450 if (nx_driver.of.flags != NX_OF_FLAG_MASK_READY)
451 goto out;
452
453 memset(&nx_driver.stats, 0, sizeof(struct nx_stats));
454
455 rc = NX_DEBUGFS_INIT(&nx_driver);
456 if (rc)
457 goto out;
458
459 rc = crypto_register_alg(&nx_ecb_aes_alg);
460 if (rc)
461 goto out;
462
463 rc = crypto_register_alg(&nx_cbc_aes_alg);
464 if (rc)
465 goto out_unreg_ecb;
466
467 rc = crypto_register_alg(&nx_ctr_aes_alg);
468 if (rc)
469 goto out_unreg_cbc;
470
471 rc = crypto_register_alg(&nx_ctr3686_aes_alg);
472 if (rc)
473 goto out_unreg_ctr;
474
475 rc = crypto_register_alg(&nx_gcm_aes_alg);
476 if (rc)
477 goto out_unreg_ctr3686;
478
479 rc = crypto_register_alg(&nx_gcm4106_aes_alg);
480 if (rc)
481 goto out_unreg_gcm;
482
483 rc = crypto_register_alg(&nx_ccm_aes_alg);
484 if (rc)
485 goto out_unreg_gcm4106;
486
487 rc = crypto_register_alg(&nx_ccm4309_aes_alg);
488 if (rc)
489 goto out_unreg_ccm;
490
491 rc = crypto_register_shash(&nx_shash_sha256_alg);
492 if (rc)
493 goto out_unreg_ccm4309;
494
495 rc = crypto_register_shash(&nx_shash_sha512_alg);
496 if (rc)
497 goto out_unreg_s256;
498
499 rc = crypto_register_shash(&nx_shash_aes_xcbc_alg);
500 if (rc)
501 goto out_unreg_s512;
502
503 nx_driver.of.status = NX_OKAY;
504
505 goto out;
506
507out_unreg_s512:
508 crypto_unregister_shash(&nx_shash_sha512_alg);
509out_unreg_s256:
510 crypto_unregister_shash(&nx_shash_sha256_alg);
511out_unreg_ccm4309:
512 crypto_unregister_alg(&nx_ccm4309_aes_alg);
513out_unreg_ccm:
514 crypto_unregister_alg(&nx_ccm_aes_alg);
515out_unreg_gcm4106:
516 crypto_unregister_alg(&nx_gcm4106_aes_alg);
517out_unreg_gcm:
518 crypto_unregister_alg(&nx_gcm_aes_alg);
519out_unreg_ctr3686:
520 crypto_unregister_alg(&nx_ctr3686_aes_alg);
521out_unreg_ctr:
522 crypto_unregister_alg(&nx_ctr_aes_alg);
523out_unreg_cbc:
524 crypto_unregister_alg(&nx_cbc_aes_alg);
525out_unreg_ecb:
526 crypto_unregister_alg(&nx_ecb_aes_alg);
527out:
528 return rc;
529}
530
531/**
532 * nx_crypto_ctx_init - create and initialize a crypto api context
533 *
534 * @nx_ctx: the crypto api context
535 * @fc: function code for the context
536 * @mode: the function code specific mode for this context
537 */
538static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode)
539{
540 if (nx_driver.of.status != NX_OKAY) {
541 pr_err("Attempt to initialize NX crypto context while device "
542 "is not available!\n");
543 return -ENODEV;
544 }
545
546 /* we need an extra page for csbcpb_aead for these modes */
547 if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
548 nx_ctx->kmem_len = (4 * NX_PAGE_SIZE) +
549 sizeof(struct nx_csbcpb);
550 else
551 nx_ctx->kmem_len = (3 * NX_PAGE_SIZE) +
552 sizeof(struct nx_csbcpb);
553
554 nx_ctx->kmem = kmalloc(nx_ctx->kmem_len, GFP_KERNEL);
555 if (!nx_ctx->kmem)
556 return -ENOMEM;
557
558 /* the csbcpb and scatterlists must be 4K aligned pages */
559 nx_ctx->csbcpb = (struct nx_csbcpb *)(round_up((u64)nx_ctx->kmem,
560 (u64)NX_PAGE_SIZE));
561 nx_ctx->in_sg = (struct nx_sg *)((u8 *)nx_ctx->csbcpb + NX_PAGE_SIZE);
562 nx_ctx->out_sg = (struct nx_sg *)((u8 *)nx_ctx->in_sg + NX_PAGE_SIZE);
563
564 if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
565 nx_ctx->csbcpb_aead =
566 (struct nx_csbcpb *)((u8 *)nx_ctx->out_sg +
567 NX_PAGE_SIZE);
568
569 /* give each context a pointer to global stats and their OF
570 * properties */
571 nx_ctx->stats = &nx_driver.stats;
572 memcpy(nx_ctx->props, nx_driver.of.ap[fc][mode],
573 sizeof(struct alg_props) * 3);
574
575 return 0;
576}
577
578/* entry points from the crypto tfm initializers */
579int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm)
580{
581 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
582 NX_MODE_AES_CCM);
583}
584
585int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm)
586{
587 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
588 NX_MODE_AES_GCM);
589}
590
591int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm)
592{
593 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
594 NX_MODE_AES_CTR);
595}
596
597int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm)
598{
599 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
600 NX_MODE_AES_CBC);
601}
602
603int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm)
604{
605 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
606 NX_MODE_AES_ECB);
607}
608
609int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm)
610{
611 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_SHA, NX_MODE_SHA);
612}
613
614int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm)
615{
616 return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
617 NX_MODE_AES_XCBC_MAC);
618}
619
620/**
621 * nx_crypto_ctx_exit - destroy a crypto api context
622 *
623 * @tfm: the crypto transform pointer for the context
624 *
625 * As crypto API contexts are destroyed, this exit hook is called to free the
626 * memory associated with it.
627 */
628void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
629{
630 struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
631
632 kzfree(nx_ctx->kmem);
633 nx_ctx->csbcpb = NULL;
634 nx_ctx->csbcpb_aead = NULL;
635 nx_ctx->in_sg = NULL;
636 nx_ctx->out_sg = NULL;
637}
638
639static int __devinit nx_probe(struct vio_dev *viodev,
640 const struct vio_device_id *id)
641{
642 dev_dbg(&viodev->dev, "driver probed: %s resource id: 0x%x\n",
643 viodev->name, viodev->resource_id);
644
645 if (nx_driver.viodev) {
646 dev_err(&viodev->dev, "%s: Attempt to register more than one "
647 "instance of the hardware\n", __func__);
648 return -EINVAL;
649 }
650
651 nx_driver.viodev = viodev;
652
653 nx_of_init(&viodev->dev, &nx_driver.of);
654
655 return nx_register_algs();
656}
657
658static int __devexit nx_remove(struct vio_dev *viodev)
659{
660 dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
661 viodev->unit_address);
662
663 if (nx_driver.of.status == NX_OKAY) {
664 NX_DEBUGFS_FINI(&nx_driver);
665
666 crypto_unregister_alg(&nx_ccm_aes_alg);
667 crypto_unregister_alg(&nx_ccm4309_aes_alg);
668 crypto_unregister_alg(&nx_gcm_aes_alg);
669 crypto_unregister_alg(&nx_gcm4106_aes_alg);
670 crypto_unregister_alg(&nx_ctr_aes_alg);
671 crypto_unregister_alg(&nx_ctr3686_aes_alg);
672 crypto_unregister_alg(&nx_cbc_aes_alg);
673 crypto_unregister_alg(&nx_ecb_aes_alg);
674 crypto_unregister_shash(&nx_shash_sha256_alg);
675 crypto_unregister_shash(&nx_shash_sha512_alg);
676 crypto_unregister_shash(&nx_shash_aes_xcbc_alg);
677 }
678
679 return 0;
680}
681
682
683/* module wide initialization/cleanup */
684static int __init nx_init(void)
685{
686 return vio_register_driver(&nx_driver.viodriver);
687}
688
689static void __exit nx_fini(void)
690{
691 vio_unregister_driver(&nx_driver.viodriver);
692}
693
694static struct vio_device_id nx_crypto_driver_ids[] __devinitdata = {
695 { "ibm,sym-encryption-v1", "ibm,sym-encryption" },
696 { "", "" }
697};
698MODULE_DEVICE_TABLE(vio, nx_crypto_driver_ids);
699
700/* driver state structure */
701struct nx_crypto_driver nx_driver = {
702 .viodriver = {
703 .id_table = nx_crypto_driver_ids,
704 .probe = nx_probe,
705 .remove = nx_remove,
706 .name = NX_NAME,
707 },
708};
709
710module_init(nx_init);
711module_exit(nx_fini);
712
713MODULE_AUTHOR("Kent Yoder <yoder1@us.ibm.com>");
714MODULE_DESCRIPTION(NX_STRING);
715MODULE_LICENSE("GPL");
716MODULE_VERSION(NX_VERSION);
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
new file mode 100644
index 000000000000..3232b182dd28
--- /dev/null
+++ b/drivers/crypto/nx/nx.h
@@ -0,0 +1,193 @@
1
2#ifndef __NX_H__
3#define __NX_H__
4
5#define NX_NAME "nx-crypto"
6#define NX_STRING "IBM Power7+ Nest Accelerator Crypto Driver"
7#define NX_VERSION "1.0"
8
9static const char nx_driver_string[] = NX_STRING;
10static const char nx_driver_version[] = NX_VERSION;
11
12/* a scatterlist in the format PHYP is expecting */
13struct nx_sg {
14 u64 addr;
15 u32 rsvd;
16 u32 len;
17} __attribute((packed));
18
19#define NX_PAGE_SIZE (4096)
20#define NX_MAX_SG_ENTRIES (NX_PAGE_SIZE/(sizeof(struct nx_sg)))
21
22enum nx_status {
23 NX_DISABLED,
24 NX_WAITING,
25 NX_OKAY
26};
27
28/* msc_triplet and max_sync_cop are used only to assist in parsing the
29 * openFirmware property */
30struct msc_triplet {
31 u32 keybitlen;
32 u32 databytelen;
33 u32 sglen;
34} __packed;
35
36struct max_sync_cop {
37 u32 fc;
38 u32 mode;
39 u32 triplets;
40 struct msc_triplet trip[0];
41} __packed;
42
43struct alg_props {
44 u32 databytelen;
45 u32 sglen;
46};
47
48#define NX_OF_FLAG_MAXSGLEN_SET (1)
49#define NX_OF_FLAG_STATUS_SET (2)
50#define NX_OF_FLAG_MAXSYNCCOP_SET (4)
51#define NX_OF_FLAG_MASK_READY (NX_OF_FLAG_MAXSGLEN_SET | \
52 NX_OF_FLAG_STATUS_SET | \
53 NX_OF_FLAG_MAXSYNCCOP_SET)
54struct nx_of {
55 u32 flags;
56 u32 max_sg_len;
57 enum nx_status status;
58 struct alg_props ap[NX_MAX_FC][NX_MAX_MODE][3];
59};
60
61struct nx_stats {
62 atomic_t aes_ops;
63 atomic64_t aes_bytes;
64 atomic_t sha256_ops;
65 atomic64_t sha256_bytes;
66 atomic_t sha512_ops;
67 atomic64_t sha512_bytes;
68
69 atomic_t sync_ops;
70
71 atomic_t errors;
72 atomic_t last_error;
73 atomic_t last_error_pid;
74};
75
76struct nx_debugfs {
77 struct dentry *dfs_root;
78 struct dentry *dfs_aes_ops, *dfs_aes_bytes;
79 struct dentry *dfs_sha256_ops, *dfs_sha256_bytes;
80 struct dentry *dfs_sha512_ops, *dfs_sha512_bytes;
81 struct dentry *dfs_errors, *dfs_last_error, *dfs_last_error_pid;
82};
83
84struct nx_crypto_driver {
85 struct nx_stats stats;
86 struct nx_of of;
87 struct vio_dev *viodev;
88 struct vio_driver viodriver;
89 struct nx_debugfs dfs;
90};
91
92#define NX_GCM4106_NONCE_LEN (4)
93#define NX_GCM_CTR_OFFSET (12)
94struct nx_gcm_priv {
95 u8 iv[16];
96 u8 iauth_tag[16];
97 u8 nonce[NX_GCM4106_NONCE_LEN];
98};
99
100#define NX_CCM_AES_KEY_LEN (16)
101#define NX_CCM4309_AES_KEY_LEN (19)
102#define NX_CCM4309_NONCE_LEN (3)
103struct nx_ccm_priv {
104 u8 iv[16];
105 u8 b0[16];
106 u8 iauth_tag[16];
107 u8 oauth_tag[16];
108 u8 nonce[NX_CCM4309_NONCE_LEN];
109};
110
111struct nx_xcbc_priv {
112 u8 key[16];
113};
114
115struct nx_ctr_priv {
116 u8 iv[16];
117};
118
119struct nx_crypto_ctx {
120 void *kmem; /* unaligned, kmalloc'd buffer */
121 size_t kmem_len; /* length of kmem */
122 struct nx_csbcpb *csbcpb; /* aligned page given to phyp @ hcall time */
123 struct vio_pfo_op op; /* operation struct with hcall parameters */
124 struct nx_csbcpb *csbcpb_aead; /* secondary csbcpb used by AEAD algs */
125 struct vio_pfo_op op_aead;/* operation struct for csbcpb_aead */
126
127 struct nx_sg *in_sg; /* aligned pointer into kmem to an sg list */
128 struct nx_sg *out_sg; /* aligned pointer into kmem to an sg list */
129
130 struct alg_props *ap; /* pointer into props based on our key size */
131 struct alg_props props[3];/* openFirmware properties for requests */
132 struct nx_stats *stats; /* pointer into an nx_crypto_driver for stats
133 reporting */
134
135 union {
136 struct nx_gcm_priv gcm;
137 struct nx_ccm_priv ccm;
138 struct nx_xcbc_priv xcbc;
139 struct nx_ctr_priv ctr;
140 } priv;
141};
142
143/* prototypes */
144int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm);
145int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm);
146int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm);
147int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm);
148int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm);
149int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm);
150int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm);
151void nx_crypto_ctx_exit(struct crypto_tfm *tfm);
152void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function);
153int nx_hcall_sync(struct nx_crypto_ctx *ctx, struct vio_pfo_op *op,
154 u32 may_sleep);
155struct nx_sg *nx_build_sg_list(struct nx_sg *, u8 *, unsigned int, u32);
156int nx_build_sg_lists(struct nx_crypto_ctx *, struct blkcipher_desc *,
157 struct scatterlist *, struct scatterlist *, unsigned int,
158 u8 *);
159struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int,
160 struct scatterlist *, unsigned int,
161 unsigned int);
162
163#ifdef CONFIG_DEBUG_FS
164#define NX_DEBUGFS_INIT(drv) nx_debugfs_init(drv)
165#define NX_DEBUGFS_FINI(drv) nx_debugfs_fini(drv)
166
167int nx_debugfs_init(struct nx_crypto_driver *);
168void nx_debugfs_fini(struct nx_crypto_driver *);
169#else
170#define NX_DEBUGFS_INIT(drv) (0)
171#define NX_DEBUGFS_FINI(drv) (0)
172#endif
173
174#define NX_PAGE_NUM(x) ((u64)(x) & 0xfffffffffffff000ULL)
175
176extern struct crypto_alg nx_cbc_aes_alg;
177extern struct crypto_alg nx_ecb_aes_alg;
178extern struct crypto_alg nx_gcm_aes_alg;
179extern struct crypto_alg nx_gcm4106_aes_alg;
180extern struct crypto_alg nx_ctr_aes_alg;
181extern struct crypto_alg nx_ctr3686_aes_alg;
182extern struct crypto_alg nx_ccm_aes_alg;
183extern struct crypto_alg nx_ccm4309_aes_alg;
184extern struct shash_alg nx_shash_aes_xcbc_alg;
185extern struct shash_alg nx_shash_sha512_alg;
186extern struct shash_alg nx_shash_sha256_alg;
187
188extern struct nx_crypto_driver nx_driver;
189
190#define SCATTERWALK_TO_SG 1
191#define SCATTERWALK_FROM_SG 0
192
193#endif
diff --git a/drivers/crypto/nx/nx_csbcpb.h b/drivers/crypto/nx/nx_csbcpb.h
new file mode 100644
index 000000000000..a304f956d6f8
--- /dev/null
+++ b/drivers/crypto/nx/nx_csbcpb.h
@@ -0,0 +1,205 @@
1
2#ifndef __NX_CSBCPB_H__
3#define __NX_CSBCPB_H__
4
5struct cop_symcpb_aes_ecb {
6 u8 key[32];
7 u8 __rsvd[80];
8} __packed;
9
10struct cop_symcpb_aes_cbc {
11 u8 iv[16];
12 u8 key[32];
13 u8 cv[16];
14 u32 spbc;
15 u8 __rsvd[44];
16} __packed;
17
18struct cop_symcpb_aes_gca {
19 u8 in_pat[16];
20 u8 key[32];
21 u8 out_pat[16];
22 u32 spbc;
23 u8 __rsvd[44];
24} __packed;
25
26struct cop_symcpb_aes_gcm {
27 u8 in_pat_or_aad[16];
28 u8 iv_or_cnt[16];
29 u64 bit_length_aad;
30 u64 bit_length_data;
31 u8 in_s0[16];
32 u8 key[32];
33 u8 __rsvd1[16];
34 u8 out_pat_or_mac[16];
35 u8 out_s0[16];
36 u8 out_cnt[16];
37 u32 spbc;
38 u8 __rsvd2[12];
39} __packed;
40
41struct cop_symcpb_aes_ctr {
42 u8 iv[16];
43 u8 key[32];
44 u8 cv[16];
45 u32 spbc;
46 u8 __rsvd2[44];
47} __packed;
48
49struct cop_symcpb_aes_cca {
50 u8 b0[16];
51 u8 b1[16];
52 u8 key[16];
53 u8 out_pat_or_b0[16];
54 u32 spbc;
55 u8 __rsvd[44];
56} __packed;
57
58struct cop_symcpb_aes_ccm {
59 u8 in_pat_or_b0[16];
60 u8 iv_or_ctr[16];
61 u8 in_s0[16];
62 u8 key[16];
63 u8 __rsvd1[48];
64 u8 out_pat_or_mac[16];
65 u8 out_s0[16];
66 u8 out_ctr[16];
67 u32 spbc;
68 u8 __rsvd2[12];
69} __packed;
70
71struct cop_symcpb_aes_xcbc {
72 u8 cv[16];
73 u8 key[16];
74 u8 __rsvd1[16];
75 u8 out_cv_mac[16];
76 u32 spbc;
77 u8 __rsvd2[44];
78} __packed;
79
80struct cop_symcpb_sha256 {
81 u64 message_bit_length;
82 u64 __rsvd1;
83 u8 input_partial_digest[32];
84 u8 message_digest[32];
85 u32 spbc;
86 u8 __rsvd2[44];
87} __packed;
88
89struct cop_symcpb_sha512 {
90 u64 message_bit_length_hi;
91 u64 message_bit_length_lo;
92 u8 input_partial_digest[64];
93 u8 __rsvd1[32];
94 u8 message_digest[64];
95 u32 spbc;
96 u8 __rsvd2[76];
97} __packed;
98
99#define NX_FDM_INTERMEDIATE 0x01
100#define NX_FDM_CONTINUATION 0x02
101#define NX_FDM_ENDE_ENCRYPT 0x80
102
103#define NX_CPB_FDM(c) ((c)->cpb.hdr.fdm)
104#define NX_CPB_KS_DS(c) ((c)->cpb.hdr.ks_ds)
105
106#define NX_CPB_KEY_SIZE(c) (NX_CPB_KS_DS(c) >> 4)
107#define NX_CPB_SET_KEY_SIZE(c, x) NX_CPB_KS_DS(c) |= ((x) << 4)
108#define NX_CPB_SET_DIGEST_SIZE(c, x) NX_CPB_KS_DS(c) |= (x)
109
110struct cop_symcpb_header {
111 u8 mode;
112 u8 fdm;
113 u8 ks_ds;
114 u8 pad_byte;
115 u8 __rsvd[12];
116} __packed;
117
118struct cop_parameter_block {
119 struct cop_symcpb_header hdr;
120 union {
121 struct cop_symcpb_aes_ecb aes_ecb;
122 struct cop_symcpb_aes_cbc aes_cbc;
123 struct cop_symcpb_aes_gca aes_gca;
124 struct cop_symcpb_aes_gcm aes_gcm;
125 struct cop_symcpb_aes_cca aes_cca;
126 struct cop_symcpb_aes_ccm aes_ccm;
127 struct cop_symcpb_aes_ctr aes_ctr;
128 struct cop_symcpb_aes_xcbc aes_xcbc;
129 struct cop_symcpb_sha256 sha256;
130 struct cop_symcpb_sha512 sha512;
131 };
132} __packed;
133
134#define NX_CSB_VALID_BIT 0x80
135
136/* co-processor status block */
137struct cop_status_block {
138 u8 valid;
139 u8 crb_seq_number;
140 u8 completion_code;
141 u8 completion_extension;
142 u32 processed_byte_count;
143 u64 address;
144} __packed;
145
146/* Nest accelerator workbook section 4.4 */
147struct nx_csbcpb {
148 unsigned char __rsvd[112];
149 struct cop_status_block csb;
150 struct cop_parameter_block cpb;
151} __packed;
152
153/* nx_csbcpb related definitions */
154#define NX_MODE_AES_ECB 0
155#define NX_MODE_AES_CBC 1
156#define NX_MODE_AES_GMAC 2
157#define NX_MODE_AES_GCA 3
158#define NX_MODE_AES_GCM 4
159#define NX_MODE_AES_CCA 5
160#define NX_MODE_AES_CCM 6
161#define NX_MODE_AES_CTR 7
162#define NX_MODE_AES_XCBC_MAC 20
163#define NX_MODE_SHA 0
164#define NX_MODE_SHA_HMAC 1
165#define NX_MODE_AES_CBC_HMAC_ETA 8
166#define NX_MODE_AES_CBC_HMAC_ATE 9
167#define NX_MODE_AES_CBC_HMAC_EAA 10
168#define NX_MODE_AES_CTR_HMAC_ETA 12
169#define NX_MODE_AES_CTR_HMAC_ATE 13
170#define NX_MODE_AES_CTR_HMAC_EAA 14
171
172#define NX_FDM_CI_FULL 0
173#define NX_FDM_CI_FIRST 1
174#define NX_FDM_CI_LAST 2
175#define NX_FDM_CI_MIDDLE 3
176
177#define NX_FDM_PR_NONE 0
178#define NX_FDM_PR_PAD 1
179
180#define NX_KS_AES_128 1
181#define NX_KS_AES_192 2
182#define NX_KS_AES_256 3
183
184#define NX_DS_SHA256 2
185#define NX_DS_SHA512 3
186
187#define NX_FC_AES 0
188#define NX_FC_SHA 2
189#define NX_FC_AES_HMAC 6
190
191#define NX_MAX_FC (NX_FC_AES_HMAC + 1)
192#define NX_MAX_MODE (NX_MODE_AES_XCBC_MAC + 1)
193
194#define HCOP_FC_AES NX_FC_AES
195#define HCOP_FC_SHA NX_FC_SHA
196#define HCOP_FC_AES_HMAC NX_FC_AES_HMAC
197
198/* indices into the array of algorithm properties */
199#define NX_PROPS_AES_128 0
200#define NX_PROPS_AES_192 1
201#define NX_PROPS_AES_256 2
202#define NX_PROPS_SHA256 1
203#define NX_PROPS_SHA512 2
204
205#endif
diff --git a/drivers/crypto/nx/nx_debugfs.c b/drivers/crypto/nx/nx_debugfs.c
new file mode 100644
index 000000000000..7ab2e8dcd9b4
--- /dev/null
+++ b/drivers/crypto/nx/nx_debugfs.c
@@ -0,0 +1,103 @@
1/**
2 * debugfs routines supporting the Power 7+ Nest Accelerators driver
3 *
4 * Copyright (C) 2011-2012 International Business Machines Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Author: Kent Yoder <yoder1@us.ibm.com>
20 */
21
22#include <linux/device.h>
23#include <linux/kobject.h>
24#include <linux/string.h>
25#include <linux/debugfs.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/crypto.h>
29#include <crypto/hash.h>
30#include <asm/vio.h>
31
32#include "nx_csbcpb.h"
33#include "nx.h"
34
35#ifdef CONFIG_DEBUG_FS
36
37/*
38 * debugfs
39 *
40 * For documentation on these attributes, please see:
41 *
42 * Documentation/ABI/testing/debugfs-pfo-nx-crypto
43 */
44
45int nx_debugfs_init(struct nx_crypto_driver *drv)
46{
47 struct nx_debugfs *dfs = &drv->dfs;
48
49 dfs->dfs_root = debugfs_create_dir(NX_NAME, NULL);
50
51 dfs->dfs_aes_ops =
52 debugfs_create_u32("aes_ops",
53 S_IRUSR | S_IRGRP | S_IROTH,
54 dfs->dfs_root, (u32 *)&drv->stats.aes_ops);
55 dfs->dfs_sha256_ops =
56 debugfs_create_u32("sha256_ops",
57 S_IRUSR | S_IRGRP | S_IROTH,
58 dfs->dfs_root,
59 (u32 *)&drv->stats.sha256_ops);
60 dfs->dfs_sha512_ops =
61 debugfs_create_u32("sha512_ops",
62 S_IRUSR | S_IRGRP | S_IROTH,
63 dfs->dfs_root,
64 (u32 *)&drv->stats.sha512_ops);
65 dfs->dfs_aes_bytes =
66 debugfs_create_u64("aes_bytes",
67 S_IRUSR | S_IRGRP | S_IROTH,
68 dfs->dfs_root,
69 (u64 *)&drv->stats.aes_bytes);
70 dfs->dfs_sha256_bytes =
71 debugfs_create_u64("sha256_bytes",
72 S_IRUSR | S_IRGRP | S_IROTH,
73 dfs->dfs_root,
74 (u64 *)&drv->stats.sha256_bytes);
75 dfs->dfs_sha512_bytes =
76 debugfs_create_u64("sha512_bytes",
77 S_IRUSR | S_IRGRP | S_IROTH,
78 dfs->dfs_root,
79 (u64 *)&drv->stats.sha512_bytes);
80 dfs->dfs_errors =
81 debugfs_create_u32("errors",
82 S_IRUSR | S_IRGRP | S_IROTH,
83 dfs->dfs_root, (u32 *)&drv->stats.errors);
84 dfs->dfs_last_error =
85 debugfs_create_u32("last_error",
86 S_IRUSR | S_IRGRP | S_IROTH,
87 dfs->dfs_root,
88 (u32 *)&drv->stats.last_error);
89 dfs->dfs_last_error_pid =
90 debugfs_create_u32("last_error_pid",
91 S_IRUSR | S_IRGRP | S_IROTH,
92 dfs->dfs_root,
93 (u32 *)&drv->stats.last_error_pid);
94 return 0;
95}
96
97void
98nx_debugfs_fini(struct nx_crypto_driver *drv)
99{
100 debugfs_remove_recursive(drv->dfs.dfs_root);
101}
102
103#endif
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 7b397c6f607e..31c47e18d83c 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -227,6 +227,72 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
227 return 0; 227 return 0;
228} 228}
229 229
230static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
231 struct pmac_i2c_bus *bus)
232{
233 struct i2c_client *newdev;
234 struct device_node *node;
235
236 for_each_child_of_node(adap->dev.of_node, node) {
237 struct i2c_board_info info = {};
238 struct dev_archdata dev_ad = {};
239 const __be32 *reg;
240 char tmp[16];
241 u32 addr;
242 int len;
243
244 /* Get address & channel */
245 reg = of_get_property(node, "reg", &len);
246 if (!reg || (len < sizeof(int))) {
247 dev_err(&adap->dev, "i2c-powermac: invalid reg on %s\n",
248 node->full_name);
249 continue;
250 }
251 addr = be32_to_cpup(reg);
252
253 /* Multibus setup, check channel */
254 if (!pmac_i2c_match_adapter(node, adap))
255 continue;
256
257 dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
258 node->full_name);
259
260 /* Make up a modalias. Note: we to _NOT_ want the standard
261 * i2c drivers to match with any of our powermac stuff
262 * unless they have been specifically modified to handle
263 * it on a case by case basis. For example, for thermal
264 * control, things like lm75 etc... shall match with their
265 * corresponding windfarm drivers, _NOT_ the generic ones,
266 * so we force a prefix of AAPL, onto the modalias to
267 * make that happen
268 */
269 if (of_modalias_node(node, tmp, sizeof(tmp)) < 0) {
270 dev_err(&adap->dev, "i2c-powermac: modalias failure"
271 " on %s\n", node->full_name);
272 continue;
273 }
274 snprintf(info.type, sizeof(info.type), "MAC,%s", tmp);
275
276 /* Fill out the rest of the info structure */
277 info.addr = (addr & 0xff) >> 1;
278 info.irq = irq_of_parse_and_map(node, 0);
279 info.of_node = of_node_get(node);
280 info.archdata = &dev_ad;
281
282 newdev = i2c_new_device(adap, &info);
283 if (!newdev) {
284 dev_err(&adap->dev, "i2c-powermac: Failure to register"
285 " %s\n", node->full_name);
286 of_node_put(node);
287 /* We do not dispose of the interrupt mapping on
288 * purpose. It's not necessary (interrupt cannot be
289 * re-used) and somebody else might have grabbed it
290 * via direct DT lookup so let's not bother
291 */
292 continue;
293 }
294 }
295}
230 296
231static int __devinit i2c_powermac_probe(struct platform_device *dev) 297static int __devinit i2c_powermac_probe(struct platform_device *dev)
232{ 298{
@@ -272,6 +338,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
272 adapter->algo = &i2c_powermac_algorithm; 338 adapter->algo = &i2c_powermac_algorithm;
273 i2c_set_adapdata(adapter, bus); 339 i2c_set_adapdata(adapter, bus);
274 adapter->dev.parent = &dev->dev; 340 adapter->dev.parent = &dev->dev;
341 adapter->dev.of_node = dev->dev.of_node;
275 rc = i2c_add_adapter(adapter); 342 rc = i2c_add_adapter(adapter);
276 if (rc) { 343 if (rc) {
277 printk(KERN_ERR "i2c-powermac: Adapter %s registration " 344 printk(KERN_ERR "i2c-powermac: Adapter %s registration "
@@ -281,33 +348,10 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
281 348
282 printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); 349 printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
283 350
284 if (!strncmp(basename, "uni-n", 5)) { 351 /* Cannot use of_i2c_register_devices() due to Apple device-tree
285 struct device_node *np; 352 * funkyness
286 const u32 *prop; 353 */
287 struct i2c_board_info info; 354 i2c_powermac_register_devices(adapter, bus);
288
289 /* Instantiate I2C motion sensor if present */
290 np = of_find_node_by_name(NULL, "accelerometer");
291 if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") &&
292 (prop = of_get_property(np, "reg", NULL))) {
293 int i2c_bus;
294 const char *tmp_bus;
295
296 /* look for bus either using "reg" or by path */
297 tmp_bus = strstr(np->full_name, "/i2c-bus@");
298 if (tmp_bus)
299 i2c_bus = *(tmp_bus + 9) - '0';
300 else
301 i2c_bus = ((*prop) >> 8) & 0x0f;
302
303 if (pmac_i2c_get_channel(bus) == i2c_bus) {
304 memset(&info, 0, sizeof(struct i2c_board_info));
305 info.addr = ((*prop) & 0xff) >> 1;
306 strlcpy(info.type, "ams", I2C_NAME_SIZE);
307 i2c_new_device(adapter, &info);
308 }
309 }
310 }
311 355
312 return rc; 356 return rc;
313} 357}
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index fa51af11c6f1..a555da64224e 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -204,11 +204,14 @@ config THERM_ADT746X
204 better fan behaviour by default, and some manual control. 204 better fan behaviour by default, and some manual control.
205 205
206config THERM_PM72 206config THERM_PM72
207 tristate "Support for thermal management on PowerMac G5" 207 tristate "Support for thermal management on PowerMac G5 (AGP)"
208 depends on I2C && I2C_POWERMAC && PPC_PMAC64 208 depends on I2C && I2C_POWERMAC && PPC_PMAC64
209 default n
209 help 210 help
210 This driver provides thermostat and fan control for the desktop 211 This driver provides thermostat and fan control for the desktop
211 G5 machines. 212 G5 machines.
213
214 This is deprecated, use windfarm instead.
212 215
213config WINDFARM 216config WINDFARM
214 tristate "New PowerMac thermal control infrastructure" 217 tristate "New PowerMac thermal control infrastructure"
@@ -221,6 +224,22 @@ config WINDFARM_PM81
221 help 224 help
222 This driver provides thermal control for the iMacG5 225 This driver provides thermal control for the iMacG5
223 226
227config WINDFARM_PM72
228 tristate "Support for thermal management on PowerMac G5 (AGP)"
229 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
230 select I2C_POWERMAC
231 help
232 This driver provides thermal control for the PowerMac G5
233 "AGP" variants (PowerMac 7,2 and 7,3)
234
235config WINDFARM_RM31
236 tristate "Support for thermal management on Xserve G5"
237 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && ADB_PMU
238 select I2C_POWERMAC
239 help
240 This driver provides thermal control for the Xserve G5
241 (RackMac3,1)
242
224config WINDFARM_PM91 243config WINDFARM_PM91
225 tristate "Support for thermal management on PowerMac9,1" 244 tristate "Support for thermal management on PowerMac9,1"
226 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU 245 depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6652a6ebb6fa..6753b65f8ede 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -29,6 +29,20 @@ obj-$(CONFIG_THERM_PM72) += therm_pm72.o
29obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o 29obj-$(CONFIG_THERM_WINDTUNNEL) += therm_windtunnel.o
30obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o 30obj-$(CONFIG_THERM_ADT746X) += therm_adt746x.o
31obj-$(CONFIG_WINDFARM) += windfarm_core.o 31obj-$(CONFIG_WINDFARM) += windfarm_core.o
32obj-$(CONFIG_WINDFARM_PM72) += windfarm_fcu_controls.o \
33 windfarm_ad7417_sensor.o \
34 windfarm_lm75_sensor.o \
35 windfarm_max6690_sensor.o \
36 windfarm_pid.o \
37 windfarm_cpufreq_clamp.o \
38 windfarm_pm72.o
39obj-$(CONFIG_WINDFARM_RM31) += windfarm_fcu_controls.o \
40 windfarm_ad7417_sensor.o \
41 windfarm_lm75_sensor.o \
42 windfarm_lm87_sensor.o \
43 windfarm_pid.o \
44 windfarm_cpufreq_clamp.o \
45 windfarm_rm31.o
32obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \ 46obj-$(CONFIG_WINDFARM_PM81) += windfarm_smu_controls.o \
33 windfarm_smu_sensors.o \ 47 windfarm_smu_sensors.o \
34 windfarm_lm75_sensor.o windfarm_pid.o \ 48 windfarm_lm75_sensor.o windfarm_pid.o \
diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c
index abeecd27b484..978eda8d6678 100644
--- a/drivers/macintosh/ams/ams-i2c.c
+++ b/drivers/macintosh/ams/ams-i2c.c
@@ -65,7 +65,7 @@ static int ams_i2c_probe(struct i2c_client *client,
65static int ams_i2c_remove(struct i2c_client *client); 65static int ams_i2c_remove(struct i2c_client *client);
66 66
67static const struct i2c_device_id ams_id[] = { 67static const struct i2c_device_id ams_id[] = {
68 { "ams", 0 }, 68 { "MAC,accelerometer_1", 0 },
69 { } 69 { }
70}; 70};
71MODULE_DEVICE_TABLE(i2c, ams_id); 71MODULE_DEVICE_TABLE(i2c, ams_id);
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index fc71723cbc48..f433521a6f9d 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -47,7 +47,7 @@ static u8 FAN_SPD_SET[2] = {0x30, 0x31};
47 47
48static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */ 48static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */
49static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */ 49static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */
50static const char *sensor_location[3]; 50static const char *sensor_location[3] = { "?", "?", "?" };
51 51
52static int limit_adjust; 52static int limit_adjust;
53static int fan_speed = -1; 53static int fan_speed = -1;
@@ -79,18 +79,16 @@ struct thermostat {
79 int last_speed[2]; 79 int last_speed[2];
80 int last_var[2]; 80 int last_var[2];
81 int pwm_inv[2]; 81 int pwm_inv[2];
82 struct task_struct *thread;
83 struct platform_device *pdev;
84 enum {
85 ADT7460,
86 ADT7467
87 } type;
82}; 88};
83 89
84static enum {ADT7460, ADT7467} therm_type;
85static int therm_bus, therm_address;
86static struct platform_device * of_dev;
87static struct thermostat* thermostat;
88static struct task_struct *thread_therm = NULL;
89
90static void write_both_fan_speed(struct thermostat *th, int speed); 90static void write_both_fan_speed(struct thermostat *th, int speed);
91static void write_fan_speed(struct thermostat *th, int speed, int fan); 91static void write_fan_speed(struct thermostat *th, int speed, int fan);
92static void thermostat_create_files(void);
93static void thermostat_remove_files(void);
94 92
95static int 93static int
96write_reg(struct thermostat* th, int reg, u8 data) 94write_reg(struct thermostat* th, int reg, u8 data)
@@ -126,66 +124,6 @@ read_reg(struct thermostat* th, int reg)
126 return data; 124 return data;
127} 125}
128 126
129static struct i2c_driver thermostat_driver;
130
131static int
132attach_thermostat(struct i2c_adapter *adapter)
133{
134 unsigned long bus_no;
135 struct i2c_board_info info;
136 struct i2c_client *client;
137
138 if (strncmp(adapter->name, "uni-n", 5))
139 return -ENODEV;
140 bus_no = simple_strtoul(adapter->name + 6, NULL, 10);
141 if (bus_no != therm_bus)
142 return -ENODEV;
143
144 memset(&info, 0, sizeof(struct i2c_board_info));
145 strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE);
146 info.addr = therm_address;
147 client = i2c_new_device(adapter, &info);
148 if (!client)
149 return -ENODEV;
150
151 /*
152 * Let i2c-core delete that device on driver removal.
153 * This is safe because i2c-core holds the core_lock mutex for us.
154 */
155 list_add_tail(&client->detected, &thermostat_driver.clients);
156 return 0;
157}
158
159static int
160remove_thermostat(struct i2c_client *client)
161{
162 struct thermostat *th = i2c_get_clientdata(client);
163 int i;
164
165 thermostat_remove_files();
166
167 if (thread_therm != NULL) {
168 kthread_stop(thread_therm);
169 }
170
171 printk(KERN_INFO "adt746x: Putting max temperatures back from "
172 "%d, %d, %d to %d, %d, %d\n",
173 th->limits[0], th->limits[1], th->limits[2],
174 th->initial_limits[0], th->initial_limits[1],
175 th->initial_limits[2]);
176
177 for (i = 0; i < 3; i++)
178 write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
179
180 write_both_fan_speed(th, -1);
181
182 thermostat = NULL;
183
184 kfree(th);
185
186 return 0;
187}
188
189static int read_fan_speed(struct thermostat *th, u8 addr) 127static int read_fan_speed(struct thermostat *th, u8 addr)
190{ 128{
191 u8 tmp[2]; 129 u8 tmp[2];
@@ -203,7 +141,7 @@ static int read_fan_speed(struct thermostat *th, u8 addr)
203static void write_both_fan_speed(struct thermostat *th, int speed) 141static void write_both_fan_speed(struct thermostat *th, int speed)
204{ 142{
205 write_fan_speed(th, speed, 0); 143 write_fan_speed(th, speed, 0);
206 if (therm_type == ADT7460) 144 if (th->type == ADT7460)
207 write_fan_speed(th, speed, 1); 145 write_fan_speed(th, speed, 1);
208} 146}
209 147
@@ -216,7 +154,7 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
216 else if (speed < -1) 154 else if (speed < -1)
217 speed = 0; 155 speed = 0;
218 156
219 if (therm_type == ADT7467 && fan == 1) 157 if (th->type == ADT7467 && fan == 1)
220 return; 158 return;
221 159
222 if (th->last_speed[fan] != speed) { 160 if (th->last_speed[fan] != speed) {
@@ -239,7 +177,7 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
239 write_reg(th, FAN_SPD_SET[fan], speed); 177 write_reg(th, FAN_SPD_SET[fan], speed);
240 } else { 178 } else {
241 /* back to automatic */ 179 /* back to automatic */
242 if(therm_type == ADT7460) { 180 if(th->type == ADT7460) {
243 manual = read_reg(th, 181 manual = read_reg(th,
244 MANUAL_MODE[fan]) & (~MANUAL_MASK); 182 MANUAL_MODE[fan]) & (~MANUAL_MASK);
245 manual &= ~INVERT_MASK; 183 manual &= ~INVERT_MASK;
@@ -293,7 +231,7 @@ static void update_fans_speed (struct thermostat *th)
293 /* we don't care about local sensor, so we start at sensor 1 */ 231 /* we don't care about local sensor, so we start at sensor 1 */
294 for (i = 1; i < 3; i++) { 232 for (i = 1; i < 3; i++) {
295 int started = 0; 233 int started = 0;
296 int fan_number = (therm_type == ADT7460 && i == 2); 234 int fan_number = (th->type == ADT7460 && i == 2);
297 int var = th->temps[i] - th->limits[i]; 235 int var = th->temps[i] - th->limits[i];
298 236
299 if (var > -1) { 237 if (var > -1) {
@@ -370,116 +308,22 @@ static int monitor_task(void *arg)
370 308
371static void set_limit(struct thermostat *th, int i) 309static void set_limit(struct thermostat *th, int i)
372{ 310{
373 /* Set sensor1 limit higher to avoid powerdowns */ 311 /* Set sensor1 limit higher to avoid powerdowns */
374 th->limits[i] = default_limits_chip[i] + limit_adjust; 312 th->limits[i] = default_limits_chip[i] + limit_adjust;
375 write_reg(th, LIMIT_REG[i], th->limits[i]); 313 write_reg(th, LIMIT_REG[i], th->limits[i]);
376 314
377 /* set our limits to normal */ 315 /* set our limits to normal */
378 th->limits[i] = default_limits_local[i] + limit_adjust; 316 th->limits[i] = default_limits_local[i] + limit_adjust;
379} 317}
380 318
381static int probe_thermostat(struct i2c_client *client, 319#define BUILD_SHOW_FUNC_INT(name, data) \
382 const struct i2c_device_id *id) 320static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
383{ 321{ \
384 struct thermostat* th; 322 struct thermostat *th = dev_get_drvdata(dev); \
385 int rc; 323 return sprintf(buf, "%d\n", data); \
386 int i;
387
388 if (thermostat)
389 return 0;
390
391 th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
392 if (!th)
393 return -ENOMEM;
394
395 i2c_set_clientdata(client, th);
396 th->clt = client;
397
398 rc = read_reg(th, CONFIG_REG);
399 if (rc < 0) {
400 dev_err(&client->dev, "Thermostat failed to read config!\n");
401 kfree(th);
402 return -ENODEV;
403 }
404
405 /* force manual control to start the fan quieter */
406 if (fan_speed == -1)
407 fan_speed = 64;
408
409 if(therm_type == ADT7460) {
410 printk(KERN_INFO "adt746x: ADT7460 initializing\n");
411 /* The 7460 needs to be started explicitly */
412 write_reg(th, CONFIG_REG, 1);
413 } else
414 printk(KERN_INFO "adt746x: ADT7467 initializing\n");
415
416 for (i = 0; i < 3; i++) {
417 th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
418 set_limit(th, i);
419 }
420
421 printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
422 " to %d, %d, %d\n",
423 th->initial_limits[0], th->initial_limits[1],
424 th->initial_limits[2], th->limits[0], th->limits[1],
425 th->limits[2]);
426
427 thermostat = th;
428
429 /* record invert bit status because fw can corrupt it after suspend */
430 th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
431 th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
432
433 /* be sure to really write fan speed the first time */
434 th->last_speed[0] = -2;
435 th->last_speed[1] = -2;
436 th->last_var[0] = -80;
437 th->last_var[1] = -80;
438
439 if (fan_speed != -1) {
440 /* manual mode, stop fans */
441 write_both_fan_speed(th, 0);
442 } else {
443 /* automatic mode */
444 write_both_fan_speed(th, -1);
445 }
446
447 thread_therm = kthread_run(monitor_task, th, "kfand");
448
449 if (thread_therm == ERR_PTR(-ENOMEM)) {
450 printk(KERN_INFO "adt746x: Kthread creation failed\n");
451 thread_therm = NULL;
452 return -ENOMEM;
453 }
454
455 thermostat_create_files();
456
457 return 0;
458} 324}
459 325
460static const struct i2c_device_id therm_adt746x_id[] = { 326#define BUILD_SHOW_FUNC_INT_LITE(name, data) \
461 { "therm_adt746x", 0 },
462 { }
463};
464
465static struct i2c_driver thermostat_driver = {
466 .driver = {
467 .name = "therm_adt746x",
468 },
469 .attach_adapter = attach_thermostat,
470 .probe = probe_thermostat,
471 .remove = remove_thermostat,
472 .id_table = therm_adt746x_id,
473};
474
475/*
476 * Now, unfortunately, sysfs doesn't give us a nice void * we could
477 * pass around to the attribute functions, so we don't really have
478 * choice but implement a bunch of them...
479 *
480 * FIXME, it does now...
481 */
482#define BUILD_SHOW_FUNC_INT(name, data) \
483static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 327static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
484{ \ 328{ \
485 return sprintf(buf, "%d\n", data); \ 329 return sprintf(buf, "%d\n", data); \
@@ -494,22 +338,24 @@ static ssize_t show_##name(struct device *dev, struct device_attribute *attr, ch
494#define BUILD_SHOW_FUNC_FAN(name, data) \ 338#define BUILD_SHOW_FUNC_FAN(name, data) \
495static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 339static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
496{ \ 340{ \
341 struct thermostat *th = dev_get_drvdata(dev); \
497 return sprintf(buf, "%d (%d rpm)\n", \ 342 return sprintf(buf, "%d (%d rpm)\n", \
498 thermostat->last_speed[data], \ 343 th->last_speed[data], \
499 read_fan_speed(thermostat, FAN_SPEED[data]) \ 344 read_fan_speed(th, FAN_SPEED[data]) \
500 ); \ 345 ); \
501} 346}
502 347
503#define BUILD_STORE_FUNC_DEG(name, data) \ 348#define BUILD_STORE_FUNC_DEG(name, data) \
504static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \ 349static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
505{ \ 350{ \
351 struct thermostat *th = dev_get_drvdata(dev); \
506 int val; \ 352 int val; \
507 int i; \ 353 int i; \
508 val = simple_strtol(buf, NULL, 10); \ 354 val = simple_strtol(buf, NULL, 10); \
509 printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \ 355 printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \
510 limit_adjust = val; \ 356 limit_adjust = val; \
511 for (i=0; i < 3; i++) \ 357 for (i=0; i < 3; i++) \
512 set_limit(thermostat, i); \ 358 set_limit(th, i); \
513 return n; \ 359 return n; \
514} 360}
515 361
@@ -525,20 +371,21 @@ static ssize_t store_##name(struct device *dev, struct device_attribute *attr, c
525 return n; \ 371 return n; \
526} 372}
527 373
528BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(thermostat, TEMP_REG[1]))) 374BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(th, TEMP_REG[1])))
529BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(thermostat, TEMP_REG[2]))) 375BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(th, TEMP_REG[2])))
530BUILD_SHOW_FUNC_INT(sensor1_limit, thermostat->limits[1]) 376BUILD_SHOW_FUNC_INT(sensor1_limit, th->limits[1])
531BUILD_SHOW_FUNC_INT(sensor2_limit, thermostat->limits[2]) 377BUILD_SHOW_FUNC_INT(sensor2_limit, th->limits[2])
532BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1]) 378BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1])
533BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2]) 379BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2])
534 380
535BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed) 381BUILD_SHOW_FUNC_INT_LITE(specified_fan_speed, fan_speed)
382BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
383
536BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0) 384BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0)
537BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1) 385BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1)
538 386
539BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed) 387BUILD_SHOW_FUNC_INT_LITE(limit_adjust, limit_adjust)
540BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust) 388BUILD_STORE_FUNC_DEG(limit_adjust, th)
541BUILD_STORE_FUNC_DEG(limit_adjust, thermostat)
542 389
543static DEVICE_ATTR(sensor1_temperature, S_IRUGO, 390static DEVICE_ATTR(sensor1_temperature, S_IRUGO,
544 show_sensor1_temperature,NULL); 391 show_sensor1_temperature,NULL);
@@ -564,53 +411,77 @@ static DEVICE_ATTR(sensor2_fan_speed, S_IRUGO,
564static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 411static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
565 show_limit_adjust, store_limit_adjust); 412 show_limit_adjust, store_limit_adjust);
566 413
567 414static void thermostat_create_files(struct thermostat *th)
568static int __init
569thermostat_init(void)
570{ 415{
571 struct device_node* np; 416 struct device_node *np = th->clt->dev.of_node;
572 const u32 *prop; 417 struct device *dev;
573 int i = 0, offset = 0; 418 int err;
574 419
575 np = of_find_node_by_name(NULL, "fan"); 420 /* To maintain ABI compatibility with userspace, create
576 if (!np) 421 * the old style platform driver and attach the attributes
577 return -ENODEV; 422 * to it here
578 if (of_device_is_compatible(np, "adt7460")) 423 */
579 therm_type = ADT7460; 424 th->pdev = of_platform_device_create(np, "temperatures", NULL);
580 else if (of_device_is_compatible(np, "adt7467")) 425 if (!th->pdev)
581 therm_type = ADT7467; 426 return;
582 else { 427 dev = &th->pdev->dev;
583 of_node_put(np); 428 dev_set_drvdata(dev, th);
584 return -ENODEV; 429 err = device_create_file(dev, &dev_attr_sensor1_temperature);
585 } 430 err |= device_create_file(dev, &dev_attr_sensor2_temperature);
431 err |= device_create_file(dev, &dev_attr_sensor1_limit);
432 err |= device_create_file(dev, &dev_attr_sensor2_limit);
433 err |= device_create_file(dev, &dev_attr_sensor1_location);
434 err |= device_create_file(dev, &dev_attr_sensor2_location);
435 err |= device_create_file(dev, &dev_attr_limit_adjust);
436 err |= device_create_file(dev, &dev_attr_specified_fan_speed);
437 err |= device_create_file(dev, &dev_attr_sensor1_fan_speed);
438 if(th->type == ADT7460)
439 err |= device_create_file(dev, &dev_attr_sensor2_fan_speed);
440 if (err)
441 printk(KERN_WARNING
442 "Failed to create temperature attribute file(s).\n");
443}
586 444
587 prop = of_get_property(np, "hwsensor-params-version", NULL); 445static void thermostat_remove_files(struct thermostat *th)
588 printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, 446{
589 (*prop == 1)?"":"un"); 447 struct device *dev;
590 if (*prop != 1) {
591 of_node_put(np);
592 return -ENODEV;
593 }
594 448
595 prop = of_get_property(np, "reg", NULL); 449 if (!th->pdev)
596 if (!prop) { 450 return;
597 of_node_put(np); 451 dev = &th->pdev->dev;
598 return -ENODEV; 452 device_remove_file(dev, &dev_attr_sensor1_temperature);
599 } 453 device_remove_file(dev, &dev_attr_sensor2_temperature);
454 device_remove_file(dev, &dev_attr_sensor1_limit);
455 device_remove_file(dev, &dev_attr_sensor2_limit);
456 device_remove_file(dev, &dev_attr_sensor1_location);
457 device_remove_file(dev, &dev_attr_sensor2_location);
458 device_remove_file(dev, &dev_attr_limit_adjust);
459 device_remove_file(dev, &dev_attr_specified_fan_speed);
460 device_remove_file(dev, &dev_attr_sensor1_fan_speed);
461 if (th->type == ADT7460)
462 device_remove_file(dev, &dev_attr_sensor2_fan_speed);
463 of_device_unregister(th->pdev);
600 464
601 /* look for bus either by path or using "reg" */ 465}
602 if (strstr(np->full_name, "/i2c-bus@") != NULL) {
603 const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9);
604 therm_bus = tmp_bus[0]-'0';
605 } else {
606 therm_bus = ((*prop) >> 8) & 0x0f;
607 }
608 466
609 therm_address = ((*prop) & 0xff) >> 1; 467static int probe_thermostat(struct i2c_client *client,
468 const struct i2c_device_id *id)
469{
470 struct device_node *np = client->dev.of_node;
471 struct thermostat* th;
472 const __be32 *prop;
473 int i, rc, vers, offset = 0;
610 474
611 printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, " 475 if (!np)
612 "limit_adjust: %d, fan_speed: %d\n", 476 return -ENXIO;
613 therm_bus, therm_address, limit_adjust, fan_speed); 477 prop = of_get_property(np, "hwsensor-params-version", NULL);
478 if (!prop)
479 return -ENXIO;
480 vers = be32_to_cpup(prop);
481 printk(KERN_INFO "adt746x: version %d (%ssupported)\n",
482 vers, vers == 1 ? "" : "un");
483 if (vers != 1)
484 return -ENXIO;
614 485
615 if (of_get_property(np, "hwsensor-location", NULL)) { 486 if (of_get_property(np, "hwsensor-location", NULL)) {
616 for (i = 0; i < 3; i++) { 487 for (i = 0; i < 3; i++) {
@@ -623,72 +494,129 @@ thermostat_init(void)
623 printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]); 494 printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]);
624 offset += strlen(sensor_location[i]) + 1; 495 offset += strlen(sensor_location[i]) + 1;
625 } 496 }
626 } else {
627 sensor_location[0] = "?";
628 sensor_location[1] = "?";
629 sensor_location[2] = "?";
630 } 497 }
631 498
632 of_dev = of_platform_device_create(np, "temperatures", NULL); 499 th = kzalloc(sizeof(struct thermostat), GFP_KERNEL);
633 of_node_put(np); 500 if (!th)
501 return -ENOMEM;
502
503 i2c_set_clientdata(client, th);
504 th->clt = client;
505 th->type = id->driver_data;
634 506
635 if (of_dev == NULL) { 507 rc = read_reg(th, CONFIG_REG);
636 printk(KERN_ERR "Can't register temperatures device !\n"); 508 if (rc < 0) {
509 dev_err(&client->dev, "Thermostat failed to read config!\n");
510 kfree(th);
637 return -ENODEV; 511 return -ENODEV;
638 } 512 }
639 513
640#ifndef CONFIG_I2C_POWERMAC 514 /* force manual control to start the fan quieter */
641 request_module("i2c-powermac"); 515 if (fan_speed == -1)
642#endif 516 fan_speed = 64;
517
518 if (th->type == ADT7460) {
519 printk(KERN_INFO "adt746x: ADT7460 initializing\n");
520 /* The 7460 needs to be started explicitly */
521 write_reg(th, CONFIG_REG, 1);
522 } else
523 printk(KERN_INFO "adt746x: ADT7467 initializing\n");
643 524
644 return i2c_add_driver(&thermostat_driver); 525 for (i = 0; i < 3; i++) {
526 th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
527 set_limit(th, i);
528 }
529
530 printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
531 " to %d, %d, %d\n",
532 th->initial_limits[0], th->initial_limits[1],
533 th->initial_limits[2], th->limits[0], th->limits[1],
534 th->limits[2]);
535
536 /* record invert bit status because fw can corrupt it after suspend */
537 th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK;
538 th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK;
539
540 /* be sure to really write fan speed the first time */
541 th->last_speed[0] = -2;
542 th->last_speed[1] = -2;
543 th->last_var[0] = -80;
544 th->last_var[1] = -80;
545
546 if (fan_speed != -1) {
547 /* manual mode, stop fans */
548 write_both_fan_speed(th, 0);
549 } else {
550 /* automatic mode */
551 write_both_fan_speed(th, -1);
552 }
553
554 th->thread = kthread_run(monitor_task, th, "kfand");
555 if (th->thread == ERR_PTR(-ENOMEM)) {
556 printk(KERN_INFO "adt746x: Kthread creation failed\n");
557 th->thread = NULL;
558 return -ENOMEM;
559 }
560
561 thermostat_create_files(th);
562
563 return 0;
645} 564}
646 565
647static void thermostat_create_files(void) 566static int remove_thermostat(struct i2c_client *client)
648{ 567{
649 int err; 568 struct thermostat *th = i2c_get_clientdata(client);
569 int i;
570
571 thermostat_remove_files(th);
650 572
651 err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); 573 if (th->thread != NULL)
652 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); 574 kthread_stop(th->thread);
653 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); 575
654 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_limit); 576 printk(KERN_INFO "adt746x: Putting max temperatures back from "
655 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_location); 577 "%d, %d, %d to %d, %d, %d\n",
656 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_location); 578 th->limits[0], th->limits[1], th->limits[2],
657 err |= device_create_file(&of_dev->dev, &dev_attr_limit_adjust); 579 th->initial_limits[0], th->initial_limits[1],
658 err |= device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed); 580 th->initial_limits[2]);
659 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_fan_speed); 581
660 if(therm_type == ADT7460) 582 for (i = 0; i < 3; i++)
661 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); 583 write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
662 if (err) 584
663 printk(KERN_WARNING 585 write_both_fan_speed(th, -1);
664 "Failed to create temperature attribute file(s).\n"); 586
587 kfree(th);
588
589 return 0;
665} 590}
666 591
667static void thermostat_remove_files(void) 592static const struct i2c_device_id therm_adt746x_id[] = {
593 { "MAC,adt7460", ADT7460 },
594 { "MAC,adt7467", ADT7467 },
595 { }
596};
597MODULE_DEVICE_TABLE(i2c, therm_adt746x_id);
598
599static struct i2c_driver thermostat_driver = {
600 .driver = {
601 .name = "therm_adt746x",
602 },
603 .probe = probe_thermostat,
604 .remove = remove_thermostat,
605 .id_table = therm_adt746x_id,
606};
607
608static int __init thermostat_init(void)
668{ 609{
669 if (of_dev) { 610#ifndef CONFIG_I2C_POWERMAC
670 device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); 611 request_module("i2c-powermac");
671 device_remove_file(&of_dev->dev, &dev_attr_sensor2_temperature); 612#endif
672 device_remove_file(&of_dev->dev, &dev_attr_sensor1_limit);
673 device_remove_file(&of_dev->dev, &dev_attr_sensor2_limit);
674 device_remove_file(&of_dev->dev, &dev_attr_sensor1_location);
675 device_remove_file(&of_dev->dev, &dev_attr_sensor2_location);
676 device_remove_file(&of_dev->dev, &dev_attr_limit_adjust);
677 device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
678 device_remove_file(&of_dev->dev, &dev_attr_sensor1_fan_speed);
679
680 if(therm_type == ADT7460)
681 device_remove_file(&of_dev->dev,
682 &dev_attr_sensor2_fan_speed);
683 613
684 } 614 return i2c_add_driver(&thermostat_driver);
685} 615}
686 616
687static void __exit 617static void __exit thermostat_exit(void)
688thermostat_exit(void)
689{ 618{
690 i2c_del_driver(&thermostat_driver); 619 i2c_del_driver(&thermostat_driver);
691 of_device_unregister(of_dev);
692} 620}
693 621
694module_init(thermostat_init); 622module_init(thermostat_init);
diff --git a/drivers/macintosh/windfarm.h b/drivers/macintosh/windfarm.h
index 7a2482cc26a7..028cdac2d33d 100644
--- a/drivers/macintosh/windfarm.h
+++ b/drivers/macintosh/windfarm.h
@@ -17,7 +17,7 @@
17#include <linux/device.h> 17#include <linux/device.h>
18 18
19/* Display a 16.16 fixed point value */ 19/* Display a 16.16 fixed point value */
20#define FIX32TOPRINT(f) ((f) >> 16),((((f) & 0xffff) * 1000) >> 16) 20#define FIX32TOPRINT(f) (((s32)(f)) >> 16),(((((s32)(f)) & 0xffff) * 1000) >> 16)
21 21
22/* 22/*
23 * Control objects 23 * Control objects
@@ -35,12 +35,13 @@ struct wf_control_ops {
35}; 35};
36 36
37struct wf_control { 37struct wf_control {
38 struct list_head link; 38 struct list_head link;
39 struct wf_control_ops *ops; 39 const struct wf_control_ops *ops;
40 char *name; 40 const char *name;
41 int type; 41 int type;
42 struct kref ref; 42 struct kref ref;
43 struct device_attribute attr; 43 struct device_attribute attr;
44 void *priv;
44}; 45};
45 46
46#define WF_CONTROL_TYPE_GENERIC 0 47#define WF_CONTROL_TYPE_GENERIC 0
@@ -72,6 +73,26 @@ static inline int wf_control_set_min(struct wf_control *ct)
72 return ct->ops->set_value(ct, vmin); 73 return ct->ops->set_value(ct, vmin);
73} 74}
74 75
76static inline int wf_control_set(struct wf_control *ct, s32 val)
77{
78 return ct->ops->set_value(ct, val);
79}
80
81static inline int wf_control_get(struct wf_control *ct, s32 *val)
82{
83 return ct->ops->get_value(ct, val);
84}
85
86static inline s32 wf_control_get_min(struct wf_control *ct)
87{
88 return ct->ops->get_min(ct);
89}
90
91static inline s32 wf_control_get_max(struct wf_control *ct)
92{
93 return ct->ops->get_max(ct);
94}
95
75/* 96/*
76 * Sensor objects 97 * Sensor objects
77 */ 98 */
@@ -85,11 +106,12 @@ struct wf_sensor_ops {
85}; 106};
86 107
87struct wf_sensor { 108struct wf_sensor {
88 struct list_head link; 109 struct list_head link;
89 struct wf_sensor_ops *ops; 110 const struct wf_sensor_ops *ops;
90 char *name; 111 const char *name;
91 struct kref ref; 112 struct kref ref;
92 struct device_attribute attr; 113 struct device_attribute attr;
114 void *priv;
93}; 115};
94 116
95/* Same lifetime rules as controls */ 117/* Same lifetime rules as controls */
@@ -99,6 +121,11 @@ extern struct wf_sensor * wf_find_sensor(const char *name);
99extern int wf_get_sensor(struct wf_sensor *sr); 121extern int wf_get_sensor(struct wf_sensor *sr);
100extern void wf_put_sensor(struct wf_sensor *sr); 122extern void wf_put_sensor(struct wf_sensor *sr);
101 123
124static inline int wf_sensor_get(struct wf_sensor *sr, s32 *val)
125{
126 return sr->ops->get_value(sr, val);
127}
128
102/* For use by clients. Note that we are a bit racy here since 129/* For use by clients. Note that we are a bit racy here since
103 * notifier_block doesn't have a module owner field. I may fix 130 * notifier_block doesn't have a module owner field. I may fix
104 * it one day ... 131 * it one day ...
diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c
new file mode 100644
index 000000000000..ac3f243b9c5a
--- /dev/null
+++ b/drivers/macintosh/windfarm_ad7417_sensor.c
@@ -0,0 +1,347 @@
1/*
2 * Windfarm PowerMac thermal control. AD7417 sensors
3 *
4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
5 *
6 * Released under the term of the GNU GPL v2.
7 */
8
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/delay.h>
13#include <linux/slab.h>
14#include <linux/init.h>
15#include <linux/wait.h>
16#include <linux/i2c.h>
17#include <asm/prom.h>
18#include <asm/machdep.h>
19#include <asm/io.h>
20#include <asm/sections.h>
21
22#include "windfarm.h"
23#include "windfarm_mpu.h"
24
25#define VERSION "1.0"
26
27struct wf_ad7417_priv {
28 struct kref ref;
29 struct i2c_client *i2c;
30 u8 config;
31 u8 cpu;
32 const struct mpu_data *mpu;
33 struct wf_sensor sensors[5];
34 struct mutex lock;
35};
36
37static int wf_ad7417_temp_get(struct wf_sensor *sr, s32 *value)
38{
39 struct wf_ad7417_priv *pv = sr->priv;
40 u8 buf[2];
41 s16 raw;
42 int rc;
43
44 *value = 0;
45 mutex_lock(&pv->lock);
46
47 /* Read temp register */
48 buf[0] = 0;
49 rc = i2c_master_send(pv->i2c, buf, 1);
50 if (rc < 0)
51 goto error;
52 rc = i2c_master_recv(pv->i2c, buf, 2);
53 if (rc < 0)
54 goto error;
55
56 /* Read a a 16-bit signed value */
57 raw = be16_to_cpup((__le16 *)buf);
58
59 /* Convert 8.8-bit to 16.16 fixed point */
60 *value = ((s32)raw) << 8;
61
62 mutex_unlock(&pv->lock);
63 return 0;
64
65error:
66 mutex_unlock(&pv->lock);
67 return -1;
68}
69
70/*
71 * Scaling factors for the AD7417 ADC converters (except
72 * for the CPU diode which is obtained from the EEPROM).
73 * Those values are obtained from the property list of
74 * the darwin driver
75 */
76#define ADC_12V_CURRENT_SCALE 0x0320 /* _AD2 */
77#define ADC_CPU_VOLTAGE_SCALE 0x00a0 /* _AD3 */
78#define ADC_CPU_CURRENT_SCALE 0x1f40 /* _AD4 */
79
80static void wf_ad7417_adc_convert(struct wf_ad7417_priv *pv,
81 int chan, s32 raw, s32 *value)
82{
83 switch(chan) {
84 case 1: /* Diode */
85 *value = (raw * (s32)pv->mpu->mdiode +
86 ((s32)pv->mpu->bdiode << 12)) >> 2;
87 break;
88 case 2: /* 12v current */
89 *value = raw * ADC_12V_CURRENT_SCALE;
90 break;
91 case 3: /* core voltage */
92 *value = raw * ADC_CPU_VOLTAGE_SCALE;
93 break;
94 case 4: /* core current */
95 *value = raw * ADC_CPU_CURRENT_SCALE;
96 break;
97 }
98}
99
100static int wf_ad7417_adc_get(struct wf_sensor *sr, s32 *value)
101{
102 struct wf_ad7417_priv *pv = sr->priv;
103 int chan = sr - pv->sensors;
104 int i, rc;
105 u8 buf[2];
106 u16 raw;
107
108 *value = 0;
109 mutex_lock(&pv->lock);
110 for (i = 0; i < 10; i++) {
111 /* Set channel */
112 buf[0] = 1;
113 buf[1] = (pv->config & 0x1f) | (chan << 5);
114 rc = i2c_master_send(pv->i2c, buf, 2);
115 if (rc < 0)
116 goto error;
117
118 /* Wait for conversion */
119 msleep(1);
120
121 /* Switch to data register */
122 buf[0] = 4;
123 rc = i2c_master_send(pv->i2c, buf, 1);
124 if (rc < 0)
125 goto error;
126
127 /* Read result */
128 rc = i2c_master_recv(pv->i2c, buf, 2);
129 if (rc < 0)
130 goto error;
131
132 /* Read a a 16-bit signed value */
133 raw = be16_to_cpup((__le16 *)buf) >> 6;
134 wf_ad7417_adc_convert(pv, chan, raw, value);
135
136 dev_vdbg(&pv->i2c->dev, "ADC chan %d [%s]"
137 " raw value: 0x%x, conv to: 0x%08x\n",
138 chan, sr->name, raw, *value);
139
140 mutex_unlock(&pv->lock);
141 return 0;
142
143 error:
144 dev_dbg(&pv->i2c->dev,
145 "Error reading ADC, try %d...\n", i);
146 if (i < 9)
147 msleep(10);
148 }
149 mutex_unlock(&pv->lock);
150 return -1;
151}
152
153static void wf_ad7417_release(struct kref *ref)
154{
155 struct wf_ad7417_priv *pv = container_of(ref,
156 struct wf_ad7417_priv, ref);
157 kfree(pv);
158}
159
160static void wf_ad7417_sensor_release(struct wf_sensor *sr)
161{
162 struct wf_ad7417_priv *pv = sr->priv;
163
164 kfree(sr->name);
165 kref_put(&pv->ref, wf_ad7417_release);
166}
167
168static const struct wf_sensor_ops wf_ad7417_temp_ops = {
169 .get_value = wf_ad7417_temp_get,
170 .release = wf_ad7417_sensor_release,
171 .owner = THIS_MODULE,
172};
173
174static const struct wf_sensor_ops wf_ad7417_adc_ops = {
175 .get_value = wf_ad7417_adc_get,
176 .release = wf_ad7417_sensor_release,
177 .owner = THIS_MODULE,
178};
179
180static void __devinit wf_ad7417_add_sensor(struct wf_ad7417_priv *pv,
181 int index, const char *name,
182 const struct wf_sensor_ops *ops)
183{
184 pv->sensors[index].name = kasprintf(GFP_KERNEL, "%s-%d", name, pv->cpu);
185 pv->sensors[index].priv = pv;
186 pv->sensors[index].ops = ops;
187 if (!wf_register_sensor(&pv->sensors[index]))
188 kref_get(&pv->ref);
189}
190
191static void __devinit wf_ad7417_init_chip(struct wf_ad7417_priv *pv)
192{
193 int rc;
194 u8 buf[2];
195 u8 config = 0;
196
197 /*
198 * Read ADC the configuration register and cache it. We
199 * also make sure Config2 contains proper values, I've seen
200 * cases where we got stale grabage in there, thus preventing
201 * proper reading of conv. values
202 */
203
204 /* Clear Config2 */
205 buf[0] = 5;
206 buf[1] = 0;
207 i2c_master_send(pv->i2c, buf, 2);
208
209 /* Read & cache Config1 */
210 buf[0] = 1;
211 rc = i2c_master_send(pv->i2c, buf, 1);
212 if (rc > 0) {
213 rc = i2c_master_recv(pv->i2c, buf, 1);
214 if (rc > 0) {
215 config = buf[0];
216
217 dev_dbg(&pv->i2c->dev, "ADC config reg: %02x\n",
218 config);
219
220 /* Disable shutdown mode */
221 config &= 0xfe;
222 buf[0] = 1;
223 buf[1] = config;
224 rc = i2c_master_send(pv->i2c, buf, 2);
225 }
226 }
227 if (rc <= 0)
228 dev_err(&pv->i2c->dev, "Error reading ADC config\n");
229
230 pv->config = config;
231}
232
233static int __devinit wf_ad7417_probe(struct i2c_client *client,
234 const struct i2c_device_id *id)
235{
236 struct wf_ad7417_priv *pv;
237 const struct mpu_data *mpu;
238 const char *loc;
239 int cpu_nr;
240
241 loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
242 if (!loc) {
243 dev_warn(&client->dev, "Missing hwsensor-location property!\n");
244 return -ENXIO;
245 }
246
247 /*
248 * Identify which CPU we belong to by looking at the first entry
249 * in the hwsensor-location list
250 */
251 if (!strncmp(loc, "CPU A", 5))
252 cpu_nr = 0;
253 else if (!strncmp(loc, "CPU B", 5))
254 cpu_nr = 1;
255 else {
256 pr_err("wf_ad7417: Can't identify location %s\n", loc);
257 return -ENXIO;
258 }
259 mpu = wf_get_mpu(cpu_nr);
260 if (!mpu) {
261 dev_err(&client->dev, "Failed to retrieve MPU data\n");
262 return -ENXIO;
263 }
264
265 pv = kzalloc(sizeof(struct wf_ad7417_priv), GFP_KERNEL);
266 if (pv == NULL)
267 return -ENODEV;
268
269 kref_init(&pv->ref);
270 mutex_init(&pv->lock);
271 pv->i2c = client;
272 pv->cpu = cpu_nr;
273 pv->mpu = mpu;
274 dev_set_drvdata(&client->dev, pv);
275
276 /* Initialize the chip */
277 wf_ad7417_init_chip(pv);
278
279 /*
280 * We cannot rely on Apple device-tree giving us child
281 * node with the names of the individual sensors so we
282 * just hard code what we know about them
283 */
284 wf_ad7417_add_sensor(pv, 0, "cpu-amb-temp", &wf_ad7417_temp_ops);
285 wf_ad7417_add_sensor(pv, 1, "cpu-diode-temp", &wf_ad7417_adc_ops);
286 wf_ad7417_add_sensor(pv, 2, "cpu-12v-current", &wf_ad7417_adc_ops);
287 wf_ad7417_add_sensor(pv, 3, "cpu-voltage", &wf_ad7417_adc_ops);
288 wf_ad7417_add_sensor(pv, 4, "cpu-current", &wf_ad7417_adc_ops);
289
290 return 0;
291}
292
293static int __devexit wf_ad7417_remove(struct i2c_client *client)
294{
295 struct wf_ad7417_priv *pv = dev_get_drvdata(&client->dev);
296 int i;
297
298 /* Mark client detached */
299 pv->i2c = NULL;
300
301 /* Release sensor */
302 for (i = 0; i < 5; i++)
303 wf_unregister_sensor(&pv->sensors[i]);
304
305 kref_put(&pv->ref, wf_ad7417_release);
306
307 return 0;
308}
309
310static const struct i2c_device_id wf_ad7417_id[] = {
311 { "MAC,ad7417", 0 },
312 { }
313};
314MODULE_DEVICE_TABLE(i2c, wf_ad7417_id);
315
316static struct i2c_driver wf_ad7417_driver = {
317 .driver = {
318 .name = "wf_ad7417",
319 },
320 .probe = wf_ad7417_probe,
321 .remove = wf_ad7417_remove,
322 .id_table = wf_ad7417_id,
323};
324
325static int __devinit wf_ad7417_init(void)
326{
327 /* This is only supported on these machines */
328 if (!of_machine_is_compatible("PowerMac7,2") &&
329 !of_machine_is_compatible("PowerMac7,3") &&
330 !of_machine_is_compatible("RackMac3,1"))
331 return -ENODEV;
332
333 return i2c_add_driver(&wf_ad7417_driver);
334}
335
336static void __devexit wf_ad7417_exit(void)
337{
338 i2c_del_driver(&wf_ad7417_driver);
339}
340
341module_init(wf_ad7417_init);
342module_exit(wf_ad7417_exit);
343
344MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
345MODULE_DESCRIPTION("ad7417 sensor driver for PowerMacs");
346MODULE_LICENSE("GPL");
347
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index ce8897933a84..3ee198b65843 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -164,13 +164,27 @@ static ssize_t wf_show_control(struct device *dev,
164 struct device_attribute *attr, char *buf) 164 struct device_attribute *attr, char *buf)
165{ 165{
166 struct wf_control *ctrl = container_of(attr, struct wf_control, attr); 166 struct wf_control *ctrl = container_of(attr, struct wf_control, attr);
167 const char *typestr;
167 s32 val = 0; 168 s32 val = 0;
168 int err; 169 int err;
169 170
170 err = ctrl->ops->get_value(ctrl, &val); 171 err = ctrl->ops->get_value(ctrl, &val);
171 if (err < 0) 172 if (err < 0) {
173 if (err == -EFAULT)
174 return sprintf(buf, "<HW FAULT>\n");
172 return err; 175 return err;
173 return sprintf(buf, "%d\n", val); 176 }
177 switch(ctrl->type) {
178 case WF_CONTROL_RPM_FAN:
179 typestr = " RPM";
180 break;
181 case WF_CONTROL_PWM_FAN:
182 typestr = " %";
183 break;
184 default:
185 typestr = "";
186 }
187 return sprintf(buf, "%d%s\n", val, typestr);
174} 188}
175 189
176/* This is really only for debugging... */ 190/* This is really only for debugging... */
@@ -470,11 +484,6 @@ static int __init windfarm_core_init(void)
470{ 484{
471 DBG("wf: core loaded\n"); 485 DBG("wf: core loaded\n");
472 486
473 /* Don't register on old machines that use therm_pm72 for now */
474 if (of_machine_is_compatible("PowerMac7,2") ||
475 of_machine_is_compatible("PowerMac7,3") ||
476 of_machine_is_compatible("RackMac3,1"))
477 return -ENODEV;
478 platform_device_register(&wf_platform_device); 487 platform_device_register(&wf_platform_device);
479 return 0; 488 return 0;
480} 489}
diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c
index 1a77a7c97d0e..72d1fdfe02a5 100644
--- a/drivers/macintosh/windfarm_cpufreq_clamp.c
+++ b/drivers/macintosh/windfarm_cpufreq_clamp.c
@@ -75,12 +75,6 @@ static int __init wf_cpufreq_clamp_init(void)
75{ 75{
76 struct wf_control *clamp; 76 struct wf_control *clamp;
77 77
78 /* Don't register on old machines that use therm_pm72 for now */
79 if (of_machine_is_compatible("PowerMac7,2") ||
80 of_machine_is_compatible("PowerMac7,3") ||
81 of_machine_is_compatible("RackMac3,1"))
82 return -ENODEV;
83
84 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); 78 clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL);
85 if (clamp == NULL) 79 if (clamp == NULL)
86 return -ENOMEM; 80 return -ENOMEM;
diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c
new file mode 100644
index 000000000000..b3411edb324b
--- /dev/null
+++ b/drivers/macintosh/windfarm_fcu_controls.c
@@ -0,0 +1,613 @@
1/*
2 * Windfarm PowerMac thermal control. FCU fan control
3 *
4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
5 *
6 * Released under the term of the GNU GPL v2.
7 */
8#undef DEBUG
9
10#include <linux/types.h>
11#include <linux/errno.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/init.h>
16#include <linux/wait.h>
17#include <linux/i2c.h>
18#include <asm/prom.h>
19#include <asm/machdep.h>
20#include <asm/io.h>
21#include <asm/sections.h>
22
23#include "windfarm.h"
24#include "windfarm_mpu.h"
25
26#define VERSION "1.0"
27
28#ifdef DEBUG
29#define DBG(args...) printk(args)
30#else
31#define DBG(args...) do { } while(0)
32#endif
33
34/*
35 * This option is "weird" :) Basically, if you define this to 1
36 * the control loop for the RPMs fans (not PWMs) will apply the
37 * correction factor obtained from the PID to the actual RPM
38 * speed read from the FCU.
39 *
40 * If you define the below constant to 0, then it will be
41 * applied to the setpoint RPM speed, that is basically the
42 * speed we proviously "asked" for.
43 *
44 * I'm using 0 for now which is what therm_pm72 used to do and
45 * what Darwin -apparently- does based on observed behaviour.
46 */
47#define RPM_PID_USE_ACTUAL_SPEED 0
48
49/* Default min/max for pumps */
50#define CPU_PUMP_OUTPUT_MAX 3200
51#define CPU_PUMP_OUTPUT_MIN 1250
52
53#define FCU_FAN_RPM 0
54#define FCU_FAN_PWM 1
55
56struct wf_fcu_priv {
57 struct kref ref;
58 struct i2c_client *i2c;
59 struct mutex lock;
60 struct list_head fan_list;
61 int rpm_shift;
62};
63
64struct wf_fcu_fan {
65 struct list_head link;
66 int id;
67 s32 min, max, target;
68 struct wf_fcu_priv *fcu_priv;
69 struct wf_control ctrl;
70};
71
72static void wf_fcu_release(struct kref *ref)
73{
74 struct wf_fcu_priv *pv = container_of(ref, struct wf_fcu_priv, ref);
75
76 kfree(pv);
77}
78
79static void wf_fcu_fan_release(struct wf_control *ct)
80{
81 struct wf_fcu_fan *fan = ct->priv;
82
83 kref_put(&fan->fcu_priv->ref, wf_fcu_release);
84 kfree(fan);
85}
86
87static int wf_fcu_read_reg(struct wf_fcu_priv *pv, int reg,
88 unsigned char *buf, int nb)
89{
90 int tries, nr, nw;
91
92 mutex_lock(&pv->lock);
93
94 buf[0] = reg;
95 tries = 0;
96 for (;;) {
97 nw = i2c_master_send(pv->i2c, buf, 1);
98 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
99 break;
100 msleep(10);
101 ++tries;
102 }
103 if (nw <= 0) {
104 pr_err("Failure writing address to FCU: %d", nw);
105 nr = nw;
106 goto bail;
107 }
108 tries = 0;
109 for (;;) {
110 nr = i2c_master_recv(pv->i2c, buf, nb);
111 if (nr > 0 || (nr < 0 && nr != -ENODEV) || tries >= 100)
112 break;
113 msleep(10);
114 ++tries;
115 }
116 if (nr <= 0)
117 pr_err("wf_fcu: Failure reading data from FCU: %d", nw);
118 bail:
119 mutex_unlock(&pv->lock);
120 return nr;
121}
122
123static int wf_fcu_write_reg(struct wf_fcu_priv *pv, int reg,
124 const unsigned char *ptr, int nb)
125{
126 int tries, nw;
127 unsigned char buf[16];
128
129 buf[0] = reg;
130 memcpy(buf+1, ptr, nb);
131 ++nb;
132 tries = 0;
133 for (;;) {
134 nw = i2c_master_send(pv->i2c, buf, nb);
135 if (nw > 0 || (nw < 0 && nw != -EIO) || tries >= 100)
136 break;
137 msleep(10);
138 ++tries;
139 }
140 if (nw < 0)
141 pr_err("wf_fcu: Failure writing to FCU: %d", nw);
142 return nw;
143}
144
145static int wf_fcu_fan_set_rpm(struct wf_control *ct, s32 value)
146{
147 struct wf_fcu_fan *fan = ct->priv;
148 struct wf_fcu_priv *pv = fan->fcu_priv;
149 int rc, shift = pv->rpm_shift;
150 unsigned char buf[2];
151
152 if (value < fan->min)
153 value = fan->min;
154 if (value > fan->max)
155 value = fan->max;
156
157 fan->target = value;
158
159 buf[0] = value >> (8 - shift);
160 buf[1] = value << shift;
161 rc = wf_fcu_write_reg(pv, 0x10 + (fan->id * 2), buf, 2);
162 if (rc < 0)
163 return -EIO;
164 return 0;
165}
166
167static int wf_fcu_fan_get_rpm(struct wf_control *ct, s32 *value)
168{
169 struct wf_fcu_fan *fan = ct->priv;
170 struct wf_fcu_priv *pv = fan->fcu_priv;
171 int rc, reg_base, shift = pv->rpm_shift;
172 unsigned char failure;
173 unsigned char active;
174 unsigned char buf[2];
175
176 rc = wf_fcu_read_reg(pv, 0xb, &failure, 1);
177 if (rc != 1)
178 return -EIO;
179 if ((failure & (1 << fan->id)) != 0)
180 return -EFAULT;
181 rc = wf_fcu_read_reg(pv, 0xd, &active, 1);
182 if (rc != 1)
183 return -EIO;
184 if ((active & (1 << fan->id)) == 0)
185 return -ENXIO;
186
187 /* Programmed value or real current speed */
188#if RPM_PID_USE_ACTUAL_SPEED
189 reg_base = 0x11;
190#else
191 reg_base = 0x10;
192#endif
193 rc = wf_fcu_read_reg(pv, reg_base + (fan->id * 2), buf, 2);
194 if (rc != 2)
195 return -EIO;
196
197 *value = (buf[0] << (8 - shift)) | buf[1] >> shift;
198
199 return 0;
200}
201
202static int wf_fcu_fan_set_pwm(struct wf_control *ct, s32 value)
203{
204 struct wf_fcu_fan *fan = ct->priv;
205 struct wf_fcu_priv *pv = fan->fcu_priv;
206 unsigned char buf[2];
207 int rc;
208
209 if (value < fan->min)
210 value = fan->min;
211 if (value > fan->max)
212 value = fan->max;
213
214 fan->target = value;
215
216 value = (value * 2559) / 1000;
217 buf[0] = value;
218 rc = wf_fcu_write_reg(pv, 0x30 + (fan->id * 2), buf, 1);
219 if (rc < 0)
220 return -EIO;
221 return 0;
222}
223
224static int wf_fcu_fan_get_pwm(struct wf_control *ct, s32 *value)
225{
226 struct wf_fcu_fan *fan = ct->priv;
227 struct wf_fcu_priv *pv = fan->fcu_priv;
228 unsigned char failure;
229 unsigned char active;
230 unsigned char buf[2];
231 int rc;
232
233 rc = wf_fcu_read_reg(pv, 0x2b, &failure, 1);
234 if (rc != 1)
235 return -EIO;
236 if ((failure & (1 << fan->id)) != 0)
237 return -EFAULT;
238 rc = wf_fcu_read_reg(pv, 0x2d, &active, 1);
239 if (rc != 1)
240 return -EIO;
241 if ((active & (1 << fan->id)) == 0)
242 return -ENXIO;
243
244 rc = wf_fcu_read_reg(pv, 0x30 + (fan->id * 2), buf, 1);
245 if (rc != 1)
246 return -EIO;
247
248 *value = (((s32)buf[0]) * 1000) / 2559;
249
250 return 0;
251}
252
253static s32 wf_fcu_fan_min(struct wf_control *ct)
254{
255 struct wf_fcu_fan *fan = ct->priv;
256
257 return fan->min;
258}
259
260static s32 wf_fcu_fan_max(struct wf_control *ct)
261{
262 struct wf_fcu_fan *fan = ct->priv;
263
264 return fan->max;
265}
266
267static const struct wf_control_ops wf_fcu_fan_rpm_ops = {
268 .set_value = wf_fcu_fan_set_rpm,
269 .get_value = wf_fcu_fan_get_rpm,
270 .get_min = wf_fcu_fan_min,
271 .get_max = wf_fcu_fan_max,
272 .release = wf_fcu_fan_release,
273 .owner = THIS_MODULE,
274};
275
276static const struct wf_control_ops wf_fcu_fan_pwm_ops = {
277 .set_value = wf_fcu_fan_set_pwm,
278 .get_value = wf_fcu_fan_get_pwm,
279 .get_min = wf_fcu_fan_min,
280 .get_max = wf_fcu_fan_max,
281 .release = wf_fcu_fan_release,
282 .owner = THIS_MODULE,
283};
284
285static void __devinit wf_fcu_get_pump_minmax(struct wf_fcu_fan *fan)
286{
287 const struct mpu_data *mpu = wf_get_mpu(0);
288 u16 pump_min = 0, pump_max = 0xffff;
289 u16 tmp[4];
290
291 /* Try to fetch pumps min/max infos from eeprom */
292 if (mpu) {
293 memcpy(&tmp, mpu->processor_part_num, 8);
294 if (tmp[0] != 0xffff && tmp[1] != 0xffff) {
295 pump_min = max(pump_min, tmp[0]);
296 pump_max = min(pump_max, tmp[1]);
297 }
298 if (tmp[2] != 0xffff && tmp[3] != 0xffff) {
299 pump_min = max(pump_min, tmp[2]);
300 pump_max = min(pump_max, tmp[3]);
301 }
302 }
303
304 /* Double check the values, this _IS_ needed as the EEPROM on
305 * some dual 2.5Ghz G5s seem, at least, to have both min & max
306 * same to the same value ... (grrrr)
307 */
308 if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) {
309 pump_min = CPU_PUMP_OUTPUT_MIN;
310 pump_max = CPU_PUMP_OUTPUT_MAX;
311 }
312
313 fan->min = pump_min;
314 fan->max = pump_max;
315
316 DBG("wf_fcu: pump min/max for %s set to: [%d..%d] RPM\n",
317 fan->ctrl.name, pump_min, pump_max);
318}
319
320static void __devinit wf_fcu_get_rpmfan_minmax(struct wf_fcu_fan *fan)
321{
322 struct wf_fcu_priv *pv = fan->fcu_priv;
323 const struct mpu_data *mpu0 = wf_get_mpu(0);
324 const struct mpu_data *mpu1 = wf_get_mpu(1);
325
326 /* Default */
327 fan->min = 2400 >> pv->rpm_shift;
328 fan->max = 56000 >> pv->rpm_shift;
329
330 /* CPU fans have min/max in MPU */
331 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-front-fan-0")) {
332 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
333 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
334 goto bail;
335 }
336 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-front-fan-1")) {
337 fan->min = max(fan->min, (s32)mpu1->rminn_intake_fan);
338 fan->max = min(fan->max, (s32)mpu1->rmaxn_intake_fan);
339 goto bail;
340 }
341 if (mpu0 && !strcmp(fan->ctrl.name, "cpu-rear-fan-0")) {
342 fan->min = max(fan->min, (s32)mpu0->rminn_exhaust_fan);
343 fan->max = min(fan->max, (s32)mpu0->rmaxn_exhaust_fan);
344 goto bail;
345 }
346 if (mpu1 && !strcmp(fan->ctrl.name, "cpu-rear-fan-1")) {
347 fan->min = max(fan->min, (s32)mpu1->rminn_exhaust_fan);
348 fan->max = min(fan->max, (s32)mpu1->rmaxn_exhaust_fan);
349 goto bail;
350 }
351 /* Rackmac variants, we just use mpu0 intake */
352 if (!strncmp(fan->ctrl.name, "cpu-fan", 7)) {
353 fan->min = max(fan->min, (s32)mpu0->rminn_intake_fan);
354 fan->max = min(fan->max, (s32)mpu0->rmaxn_intake_fan);
355 goto bail;
356 }
357 bail:
358 DBG("wf_fcu: fan min/max for %s set to: [%d..%d] RPM\n",
359 fan->ctrl.name, fan->min, fan->max);
360}
361
362static void __devinit wf_fcu_add_fan(struct wf_fcu_priv *pv,
363 const char *name,
364 int type, int id)
365{
366 struct wf_fcu_fan *fan;
367
368 fan = kzalloc(sizeof(*fan), GFP_KERNEL);
369 if (!fan)
370 return;
371 fan->fcu_priv = pv;
372 fan->id = id;
373 fan->ctrl.name = name;
374 fan->ctrl.priv = fan;
375
376 /* min/max is oddball but the code comes from
377 * therm_pm72 which seems to work so ...
378 */
379 if (type == FCU_FAN_RPM) {
380 if (!strncmp(name, "cpu-pump", strlen("cpu-pump")))
381 wf_fcu_get_pump_minmax(fan);
382 else
383 wf_fcu_get_rpmfan_minmax(fan);
384 fan->ctrl.type = WF_CONTROL_RPM_FAN;
385 fan->ctrl.ops = &wf_fcu_fan_rpm_ops;
386 } else {
387 fan->min = 10;
388 fan->max = 100;
389 fan->ctrl.type = WF_CONTROL_PWM_FAN;
390 fan->ctrl.ops = &wf_fcu_fan_pwm_ops;
391 }
392
393 if (wf_register_control(&fan->ctrl)) {
394 pr_err("wf_fcu: Failed to register fan %s\n", name);
395 kfree(fan);
396 return;
397 }
398 list_add(&fan->link, &pv->fan_list);
399 kref_get(&pv->ref);
400}
401
402static void __devinit wf_fcu_lookup_fans(struct wf_fcu_priv *pv)
403{
404 /* Translation of device-tree location properties to
405 * windfarm fan names
406 */
407 static const struct {
408 const char *dt_name; /* Device-tree name */
409 const char *ct_name; /* Control name */
410 } loc_trans[] = {
411 { "BACKSIDE", "backside-fan", },
412 { "SYS CTRLR FAN", "backside-fan", },
413 { "DRIVE BAY", "drive-bay-fan", },
414 { "SLOT", "slots-fan", },
415 { "PCI FAN", "slots-fan", },
416 { "CPU A INTAKE", "cpu-front-fan-0", },
417 { "CPU A EXHAUST", "cpu-rear-fan-0", },
418 { "CPU B INTAKE", "cpu-front-fan-1", },
419 { "CPU B EXHAUST", "cpu-rear-fan-1", },
420 { "CPU A PUMP", "cpu-pump-0", },
421 { "CPU B PUMP", "cpu-pump-1", },
422 { "CPU A 1", "cpu-fan-a-0", },
423 { "CPU A 2", "cpu-fan-b-0", },
424 { "CPU A 3", "cpu-fan-c-0", },
425 { "CPU B 1", "cpu-fan-a-1", },
426 { "CPU B 2", "cpu-fan-b-1", },
427 { "CPU B 3", "cpu-fan-c-1", },
428 };
429 struct device_node *np = NULL, *fcu = pv->i2c->dev.of_node;
430 int i;
431
432 DBG("Looking up FCU controls in device-tree...\n");
433
434 while ((np = of_get_next_child(fcu, np)) != NULL) {
435 int id, type = -1;
436 const char *loc;
437 const char *name;
438 const u32 *reg;
439
440 DBG(" control: %s, type: %s\n", np->name, np->type);
441
442 /* Detect control type */
443 if (!strcmp(np->type, "fan-rpm-control") ||
444 !strcmp(np->type, "fan-rpm"))
445 type = FCU_FAN_RPM;
446 if (!strcmp(np->type, "fan-pwm-control") ||
447 !strcmp(np->type, "fan-pwm"))
448 type = FCU_FAN_PWM;
449 /* Only care about fans for now */
450 if (type == -1)
451 continue;
452
453 /* Lookup for a matching location */
454 loc = of_get_property(np, "location", NULL);
455 reg = of_get_property(np, "reg", NULL);
456 if (loc == NULL || reg == NULL)
457 continue;
458 DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
459
460 for (i = 0; i < ARRAY_SIZE(loc_trans); i++) {
461 if (strncmp(loc, loc_trans[i].dt_name,
462 strlen(loc_trans[i].dt_name)))
463 continue;
464 name = loc_trans[i].ct_name;
465
466 DBG(" location match, name: %s\n", name);
467
468 if (type == FCU_FAN_RPM)
469 id = ((*reg) - 0x10) / 2;
470 else
471 id = ((*reg) - 0x30) / 2;
472 if (id > 7) {
473 pr_warning("wf_fcu: Can't parse "
474 "fan ID in device-tree for %s\n",
475 np->full_name);
476 break;
477 }
478 wf_fcu_add_fan(pv, name, type, id);
479 break;
480 }
481 }
482}
483
484static void __devinit wf_fcu_default_fans(struct wf_fcu_priv *pv)
485{
486 /* We only support the default fans for PowerMac7,2 */
487 if (!of_machine_is_compatible("PowerMac7,2"))
488 return;
489
490 wf_fcu_add_fan(pv, "backside-fan", FCU_FAN_PWM, 1);
491 wf_fcu_add_fan(pv, "drive-bay-fan", FCU_FAN_RPM, 2);
492 wf_fcu_add_fan(pv, "slots-fan", FCU_FAN_PWM, 2);
493 wf_fcu_add_fan(pv, "cpu-front-fan-0", FCU_FAN_RPM, 3);
494 wf_fcu_add_fan(pv, "cpu-rear-fan-0", FCU_FAN_RPM, 4);
495 wf_fcu_add_fan(pv, "cpu-front-fan-1", FCU_FAN_RPM, 5);
496 wf_fcu_add_fan(pv, "cpu-rear-fan-1", FCU_FAN_RPM, 6);
497}
498
499static int __devinit wf_fcu_init_chip(struct wf_fcu_priv *pv)
500{
501 unsigned char buf = 0xff;
502 int rc;
503
504 rc = wf_fcu_write_reg(pv, 0xe, &buf, 1);
505 if (rc < 0)
506 return -EIO;
507 rc = wf_fcu_write_reg(pv, 0x2e, &buf, 1);
508 if (rc < 0)
509 return -EIO;
510 rc = wf_fcu_read_reg(pv, 0, &buf, 1);
511 if (rc < 0)
512 return -EIO;
513 pv->rpm_shift = (buf == 1) ? 2 : 3;
514
515 pr_debug("wf_fcu: FCU Initialized, RPM fan shift is %d\n",
516 pv->rpm_shift);
517
518 return 0;
519}
520
521static int __devinit wf_fcu_probe(struct i2c_client *client,
522 const struct i2c_device_id *id)
523{
524 struct wf_fcu_priv *pv;
525
526 pv = kzalloc(sizeof(*pv), GFP_KERNEL);
527 if (!pv)
528 return -ENOMEM;
529
530 kref_init(&pv->ref);
531 mutex_init(&pv->lock);
532 INIT_LIST_HEAD(&pv->fan_list);
533 pv->i2c = client;
534
535 /*
536 * First we must start the FCU which will query the
537 * shift value to apply to RPMs
538 */
539 if (wf_fcu_init_chip(pv)) {
540 pr_err("wf_fcu: Initialization failed !\n");
541 kfree(pv);
542 return -ENXIO;
543 }
544
545 /* First lookup fans in the device-tree */
546 wf_fcu_lookup_fans(pv);
547
548 /*
549 * Older machines don't have the device-tree entries
550 * we are looking for, just hard code the list
551 */
552 if (list_empty(&pv->fan_list))
553 wf_fcu_default_fans(pv);
554
555 /* Still no fans ? FAIL */
556 if (list_empty(&pv->fan_list)) {
557 pr_err("wf_fcu: Failed to find fans for your machine\n");
558 kfree(pv);
559 return -ENODEV;
560 }
561
562 dev_set_drvdata(&client->dev, pv);
563
564 return 0;
565}
566
567static int __devexit wf_fcu_remove(struct i2c_client *client)
568{
569 struct wf_fcu_priv *pv = dev_get_drvdata(&client->dev);
570 struct wf_fcu_fan *fan;
571
572 while (!list_empty(&pv->fan_list)) {
573 fan = list_first_entry(&pv->fan_list, struct wf_fcu_fan, link);
574 list_del(&fan->link);
575 wf_unregister_control(&fan->ctrl);
576 }
577 kref_put(&pv->ref, wf_fcu_release);
578 return 0;
579}
580
581static const struct i2c_device_id wf_fcu_id[] = {
582 { "MAC,fcu", 0 },
583 { }
584};
585MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
586
587static struct i2c_driver wf_fcu_driver = {
588 .driver = {
589 .name = "wf_fcu",
590 },
591 .probe = wf_fcu_probe,
592 .remove = wf_fcu_remove,
593 .id_table = wf_fcu_id,
594};
595
596static int __init wf_fcu_init(void)
597{
598 return i2c_add_driver(&wf_fcu_driver);
599}
600
601static void __exit wf_fcu_exit(void)
602{
603 i2c_del_driver(&wf_fcu_driver);
604}
605
606
607module_init(wf_fcu_init);
608module_exit(wf_fcu_exit);
609
610MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
611MODULE_DESCRIPTION("FCU control objects for PowerMacs thermal control");
612MODULE_LICENSE("GPL");
613
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index 4d6a90a1372b..b0c2d3695b34 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -23,7 +23,7 @@
23 23
24#include "windfarm.h" 24#include "windfarm.h"
25 25
26#define VERSION "0.2" 26#define VERSION "1.0"
27 27
28#undef DEBUG 28#undef DEBUG
29 29
@@ -36,8 +36,8 @@
36struct wf_lm75_sensor { 36struct wf_lm75_sensor {
37 int ds1775 : 1; 37 int ds1775 : 1;
38 int inited : 1; 38 int inited : 1;
39 struct i2c_client *i2c; 39 struct i2c_client *i2c;
40 struct wf_sensor sens; 40 struct wf_sensor sens;
41}; 41};
42#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) 42#define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
43 43
@@ -90,40 +90,19 @@ static struct wf_sensor_ops wf_lm75_ops = {
90 90
91static int wf_lm75_probe(struct i2c_client *client, 91static int wf_lm75_probe(struct i2c_client *client,
92 const struct i2c_device_id *id) 92 const struct i2c_device_id *id)
93{ 93{
94 struct wf_lm75_sensor *lm; 94 struct wf_lm75_sensor *lm;
95 int rc; 95 int rc, ds1775 = id->driver_data;
96 96 const char *name, *loc;
97 lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
98 if (lm == NULL)
99 return -ENODEV;
100
101 lm->inited = 0;
102 lm->ds1775 = id->driver_data;
103 lm->i2c = client;
104 lm->sens.name = client->dev.platform_data;
105 lm->sens.ops = &wf_lm75_ops;
106 i2c_set_clientdata(client, lm);
107
108 rc = wf_register_sensor(&lm->sens);
109 if (rc)
110 kfree(lm);
111
112 return rc;
113}
114
115static struct i2c_driver wf_lm75_driver;
116
117static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
118 u8 addr, int ds1775,
119 const char *loc)
120{
121 struct i2c_board_info info;
122 struct i2c_client *client;
123 char *name;
124 97
125 DBG("wf_lm75: creating %s device at address 0x%02x\n", 98 DBG("wf_lm75: creating %s device at address 0x%02x\n",
126 ds1775 ? "ds1775" : "lm75", addr); 99 ds1775 ? "ds1775" : "lm75", client->addr);
100
101 loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
102 if (!loc) {
103 dev_warn(&client->dev, "Missing hwsensor-location property!\n");
104 return -ENXIO;
105 }
127 106
128 /* Usual rant about sensor names not beeing very consistent in 107 /* Usual rant about sensor names not beeing very consistent in
129 * the device-tree, oh well ... 108 * the device-tree, oh well ...
@@ -137,68 +116,31 @@ static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter,
137 name = "optical-drive-temp"; 116 name = "optical-drive-temp";
138 else if (!strcmp(loc, "HD Temp")) 117 else if (!strcmp(loc, "HD Temp"))
139 name = "hard-drive-temp"; 118 name = "hard-drive-temp";
119 else if (!strcmp(loc, "PCI SLOTS"))
120 name = "slots-temp";
121 else if (!strcmp(loc, "CPU A INLET"))
122 name = "cpu-inlet-temp-0";
123 else if (!strcmp(loc, "CPU B INLET"))
124 name = "cpu-inlet-temp-1";
140 else 125 else
141 goto fail; 126 return -ENXIO;
142 127
143 memset(&info, 0, sizeof(struct i2c_board_info));
144 info.addr = (addr >> 1) & 0x7f;
145 info.platform_data = name;
146 strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE);
147
148 client = i2c_new_device(adapter, &info);
149 if (client == NULL) {
150 printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n",
151 ds1775 ? "ds1775" : "lm75", name);
152 goto fail;
153 }
154
155 /*
156 * Let i2c-core delete that device on driver removal.
157 * This is safe because i2c-core holds the core_lock mutex for us.
158 */
159 list_add_tail(&client->detected, &wf_lm75_driver.clients);
160 return client;
161 fail:
162 return NULL;
163}
164
165static int wf_lm75_attach(struct i2c_adapter *adapter)
166{
167 struct device_node *busnode, *dev;
168 struct pmac_i2c_bus *bus;
169 128
170 DBG("wf_lm75: adapter %s detected\n", adapter->name); 129 lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
171 130 if (lm == NULL)
172 bus = pmac_i2c_adapter_to_bus(adapter);
173 if (bus == NULL)
174 return -ENODEV; 131 return -ENODEV;
175 busnode = pmac_i2c_get_bus_node(bus);
176 132
177 DBG("wf_lm75: bus found, looking for device...\n"); 133 lm->inited = 0;
178 134 lm->ds1775 = ds1775;
179 /* Now look for lm75(s) in there */ 135 lm->i2c = client;
180 for (dev = NULL; 136 lm->sens.name = (char *)name; /* XXX fix constness in structure */
181 (dev = of_get_next_child(busnode, dev)) != NULL;) { 137 lm->sens.ops = &wf_lm75_ops;
182 const char *loc = 138 i2c_set_clientdata(client, lm);
183 of_get_property(dev, "hwsensor-location", NULL);
184 u8 addr;
185 139
186 /* We must re-match the adapter in order to properly check 140 rc = wf_register_sensor(&lm->sens);
187 * the channel on multibus setups 141 if (rc)
188 */ 142 kfree(lm);
189 if (!pmac_i2c_match_adapter(dev, adapter)) 143 return rc;
190 continue;
191 addr = pmac_i2c_get_dev_addr(dev);
192 if (loc == NULL || addr == 0)
193 continue;
194 /* real lm75 */
195 if (of_device_is_compatible(dev, "lm75"))
196 wf_lm75_create(adapter, addr, 0, loc);
197 /* ds1775 (compatible, better resolution */
198 else if (of_device_is_compatible(dev, "ds1775"))
199 wf_lm75_create(adapter, addr, 1, loc);
200 }
201 return 0;
202} 144}
203 145
204static int wf_lm75_remove(struct i2c_client *client) 146static int wf_lm75_remove(struct i2c_client *client)
@@ -217,16 +159,16 @@ static int wf_lm75_remove(struct i2c_client *client)
217} 159}
218 160
219static const struct i2c_device_id wf_lm75_id[] = { 161static const struct i2c_device_id wf_lm75_id[] = {
220 { "wf_lm75", 0 }, 162 { "MAC,lm75", 0 },
221 { "wf_ds1775", 1 }, 163 { "MAC,ds1775", 1 },
222 { } 164 { }
223}; 165};
166MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
224 167
225static struct i2c_driver wf_lm75_driver = { 168static struct i2c_driver wf_lm75_driver = {
226 .driver = { 169 .driver = {
227 .name = "wf_lm75", 170 .name = "wf_lm75",
228 }, 171 },
229 .attach_adapter = wf_lm75_attach,
230 .probe = wf_lm75_probe, 172 .probe = wf_lm75_probe,
231 .remove = wf_lm75_remove, 173 .remove = wf_lm75_remove,
232 .id_table = wf_lm75_id, 174 .id_table = wf_lm75_id,
@@ -234,11 +176,6 @@ static struct i2c_driver wf_lm75_driver = {
234 176
235static int __init wf_lm75_sensor_init(void) 177static int __init wf_lm75_sensor_init(void)
236{ 178{
237 /* Don't register on old machines that use therm_pm72 for now */
238 if (of_machine_is_compatible("PowerMac7,2") ||
239 of_machine_is_compatible("PowerMac7,3") ||
240 of_machine_is_compatible("RackMac3,1"))
241 return -ENODEV;
242 return i2c_add_driver(&wf_lm75_driver); 179 return i2c_add_driver(&wf_lm75_driver);
243} 180}
244 181
diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c
new file mode 100644
index 000000000000..c071aab79dd1
--- /dev/null
+++ b/drivers/macintosh/windfarm_lm87_sensor.c
@@ -0,0 +1,201 @@
1/*
2 * Windfarm PowerMac thermal control. LM87 sensor
3 *
4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
5 *
6 * Released under the term of the GNU GPL v2.
7 *
8 */
9
10#include <linux/types.h>
11#include <linux/errno.h>
12#include <linux/kernel.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/init.h>
16#include <linux/wait.h>
17#include <linux/i2c.h>
18#include <asm/prom.h>
19#include <asm/machdep.h>
20#include <asm/io.h>
21#include <asm/sections.h>
22#include <asm/pmac_low_i2c.h>
23
24#include "windfarm.h"
25
26#define VERSION "1.0"
27
28#undef DEBUG
29
30#ifdef DEBUG
31#define DBG(args...) printk(args)
32#else
33#define DBG(args...) do { } while(0)
34#endif
35
36struct wf_lm87_sensor {
37 struct i2c_client *i2c;
38 struct wf_sensor sens;
39};
40#define wf_to_lm87(c) container_of(c, struct wf_lm87_sensor, sens)
41
42
43static int wf_lm87_read_reg(struct i2c_client *chip, int reg)
44{
45 int rc, tries = 0;
46 u8 buf;
47
48 for (;;) {
49 /* Set address */
50 buf = (u8)reg;
51 rc = i2c_master_send(chip, &buf, 1);
52 if (rc <= 0)
53 goto error;
54 rc = i2c_master_recv(chip, &buf, 1);
55 if (rc <= 0)
56 goto error;
57 return (int)buf;
58 error:
59 DBG("wf_lm87: Error reading LM87, retrying...\n");
60 if (++tries > 10) {
61 printk(KERN_ERR "wf_lm87: Error reading LM87 !\n");
62 return -EIO;
63 }
64 msleep(10);
65 }
66}
67
68static int wf_lm87_get(struct wf_sensor *sr, s32 *value)
69{
70 struct wf_lm87_sensor *lm = sr->priv;
71 s32 temp;
72
73 if (lm->i2c == NULL)
74 return -ENODEV;
75
76#define LM87_INT_TEMP 0x27
77
78 /* Read temperature register */
79 temp = wf_lm87_read_reg(lm->i2c, LM87_INT_TEMP);
80 if (temp < 0)
81 return temp;
82 *value = temp << 16;
83
84 return 0;
85}
86
87static void wf_lm87_release(struct wf_sensor *sr)
88{
89 struct wf_lm87_sensor *lm = wf_to_lm87(sr);
90
91 kfree(lm);
92}
93
94static struct wf_sensor_ops wf_lm87_ops = {
95 .get_value = wf_lm87_get,
96 .release = wf_lm87_release,
97 .owner = THIS_MODULE,
98};
99
100static int wf_lm87_probe(struct i2c_client *client,
101 const struct i2c_device_id *id)
102{
103 struct wf_lm87_sensor *lm;
104 const char *name = NULL, *loc;
105 struct device_node *np = NULL;
106 int rc;
107
108 /*
109 * The lm87 contains a whole pile of sensors, additionally,
110 * the Xserve G5 has several lm87's. However, for now we only
111 * care about the internal temperature sensor
112 */
113 while ((np = of_get_next_child(client->dev.of_node, np)) != NULL) {
114 if (strcmp(np->name, "int-temp"))
115 continue;
116 loc = of_get_property(np, "location", NULL);
117 if (!loc)
118 continue;
119 if (strstr(loc, "DIMM"))
120 name = "dimms-temp";
121 else if (strstr(loc, "Processors"))
122 name = "between-cpus-temp";
123 if (name) {
124 of_node_put(np);
125 break;
126 }
127 }
128 if (!name) {
129 pr_warning("wf_lm87: Unsupported sensor %s\n",
130 client->dev.of_node->full_name);
131 return -ENODEV;
132 }
133
134 lm = kzalloc(sizeof(struct wf_lm87_sensor), GFP_KERNEL);
135 if (lm == NULL)
136 return -ENODEV;
137
138 lm->i2c = client;
139 lm->sens.name = name;
140 lm->sens.ops = &wf_lm87_ops;
141 lm->sens.priv = lm;
142 i2c_set_clientdata(client, lm);
143
144 rc = wf_register_sensor(&lm->sens);
145 if (rc)
146 kfree(lm);
147 return rc;
148}
149
150static int wf_lm87_remove(struct i2c_client *client)
151{
152 struct wf_lm87_sensor *lm = i2c_get_clientdata(client);
153
154 DBG("wf_lm87: i2c detatch called for %s\n", lm->sens.name);
155
156 /* Mark client detached */
157 lm->i2c = NULL;
158
159 /* release sensor */
160 wf_unregister_sensor(&lm->sens);
161
162 return 0;
163}
164
165static const struct i2c_device_id wf_lm87_id[] = {
166 { "MAC,lm87cimt", 0 },
167 { }
168};
169MODULE_DEVICE_TABLE(i2c, wf_lm87_id);
170
171static struct i2c_driver wf_lm87_driver = {
172 .driver = {
173 .name = "wf_lm87",
174 },
175 .probe = wf_lm87_probe,
176 .remove = wf_lm87_remove,
177 .id_table = wf_lm87_id,
178};
179
180static int __init wf_lm87_sensor_init(void)
181{
182 /* We only support this on the Xserve */
183 if (!of_machine_is_compatible("RackMac3,1"))
184 return -ENODEV;
185
186 return i2c_add_driver(&wf_lm87_driver);
187}
188
189static void __exit wf_lm87_sensor_exit(void)
190{
191 i2c_del_driver(&wf_lm87_driver);
192}
193
194
195module_init(wf_lm87_sensor_init);
196module_exit(wf_lm87_sensor_exit);
197
198MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
199MODULE_DESCRIPTION("LM87 sensor objects for PowerMacs thermal control");
200MODULE_LICENSE("GPL");
201
diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c
index 8204113268f4..371b058d2f7d 100644
--- a/drivers/macintosh/windfarm_max6690_sensor.c
+++ b/drivers/macintosh/windfarm_max6690_sensor.c
@@ -16,7 +16,7 @@
16 16
17#include "windfarm.h" 17#include "windfarm.h"
18 18
19#define VERSION "0.2" 19#define VERSION "1.0"
20 20
21/* This currently only exports the external temperature sensor, 21/* This currently only exports the external temperature sensor,
22 since that's all the control loops need. */ 22 since that's all the control loops need. */
@@ -64,9 +64,29 @@ static struct wf_sensor_ops wf_max6690_ops = {
64static int wf_max6690_probe(struct i2c_client *client, 64static int wf_max6690_probe(struct i2c_client *client,
65 const struct i2c_device_id *id) 65 const struct i2c_device_id *id)
66{ 66{
67 const char *name, *loc;
67 struct wf_6690_sensor *max; 68 struct wf_6690_sensor *max;
68 int rc; 69 int rc;
69 70
71 loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
72 if (!loc) {
73 dev_warn(&client->dev, "Missing hwsensor-location property!\n");
74 return -ENXIO;
75 }
76
77 /*
78 * We only expose the external temperature register for
79 * now as this is all we need for our control loops
80 */
81 if (!strcmp(loc, "BACKSIDE") || !strcmp(loc, "SYS CTRLR AMBIENT"))
82 name = "backside-temp";
83 else if (!strcmp(loc, "NB Ambient"))
84 name = "north-bridge-temp";
85 else if (!strcmp(loc, "GPU Ambient"))
86 name = "gpu-temp";
87 else
88 return -ENXIO;
89
70 max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); 90 max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
71 if (max == NULL) { 91 if (max == NULL) {
72 printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: " 92 printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
@@ -75,90 +95,16 @@ static int wf_max6690_probe(struct i2c_client *client,
75 } 95 }
76 96
77 max->i2c = client; 97 max->i2c = client;
78 max->sens.name = client->dev.platform_data; 98 max->sens.name = (char *)name; /* XXX fix constness in structure */
79 max->sens.ops = &wf_max6690_ops; 99 max->sens.ops = &wf_max6690_ops;
80 i2c_set_clientdata(client, max); 100 i2c_set_clientdata(client, max);
81 101
82 rc = wf_register_sensor(&max->sens); 102 rc = wf_register_sensor(&max->sens);
83 if (rc) { 103 if (rc)
84 kfree(max); 104 kfree(max);
85 }
86
87 return rc; 105 return rc;
88} 106}
89 107
90static struct i2c_driver wf_max6690_driver;
91
92static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter,
93 u8 addr, const char *loc)
94{
95 struct i2c_board_info info;
96 struct i2c_client *client;
97 char *name;
98
99 if (!strcmp(loc, "BACKSIDE"))
100 name = "backside-temp";
101 else if (!strcmp(loc, "NB Ambient"))
102 name = "north-bridge-temp";
103 else if (!strcmp(loc, "GPU Ambient"))
104 name = "gpu-temp";
105 else
106 goto fail;
107
108 memset(&info, 0, sizeof(struct i2c_board_info));
109 info.addr = addr >> 1;
110 info.platform_data = name;
111 strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE);
112
113 client = i2c_new_device(adapter, &info);
114 if (client == NULL) {
115 printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n");
116 goto fail;
117 }
118
119 /*
120 * Let i2c-core delete that device on driver removal.
121 * This is safe because i2c-core holds the core_lock mutex for us.
122 */
123 list_add_tail(&client->detected, &wf_max6690_driver.clients);
124 return client;
125
126 fail:
127 return NULL;
128}
129
130static int wf_max6690_attach(struct i2c_adapter *adapter)
131{
132 struct device_node *busnode, *dev = NULL;
133 struct pmac_i2c_bus *bus;
134 const char *loc;
135
136 bus = pmac_i2c_adapter_to_bus(adapter);
137 if (bus == NULL)
138 return -ENODEV;
139 busnode = pmac_i2c_get_bus_node(bus);
140
141 while ((dev = of_get_next_child(busnode, dev)) != NULL) {
142 u8 addr;
143
144 /* We must re-match the adapter in order to properly check
145 * the channel on multibus setups
146 */
147 if (!pmac_i2c_match_adapter(dev, adapter))
148 continue;
149 if (!of_device_is_compatible(dev, "max6690"))
150 continue;
151 addr = pmac_i2c_get_dev_addr(dev);
152 loc = of_get_property(dev, "hwsensor-location", NULL);
153 if (loc == NULL || addr == 0)
154 continue;
155 printk("found max6690, loc=%s addr=0x%02x\n", loc, addr);
156 wf_max6690_create(adapter, addr, loc);
157 }
158
159 return 0;
160}
161
162static int wf_max6690_remove(struct i2c_client *client) 108static int wf_max6690_remove(struct i2c_client *client)
163{ 109{
164 struct wf_6690_sensor *max = i2c_get_clientdata(client); 110 struct wf_6690_sensor *max = i2c_get_clientdata(client);
@@ -170,15 +116,15 @@ static int wf_max6690_remove(struct i2c_client *client)
170} 116}
171 117
172static const struct i2c_device_id wf_max6690_id[] = { 118static const struct i2c_device_id wf_max6690_id[] = {
173 { "wf_max6690", 0 }, 119 { "MAC,max6690", 0 },
174 { } 120 { }
175}; 121};
122MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
176 123
177static struct i2c_driver wf_max6690_driver = { 124static struct i2c_driver wf_max6690_driver = {
178 .driver = { 125 .driver = {
179 .name = "wf_max6690", 126 .name = "wf_max6690",
180 }, 127 },
181 .attach_adapter = wf_max6690_attach,
182 .probe = wf_max6690_probe, 128 .probe = wf_max6690_probe,
183 .remove = wf_max6690_remove, 129 .remove = wf_max6690_remove,
184 .id_table = wf_max6690_id, 130 .id_table = wf_max6690_id,
@@ -186,11 +132,6 @@ static struct i2c_driver wf_max6690_driver = {
186 132
187static int __init wf_max6690_sensor_init(void) 133static int __init wf_max6690_sensor_init(void)
188{ 134{
189 /* Don't register on old machines that use therm_pm72 for now */
190 if (of_machine_is_compatible("PowerMac7,2") ||
191 of_machine_is_compatible("PowerMac7,3") ||
192 of_machine_is_compatible("RackMac3,1"))
193 return -ENODEV;
194 return i2c_add_driver(&wf_max6690_driver); 135 return i2c_add_driver(&wf_max6690_driver);
195} 136}
196 137
diff --git a/drivers/macintosh/windfarm_mpu.h b/drivers/macintosh/windfarm_mpu.h
new file mode 100644
index 000000000000..046edc8c2ec5
--- /dev/null
+++ b/drivers/macintosh/windfarm_mpu.h
@@ -0,0 +1,105 @@
1/*
2 * Windfarm PowerMac thermal control
3 *
4 * Copyright 2012 Benjamin Herrenschmidt, IBM Corp.
5 *
6 * Released under the term of the GNU GPL v2.
7 */
8
9#ifndef __WINDFARM_MPU_H
10#define __WINDFARM_MPU_H
11
12typedef unsigned short fu16;
13typedef int fs32;
14typedef short fs16;
15
16/* Definition of the MPU data structure which contains per CPU
17 * calibration information (among others) for the G5 machines
18 */
19struct mpu_data
20{
21 u8 signature; /* 0x00 - EEPROM sig. */
22 u8 bytes_used; /* 0x01 - Bytes used in eeprom (160 ?) */
23 u8 size; /* 0x02 - EEPROM size (256 ?) */
24 u8 version; /* 0x03 - EEPROM version */
25 u32 data_revision; /* 0x04 - Dataset revision */
26 u8 processor_bin_code[3]; /* 0x08 - Processor BIN code */
27 u8 bin_code_expansion; /* 0x0b - ??? (padding ?) */
28 u8 processor_num; /* 0x0c - Number of CPUs on this MPU */
29 u8 input_mul_bus_div; /* 0x0d - Clock input multiplier/bus divider */
30 u8 reserved1[2]; /* 0x0e - */
31 u32 input_clk_freq_high; /* 0x10 - Input clock frequency high */
32 u8 cpu_nb_target_cycles; /* 0x14 - ??? */
33 u8 cpu_statlat; /* 0x15 - ??? */
34 u8 cpu_snooplat; /* 0x16 - ??? */
35 u8 cpu_snoopacc; /* 0x17 - ??? */
36 u8 nb_paamwin; /* 0x18 - ??? */
37 u8 nb_statlat; /* 0x19 - ??? */
38 u8 nb_snooplat; /* 0x1a - ??? */
39 u8 nb_snoopwin; /* 0x1b - ??? */
40 u8 api_bus_mode; /* 0x1c - ??? */
41 u8 reserved2[3]; /* 0x1d - */
42 u32 input_clk_freq_low; /* 0x20 - Input clock frequency low */
43 u8 processor_card_slot; /* 0x24 - Processor card slot number */
44 u8 reserved3[2]; /* 0x25 - */
45 u8 padjmax; /* 0x27 - Max power adjustment (Not in OF!) */
46 u8 ttarget; /* 0x28 - Target temperature */
47 u8 tmax; /* 0x29 - Max temperature */
48 u8 pmaxh; /* 0x2a - Max power */
49 u8 tguardband; /* 0x2b - Guardband temp ??? Hist. len in OSX */
50 fs32 pid_gp; /* 0x2c - PID proportional gain */
51 fs32 pid_gr; /* 0x30 - PID reset gain */
52 fs32 pid_gd; /* 0x34 - PID derivative gain */
53 fu16 voph; /* 0x38 - Vop High */
54 fu16 vopl; /* 0x3a - Vop Low */
55 fs16 nactual_die; /* 0x3c - nActual Die */
56 fs16 nactual_heatsink; /* 0x3e - nActual Heatsink */
57 fs16 nactual_system; /* 0x40 - nActual System */
58 u16 calibration_flags; /* 0x42 - Calibration flags */
59 fu16 mdiode; /* 0x44 - Diode M value (scaling factor) */
60 fs16 bdiode; /* 0x46 - Diode B value (offset) */
61 fs32 theta_heat_sink; /* 0x48 - Theta heat sink */
62 u16 rminn_intake_fan; /* 0x4c - Intake fan min RPM */
63 u16 rmaxn_intake_fan; /* 0x4e - Intake fan max RPM */
64 u16 rminn_exhaust_fan; /* 0x50 - Exhaust fan min RPM */
65 u16 rmaxn_exhaust_fan; /* 0x52 - Exhaust fan max RPM */
66 u8 processor_part_num[8]; /* 0x54 - Processor part number XX pumps min/max */
67 u32 processor_lot_num; /* 0x5c - Processor lot number */
68 u8 orig_card_sernum[0x10]; /* 0x60 - Card original serial number */
69 u8 curr_card_sernum[0x10]; /* 0x70 - Card current serial number */
70 u8 mlb_sernum[0x18]; /* 0x80 - MLB serial number */
71 u32 checksum1; /* 0x98 - */
72 u32 checksum2; /* 0x9c - */
73}; /* Total size = 0xa0 */
74
75static inline const struct mpu_data *wf_get_mpu(int cpu)
76{
77 struct device_node *np;
78 char nodename[64];
79 const void *data;
80 int len;
81
82 /*
83 * prom.c routine for finding a node by path is a bit brain dead
84 * and requires exact @xxx unit numbers. This is a bit ugly but
85 * will work for these machines
86 */
87 sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
88 np = of_find_node_by_path(nodename);
89 if (!np)
90 return NULL;
91 data = of_get_property(np, "cpuid", &len);
92 of_node_put(np);
93 if (!data)
94 return NULL;
95
96 /*
97 * We are naughty, we have dropped the reference to the device
98 * node and still return a pointer to the content. We know we
99 * can do that though as this is only ever called on PowerMac
100 * which cannot remove those nodes
101 */
102 return data;
103}
104
105#endif /* __WINDFARM_MPU_H */
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
new file mode 100644
index 000000000000..84ac913d7e3a
--- /dev/null
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -0,0 +1,847 @@
1/*
2 * Windfarm PowerMac thermal control.
3 * Control loops for PowerMac7,2 and 7,3
4 *
5 * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
6 *
7 * Use and redistribute under the terms of the GNU GPL v2.
8 */
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/platform_device.h>
14#include <linux/reboot.h>
15#include <asm/prom.h>
16#include <asm/smu.h>
17
18#include "windfarm.h"
19#include "windfarm_pid.h"
20#include "windfarm_mpu.h"
21
22#define VERSION "1.0"
23
24#undef DEBUG
25#undef LOTSA_DEBUG
26
27#ifdef DEBUG
28#define DBG(args...) printk(args)
29#else
30#define DBG(args...) do { } while(0)
31#endif
32
33#ifdef LOTSA_DEBUG
34#define DBG_LOTS(args...) printk(args)
35#else
36#define DBG_LOTS(args...) do { } while(0)
37#endif
38
39/* define this to force CPU overtemp to 60 degree, useful for testing
40 * the overtemp code
41 */
42#undef HACKED_OVERTEMP
43
44/* We currently only handle 2 chips */
45#define NR_CHIPS 2
46#define NR_CPU_FANS 3 * NR_CHIPS
47
48/* Controls and sensors */
49static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
50static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
51static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
52static struct wf_sensor *backside_temp;
53static struct wf_sensor *drives_temp;
54
55static struct wf_control *cpu_front_fans[NR_CHIPS];
56static struct wf_control *cpu_rear_fans[NR_CHIPS];
57static struct wf_control *cpu_pumps[NR_CHIPS];
58static struct wf_control *backside_fan;
59static struct wf_control *drives_fan;
60static struct wf_control *slots_fan;
61static struct wf_control *cpufreq_clamp;
62
63/* We keep a temperature history for average calculation of 180s */
64#define CPU_TEMP_HIST_SIZE 180
65
66/* Fixed speed for slot fan */
67#define SLOTS_FAN_DEFAULT_PWM 40
68
69/* Scale value for CPU intake fans */
70#define CPU_INTAKE_SCALE 0x0000f852
71
72/* PID loop state */
73static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
74static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
75static bool cpu_pid_combined;
76static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
77static int cpu_thist_pt;
78static s64 cpu_thist_total;
79static s32 cpu_all_tmax = 100 << 16;
80static struct wf_pid_state backside_pid;
81static int backside_tick;
82static struct wf_pid_state drives_pid;
83static int drives_tick;
84
85static int nr_chips;
86static bool have_all_controls;
87static bool have_all_sensors;
88static bool started;
89
90static int failure_state;
91#define FAILURE_SENSOR 1
92#define FAILURE_FAN 2
93#define FAILURE_PERM 4
94#define FAILURE_LOW_OVERTEMP 8
95#define FAILURE_HIGH_OVERTEMP 16
96
97/* Overtemp values */
98#define LOW_OVER_AVERAGE 0
99#define LOW_OVER_IMMEDIATE (10 << 16)
100#define LOW_OVER_CLEAR ((-10) << 16)
101#define HIGH_OVER_IMMEDIATE (14 << 16)
102#define HIGH_OVER_AVERAGE (10 << 16)
103#define HIGH_OVER_IMMEDIATE (14 << 16)
104
105
106static void cpu_max_all_fans(void)
107{
108 int i;
109
110 /* We max all CPU fans in case of a sensor error. We also do the
111 * cpufreq clamping now, even if it's supposedly done later by the
112 * generic code anyway, we do it earlier here to react faster
113 */
114 if (cpufreq_clamp)
115 wf_control_set_max(cpufreq_clamp);
116 for (i = 0; i < nr_chips; i++) {
117 if (cpu_front_fans[i])
118 wf_control_set_max(cpu_front_fans[i]);
119 if (cpu_rear_fans[i])
120 wf_control_set_max(cpu_rear_fans[i]);
121 if (cpu_pumps[i])
122 wf_control_set_max(cpu_pumps[i]);
123 }
124}
125
126static int cpu_check_overtemp(s32 temp)
127{
128 int new_state = 0;
129 s32 t_avg, t_old;
130 static bool first = true;
131
132 /* First check for immediate overtemps */
133 if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
134 new_state |= FAILURE_LOW_OVERTEMP;
135 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
136 printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
137 " temperature !\n");
138 }
139 if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
140 new_state |= FAILURE_HIGH_OVERTEMP;
141 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
142 printk(KERN_ERR "windfarm: Critical overtemp due to"
143 " immediate CPU temperature !\n");
144 }
145
146 /*
147 * The first time around, initialize the array with the first
148 * temperature reading
149 */
150 if (first) {
151 int i;
152
153 cpu_thist_total = 0;
154 for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
155 cpu_thist[i] = temp;
156 cpu_thist_total += temp;
157 }
158 first = false;
159 }
160
161 /*
162 * We calculate a history of max temperatures and use that for the
163 * overtemp management
164 */
165 t_old = cpu_thist[cpu_thist_pt];
166 cpu_thist[cpu_thist_pt] = temp;
167 cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
168 cpu_thist_total -= t_old;
169 cpu_thist_total += temp;
170 t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
171
172 DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
173 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
174
175 /* Now check for average overtemps */
176 if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
177 new_state |= FAILURE_LOW_OVERTEMP;
178 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
179 printk(KERN_ERR "windfarm: Overtemp due to average CPU"
180 " temperature !\n");
181 }
182 if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
183 new_state |= FAILURE_HIGH_OVERTEMP;
184 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
185 printk(KERN_ERR "windfarm: Critical overtemp due to"
186 " average CPU temperature !\n");
187 }
188
189 /* Now handle overtemp conditions. We don't currently use the windfarm
190 * overtemp handling core as it's not fully suited to the needs of those
191 * new machine. This will be fixed later.
192 */
193 if (new_state) {
194 /* High overtemp -> immediate shutdown */
195 if (new_state & FAILURE_HIGH_OVERTEMP)
196 machine_power_off();
197 if ((failure_state & new_state) != new_state)
198 cpu_max_all_fans();
199 failure_state |= new_state;
200 } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
201 (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
202 printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
203 failure_state &= ~FAILURE_LOW_OVERTEMP;
204 }
205
206 return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
207}
208
209static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
210{
211 s32 dtemp, volts, amps;
212 int rc;
213
214 /* Get diode temperature */
215 rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
216 if (rc) {
217 DBG(" CPU%d: temp reading error !\n", cpu);
218 return -EIO;
219 }
220 DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
221 *temp = dtemp;
222
223 /* Get voltage */
224 rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
225 if (rc) {
226 DBG(" CPU%d, volts reading error !\n", cpu);
227 return -EIO;
228 }
229 DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
230
231 /* Get current */
232 rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
233 if (rc) {
234 DBG(" CPU%d, current reading error !\n", cpu);
235 return -EIO;
236 }
237 DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
238
239 /* Calculate power */
240
241 /* Scale voltage and current raw sensor values according to fixed scales
242 * obtained in Darwin and calculate power from I and V
243 */
244 *power = (((u64)volts) * ((u64)amps)) >> 16;
245
246 DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
247
248 return 0;
249
250}
251
252static void cpu_fans_tick_split(void)
253{
254 int err, cpu;
255 s32 intake, temp, power, t_max = 0;
256
257 DBG_LOTS("* cpu fans_tick_split()\n");
258
259 for (cpu = 0; cpu < nr_chips; ++cpu) {
260 struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
261
262 /* Read current speed */
263 wf_control_get(cpu_rear_fans[cpu], &sp->target);
264
265 DBG_LOTS(" CPU%d: cur_target = %d RPM\n", cpu, sp->target);
266
267 err = read_one_cpu_vals(cpu, &temp, &power);
268 if (err) {
269 failure_state |= FAILURE_SENSOR;
270 cpu_max_all_fans();
271 return;
272 }
273
274 /* Keep track of highest temp */
275 t_max = max(t_max, temp);
276
277 /* Handle possible overtemps */
278 if (cpu_check_overtemp(t_max))
279 return;
280
281 /* Run PID */
282 wf_cpu_pid_run(sp, power, temp);
283
284 DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
285
286 /* Apply result directly to exhaust fan */
287 err = wf_control_set(cpu_rear_fans[cpu], sp->target);
288 if (err) {
289 pr_warning("wf_pm72: Fan %s reports error %d\n",
290 cpu_rear_fans[cpu]->name, err);
291 failure_state |= FAILURE_FAN;
292 break;
293 }
294
295 /* Scale result for intake fan */
296 intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
297 DBG_LOTS(" CPU%d: intake = %d RPM\n", cpu, intake);
298 err = wf_control_set(cpu_front_fans[cpu], intake);
299 if (err) {
300 pr_warning("wf_pm72: Fan %s reports error %d\n",
301 cpu_front_fans[cpu]->name, err);
302 failure_state |= FAILURE_FAN;
303 break;
304 }
305 }
306}
307
308static void cpu_fans_tick_combined(void)
309{
310 s32 temp0, power0, temp1, power1, t_max = 0;
311 s32 temp, power, intake, pump;
312 struct wf_control *pump0, *pump1;
313 struct wf_cpu_pid_state *sp = &cpu_pid[0];
314 int err, cpu;
315
316 DBG_LOTS("* cpu fans_tick_combined()\n");
317
318 /* Read current speed from cpu 0 */
319 wf_control_get(cpu_rear_fans[0], &sp->target);
320
321 DBG_LOTS(" CPUs: cur_target = %d RPM\n", sp->target);
322
323 /* Read values for both CPUs */
324 err = read_one_cpu_vals(0, &temp0, &power0);
325 if (err) {
326 failure_state |= FAILURE_SENSOR;
327 cpu_max_all_fans();
328 return;
329 }
330 err = read_one_cpu_vals(1, &temp1, &power1);
331 if (err) {
332 failure_state |= FAILURE_SENSOR;
333 cpu_max_all_fans();
334 return;
335 }
336
337 /* Keep track of highest temp */
338 t_max = max(t_max, max(temp0, temp1));
339
340 /* Handle possible overtemps */
341 if (cpu_check_overtemp(t_max))
342 return;
343
344 /* Use the max temp & power of both */
345 temp = max(temp0, temp1);
346 power = max(power0, power1);
347
348 /* Run PID */
349 wf_cpu_pid_run(sp, power, temp);
350
351 /* Scale result for intake fan */
352 intake = (sp->target * CPU_INTAKE_SCALE) >> 16;
353
354 /* Same deal with pump speed */
355 pump0 = cpu_pumps[0];
356 pump1 = cpu_pumps[1];
357 if (!pump0) {
358 pump0 = pump1;
359 pump1 = NULL;
360 }
361 pump = (sp->target * wf_control_get_max(pump0)) /
362 cpu_mpu_data[0]->rmaxn_exhaust_fan;
363
364 DBG_LOTS(" CPUs: target = %d RPM\n", sp->target);
365 DBG_LOTS(" CPUs: intake = %d RPM\n", intake);
366 DBG_LOTS(" CPUs: pump = %d RPM\n", pump);
367
368 for (cpu = 0; cpu < nr_chips; cpu++) {
369 err = wf_control_set(cpu_rear_fans[cpu], sp->target);
370 if (err) {
371 pr_warning("wf_pm72: Fan %s reports error %d\n",
372 cpu_rear_fans[cpu]->name, err);
373 failure_state |= FAILURE_FAN;
374 }
375 err = wf_control_set(cpu_front_fans[cpu], intake);
376 if (err) {
377 pr_warning("wf_pm72: Fan %s reports error %d\n",
378 cpu_front_fans[cpu]->name, err);
379 failure_state |= FAILURE_FAN;
380 }
381 err = 0;
382 if (cpu_pumps[cpu])
383 err = wf_control_set(cpu_pumps[cpu], pump);
384 if (err) {
385 pr_warning("wf_pm72: Pump %s reports error %d\n",
386 cpu_pumps[cpu]->name, err);
387 failure_state |= FAILURE_FAN;
388 }
389 }
390}
391
392/* Implementation... */
393static int cpu_setup_pid(int cpu)
394{
395 struct wf_cpu_pid_param pid;
396 const struct mpu_data *mpu = cpu_mpu_data[cpu];
397 s32 tmax, ttarget, ptarget;
398 int fmin, fmax, hsize;
399
400 /* Get PID params from the appropriate MPU EEPROM */
401 tmax = mpu->tmax << 16;
402 ttarget = mpu->ttarget << 16;
403 ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
404
405 DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
406 cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
407
408 /* We keep a global tmax for overtemp calculations */
409 if (tmax < cpu_all_tmax)
410 cpu_all_tmax = tmax;
411
412 /* Set PID min/max by using the rear fan min/max */
413 fmin = wf_control_get_min(cpu_rear_fans[cpu]);
414 fmax = wf_control_get_max(cpu_rear_fans[cpu]);
415 DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
416
417 /* History size */
418 hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
419 DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
420
421 /* Initialize PID loop */
422 pid.interval = 1; /* seconds */
423 pid.history_len = hsize;
424 pid.gd = mpu->pid_gd;
425 pid.gp = mpu->pid_gp;
426 pid.gr = mpu->pid_gr;
427 pid.tmax = tmax;
428 pid.ttarget = ttarget;
429 pid.pmaxadj = ptarget;
430 pid.min = fmin;
431 pid.max = fmax;
432
433 wf_cpu_pid_init(&cpu_pid[cpu], &pid);
434 cpu_pid[cpu].target = 1000;
435
436 return 0;
437}
438
439/* Backside/U3 fan */
440static struct wf_pid_param backside_u3_param = {
441 .interval = 5,
442 .history_len = 2,
443 .gd = 40 << 20,
444 .gp = 5 << 20,
445 .gr = 0,
446 .itarget = 65 << 16,
447 .additive = 1,
448 .min = 20,
449 .max = 100,
450};
451
452static struct wf_pid_param backside_u3h_param = {
453 .interval = 5,
454 .history_len = 2,
455 .gd = 20 << 20,
456 .gp = 5 << 20,
457 .gr = 0,
458 .itarget = 75 << 16,
459 .additive = 1,
460 .min = 20,
461 .max = 100,
462};
463
464static void backside_fan_tick(void)
465{
466 s32 temp;
467 int speed;
468 int err;
469
470 if (!backside_fan || !backside_temp || !backside_tick)
471 return;
472 if (--backside_tick > 0)
473 return;
474 backside_tick = backside_pid.param.interval;
475
476 DBG_LOTS("* backside fans tick\n");
477
478 /* Update fan speed from actual fans */
479 err = wf_control_get(backside_fan, &speed);
480 if (!err)
481 backside_pid.target = speed;
482
483 err = wf_sensor_get(backside_temp, &temp);
484 if (err) {
485 printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
486 err);
487 failure_state |= FAILURE_SENSOR;
488 wf_control_set_max(backside_fan);
489 return;
490 }
491 speed = wf_pid_run(&backside_pid, temp);
492
493 DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
494 FIX32TOPRINT(temp), speed);
495
496 err = wf_control_set(backside_fan, speed);
497 if (err) {
498 printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
499 failure_state |= FAILURE_FAN;
500 }
501}
502
503static void backside_setup_pid(void)
504{
505 /* first time initialize things */
506 s32 fmin = wf_control_get_min(backside_fan);
507 s32 fmax = wf_control_get_max(backside_fan);
508 struct wf_pid_param param;
509 struct device_node *u3;
510 int u3h = 1; /* conservative by default */
511
512 u3 = of_find_node_by_path("/u3@0,f8000000");
513 if (u3 != NULL) {
514 const u32 *vers = of_get_property(u3, "device-rev", NULL);
515 if (vers)
516 if (((*vers) & 0x3f) < 0x34)
517 u3h = 0;
518 of_node_put(u3);
519 }
520
521 param = u3h ? backside_u3h_param : backside_u3_param;
522
523 param.min = max(param.min, fmin);
524 param.max = min(param.max, fmax);
525 wf_pid_init(&backside_pid, &param);
526 backside_tick = 1;
527
528 pr_info("wf_pm72: Backside control loop started.\n");
529}
530
531/* Drive bay fan */
532static const struct wf_pid_param drives_param = {
533 .interval = 5,
534 .history_len = 2,
535 .gd = 30 << 20,
536 .gp = 5 << 20,
537 .gr = 0,
538 .itarget = 40 << 16,
539 .additive = 1,
540 .min = 300,
541 .max = 4000,
542};
543
544static void drives_fan_tick(void)
545{
546 s32 temp;
547 int speed;
548 int err;
549
550 if (!drives_fan || !drives_temp || !drives_tick)
551 return;
552 if (--drives_tick > 0)
553 return;
554 drives_tick = drives_pid.param.interval;
555
556 DBG_LOTS("* drives fans tick\n");
557
558 /* Update fan speed from actual fans */
559 err = wf_control_get(drives_fan, &speed);
560 if (!err)
561 drives_pid.target = speed;
562
563 err = wf_sensor_get(drives_temp, &temp);
564 if (err) {
565 pr_warning("wf_pm72: drive bay temp sensor error %d\n", err);
566 failure_state |= FAILURE_SENSOR;
567 wf_control_set_max(drives_fan);
568 return;
569 }
570 speed = wf_pid_run(&drives_pid, temp);
571
572 DBG_LOTS("drives PID temp=%d.%.3d speed=%d\n",
573 FIX32TOPRINT(temp), speed);
574
575 err = wf_control_set(drives_fan, speed);
576 if (err) {
577 printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
578 failure_state |= FAILURE_FAN;
579 }
580}
581
582static void drives_setup_pid(void)
583{
584 /* first time initialize things */
585 s32 fmin = wf_control_get_min(drives_fan);
586 s32 fmax = wf_control_get_max(drives_fan);
587 struct wf_pid_param param = drives_param;
588
589 param.min = max(param.min, fmin);
590 param.max = min(param.max, fmax);
591 wf_pid_init(&drives_pid, &param);
592 drives_tick = 1;
593
594 pr_info("wf_pm72: Drive bay control loop started.\n");
595}
596
597static void set_fail_state(void)
598{
599 cpu_max_all_fans();
600
601 if (backside_fan)
602 wf_control_set_max(backside_fan);
603 if (slots_fan)
604 wf_control_set_max(slots_fan);
605 if (drives_fan)
606 wf_control_set_max(drives_fan);
607}
608
609static void pm72_tick(void)
610{
611 int i, last_failure;
612
613 if (!started) {
614 started = 1;
615 printk(KERN_INFO "windfarm: CPUs control loops started.\n");
616 for (i = 0; i < nr_chips; ++i) {
617 if (cpu_setup_pid(i) < 0) {
618 failure_state = FAILURE_PERM;
619 set_fail_state();
620 break;
621 }
622 }
623 DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
624
625 backside_setup_pid();
626 drives_setup_pid();
627
628 /*
629 * We don't have the right stuff to drive the PCI fan
630 * so we fix it to a default value
631 */
632 wf_control_set(slots_fan, SLOTS_FAN_DEFAULT_PWM);
633
634#ifdef HACKED_OVERTEMP
635 cpu_all_tmax = 60 << 16;
636#endif
637 }
638
639 /* Permanent failure, bail out */
640 if (failure_state & FAILURE_PERM)
641 return;
642
643 /*
644 * Clear all failure bits except low overtemp which will be eventually
645 * cleared by the control loop itself
646 */
647 last_failure = failure_state;
648 failure_state &= FAILURE_LOW_OVERTEMP;
649 if (cpu_pid_combined)
650 cpu_fans_tick_combined();
651 else
652 cpu_fans_tick_split();
653 backside_fan_tick();
654 drives_fan_tick();
655
656 DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
657 last_failure, failure_state);
658
659 /* Check for failures. Any failure causes cpufreq clamping */
660 if (failure_state && last_failure == 0 && cpufreq_clamp)
661 wf_control_set_max(cpufreq_clamp);
662 if (failure_state == 0 && last_failure && cpufreq_clamp)
663 wf_control_set_min(cpufreq_clamp);
664
665 /* That's it for now, we might want to deal with other failures
666 * differently in the future though
667 */
668}
669
670static void pm72_new_control(struct wf_control *ct)
671{
672 bool all_controls;
673 bool had_pump = cpu_pumps[0] || cpu_pumps[1];
674
675 if (!strcmp(ct->name, "cpu-front-fan-0"))
676 cpu_front_fans[0] = ct;
677 else if (!strcmp(ct->name, "cpu-front-fan-1"))
678 cpu_front_fans[1] = ct;
679 else if (!strcmp(ct->name, "cpu-rear-fan-0"))
680 cpu_rear_fans[0] = ct;
681 else if (!strcmp(ct->name, "cpu-rear-fan-1"))
682 cpu_rear_fans[1] = ct;
683 else if (!strcmp(ct->name, "cpu-pump-0"))
684 cpu_pumps[0] = ct;
685 else if (!strcmp(ct->name, "cpu-pump-1"))
686 cpu_pumps[1] = ct;
687 else if (!strcmp(ct->name, "backside-fan"))
688 backside_fan = ct;
689 else if (!strcmp(ct->name, "slots-fan"))
690 slots_fan = ct;
691 else if (!strcmp(ct->name, "drive-bay-fan"))
692 drives_fan = ct;
693 else if (!strcmp(ct->name, "cpufreq-clamp"))
694 cpufreq_clamp = ct;
695
696 all_controls =
697 cpu_front_fans[0] &&
698 cpu_rear_fans[0] &&
699 backside_fan &&
700 slots_fan &&
701 drives_fan;
702 if (nr_chips > 1)
703 all_controls &=
704 cpu_front_fans[1] &&
705 cpu_rear_fans[1];
706 have_all_controls = all_controls;
707
708 if ((cpu_pumps[0] || cpu_pumps[1]) && !had_pump) {
709 pr_info("wf_pm72: Liquid cooling pump(s) detected,"
710 " using new algorithm !\n");
711 cpu_pid_combined = true;
712 }
713}
714
715
716static void pm72_new_sensor(struct wf_sensor *sr)
717{
718 bool all_sensors;
719
720 if (!strcmp(sr->name, "cpu-diode-temp-0"))
721 sens_cpu_temp[0] = sr;
722 else if (!strcmp(sr->name, "cpu-diode-temp-1"))
723 sens_cpu_temp[1] = sr;
724 else if (!strcmp(sr->name, "cpu-voltage-0"))
725 sens_cpu_volts[0] = sr;
726 else if (!strcmp(sr->name, "cpu-voltage-1"))
727 sens_cpu_volts[1] = sr;
728 else if (!strcmp(sr->name, "cpu-current-0"))
729 sens_cpu_amps[0] = sr;
730 else if (!strcmp(sr->name, "cpu-current-1"))
731 sens_cpu_amps[1] = sr;
732 else if (!strcmp(sr->name, "backside-temp"))
733 backside_temp = sr;
734 else if (!strcmp(sr->name, "hd-temp"))
735 drives_temp = sr;
736
737 all_sensors =
738 sens_cpu_temp[0] &&
739 sens_cpu_volts[0] &&
740 sens_cpu_amps[0] &&
741 backside_temp &&
742 drives_temp;
743 if (nr_chips > 1)
744 all_sensors &=
745 sens_cpu_temp[1] &&
746 sens_cpu_volts[1] &&
747 sens_cpu_amps[1];
748
749 have_all_sensors = all_sensors;
750}
751
752static int pm72_wf_notify(struct notifier_block *self,
753 unsigned long event, void *data)
754{
755 switch (event) {
756 case WF_EVENT_NEW_SENSOR:
757 pm72_new_sensor(data);
758 break;
759 case WF_EVENT_NEW_CONTROL:
760 pm72_new_control(data);
761 break;
762 case WF_EVENT_TICK:
763 if (have_all_controls && have_all_sensors)
764 pm72_tick();
765 }
766 return 0;
767}
768
769static struct notifier_block pm72_events = {
770 .notifier_call = pm72_wf_notify,
771};
772
773static int wf_pm72_probe(struct platform_device *dev)
774{
775 wf_register_client(&pm72_events);
776 return 0;
777}
778
779static int __devexit wf_pm72_remove(struct platform_device *dev)
780{
781 wf_unregister_client(&pm72_events);
782
783 /* should release all sensors and controls */
784 return 0;
785}
786
787static struct platform_driver wf_pm72_driver = {
788 .probe = wf_pm72_probe,
789 .remove = wf_pm72_remove,
790 .driver = {
791 .name = "windfarm",
792 .owner = THIS_MODULE,
793 },
794};
795
796static int __init wf_pm72_init(void)
797{
798 struct device_node *cpu;
799 int i;
800
801 if (!of_machine_is_compatible("PowerMac7,2") &&
802 !of_machine_is_compatible("PowerMac7,3"))
803 return -ENODEV;
804
805 /* Count the number of CPU cores */
806 nr_chips = 0;
807 for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
808 ++nr_chips;
809 if (nr_chips > NR_CHIPS)
810 nr_chips = NR_CHIPS;
811
812 pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
813 nr_chips);
814
815 /* Get MPU data for each CPU */
816 for (i = 0; i < nr_chips; i++) {
817 cpu_mpu_data[i] = wf_get_mpu(i);
818 if (!cpu_mpu_data[i]) {
819 pr_err("wf_pm72: Failed to find MPU data for CPU %d\n", i);
820 return -ENXIO;
821 }
822 }
823
824#ifdef MODULE
825 request_module("windfarm_fcu_controls");
826 request_module("windfarm_lm75_sensor");
827 request_module("windfarm_ad7417_sensor");
828 request_module("windfarm_max6690_sensor");
829 request_module("windfarm_cpufreq_clamp");
830#endif /* MODULE */
831
832 platform_driver_register(&wf_pm72_driver);
833 return 0;
834}
835
836static void __exit wf_pm72_exit(void)
837{
838 platform_driver_unregister(&wf_pm72_driver);
839}
840
841module_init(wf_pm72_init);
842module_exit(wf_pm72_exit);
843
844MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
845MODULE_DESCRIPTION("Thermal control for AGP PowerMac G5s");
846MODULE_LICENSE("GPL");
847MODULE_ALIAS("platform:windfarm");
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index fc13d0f2663b..990c87606be9 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -302,13 +302,13 @@ static void wf_smu_create_sys_fans(void)
302 pid_param.interval = WF_SMU_SYS_FANS_INTERVAL; 302 pid_param.interval = WF_SMU_SYS_FANS_INTERVAL;
303 pid_param.history_len = WF_SMU_SYS_FANS_HISTORY_SIZE; 303 pid_param.history_len = WF_SMU_SYS_FANS_HISTORY_SIZE;
304 pid_param.itarget = param->itarget; 304 pid_param.itarget = param->itarget;
305 pid_param.min = fan_system->ops->get_min(fan_system); 305 pid_param.min = wf_control_get_min(fan_system);
306 pid_param.max = fan_system->ops->get_max(fan_system); 306 pid_param.max = wf_control_get_max(fan_system);
307 if (fan_hd) { 307 if (fan_hd) {
308 pid_param.min = 308 pid_param.min =
309 max(pid_param.min,fan_hd->ops->get_min(fan_hd)); 309 max(pid_param.min, wf_control_get_min(fan_hd));
310 pid_param.max = 310 pid_param.max =
311 min(pid_param.max,fan_hd->ops->get_max(fan_hd)); 311 min(pid_param.max, wf_control_get_max(fan_hd));
312 } 312 }
313 wf_pid_init(&wf_smu_sys_fans->pid, &pid_param); 313 wf_pid_init(&wf_smu_sys_fans->pid, &pid_param);
314 314
@@ -337,7 +337,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
337 } 337 }
338 st->ticks = WF_SMU_SYS_FANS_INTERVAL; 338 st->ticks = WF_SMU_SYS_FANS_INTERVAL;
339 339
340 rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp); 340 rc = wf_sensor_get(sensor_hd_temp, &temp);
341 if (rc) { 341 if (rc) {
342 printk(KERN_WARNING "windfarm: HD temp sensor error %d\n", 342 printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
343 rc); 343 rc);
@@ -373,7 +373,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
373 st->hd_setpoint = new_setpoint; 373 st->hd_setpoint = new_setpoint;
374 readjust: 374 readjust:
375 if (fan_system && wf_smu_failure_state == 0) { 375 if (fan_system && wf_smu_failure_state == 0) {
376 rc = fan_system->ops->set_value(fan_system, st->sys_setpoint); 376 rc = wf_control_set(fan_system, st->sys_setpoint);
377 if (rc) { 377 if (rc) {
378 printk(KERN_WARNING "windfarm: Sys fan error %d\n", 378 printk(KERN_WARNING "windfarm: Sys fan error %d\n",
379 rc); 379 rc);
@@ -381,7 +381,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st)
381 } 381 }
382 } 382 }
383 if (fan_hd && wf_smu_failure_state == 0) { 383 if (fan_hd && wf_smu_failure_state == 0) {
384 rc = fan_hd->ops->set_value(fan_hd, st->hd_setpoint); 384 rc = wf_control_set(fan_hd, st->hd_setpoint);
385 if (rc) { 385 if (rc) {
386 printk(KERN_WARNING "windfarm: HD fan error %d\n", 386 printk(KERN_WARNING "windfarm: HD fan error %d\n",
387 rc); 387 rc);
@@ -447,8 +447,8 @@ static void wf_smu_create_cpu_fans(void)
447 pid_param.ttarget = tmax - tdelta; 447 pid_param.ttarget = tmax - tdelta;
448 pid_param.pmaxadj = maxpow - powadj; 448 pid_param.pmaxadj = maxpow - powadj;
449 449
450 pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main); 450 pid_param.min = wf_control_get_min(fan_cpu_main);
451 pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main); 451 pid_param.max = wf_control_get_max(fan_cpu_main);
452 452
453 wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); 453 wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
454 454
@@ -481,7 +481,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
481 } 481 }
482 st->ticks = WF_SMU_CPU_FANS_INTERVAL; 482 st->ticks = WF_SMU_CPU_FANS_INTERVAL;
483 483
484 rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp); 484 rc = wf_sensor_get(sensor_cpu_temp, &temp);
485 if (rc) { 485 if (rc) {
486 printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n", 486 printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
487 rc); 487 rc);
@@ -489,7 +489,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
489 return; 489 return;
490 } 490 }
491 491
492 rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power); 492 rc = wf_sensor_get(sensor_cpu_power, &power);
493 if (rc) { 493 if (rc) {
494 printk(KERN_WARNING "windfarm: CPU power sensor error %d\n", 494 printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
495 rc); 495 rc);
@@ -525,8 +525,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
525 st->cpu_setpoint = new_setpoint; 525 st->cpu_setpoint = new_setpoint;
526 readjust: 526 readjust:
527 if (fan_cpu_main && wf_smu_failure_state == 0) { 527 if (fan_cpu_main && wf_smu_failure_state == 0) {
528 rc = fan_cpu_main->ops->set_value(fan_cpu_main, 528 rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
529 st->cpu_setpoint);
530 if (rc) { 529 if (rc) {
531 printk(KERN_WARNING "windfarm: CPU main fan" 530 printk(KERN_WARNING "windfarm: CPU main fan"
532 " error %d\n", rc); 531 " error %d\n", rc);
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index a9430ed4f36c..7653603cb00e 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -192,8 +192,8 @@ static void wf_smu_create_cpu_fans(void)
192 pid_param.ttarget = tmax - tdelta; 192 pid_param.ttarget = tmax - tdelta;
193 pid_param.pmaxadj = maxpow - powadj; 193 pid_param.pmaxadj = maxpow - powadj;
194 194
195 pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main); 195 pid_param.min = wf_control_get_min(fan_cpu_main);
196 pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main); 196 pid_param.max = wf_control_get_max(fan_cpu_main);
197 197
198 wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); 198 wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param);
199 199
@@ -226,7 +226,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
226 } 226 }
227 st->ticks = WF_SMU_CPU_FANS_INTERVAL; 227 st->ticks = WF_SMU_CPU_FANS_INTERVAL;
228 228
229 rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp); 229 rc = wf_sensor_get(sensor_cpu_temp, &temp);
230 if (rc) { 230 if (rc) {
231 printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n", 231 printk(KERN_WARNING "windfarm: CPU temp sensor error %d\n",
232 rc); 232 rc);
@@ -234,7 +234,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
234 return; 234 return;
235 } 235 }
236 236
237 rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power); 237 rc = wf_sensor_get(sensor_cpu_power, &power);
238 if (rc) { 238 if (rc) {
239 printk(KERN_WARNING "windfarm: CPU power sensor error %d\n", 239 printk(KERN_WARNING "windfarm: CPU power sensor error %d\n",
240 rc); 240 rc);
@@ -261,8 +261,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
261 st->cpu_setpoint = new_setpoint; 261 st->cpu_setpoint = new_setpoint;
262 readjust: 262 readjust:
263 if (fan_cpu_main && wf_smu_failure_state == 0) { 263 if (fan_cpu_main && wf_smu_failure_state == 0) {
264 rc = fan_cpu_main->ops->set_value(fan_cpu_main, 264 rc = wf_control_set(fan_cpu_main, st->cpu_setpoint);
265 st->cpu_setpoint);
266 if (rc) { 265 if (rc) {
267 printk(KERN_WARNING "windfarm: CPU main fan" 266 printk(KERN_WARNING "windfarm: CPU main fan"
268 " error %d\n", rc); 267 " error %d\n", rc);
@@ -270,8 +269,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
270 } 269 }
271 } 270 }
272 if (fan_cpu_second && wf_smu_failure_state == 0) { 271 if (fan_cpu_second && wf_smu_failure_state == 0) {
273 rc = fan_cpu_second->ops->set_value(fan_cpu_second, 272 rc = wf_control_set(fan_cpu_second, st->cpu_setpoint);
274 st->cpu_setpoint);
275 if (rc) { 273 if (rc) {
276 printk(KERN_WARNING "windfarm: CPU second fan" 274 printk(KERN_WARNING "windfarm: CPU second fan"
277 " error %d\n", rc); 275 " error %d\n", rc);
@@ -279,8 +277,7 @@ static void wf_smu_cpu_fans_tick(struct wf_smu_cpu_fans_state *st)
279 } 277 }
280 } 278 }
281 if (fan_cpu_third && wf_smu_failure_state == 0) { 279 if (fan_cpu_third && wf_smu_failure_state == 0) {
282 rc = fan_cpu_main->ops->set_value(fan_cpu_third, 280 rc = wf_control_set(fan_cpu_third, st->cpu_setpoint);
283 st->cpu_setpoint);
284 if (rc) { 281 if (rc) {
285 printk(KERN_WARNING "windfarm: CPU third fan" 282 printk(KERN_WARNING "windfarm: CPU third fan"
286 " error %d\n", rc); 283 " error %d\n", rc);
@@ -312,8 +309,8 @@ static void wf_smu_create_drive_fans(void)
312 309
313 /* Fill PID params */ 310 /* Fill PID params */
314 param.additive = (fan_hd->type == WF_CONTROL_RPM_FAN); 311 param.additive = (fan_hd->type == WF_CONTROL_RPM_FAN);
315 param.min = fan_hd->ops->get_min(fan_hd); 312 param.min = wf_control_get_min(fan_hd);
316 param.max = fan_hd->ops->get_max(fan_hd); 313 param.max = wf_control_get_max(fan_hd);
317 wf_pid_init(&wf_smu_drive_fans->pid, &param); 314 wf_pid_init(&wf_smu_drive_fans->pid, &param);
318 315
319 DBG("wf: Drive Fan control initialized.\n"); 316 DBG("wf: Drive Fan control initialized.\n");
@@ -338,7 +335,7 @@ static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st)
338 } 335 }
339 st->ticks = st->pid.param.interval; 336 st->ticks = st->pid.param.interval;
340 337
341 rc = sensor_hd_temp->ops->get_value(sensor_hd_temp, &temp); 338 rc = wf_sensor_get(sensor_hd_temp, &temp);
342 if (rc) { 339 if (rc) {
343 printk(KERN_WARNING "windfarm: HD temp sensor error %d\n", 340 printk(KERN_WARNING "windfarm: HD temp sensor error %d\n",
344 rc); 341 rc);
@@ -361,7 +358,7 @@ static void wf_smu_drive_fans_tick(struct wf_smu_drive_fans_state *st)
361 st->setpoint = new_setpoint; 358 st->setpoint = new_setpoint;
362 readjust: 359 readjust:
363 if (fan_hd && wf_smu_failure_state == 0) { 360 if (fan_hd && wf_smu_failure_state == 0) {
364 rc = fan_hd->ops->set_value(fan_hd, st->setpoint); 361 rc = wf_control_set(fan_hd, st->setpoint);
365 if (rc) { 362 if (rc) {
366 printk(KERN_WARNING "windfarm: HD fan error %d\n", 363 printk(KERN_WARNING "windfarm: HD fan error %d\n",
367 rc); 364 rc);
@@ -393,8 +390,8 @@ static void wf_smu_create_slots_fans(void)
393 390
394 /* Fill PID params */ 391 /* Fill PID params */
395 param.additive = (fan_slots->type == WF_CONTROL_RPM_FAN); 392 param.additive = (fan_slots->type == WF_CONTROL_RPM_FAN);
396 param.min = fan_slots->ops->get_min(fan_slots); 393 param.min = wf_control_get_min(fan_slots);
397 param.max = fan_slots->ops->get_max(fan_slots); 394 param.max = wf_control_get_max(fan_slots);
398 wf_pid_init(&wf_smu_slots_fans->pid, &param); 395 wf_pid_init(&wf_smu_slots_fans->pid, &param);
399 396
400 DBG("wf: Slots Fan control initialized.\n"); 397 DBG("wf: Slots Fan control initialized.\n");
@@ -419,7 +416,7 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
419 } 416 }
420 st->ticks = st->pid.param.interval; 417 st->ticks = st->pid.param.interval;
421 418
422 rc = sensor_slots_power->ops->get_value(sensor_slots_power, &power); 419 rc = wf_sensor_get(sensor_slots_power, &power);
423 if (rc) { 420 if (rc) {
424 printk(KERN_WARNING "windfarm: Slots power sensor error %d\n", 421 printk(KERN_WARNING "windfarm: Slots power sensor error %d\n",
425 rc); 422 rc);
@@ -444,7 +441,7 @@ static void wf_smu_slots_fans_tick(struct wf_smu_slots_fans_state *st)
444 st->setpoint = new_setpoint; 441 st->setpoint = new_setpoint;
445 readjust: 442 readjust:
446 if (fan_slots && wf_smu_failure_state == 0) { 443 if (fan_slots && wf_smu_failure_state == 0) {
447 rc = fan_slots->ops->set_value(fan_slots, st->setpoint); 444 rc = wf_control_set(fan_slots, st->setpoint);
448 if (rc) { 445 if (rc) {
449 printk(KERN_WARNING "windfarm: Slots fan error %d\n", 446 printk(KERN_WARNING "windfarm: Slots fan error %d\n",
450 rc); 447 rc);
diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c
new file mode 100644
index 000000000000..3eca6d4b52fc
--- /dev/null
+++ b/drivers/macintosh/windfarm_rm31.c
@@ -0,0 +1,740 @@
1/*
2 * Windfarm PowerMac thermal control.
3 * Control loops for RackMack3,1 (Xserve G5)
4 *
5 * Copyright (C) 2012 Benjamin Herrenschmidt, IBM Corp.
6 *
7 * Use and redistribute under the terms of the GNU GPL v2.
8 */
9#include <linux/types.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/device.h>
13#include <linux/platform_device.h>
14#include <linux/reboot.h>
15#include <asm/prom.h>
16#include <asm/smu.h>
17
18#include "windfarm.h"
19#include "windfarm_pid.h"
20#include "windfarm_mpu.h"
21
22#define VERSION "1.0"
23
24#undef DEBUG
25#undef LOTSA_DEBUG
26
27#ifdef DEBUG
28#define DBG(args...) printk(args)
29#else
30#define DBG(args...) do { } while(0)
31#endif
32
33#ifdef LOTSA_DEBUG
34#define DBG_LOTS(args...) printk(args)
35#else
36#define DBG_LOTS(args...) do { } while(0)
37#endif
38
39/* define this to force CPU overtemp to 60 degree, useful for testing
40 * the overtemp code
41 */
42#undef HACKED_OVERTEMP
43
44/* We currently only handle 2 chips */
45#define NR_CHIPS 2
46#define NR_CPU_FANS 3 * NR_CHIPS
47
48/* Controls and sensors */
49static struct wf_sensor *sens_cpu_temp[NR_CHIPS];
50static struct wf_sensor *sens_cpu_volts[NR_CHIPS];
51static struct wf_sensor *sens_cpu_amps[NR_CHIPS];
52static struct wf_sensor *backside_temp;
53static struct wf_sensor *slots_temp;
54static struct wf_sensor *dimms_temp;
55
56static struct wf_control *cpu_fans[NR_CHIPS][3];
57static struct wf_control *backside_fan;
58static struct wf_control *slots_fan;
59static struct wf_control *cpufreq_clamp;
60
61/* We keep a temperature history for average calculation of 180s */
62#define CPU_TEMP_HIST_SIZE 180
63
64/* PID loop state */
65static const struct mpu_data *cpu_mpu_data[NR_CHIPS];
66static struct wf_cpu_pid_state cpu_pid[NR_CHIPS];
67static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
68static int cpu_thist_pt;
69static s64 cpu_thist_total;
70static s32 cpu_all_tmax = 100 << 16;
71static struct wf_pid_state backside_pid;
72static int backside_tick;
73static struct wf_pid_state slots_pid;
74static int slots_tick;
75static int slots_speed;
76static struct wf_pid_state dimms_pid;
77static int dimms_output_clamp;
78
79static int nr_chips;
80static bool have_all_controls;
81static bool have_all_sensors;
82static bool started;
83
84static int failure_state;
85#define FAILURE_SENSOR 1
86#define FAILURE_FAN 2
87#define FAILURE_PERM 4
88#define FAILURE_LOW_OVERTEMP 8
89#define FAILURE_HIGH_OVERTEMP 16
90
91/* Overtemp values */
92#define LOW_OVER_AVERAGE 0
93#define LOW_OVER_IMMEDIATE (10 << 16)
94#define LOW_OVER_CLEAR ((-10) << 16)
95#define HIGH_OVER_IMMEDIATE (14 << 16)
96#define HIGH_OVER_AVERAGE (10 << 16)
97#define HIGH_OVER_IMMEDIATE (14 << 16)
98
99
100static void cpu_max_all_fans(void)
101{
102 int i;
103
104 /* We max all CPU fans in case of a sensor error. We also do the
105 * cpufreq clamping now, even if it's supposedly done later by the
106 * generic code anyway, we do it earlier here to react faster
107 */
108 if (cpufreq_clamp)
109 wf_control_set_max(cpufreq_clamp);
110 for (i = 0; i < nr_chips; i++) {
111 if (cpu_fans[i][0])
112 wf_control_set_max(cpu_fans[i][0]);
113 if (cpu_fans[i][1])
114 wf_control_set_max(cpu_fans[i][1]);
115 if (cpu_fans[i][2])
116 wf_control_set_max(cpu_fans[i][2]);
117 }
118}
119
120static int cpu_check_overtemp(s32 temp)
121{
122 int new_state = 0;
123 s32 t_avg, t_old;
124 static bool first = true;
125
126 /* First check for immediate overtemps */
127 if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
128 new_state |= FAILURE_LOW_OVERTEMP;
129 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
130 printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
131 " temperature !\n");
132 }
133 if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
134 new_state |= FAILURE_HIGH_OVERTEMP;
135 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
136 printk(KERN_ERR "windfarm: Critical overtemp due to"
137 " immediate CPU temperature !\n");
138 }
139
140 /*
141 * The first time around, initialize the array with the first
142 * temperature reading
143 */
144 if (first) {
145 int i;
146
147 cpu_thist_total = 0;
148 for (i = 0; i < CPU_TEMP_HIST_SIZE; i++) {
149 cpu_thist[i] = temp;
150 cpu_thist_total += temp;
151 }
152 first = false;
153 }
154
155 /*
156 * We calculate a history of max temperatures and use that for the
157 * overtemp management
158 */
159 t_old = cpu_thist[cpu_thist_pt];
160 cpu_thist[cpu_thist_pt] = temp;
161 cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
162 cpu_thist_total -= t_old;
163 cpu_thist_total += temp;
164 t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
165
166 DBG_LOTS(" t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
167 FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
168
169 /* Now check for average overtemps */
170 if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
171 new_state |= FAILURE_LOW_OVERTEMP;
172 if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
173 printk(KERN_ERR "windfarm: Overtemp due to average CPU"
174 " temperature !\n");
175 }
176 if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
177 new_state |= FAILURE_HIGH_OVERTEMP;
178 if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
179 printk(KERN_ERR "windfarm: Critical overtemp due to"
180 " average CPU temperature !\n");
181 }
182
183 /* Now handle overtemp conditions. We don't currently use the windfarm
184 * overtemp handling core as it's not fully suited to the needs of those
185 * new machine. This will be fixed later.
186 */
187 if (new_state) {
188 /* High overtemp -> immediate shutdown */
189 if (new_state & FAILURE_HIGH_OVERTEMP)
190 machine_power_off();
191 if ((failure_state & new_state) != new_state)
192 cpu_max_all_fans();
193 failure_state |= new_state;
194 } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
195 (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
196 printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
197 failure_state &= ~FAILURE_LOW_OVERTEMP;
198 }
199
200 return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
201}
202
203static int read_one_cpu_vals(int cpu, s32 *temp, s32 *power)
204{
205 s32 dtemp, volts, amps;
206 int rc;
207
208 /* Get diode temperature */
209 rc = wf_sensor_get(sens_cpu_temp[cpu], &dtemp);
210 if (rc) {
211 DBG(" CPU%d: temp reading error !\n", cpu);
212 return -EIO;
213 }
214 DBG_LOTS(" CPU%d: temp = %d.%03d\n", cpu, FIX32TOPRINT((dtemp)));
215 *temp = dtemp;
216
217 /* Get voltage */
218 rc = wf_sensor_get(sens_cpu_volts[cpu], &volts);
219 if (rc) {
220 DBG(" CPU%d, volts reading error !\n", cpu);
221 return -EIO;
222 }
223 DBG_LOTS(" CPU%d: volts = %d.%03d\n", cpu, FIX32TOPRINT((volts)));
224
225 /* Get current */
226 rc = wf_sensor_get(sens_cpu_amps[cpu], &amps);
227 if (rc) {
228 DBG(" CPU%d, current reading error !\n", cpu);
229 return -EIO;
230 }
231 DBG_LOTS(" CPU%d: amps = %d.%03d\n", cpu, FIX32TOPRINT((amps)));
232
233 /* Calculate power */
234
235 /* Scale voltage and current raw sensor values according to fixed scales
236 * obtained in Darwin and calculate power from I and V
237 */
238 *power = (((u64)volts) * ((u64)amps)) >> 16;
239
240 DBG_LOTS(" CPU%d: power = %d.%03d\n", cpu, FIX32TOPRINT((*power)));
241
242 return 0;
243
244}
245
246static void cpu_fans_tick(void)
247{
248 int err, cpu, i;
249 s32 speed, temp, power, t_max = 0;
250
251 DBG_LOTS("* cpu fans_tick_split()\n");
252
253 for (cpu = 0; cpu < nr_chips; ++cpu) {
254 struct wf_cpu_pid_state *sp = &cpu_pid[cpu];
255
256 /* Read current speed */
257 wf_control_get(cpu_fans[cpu][0], &sp->target);
258
259 err = read_one_cpu_vals(cpu, &temp, &power);
260 if (err) {
261 failure_state |= FAILURE_SENSOR;
262 cpu_max_all_fans();
263 return;
264 }
265
266 /* Keep track of highest temp */
267 t_max = max(t_max, temp);
268
269 /* Handle possible overtemps */
270 if (cpu_check_overtemp(t_max))
271 return;
272
273 /* Run PID */
274 wf_cpu_pid_run(sp, power, temp);
275
276 DBG_LOTS(" CPU%d: target = %d RPM\n", cpu, sp->target);
277
278 /* Apply DIMMs clamp */
279 speed = max(sp->target, dimms_output_clamp);
280
281 /* Apply result to all cpu fans */
282 for (i = 0; i < 3; i++) {
283 err = wf_control_set(cpu_fans[cpu][i], speed);
284 if (err) {
285 pr_warning("wf_rm31: Fan %s reports error %d\n",
286 cpu_fans[cpu][i]->name, err);
287 failure_state |= FAILURE_FAN;
288 }
289 }
290 }
291}
292
293/* Implementation... */
294static int cpu_setup_pid(int cpu)
295{
296 struct wf_cpu_pid_param pid;
297 const struct mpu_data *mpu = cpu_mpu_data[cpu];
298 s32 tmax, ttarget, ptarget;
299 int fmin, fmax, hsize;
300
301 /* Get PID params from the appropriate MPU EEPROM */
302 tmax = mpu->tmax << 16;
303 ttarget = mpu->ttarget << 16;
304 ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16;
305
306 DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n",
307 cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax));
308
309 /* We keep a global tmax for overtemp calculations */
310 if (tmax < cpu_all_tmax)
311 cpu_all_tmax = tmax;
312
313 /* Set PID min/max by using the rear fan min/max */
314 fmin = wf_control_get_min(cpu_fans[cpu][0]);
315 fmax = wf_control_get_max(cpu_fans[cpu][0]);
316 DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax);
317
318 /* History size */
319 hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY);
320 DBG("wf_72: CPU%d history size = %d\n", cpu, hsize);
321
322 /* Initialize PID loop */
323 pid.interval = 1; /* seconds */
324 pid.history_len = hsize;
325 pid.gd = mpu->pid_gd;
326 pid.gp = mpu->pid_gp;
327 pid.gr = mpu->pid_gr;
328 pid.tmax = tmax;
329 pid.ttarget = ttarget;
330 pid.pmaxadj = ptarget;
331 pid.min = fmin;
332 pid.max = fmax;
333
334 wf_cpu_pid_init(&cpu_pid[cpu], &pid);
335 cpu_pid[cpu].target = 4000;
336
337 return 0;
338}
339
340/* Backside/U3 fan */
341static struct wf_pid_param backside_param = {
342 .interval = 1,
343 .history_len = 2,
344 .gd = 0x00500000,
345 .gp = 0x0004cccc,
346 .gr = 0,
347 .itarget = 70 << 16,
348 .additive = 0,
349 .min = 20,
350 .max = 100,
351};
352
353/* DIMMs temperature (clamp the backside fan) */
354static struct wf_pid_param dimms_param = {
355 .interval = 1,
356 .history_len = 20,
357 .gd = 0,
358 .gp = 0,
359 .gr = 0x06553600,
360 .itarget = 50 << 16,
361 .additive = 0,
362 .min = 4000,
363 .max = 14000,
364};
365
366static void backside_fan_tick(void)
367{
368 s32 temp, dtemp;
369 int speed, dspeed, fan_min;
370 int err;
371
372 if (!backside_fan || !backside_temp || !dimms_temp || !backside_tick)
373 return;
374 if (--backside_tick > 0)
375 return;
376 backside_tick = backside_pid.param.interval;
377
378 DBG_LOTS("* backside fans tick\n");
379
380 /* Update fan speed from actual fans */
381 err = wf_control_get(backside_fan, &speed);
382 if (!err)
383 backside_pid.target = speed;
384
385 err = wf_sensor_get(backside_temp, &temp);
386 if (err) {
387 printk(KERN_WARNING "windfarm: U3 temp sensor error %d\n",
388 err);
389 failure_state |= FAILURE_SENSOR;
390 wf_control_set_max(backside_fan);
391 return;
392 }
393 speed = wf_pid_run(&backside_pid, temp);
394
395 DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
396 FIX32TOPRINT(temp), speed);
397
398 err = wf_sensor_get(dimms_temp, &dtemp);
399 if (err) {
400 printk(KERN_WARNING "windfarm: DIMMs temp sensor error %d\n",
401 err);
402 failure_state |= FAILURE_SENSOR;
403 wf_control_set_max(backside_fan);
404 return;
405 }
406 dspeed = wf_pid_run(&dimms_pid, dtemp);
407 dimms_output_clamp = dspeed;
408
409 fan_min = (dspeed * 100) / 14000;
410 fan_min = max(fan_min, backside_param.min);
411 speed = max(speed, fan_min);
412
413 err = wf_control_set(backside_fan, speed);
414 if (err) {
415 printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
416 failure_state |= FAILURE_FAN;
417 }
418}
419
420static void backside_setup_pid(void)
421{
422 /* first time initialize things */
423 s32 fmin = wf_control_get_min(backside_fan);
424 s32 fmax = wf_control_get_max(backside_fan);
425 struct wf_pid_param param;
426
427 param = backside_param;
428 param.min = max(param.min, fmin);
429 param.max = min(param.max, fmax);
430 wf_pid_init(&backside_pid, &param);
431
432 param = dimms_param;
433 wf_pid_init(&dimms_pid, &param);
434
435 backside_tick = 1;
436
437 pr_info("wf_rm31: Backside control loop started.\n");
438}
439
440/* Slots fan */
441static const struct wf_pid_param slots_param = {
442 .interval = 5,
443 .history_len = 2,
444 .gd = 30 << 20,
445 .gp = 5 << 20,
446 .gr = 0,
447 .itarget = 40 << 16,
448 .additive = 1,
449 .min = 300,
450 .max = 4000,
451};
452
453static void slots_fan_tick(void)
454{
455 s32 temp;
456 int speed;
457 int err;
458
459 if (!slots_fan || !slots_temp || !slots_tick)
460 return;
461 if (--slots_tick > 0)
462 return;
463 slots_tick = slots_pid.param.interval;
464
465 DBG_LOTS("* slots fans tick\n");
466
467 err = wf_sensor_get(slots_temp, &temp);
468 if (err) {
469 pr_warning("wf_rm31: slots temp sensor error %d\n", err);
470 failure_state |= FAILURE_SENSOR;
471 wf_control_set_max(slots_fan);
472 return;
473 }
474 speed = wf_pid_run(&slots_pid, temp);
475
476 DBG_LOTS("slots PID temp=%d.%.3d speed=%d\n",
477 FIX32TOPRINT(temp), speed);
478
479 slots_speed = speed;
480 err = wf_control_set(slots_fan, speed);
481 if (err) {
482 printk(KERN_WARNING "windfarm: slots bay fan error %d\n", err);
483 failure_state |= FAILURE_FAN;
484 }
485}
486
487static void slots_setup_pid(void)
488{
489 /* first time initialize things */
490 s32 fmin = wf_control_get_min(slots_fan);
491 s32 fmax = wf_control_get_max(slots_fan);
492 struct wf_pid_param param = slots_param;
493
494 param.min = max(param.min, fmin);
495 param.max = min(param.max, fmax);
496 wf_pid_init(&slots_pid, &param);
497 slots_tick = 1;
498
499 pr_info("wf_rm31: Slots control loop started.\n");
500}
501
502static void set_fail_state(void)
503{
504 cpu_max_all_fans();
505
506 if (backside_fan)
507 wf_control_set_max(backside_fan);
508 if (slots_fan)
509 wf_control_set_max(slots_fan);
510}
511
512static void rm31_tick(void)
513{
514 int i, last_failure;
515
516 if (!started) {
517 started = 1;
518 printk(KERN_INFO "windfarm: CPUs control loops started.\n");
519 for (i = 0; i < nr_chips; ++i) {
520 if (cpu_setup_pid(i) < 0) {
521 failure_state = FAILURE_PERM;
522 set_fail_state();
523 break;
524 }
525 }
526 DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
527
528 backside_setup_pid();
529 slots_setup_pid();
530
531#ifdef HACKED_OVERTEMP
532 cpu_all_tmax = 60 << 16;
533#endif
534 }
535
536 /* Permanent failure, bail out */
537 if (failure_state & FAILURE_PERM)
538 return;
539
540 /*
541 * Clear all failure bits except low overtemp which will be eventually
542 * cleared by the control loop itself
543 */
544 last_failure = failure_state;
545 failure_state &= FAILURE_LOW_OVERTEMP;
546 backside_fan_tick();
547 slots_fan_tick();
548
549 /* We do CPUs last because they can be clamped high by
550 * DIMM temperature
551 */
552 cpu_fans_tick();
553
554 DBG_LOTS(" last_failure: 0x%x, failure_state: %x\n",
555 last_failure, failure_state);
556
557 /* Check for failures. Any failure causes cpufreq clamping */
558 if (failure_state && last_failure == 0 && cpufreq_clamp)
559 wf_control_set_max(cpufreq_clamp);
560 if (failure_state == 0 && last_failure && cpufreq_clamp)
561 wf_control_set_min(cpufreq_clamp);
562
563 /* That's it for now, we might want to deal with other failures
564 * differently in the future though
565 */
566}
567
568static void rm31_new_control(struct wf_control *ct)
569{
570 bool all_controls;
571
572 if (!strcmp(ct->name, "cpu-fan-a-0"))
573 cpu_fans[0][0] = ct;
574 else if (!strcmp(ct->name, "cpu-fan-b-0"))
575 cpu_fans[0][1] = ct;
576 else if (!strcmp(ct->name, "cpu-fan-c-0"))
577 cpu_fans[0][2] = ct;
578 else if (!strcmp(ct->name, "cpu-fan-a-1"))
579 cpu_fans[1][0] = ct;
580 else if (!strcmp(ct->name, "cpu-fan-b-1"))
581 cpu_fans[1][1] = ct;
582 else if (!strcmp(ct->name, "cpu-fan-c-1"))
583 cpu_fans[1][2] = ct;
584 else if (!strcmp(ct->name, "backside-fan"))
585 backside_fan = ct;
586 else if (!strcmp(ct->name, "slots-fan"))
587 slots_fan = ct;
588 else if (!strcmp(ct->name, "cpufreq-clamp"))
589 cpufreq_clamp = ct;
590
591 all_controls =
592 cpu_fans[0][0] &&
593 cpu_fans[0][1] &&
594 cpu_fans[0][2] &&
595 backside_fan &&
596 slots_fan;
597 if (nr_chips > 1)
598 all_controls &=
599 cpu_fans[1][0] &&
600 cpu_fans[1][1] &&
601 cpu_fans[1][2];
602 have_all_controls = all_controls;
603}
604
605
606static void rm31_new_sensor(struct wf_sensor *sr)
607{
608 bool all_sensors;
609
610 if (!strcmp(sr->name, "cpu-diode-temp-0"))
611 sens_cpu_temp[0] = sr;
612 else if (!strcmp(sr->name, "cpu-diode-temp-1"))
613 sens_cpu_temp[1] = sr;
614 else if (!strcmp(sr->name, "cpu-voltage-0"))
615 sens_cpu_volts[0] = sr;
616 else if (!strcmp(sr->name, "cpu-voltage-1"))
617 sens_cpu_volts[1] = sr;
618 else if (!strcmp(sr->name, "cpu-current-0"))
619 sens_cpu_amps[0] = sr;
620 else if (!strcmp(sr->name, "cpu-current-1"))
621 sens_cpu_amps[1] = sr;
622 else if (!strcmp(sr->name, "backside-temp"))
623 backside_temp = sr;
624 else if (!strcmp(sr->name, "slots-temp"))
625 slots_temp = sr;
626 else if (!strcmp(sr->name, "dimms-temp"))
627 dimms_temp = sr;
628
629 all_sensors =
630 sens_cpu_temp[0] &&
631 sens_cpu_volts[0] &&
632 sens_cpu_amps[0] &&
633 backside_temp &&
634 slots_temp &&
635 dimms_temp;
636 if (nr_chips > 1)
637 all_sensors &=
638 sens_cpu_temp[1] &&
639 sens_cpu_volts[1] &&
640 sens_cpu_amps[1];
641
642 have_all_sensors = all_sensors;
643}
644
645static int rm31_wf_notify(struct notifier_block *self,
646 unsigned long event, void *data)
647{
648 switch (event) {
649 case WF_EVENT_NEW_SENSOR:
650 rm31_new_sensor(data);
651 break;
652 case WF_EVENT_NEW_CONTROL:
653 rm31_new_control(data);
654 break;
655 case WF_EVENT_TICK:
656 if (have_all_controls && have_all_sensors)
657 rm31_tick();
658 }
659 return 0;
660}
661
662static struct notifier_block rm31_events = {
663 .notifier_call = rm31_wf_notify,
664};
665
666static int wf_rm31_probe(struct platform_device *dev)
667{
668 wf_register_client(&rm31_events);
669 return 0;
670}
671
672static int __devexit wf_rm31_remove(struct platform_device *dev)
673{
674 wf_unregister_client(&rm31_events);
675
676 /* should release all sensors and controls */
677 return 0;
678}
679
680static struct platform_driver wf_rm31_driver = {
681 .probe = wf_rm31_probe,
682 .remove = wf_rm31_remove,
683 .driver = {
684 .name = "windfarm",
685 .owner = THIS_MODULE,
686 },
687};
688
689static int __init wf_rm31_init(void)
690{
691 struct device_node *cpu;
692 int i;
693
694 if (!of_machine_is_compatible("RackMac3,1"))
695 return -ENODEV;
696
697 /* Count the number of CPU cores */
698 nr_chips = 0;
699 for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
700 ++nr_chips;
701 if (nr_chips > NR_CHIPS)
702 nr_chips = NR_CHIPS;
703
704 pr_info("windfarm: Initializing for desktop G5 with %d chips\n",
705 nr_chips);
706
707 /* Get MPU data for each CPU */
708 for (i = 0; i < nr_chips; i++) {
709 cpu_mpu_data[i] = wf_get_mpu(i);
710 if (!cpu_mpu_data[i]) {
711 pr_err("wf_rm31: Failed to find MPU data for CPU %d\n", i);
712 return -ENXIO;
713 }
714 }
715
716#ifdef MODULE
717 request_module("windfarm_fcu_controls");
718 request_module("windfarm_lm75_sensor");
719 request_module("windfarm_lm87_sensor");
720 request_module("windfarm_ad7417_sensor");
721 request_module("windfarm_max6690_sensor");
722 request_module("windfarm_cpufreq_clamp");
723#endif /* MODULE */
724
725 platform_driver_register(&wf_rm31_driver);
726 return 0;
727}
728
729static void __exit wf_rm31_exit(void)
730{
731 platform_driver_unregister(&wf_rm31_driver);
732}
733
734module_init(wf_rm31_init);
735module_exit(wf_rm31_exit);
736
737MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
738MODULE_DESCRIPTION("Thermal control for Xserve G5");
739MODULE_LICENSE("GPL");
740MODULE_ALIAS("platform:windfarm");
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 3c2be5193fd5..c155a54e8638 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -172,7 +172,6 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
172 172
173 fct->fan_type = pwm_fan; 173 fct->fan_type = pwm_fan;
174 fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN; 174 fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN;
175 sysfs_attr_init(&fct->ctrl.attr.attr);
176 175
177 /* We use the name & location here the same way we do for SMU sensors, 176 /* We use the name & location here the same way we do for SMU sensors,
178 * see the comment in windfarm_smu_sensors.c. The locations are a bit 177 * see the comment in windfarm_smu_sensors.c. The locations are a bit
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 65a8ff3e1f8e..426e810233d7 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -20,7 +20,7 @@
20 20
21#include "windfarm.h" 21#include "windfarm.h"
22 22
23#define VERSION "0.2" 23#define VERSION "1.0"
24 24
25#define DEBUG 25#define DEBUG
26 26
@@ -34,11 +34,12 @@
34#define MAX_AGE msecs_to_jiffies(800) 34#define MAX_AGE msecs_to_jiffies(800)
35 35
36struct wf_sat { 36struct wf_sat {
37 struct kref ref;
37 int nr; 38 int nr;
38 atomic_t refcnt;
39 struct mutex mutex; 39 struct mutex mutex;
40 unsigned long last_read; /* jiffies when cache last updated */ 40 unsigned long last_read; /* jiffies when cache last updated */
41 u8 cache[16]; 41 u8 cache[16];
42 struct list_head sensors;
42 struct i2c_client *i2c; 43 struct i2c_client *i2c;
43 struct device_node *node; 44 struct device_node *node;
44}; 45};
@@ -46,11 +47,12 @@ struct wf_sat {
46static struct wf_sat *sats[2]; 47static struct wf_sat *sats[2];
47 48
48struct wf_sat_sensor { 49struct wf_sat_sensor {
49 int index; 50 struct list_head link;
50 int index2; /* used for power sensors */ 51 int index;
51 int shift; 52 int index2; /* used for power sensors */
52 struct wf_sat *sat; 53 int shift;
53 struct wf_sensor sens; 54 struct wf_sat *sat;
55 struct wf_sensor sens;
54}; 56};
55 57
56#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) 58#define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens)
@@ -142,7 +144,7 @@ static int wf_sat_read_cache(struct wf_sat *sat)
142 return 0; 144 return 0;
143} 145}
144 146
145static int wf_sat_get(struct wf_sensor *sr, s32 *value) 147static int wf_sat_sensor_get(struct wf_sensor *sr, s32 *value)
146{ 148{
147 struct wf_sat_sensor *sens = wf_to_sat(sr); 149 struct wf_sat_sensor *sens = wf_to_sat(sr);
148 struct wf_sat *sat = sens->sat; 150 struct wf_sat *sat = sens->sat;
@@ -175,62 +177,34 @@ static int wf_sat_get(struct wf_sensor *sr, s32 *value)
175 return err; 177 return err;
176} 178}
177 179
178static void wf_sat_release(struct wf_sensor *sr) 180static void wf_sat_release(struct kref *ref)
181{
182 struct wf_sat *sat = container_of(ref, struct wf_sat, ref);
183
184 if (sat->nr >= 0)
185 sats[sat->nr] = NULL;
186 kfree(sat);
187}
188
189static void wf_sat_sensor_release(struct wf_sensor *sr)
179{ 190{
180 struct wf_sat_sensor *sens = wf_to_sat(sr); 191 struct wf_sat_sensor *sens = wf_to_sat(sr);
181 struct wf_sat *sat = sens->sat; 192 struct wf_sat *sat = sens->sat;
182 193
183 if (atomic_dec_and_test(&sat->refcnt)) {
184 if (sat->nr >= 0)
185 sats[sat->nr] = NULL;
186 kfree(sat);
187 }
188 kfree(sens); 194 kfree(sens);
195 kref_put(&sat->ref, wf_sat_release);
189} 196}
190 197
191static struct wf_sensor_ops wf_sat_ops = { 198static struct wf_sensor_ops wf_sat_ops = {
192 .get_value = wf_sat_get, 199 .get_value = wf_sat_sensor_get,
193 .release = wf_sat_release, 200 .release = wf_sat_sensor_release,
194 .owner = THIS_MODULE, 201 .owner = THIS_MODULE,
195}; 202};
196 203
197static struct i2c_driver wf_sat_driver;
198
199static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev)
200{
201 struct i2c_board_info info;
202 struct i2c_client *client;
203 const u32 *reg;
204 u8 addr;
205
206 reg = of_get_property(dev, "reg", NULL);
207 if (reg == NULL)
208 return;
209 addr = *reg;
210 DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr);
211
212 memset(&info, 0, sizeof(struct i2c_board_info));
213 info.addr = (addr >> 1) & 0x7f;
214 info.platform_data = dev;
215 strlcpy(info.type, "wf_sat", I2C_NAME_SIZE);
216
217 client = i2c_new_device(adapter, &info);
218 if (client == NULL) {
219 printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n");
220 return;
221 }
222
223 /*
224 * Let i2c-core delete that device on driver removal.
225 * This is safe because i2c-core holds the core_lock mutex for us.
226 */
227 list_add_tail(&client->detected, &wf_sat_driver.clients);
228}
229
230static int wf_sat_probe(struct i2c_client *client, 204static int wf_sat_probe(struct i2c_client *client,
231 const struct i2c_device_id *id) 205 const struct i2c_device_id *id)
232{ 206{
233 struct device_node *dev = client->dev.platform_data; 207 struct device_node *dev = client->dev.of_node;
234 struct wf_sat *sat; 208 struct wf_sat *sat;
235 struct wf_sat_sensor *sens; 209 struct wf_sat_sensor *sens;
236 const u32 *reg; 210 const u32 *reg;
@@ -246,9 +220,10 @@ static int wf_sat_probe(struct i2c_client *client,
246 return -ENOMEM; 220 return -ENOMEM;
247 sat->nr = -1; 221 sat->nr = -1;
248 sat->node = of_node_get(dev); 222 sat->node = of_node_get(dev);
249 atomic_set(&sat->refcnt, 0); 223 kref_init(&sat->ref);
250 mutex_init(&sat->mutex); 224 mutex_init(&sat->mutex);
251 sat->i2c = client; 225 sat->i2c = client;
226 INIT_LIST_HEAD(&sat->sensors);
252 i2c_set_clientdata(client, sat); 227 i2c_set_clientdata(client, sat);
253 228
254 vsens[0] = vsens[1] = -1; 229 vsens[0] = vsens[1] = -1;
@@ -310,14 +285,15 @@ static int wf_sat_probe(struct i2c_client *client,
310 sens->index2 = -1; 285 sens->index2 = -1;
311 sens->shift = shift; 286 sens->shift = shift;
312 sens->sat = sat; 287 sens->sat = sat;
313 atomic_inc(&sat->refcnt);
314 sens->sens.ops = &wf_sat_ops; 288 sens->sens.ops = &wf_sat_ops;
315 sens->sens.name = (char *) (sens + 1); 289 sens->sens.name = (char *) (sens + 1);
316 snprintf(sens->sens.name, 16, "%s-%d", name, cpu); 290 snprintf((char *)sens->sens.name, 16, "%s-%d", name, cpu);
317 291
318 if (wf_register_sensor(&sens->sens)) { 292 if (wf_register_sensor(&sens->sens))
319 atomic_dec(&sat->refcnt);
320 kfree(sens); 293 kfree(sens);
294 else {
295 list_add(&sens->link, &sat->sensors);
296 kref_get(&sat->ref);
321 } 297 }
322 } 298 }
323 299
@@ -336,14 +312,15 @@ static int wf_sat_probe(struct i2c_client *client,
336 sens->index2 = isens[core]; 312 sens->index2 = isens[core];
337 sens->shift = 0; 313 sens->shift = 0;
338 sens->sat = sat; 314 sens->sat = sat;
339 atomic_inc(&sat->refcnt);
340 sens->sens.ops = &wf_sat_ops; 315 sens->sens.ops = &wf_sat_ops;
341 sens->sens.name = (char *) (sens + 1); 316 sens->sens.name = (char *) (sens + 1);
342 snprintf(sens->sens.name, 16, "cpu-power-%d", cpu); 317 snprintf((char *)sens->sens.name, 16, "cpu-power-%d", cpu);
343 318
344 if (wf_register_sensor(&sens->sens)) { 319 if (wf_register_sensor(&sens->sens))
345 atomic_dec(&sat->refcnt);
346 kfree(sens); 320 kfree(sens);
321 else {
322 list_add(&sens->link, &sat->sensors);
323 kref_get(&sat->ref);
347 } 324 }
348 } 325 }
349 326
@@ -353,42 +330,35 @@ static int wf_sat_probe(struct i2c_client *client,
353 return 0; 330 return 0;
354} 331}
355 332
356static int wf_sat_attach(struct i2c_adapter *adapter)
357{
358 struct device_node *busnode, *dev = NULL;
359 struct pmac_i2c_bus *bus;
360
361 bus = pmac_i2c_adapter_to_bus(adapter);
362 if (bus == NULL)
363 return -ENODEV;
364 busnode = pmac_i2c_get_bus_node(bus);
365
366 while ((dev = of_get_next_child(busnode, dev)) != NULL)
367 if (of_device_is_compatible(dev, "smu-sat"))
368 wf_sat_create(adapter, dev);
369 return 0;
370}
371
372static int wf_sat_remove(struct i2c_client *client) 333static int wf_sat_remove(struct i2c_client *client)
373{ 334{
374 struct wf_sat *sat = i2c_get_clientdata(client); 335 struct wf_sat *sat = i2c_get_clientdata(client);
336 struct wf_sat_sensor *sens;
375 337
376 /* XXX TODO */ 338 /* release sensors */
377 339 while(!list_empty(&sat->sensors)) {
340 sens = list_first_entry(&sat->sensors,
341 struct wf_sat_sensor, link);
342 list_del(&sens->link);
343 wf_unregister_sensor(&sens->sens);
344 }
378 sat->i2c = NULL; 345 sat->i2c = NULL;
346 i2c_set_clientdata(client, NULL);
347 kref_put(&sat->ref, wf_sat_release);
348
379 return 0; 349 return 0;
380} 350}
381 351
382static const struct i2c_device_id wf_sat_id[] = { 352static const struct i2c_device_id wf_sat_id[] = {
383 { "wf_sat", 0 }, 353 { "MAC,smu-sat", 0 },
384 { } 354 { }
385}; 355};
356MODULE_DEVICE_TABLE(i2c, wf_sat_id);
386 357
387static struct i2c_driver wf_sat_driver = { 358static struct i2c_driver wf_sat_driver = {
388 .driver = { 359 .driver = {
389 .name = "wf_smu_sat", 360 .name = "wf_smu_sat",
390 }, 361 },
391 .attach_adapter = wf_sat_attach,
392 .probe = wf_sat_probe, 362 .probe = wf_sat_probe,
393 .remove = wf_sat_remove, 363 .remove = wf_sat_remove,
394 .id_table = wf_sat_id, 364 .id_table = wf_sat_id,
@@ -399,15 +369,13 @@ static int __init sat_sensors_init(void)
399 return i2c_add_driver(&wf_sat_driver); 369 return i2c_add_driver(&wf_sat_driver);
400} 370}
401 371
402#if 0 /* uncomment when module_exit() below is uncommented */
403static void __exit sat_sensors_exit(void) 372static void __exit sat_sensors_exit(void)
404{ 373{
405 i2c_del_driver(&wf_sat_driver); 374 i2c_del_driver(&wf_sat_driver);
406} 375}
407#endif
408 376
409module_init(sat_sensors_init); 377module_init(sat_sensors_init);
410/*module_exit(sat_sensors_exit); Uncomment when cleanup is implemented */ 378module_exit(sat_sensors_exit);
411 379
412MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>"); 380MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
413MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control"); 381MODULE_DESCRIPTION("SMU satellite sensors for PowerMac thermal control");
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index a409fa050a1a..93d0a8b7718a 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -338,7 +338,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
338 mutex_unlock(&ps3av->mutex); 338 mutex_unlock(&ps3av->mutex);
339 return 0; 339 return 0;
340 340
341 err: 341err:
342 mutex_unlock(&ps3av->mutex); 342 mutex_unlock(&ps3av->mutex);
343 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); 343 printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res);
344 return res; 344 return res;
@@ -477,7 +477,6 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
477 477
478 return 0; 478 return 0;
479} 479}
480
481EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); 480EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
482 481
483static int ps3av_set_videomode(void) 482static int ps3av_set_videomode(void)
@@ -501,7 +500,7 @@ static void ps3av_set_videomode_packet(u32 id)
501 500
502 video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; 501 video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
503 502
504 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ 503 avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */
505 avb_param.num_of_audio_pkt = 0; 504 avb_param.num_of_audio_pkt = 0;
506 avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + 505 avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi +
507 ps3av->av_hw_conf.num_of_avmulti; 506 ps3av->av_hw_conf.num_of_avmulti;
@@ -521,7 +520,7 @@ static void ps3av_set_videomode_packet(u32 id)
521#ifndef PS3AV_HDMI_YUV 520#ifndef PS3AV_HDMI_YUV
522 if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || 521 if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
523 ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) 522 ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
524 av_video_cs = RGB8; /* use RGB for HDMI */ 523 av_video_cs = RGB8; /* use RGB for HDMI */
525#endif 524#endif
526 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], 525 len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
527 ps3av->av_port[i], 526 ps3av->av_port[i],
@@ -590,8 +589,8 @@ static void ps3avd(struct work_struct *work)
590#define SHIFT_VESA 8 589#define SHIFT_VESA 8
591 590
592static const struct { 591static const struct {
593 unsigned mask : 19; 592 unsigned mask:19;
594 unsigned id : 4; 593 unsigned id:4;
595} ps3av_preferred_modes[] = { 594} ps3av_preferred_modes[] = {
596 { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, 595 { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA },
597 { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, 596 { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 },
@@ -667,7 +666,8 @@ static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
667 return id; 666 return id;
668} 667}
669 668
670static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) 669static void ps3av_monitor_info_dump(
670 const struct ps3av_pkt_av_get_monitor_info *monitor_info)
671{ 671{
672 const struct ps3av_info_monitor *info = &monitor_info->info; 672 const struct ps3av_info_monitor *info = &monitor_info->info;
673 const struct ps3av_info_audio *audio = info->audio; 673 const struct ps3av_info_audio *audio = info->audio;
@@ -717,8 +717,8 @@ static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *
717 717
718 /* audio block */ 718 /* audio block */
719 for (i = 0; i < info->num_of_audio_block; i++) { 719 for (i = 0; i < info->num_of_audio_block; i++) {
720 pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " 720 pr_debug(
721 "%02x\n", 721 "audio[%d] type: %02x max_ch: %02x fs: %02x sbit: %02x\n",
722 i, audio->type, audio->max_num_of_ch, audio->fs, 722 i, audio->type, audio->max_num_of_ch, audio->fs,
723 audio->sbit); 723 audio->sbit);
724 audio++; 724 audio++;
@@ -870,21 +870,18 @@ int ps3av_set_video_mode(int id)
870 870
871 return 0; 871 return 0;
872} 872}
873
874EXPORT_SYMBOL_GPL(ps3av_set_video_mode); 873EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
875 874
876int ps3av_get_auto_mode(void) 875int ps3av_get_auto_mode(void)
877{ 876{
878 return ps3av_auto_videomode(&ps3av->av_hw_conf); 877 return ps3av_auto_videomode(&ps3av->av_hw_conf);
879} 878}
880
881EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); 879EXPORT_SYMBOL_GPL(ps3av_get_auto_mode);
882 880
883int ps3av_get_mode(void) 881int ps3av_get_mode(void)
884{ 882{
885 return ps3av ? ps3av->ps3av_mode : 0; 883 return ps3av ? ps3av->ps3av_mode : 0;
886} 884}
887
888EXPORT_SYMBOL_GPL(ps3av_get_mode); 885EXPORT_SYMBOL_GPL(ps3av_get_mode);
889 886
890/* get resolution by video_mode */ 887/* get resolution by video_mode */
@@ -902,7 +899,6 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
902 *yres = video_mode_table[id].y; 899 *yres = video_mode_table[id].y;
903 return 0; 900 return 0;
904} 901}
905
906EXPORT_SYMBOL_GPL(ps3av_video_mode2res); 902EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
907 903
908/* mute */ 904/* mute */
@@ -911,7 +907,6 @@ int ps3av_video_mute(int mute)
911 return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON 907 return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
912 : PS3AV_CMD_MUTE_OFF); 908 : PS3AV_CMD_MUTE_OFF);
913} 909}
914
915EXPORT_SYMBOL_GPL(ps3av_video_mute); 910EXPORT_SYMBOL_GPL(ps3av_video_mute);
916 911
917/* mute analog output only */ 912/* mute analog output only */
@@ -935,7 +930,6 @@ int ps3av_audio_mute(int mute)
935 return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON 930 return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
936 : PS3AV_CMD_MUTE_OFF); 931 : PS3AV_CMD_MUTE_OFF);
937} 932}
938
939EXPORT_SYMBOL_GPL(ps3av_audio_mute); 933EXPORT_SYMBOL_GPL(ps3av_audio_mute);
940 934
941static int __devinit ps3av_probe(struct ps3_system_bus_device *dev) 935static int __devinit ps3av_probe(struct ps3_system_bus_device *dev)