1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2004-2006, Advanced Micro Devices, Inc.
5 #include <linux/module.h>
6 #include <linux/kernel.h>
8 #include <linux/pci_ids.h>
9 #include <linux/crypto.h>
10 #include <linux/spinlock.h>
11 #include <crypto/algapi.h>
12 #include <crypto/aes.h>
13 #include <crypto/internal/cipher.h>
14 #include <crypto/internal/skcipher.h>
17 #include <linux/delay.h>
19 #include "geode-aes.h"
21 /* Static structures */
23 static void __iomem
*_iobase
;
24 static DEFINE_SPINLOCK(lock
);
26 /* Write a 128 bit field (either a writable key or IV) */
28 _writefield(u32 offset
, const void *value
)
32 for (i
= 0; i
< 4; i
++)
33 iowrite32(((const u32
*) value
)[i
], _iobase
+ offset
+ (i
* 4));
36 /* Read a 128 bit field (either a writable key or IV) */
38 _readfield(u32 offset
, void *value
)
42 for (i
= 0; i
< 4; i
++)
43 ((u32
*) value
)[i
] = ioread32(_iobase
+ offset
+ (i
* 4));
47 do_crypt(const void *src
, void *dst
, u32 len
, u32 flags
)
50 u32 counter
= AES_OP_TIMEOUT
;
52 iowrite32(virt_to_phys((void *)src
), _iobase
+ AES_SOURCEA_REG
);
53 iowrite32(virt_to_phys(dst
), _iobase
+ AES_DSTA_REG
);
54 iowrite32(len
, _iobase
+ AES_LENA_REG
);
56 /* Start the operation */
57 iowrite32(AES_CTRL_START
| flags
, _iobase
+ AES_CTRLA_REG
);
60 status
= ioread32(_iobase
+ AES_INTR_REG
);
62 } while (!(status
& AES_INTRA_PENDING
) && --counter
);
65 iowrite32((status
& 0xFF) | AES_INTRA_PENDING
, _iobase
+ AES_INTR_REG
);
66 return counter
? 0 : 1;
70 geode_aes_crypt(const struct geode_aes_tfm_ctx
*tctx
, const void *src
,
71 void *dst
, u32 len
, u8
*iv
, int mode
, int dir
)
77 /* If the source and destination is the same, then
78 * we need to turn on the coherent flags, otherwise
79 * we don't need to worry
82 flags
|= (AES_CTRL_DCA
| AES_CTRL_SCA
);
84 if (dir
== AES_DIR_ENCRYPT
)
85 flags
|= AES_CTRL_ENCRYPT
;
87 /* Start the critical section */
89 spin_lock_irqsave(&lock
, iflags
);
91 if (mode
== AES_MODE_CBC
) {
92 flags
|= AES_CTRL_CBC
;
93 _writefield(AES_WRITEIV0_REG
, iv
);
96 flags
|= AES_CTRL_WRKEY
;
97 _writefield(AES_WRITEKEY0_REG
, tctx
->key
);
99 ret
= do_crypt(src
, dst
, len
, flags
);
102 if (mode
== AES_MODE_CBC
)
103 _readfield(AES_WRITEIV0_REG
, iv
);
105 spin_unlock_irqrestore(&lock
, iflags
);
108 /* CRYPTO-API Functions */
110 static int geode_setkey_cip(struct crypto_tfm
*tfm
, const u8
*key
,
113 struct geode_aes_tfm_ctx
*tctx
= crypto_tfm_ctx(tfm
);
117 if (len
== AES_KEYSIZE_128
) {
118 memcpy(tctx
->key
, key
, len
);
122 if (len
!= AES_KEYSIZE_192
&& len
!= AES_KEYSIZE_256
)
123 /* not supported at all */
127 * The requested key size is not supported by HW, do a fallback
129 tctx
->fallback
.cip
->base
.crt_flags
&= ~CRYPTO_TFM_REQ_MASK
;
130 tctx
->fallback
.cip
->base
.crt_flags
|=
131 (tfm
->crt_flags
& CRYPTO_TFM_REQ_MASK
);
133 return crypto_cipher_setkey(tctx
->fallback
.cip
, key
, len
);
136 static int geode_setkey_skcipher(struct crypto_skcipher
*tfm
, const u8
*key
,
139 struct geode_aes_tfm_ctx
*tctx
= crypto_skcipher_ctx(tfm
);
143 if (len
== AES_KEYSIZE_128
) {
144 memcpy(tctx
->key
, key
, len
);
148 if (len
!= AES_KEYSIZE_192
&& len
!= AES_KEYSIZE_256
)
149 /* not supported at all */
153 * The requested key size is not supported by HW, do a fallback
155 crypto_skcipher_clear_flags(tctx
->fallback
.skcipher
,
156 CRYPTO_TFM_REQ_MASK
);
157 crypto_skcipher_set_flags(tctx
->fallback
.skcipher
,
158 crypto_skcipher_get_flags(tfm
) &
159 CRYPTO_TFM_REQ_MASK
);
160 return crypto_skcipher_setkey(tctx
->fallback
.skcipher
, key
, len
);
164 geode_encrypt(struct crypto_tfm
*tfm
, u8
*out
, const u8
*in
)
166 const struct geode_aes_tfm_ctx
*tctx
= crypto_tfm_ctx(tfm
);
168 if (unlikely(tctx
->keylen
!= AES_KEYSIZE_128
)) {
169 crypto_cipher_encrypt_one(tctx
->fallback
.cip
, out
, in
);
173 geode_aes_crypt(tctx
, in
, out
, AES_BLOCK_SIZE
, NULL
,
174 AES_MODE_ECB
, AES_DIR_ENCRYPT
);
179 geode_decrypt(struct crypto_tfm
*tfm
, u8
*out
, const u8
*in
)
181 const struct geode_aes_tfm_ctx
*tctx
= crypto_tfm_ctx(tfm
);
183 if (unlikely(tctx
->keylen
!= AES_KEYSIZE_128
)) {
184 crypto_cipher_decrypt_one(tctx
->fallback
.cip
, out
, in
);
188 geode_aes_crypt(tctx
, in
, out
, AES_BLOCK_SIZE
, NULL
,
189 AES_MODE_ECB
, AES_DIR_DECRYPT
);
192 static int fallback_init_cip(struct crypto_tfm
*tfm
)
194 const char *name
= crypto_tfm_alg_name(tfm
);
195 struct geode_aes_tfm_ctx
*tctx
= crypto_tfm_ctx(tfm
);
197 tctx
->fallback
.cip
= crypto_alloc_cipher(name
, 0,
198 CRYPTO_ALG_NEED_FALLBACK
);
200 if (IS_ERR(tctx
->fallback
.cip
)) {
201 printk(KERN_ERR
"Error allocating fallback algo %s\n", name
);
202 return PTR_ERR(tctx
->fallback
.cip
);
208 static void fallback_exit_cip(struct crypto_tfm
*tfm
)
210 struct geode_aes_tfm_ctx
*tctx
= crypto_tfm_ctx(tfm
);
212 crypto_free_cipher(tctx
->fallback
.cip
);
215 static struct crypto_alg geode_alg
= {
217 .cra_driver_name
= "geode-aes",
220 .cra_flags
= CRYPTO_ALG_TYPE_CIPHER
|
221 CRYPTO_ALG_NEED_FALLBACK
,
222 .cra_init
= fallback_init_cip
,
223 .cra_exit
= fallback_exit_cip
,
224 .cra_blocksize
= AES_BLOCK_SIZE
,
225 .cra_ctxsize
= sizeof(struct geode_aes_tfm_ctx
),
226 .cra_module
= THIS_MODULE
,
229 .cia_min_keysize
= AES_MIN_KEY_SIZE
,
230 .cia_max_keysize
= AES_MAX_KEY_SIZE
,
231 .cia_setkey
= geode_setkey_cip
,
232 .cia_encrypt
= geode_encrypt
,
233 .cia_decrypt
= geode_decrypt
238 static int geode_init_skcipher(struct crypto_skcipher
*tfm
)
240 const char *name
= crypto_tfm_alg_name(&tfm
->base
);
241 struct geode_aes_tfm_ctx
*tctx
= crypto_skcipher_ctx(tfm
);
243 tctx
->fallback
.skcipher
=
244 crypto_alloc_skcipher(name
, 0, CRYPTO_ALG_NEED_FALLBACK
|
246 if (IS_ERR(tctx
->fallback
.skcipher
)) {
247 printk(KERN_ERR
"Error allocating fallback algo %s\n", name
);
248 return PTR_ERR(tctx
->fallback
.skcipher
);
251 crypto_skcipher_set_reqsize(tfm
, sizeof(struct skcipher_request
) +
252 crypto_skcipher_reqsize(tctx
->fallback
.skcipher
));
256 static void geode_exit_skcipher(struct crypto_skcipher
*tfm
)
258 struct geode_aes_tfm_ctx
*tctx
= crypto_skcipher_ctx(tfm
);
260 crypto_free_skcipher(tctx
->fallback
.skcipher
);
263 static int geode_skcipher_crypt(struct skcipher_request
*req
, int mode
, int dir
)
265 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
266 const struct geode_aes_tfm_ctx
*tctx
= crypto_skcipher_ctx(tfm
);
267 struct skcipher_walk walk
;
271 if (unlikely(tctx
->keylen
!= AES_KEYSIZE_128
)) {
272 struct skcipher_request
*subreq
= skcipher_request_ctx(req
);
275 skcipher_request_set_tfm(subreq
, tctx
->fallback
.skcipher
);
276 if (dir
== AES_DIR_DECRYPT
)
277 return crypto_skcipher_decrypt(subreq
);
279 return crypto_skcipher_encrypt(subreq
);
282 err
= skcipher_walk_virt(&walk
, req
, false);
284 while ((nbytes
= walk
.nbytes
) != 0) {
285 geode_aes_crypt(tctx
, walk
.src
.virt
.addr
, walk
.dst
.virt
.addr
,
286 round_down(nbytes
, AES_BLOCK_SIZE
),
288 err
= skcipher_walk_done(&walk
, nbytes
% AES_BLOCK_SIZE
);
294 static int geode_cbc_encrypt(struct skcipher_request
*req
)
296 return geode_skcipher_crypt(req
, AES_MODE_CBC
, AES_DIR_ENCRYPT
);
299 static int geode_cbc_decrypt(struct skcipher_request
*req
)
301 return geode_skcipher_crypt(req
, AES_MODE_CBC
, AES_DIR_DECRYPT
);
304 static int geode_ecb_encrypt(struct skcipher_request
*req
)
306 return geode_skcipher_crypt(req
, AES_MODE_ECB
, AES_DIR_ENCRYPT
);
309 static int geode_ecb_decrypt(struct skcipher_request
*req
)
311 return geode_skcipher_crypt(req
, AES_MODE_ECB
, AES_DIR_DECRYPT
);
314 static struct skcipher_alg geode_skcipher_algs
[] = {
316 .base
.cra_name
= "cbc(aes)",
317 .base
.cra_driver_name
= "cbc-aes-geode",
318 .base
.cra_priority
= 400,
319 .base
.cra_flags
= CRYPTO_ALG_KERN_DRIVER_ONLY
|
320 CRYPTO_ALG_NEED_FALLBACK
,
321 .base
.cra_blocksize
= AES_BLOCK_SIZE
,
322 .base
.cra_ctxsize
= sizeof(struct geode_aes_tfm_ctx
),
323 .base
.cra_alignmask
= 15,
324 .base
.cra_module
= THIS_MODULE
,
325 .init
= geode_init_skcipher
,
326 .exit
= geode_exit_skcipher
,
327 .setkey
= geode_setkey_skcipher
,
328 .encrypt
= geode_cbc_encrypt
,
329 .decrypt
= geode_cbc_decrypt
,
330 .min_keysize
= AES_MIN_KEY_SIZE
,
331 .max_keysize
= AES_MAX_KEY_SIZE
,
332 .ivsize
= AES_BLOCK_SIZE
,
334 .base
.cra_name
= "ecb(aes)",
335 .base
.cra_driver_name
= "ecb-aes-geode",
336 .base
.cra_priority
= 400,
337 .base
.cra_flags
= CRYPTO_ALG_KERN_DRIVER_ONLY
|
338 CRYPTO_ALG_NEED_FALLBACK
,
339 .base
.cra_blocksize
= AES_BLOCK_SIZE
,
340 .base
.cra_ctxsize
= sizeof(struct geode_aes_tfm_ctx
),
341 .base
.cra_alignmask
= 15,
342 .base
.cra_module
= THIS_MODULE
,
343 .init
= geode_init_skcipher
,
344 .exit
= geode_exit_skcipher
,
345 .setkey
= geode_setkey_skcipher
,
346 .encrypt
= geode_ecb_encrypt
,
347 .decrypt
= geode_ecb_decrypt
,
348 .min_keysize
= AES_MIN_KEY_SIZE
,
349 .max_keysize
= AES_MAX_KEY_SIZE
,
353 static void geode_aes_remove(struct pci_dev
*dev
)
355 crypto_unregister_alg(&geode_alg
);
356 crypto_unregister_skciphers(geode_skcipher_algs
,
357 ARRAY_SIZE(geode_skcipher_algs
));
359 pci_iounmap(dev
, _iobase
);
362 pci_release_regions(dev
);
363 pci_disable_device(dev
);
367 static int geode_aes_probe(struct pci_dev
*dev
, const struct pci_device_id
*id
)
371 ret
= pci_enable_device(dev
);
375 ret
= pci_request_regions(dev
, "geode-aes");
379 _iobase
= pci_iomap(dev
, 0, 0);
381 if (_iobase
== NULL
) {
386 /* Clear any pending activity */
387 iowrite32(AES_INTR_PENDING
| AES_INTR_MASK
, _iobase
+ AES_INTR_REG
);
389 ret
= crypto_register_alg(&geode_alg
);
393 ret
= crypto_register_skciphers(geode_skcipher_algs
,
394 ARRAY_SIZE(geode_skcipher_algs
));
398 dev_notice(&dev
->dev
, "GEODE AES engine enabled.\n");
402 crypto_unregister_alg(&geode_alg
);
405 pci_iounmap(dev
, _iobase
);
408 pci_release_regions(dev
);
411 pci_disable_device(dev
);
413 dev_err(&dev
->dev
, "GEODE AES initialization failed.\n");
417 static struct pci_device_id geode_aes_tbl
[] = {
418 { PCI_VDEVICE(AMD
, PCI_DEVICE_ID_AMD_LX_AES
), },
422 MODULE_DEVICE_TABLE(pci
, geode_aes_tbl
);
424 static struct pci_driver geode_aes_driver
= {
425 .name
= "Geode LX AES",
426 .id_table
= geode_aes_tbl
,
427 .probe
= geode_aes_probe
,
428 .remove
= geode_aes_remove
,
431 module_pci_driver(geode_aes_driver
);
433 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
434 MODULE_DESCRIPTION("Geode LX Hardware AES driver");
435 MODULE_LICENSE("GPL");
436 MODULE_IMPORT_NS("CRYPTO_INTERNAL");