aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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 /drivers
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 ...
Diffstat (limited to 'drivers')
-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
38 files changed, 6747 insertions, 643 deletions
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)