blob: ccb8a8322bf704b923ab045437cd7f769d0273d3 [file] [log] [blame]
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001/*
2 * Cryptographic API.
3 *
4 * Support for ATMEL AES HW acceleration.
5 *
6 * Copyright (c) 2012 Eukréa Electromatique - ATMEL
7 * Author: Nicolas Royer <nicolas@eukrea.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 *
13 * Some ideas are from omap-aes.c driver.
14 */
15
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/err.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23#include <linux/hw_random.h>
24#include <linux/platform_device.h>
25
26#include <linux/device.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020027#include <linux/init.h>
28#include <linux/errno.h>
29#include <linux/interrupt.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020030#include <linux/irq.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020031#include <linux/scatterlist.h>
32#include <linux/dma-mapping.h>
Nicolas Ferrebe943c72013-10-14 17:52:38 +020033#include <linux/of_device.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020034#include <linux/delay.h>
35#include <linux/crypto.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020036#include <crypto/scatterwalk.h>
37#include <crypto/algapi.h>
38#include <crypto/aes.h>
Nicolas Royercadc4ab2013-02-20 17:10:24 +010039#include <linux/platform_data/crypto-atmel.h>
Nicolas Ferrebe943c72013-10-14 17:52:38 +020040#include <dt-bindings/dma/at91.h>
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020041#include "atmel-aes-regs.h"
42
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +010043#define ATMEL_AES_PRIORITY 300
44
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020045#define CFB8_BLOCK_SIZE 1
46#define CFB16_BLOCK_SIZE 2
47#define CFB32_BLOCK_SIZE 4
48#define CFB64_BLOCK_SIZE 8
49
50/* AES flags */
Nicolas Royercadc4ab2013-02-20 17:10:24 +010051#define AES_FLAGS_MODE_MASK 0x03ff
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020052#define AES_FLAGS_ENCRYPT BIT(0)
53#define AES_FLAGS_CBC BIT(1)
54#define AES_FLAGS_CFB BIT(2)
55#define AES_FLAGS_CFB8 BIT(3)
56#define AES_FLAGS_CFB16 BIT(4)
57#define AES_FLAGS_CFB32 BIT(5)
58#define AES_FLAGS_CFB64 BIT(6)
Nicolas Royercadc4ab2013-02-20 17:10:24 +010059#define AES_FLAGS_CFB128 BIT(7)
60#define AES_FLAGS_OFB BIT(8)
61#define AES_FLAGS_CTR BIT(9)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020062
63#define AES_FLAGS_INIT BIT(16)
64#define AES_FLAGS_DMA BIT(17)
65#define AES_FLAGS_BUSY BIT(18)
Nicolas Royercadc4ab2013-02-20 17:10:24 +010066#define AES_FLAGS_FAST BIT(19)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020067
Nicolas Royercadc4ab2013-02-20 17:10:24 +010068#define ATMEL_AES_QUEUE_LENGTH 50
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020069
70#define ATMEL_AES_DMA_THRESHOLD 16
71
72
Nicolas Royercadc4ab2013-02-20 17:10:24 +010073struct atmel_aes_caps {
74 bool has_dualbuff;
75 bool has_cfb64;
76 u32 max_burst_size;
77};
78
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020079struct atmel_aes_dev;
80
81struct atmel_aes_ctx {
82 struct atmel_aes_dev *dd;
83
84 int keylen;
85 u32 key[AES_KEYSIZE_256 / sizeof(u32)];
Nicolas Royercadc4ab2013-02-20 17:10:24 +010086
87 u16 block_size;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +020088};
89
90struct atmel_aes_reqctx {
91 unsigned long mode;
92};
93
94struct atmel_aes_dma {
95 struct dma_chan *chan;
96 struct dma_slave_config dma_conf;
97};
98
99struct atmel_aes_dev {
100 struct list_head list;
101 unsigned long phys_base;
102 void __iomem *io_base;
103
104 struct atmel_aes_ctx *ctx;
105 struct device *dev;
106 struct clk *iclk;
107 int irq;
108
109 unsigned long flags;
110 int err;
111
112 spinlock_t lock;
113 struct crypto_queue queue;
114
115 struct tasklet_struct done_task;
116 struct tasklet_struct queue_task;
117
118 struct ablkcipher_request *req;
119 size_t total;
120
121 struct scatterlist *in_sg;
122 unsigned int nb_in_sg;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100123 size_t in_offset;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200124 struct scatterlist *out_sg;
125 unsigned int nb_out_sg;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100126 size_t out_offset;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200127
128 size_t bufcnt;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100129 size_t buflen;
130 size_t dma_size;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200131
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100132 void *buf_in;
133 int dma_in;
134 dma_addr_t dma_addr_in;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200135 struct atmel_aes_dma dma_lch_in;
136
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100137 void *buf_out;
138 int dma_out;
139 dma_addr_t dma_addr_out;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200140 struct atmel_aes_dma dma_lch_out;
141
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100142 struct atmel_aes_caps caps;
143
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200144 u32 hw_version;
145};
146
147struct atmel_aes_drv {
148 struct list_head dev_list;
149 spinlock_t lock;
150};
151
152static struct atmel_aes_drv atmel_aes = {
153 .dev_list = LIST_HEAD_INIT(atmel_aes.dev_list),
154 .lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
155};
156
157static int atmel_aes_sg_length(struct ablkcipher_request *req,
158 struct scatterlist *sg)
159{
160 unsigned int total = req->nbytes;
161 int sg_nb;
162 unsigned int len;
163 struct scatterlist *sg_list;
164
165 sg_nb = 0;
166 sg_list = sg;
167 total = req->nbytes;
168
169 while (total) {
170 len = min(sg_list->length, total);
171
172 sg_nb++;
173 total -= len;
174
175 sg_list = sg_next(sg_list);
176 if (!sg_list)
177 total = 0;
178 }
179
180 return sg_nb;
181}
182
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100183static int atmel_aes_sg_copy(struct scatterlist **sg, size_t *offset,
184 void *buf, size_t buflen, size_t total, int out)
185{
Arnd Bergmann20ecae72015-11-17 10:22:06 +0100186 size_t count, off = 0;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100187
188 while (buflen && total) {
189 count = min((*sg)->length - *offset, total);
190 count = min(count, buflen);
191
192 if (!count)
193 return off;
194
195 scatterwalk_map_and_copy(buf + off, *sg, *offset, count, out);
196
197 off += count;
198 buflen -= count;
199 *offset += count;
200 total -= count;
201
202 if (*offset == (*sg)->length) {
203 *sg = sg_next(*sg);
204 if (*sg)
205 *offset = 0;
206 else
207 total = 0;
208 }
209 }
210
211 return off;
212}
213
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200214static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
215{
216 return readl_relaxed(dd->io_base + offset);
217}
218
219static inline void atmel_aes_write(struct atmel_aes_dev *dd,
220 u32 offset, u32 value)
221{
222 writel_relaxed(value, dd->io_base + offset);
223}
224
225static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 offset,
226 u32 *value, int count)
227{
228 for (; count--; value++, offset += 4)
229 *value = atmel_aes_read(dd, offset);
230}
231
232static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
Cyrille Pitchenc0b28d82015-12-17 17:48:33 +0100233 const u32 *value, int count)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200234{
235 for (; count--; value++, offset += 4)
236 atmel_aes_write(dd, offset, *value);
237}
238
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200239static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_ctx *ctx)
240{
241 struct atmel_aes_dev *aes_dd = NULL;
242 struct atmel_aes_dev *tmp;
243
244 spin_lock_bh(&atmel_aes.lock);
245 if (!ctx->dd) {
246 list_for_each_entry(tmp, &atmel_aes.dev_list, list) {
247 aes_dd = tmp;
248 break;
249 }
250 ctx->dd = aes_dd;
251 } else {
252 aes_dd = ctx->dd;
253 }
254
255 spin_unlock_bh(&atmel_aes.lock);
256
257 return aes_dd;
258}
259
260static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
261{
LABBE Corentin9d83d292015-10-02 14:12:58 +0200262 int err;
263
264 err = clk_prepare_enable(dd->iclk);
265 if (err)
266 return err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200267
268 if (!(dd->flags & AES_FLAGS_INIT)) {
269 atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100270 atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200271 dd->flags |= AES_FLAGS_INIT;
272 dd->err = 0;
273 }
274
275 return 0;
276}
277
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100278static inline unsigned int atmel_aes_get_version(struct atmel_aes_dev *dd)
279{
280 return atmel_aes_read(dd, AES_HW_VERSION) & 0x00000fff;
281}
282
Cyrille Pitchenaab0a392015-12-17 17:48:37 +0100283static int atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200284{
Cyrille Pitchenaab0a392015-12-17 17:48:37 +0100285 int err;
286
287 err = atmel_aes_hw_init(dd);
288 if (err)
289 return err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200290
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100291 dd->hw_version = atmel_aes_get_version(dd);
292
Cyrille Pitchenaab0a392015-12-17 17:48:37 +0100293 dev_info(dd->dev, "version: 0x%x\n", dd->hw_version);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200294
295 clk_disable_unprepare(dd->iclk);
Cyrille Pitchenaab0a392015-12-17 17:48:37 +0100296 return 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200297}
298
299static void atmel_aes_finish_req(struct atmel_aes_dev *dd, int err)
300{
301 struct ablkcipher_request *req = dd->req;
302
303 clk_disable_unprepare(dd->iclk);
304 dd->flags &= ~AES_FLAGS_BUSY;
305
306 req->base.complete(&req->base, err);
307}
308
309static void atmel_aes_dma_callback(void *data)
310{
311 struct atmel_aes_dev *dd = data;
312
313 /* dma_lch_out - completed */
314 tasklet_schedule(&dd->done_task);
315}
316
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100317static int atmel_aes_crypt_dma(struct atmel_aes_dev *dd,
318 dma_addr_t dma_addr_in, dma_addr_t dma_addr_out, int length)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200319{
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100320 struct scatterlist sg[2];
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200321 struct dma_async_tx_descriptor *in_desc, *out_desc;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200322
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100323 dd->dma_size = length;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200324
Leilei Zhao289b2622015-04-07 17:45:10 +0800325 dma_sync_single_for_device(dd->dev, dma_addr_in, length,
326 DMA_TO_DEVICE);
327 dma_sync_single_for_device(dd->dev, dma_addr_out, length,
328 DMA_FROM_DEVICE);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200329
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100330 if (dd->flags & AES_FLAGS_CFB8) {
331 dd->dma_lch_in.dma_conf.dst_addr_width =
332 DMA_SLAVE_BUSWIDTH_1_BYTE;
333 dd->dma_lch_out.dma_conf.src_addr_width =
334 DMA_SLAVE_BUSWIDTH_1_BYTE;
335 } else if (dd->flags & AES_FLAGS_CFB16) {
336 dd->dma_lch_in.dma_conf.dst_addr_width =
337 DMA_SLAVE_BUSWIDTH_2_BYTES;
338 dd->dma_lch_out.dma_conf.src_addr_width =
339 DMA_SLAVE_BUSWIDTH_2_BYTES;
340 } else {
341 dd->dma_lch_in.dma_conf.dst_addr_width =
342 DMA_SLAVE_BUSWIDTH_4_BYTES;
343 dd->dma_lch_out.dma_conf.src_addr_width =
344 DMA_SLAVE_BUSWIDTH_4_BYTES;
345 }
346
347 if (dd->flags & (AES_FLAGS_CFB8 | AES_FLAGS_CFB16 |
348 AES_FLAGS_CFB32 | AES_FLAGS_CFB64)) {
349 dd->dma_lch_in.dma_conf.src_maxburst = 1;
350 dd->dma_lch_in.dma_conf.dst_maxburst = 1;
351 dd->dma_lch_out.dma_conf.src_maxburst = 1;
352 dd->dma_lch_out.dma_conf.dst_maxburst = 1;
353 } else {
354 dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
355 dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
356 dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
357 dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
358 }
359
360 dmaengine_slave_config(dd->dma_lch_in.chan, &dd->dma_lch_in.dma_conf);
361 dmaengine_slave_config(dd->dma_lch_out.chan, &dd->dma_lch_out.dma_conf);
362
363 dd->flags |= AES_FLAGS_DMA;
364
365 sg_init_table(&sg[0], 1);
366 sg_dma_address(&sg[0]) = dma_addr_in;
367 sg_dma_len(&sg[0]) = length;
368
369 sg_init_table(&sg[1], 1);
370 sg_dma_address(&sg[1]) = dma_addr_out;
371 sg_dma_len(&sg[1]) = length;
372
373 in_desc = dmaengine_prep_slave_sg(dd->dma_lch_in.chan, &sg[0],
374 1, DMA_MEM_TO_DEV,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200375 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200376 if (!in_desc)
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100377 return -EINVAL;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200378
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100379 out_desc = dmaengine_prep_slave_sg(dd->dma_lch_out.chan, &sg[1],
380 1, DMA_DEV_TO_MEM,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200381 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200382 if (!out_desc)
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100383 return -EINVAL;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200384
385 out_desc->callback = atmel_aes_dma_callback;
386 out_desc->callback_param = dd;
387
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200388 dmaengine_submit(out_desc);
389 dma_async_issue_pending(dd->dma_lch_out.chan);
390
391 dmaengine_submit(in_desc);
392 dma_async_issue_pending(dd->dma_lch_in.chan);
393
394 return 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200395}
396
397static int atmel_aes_crypt_cpu_start(struct atmel_aes_dev *dd)
398{
399 dd->flags &= ~AES_FLAGS_DMA;
400
Leilei Zhao289b2622015-04-07 17:45:10 +0800401 dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in,
402 dd->dma_size, DMA_TO_DEVICE);
403 dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
404 dd->dma_size, DMA_FROM_DEVICE);
405
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200406 /* use cache buffers */
407 dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg);
408 if (!dd->nb_in_sg)
409 return -EINVAL;
410
411 dd->nb_out_sg = atmel_aes_sg_length(dd->req, dd->out_sg);
Julia Lawall7b5c253c2013-01-21 14:02:51 +0100412 if (!dd->nb_out_sg)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200413 return -EINVAL;
414
415 dd->bufcnt = sg_copy_to_buffer(dd->in_sg, dd->nb_in_sg,
416 dd->buf_in, dd->total);
417
418 if (!dd->bufcnt)
419 return -EINVAL;
420
421 dd->total -= dd->bufcnt;
422
423 atmel_aes_write(dd, AES_IER, AES_INT_DATARDY);
424 atmel_aes_write_n(dd, AES_IDATAR(0), (u32 *) dd->buf_in,
425 dd->bufcnt >> 2);
426
427 return 0;
428}
429
430static int atmel_aes_crypt_dma_start(struct atmel_aes_dev *dd)
431{
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100432 int err, fast = 0, in, out;
433 size_t count;
434 dma_addr_t addr_in, addr_out;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200435
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100436 if ((!dd->in_offset) && (!dd->out_offset)) {
437 /* check for alignment */
438 in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32)) &&
439 IS_ALIGNED(dd->in_sg->length, dd->ctx->block_size);
440 out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32)) &&
441 IS_ALIGNED(dd->out_sg->length, dd->ctx->block_size);
442 fast = in && out;
443
444 if (sg_dma_len(dd->in_sg) != sg_dma_len(dd->out_sg))
445 fast = 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200446 }
447
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200448
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100449 if (fast) {
Arnd Bergmann20ecae72015-11-17 10:22:06 +0100450 count = min_t(size_t, dd->total, sg_dma_len(dd->in_sg));
451 count = min_t(size_t, count, sg_dma_len(dd->out_sg));
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100452
453 err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
454 if (!err) {
455 dev_err(dd->dev, "dma_map_sg() error\n");
456 return -EINVAL;
457 }
458
459 err = dma_map_sg(dd->dev, dd->out_sg, 1,
460 DMA_FROM_DEVICE);
461 if (!err) {
462 dev_err(dd->dev, "dma_map_sg() error\n");
463 dma_unmap_sg(dd->dev, dd->in_sg, 1,
464 DMA_TO_DEVICE);
465 return -EINVAL;
466 }
467
468 addr_in = sg_dma_address(dd->in_sg);
469 addr_out = sg_dma_address(dd->out_sg);
470
471 dd->flags |= AES_FLAGS_FAST;
472
473 } else {
Leilei Zhao289b2622015-04-07 17:45:10 +0800474 dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in,
475 dd->dma_size, DMA_TO_DEVICE);
476
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100477 /* use cache buffers */
478 count = atmel_aes_sg_copy(&dd->in_sg, &dd->in_offset,
479 dd->buf_in, dd->buflen, dd->total, 0);
480
481 addr_in = dd->dma_addr_in;
482 addr_out = dd->dma_addr_out;
483
484 dd->flags &= ~AES_FLAGS_FAST;
485 }
486
487 dd->total -= count;
488
489 err = atmel_aes_crypt_dma(dd, addr_in, addr_out, count);
490
491 if (err && (dd->flags & AES_FLAGS_FAST)) {
492 dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
493 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
494 }
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200495
496 return err;
497}
498
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100499static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
500 const u32 *iv)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200501{
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200502 u32 valcr = 0, valmr = 0;
503
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200504 /* MR register must be set before IV registers */
505 if (dd->ctx->keylen == AES_KEYSIZE_128)
506 valmr |= AES_MR_KEYSIZE_128;
507 else if (dd->ctx->keylen == AES_KEYSIZE_192)
508 valmr |= AES_MR_KEYSIZE_192;
509 else
510 valmr |= AES_MR_KEYSIZE_256;
511
512 if (dd->flags & AES_FLAGS_CBC) {
513 valmr |= AES_MR_OPMOD_CBC;
514 } else if (dd->flags & AES_FLAGS_CFB) {
515 valmr |= AES_MR_OPMOD_CFB;
516 if (dd->flags & AES_FLAGS_CFB8)
517 valmr |= AES_MR_CFBS_8b;
518 else if (dd->flags & AES_FLAGS_CFB16)
519 valmr |= AES_MR_CFBS_16b;
520 else if (dd->flags & AES_FLAGS_CFB32)
521 valmr |= AES_MR_CFBS_32b;
522 else if (dd->flags & AES_FLAGS_CFB64)
523 valmr |= AES_MR_CFBS_64b;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100524 else if (dd->flags & AES_FLAGS_CFB128)
525 valmr |= AES_MR_CFBS_128b;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200526 } else if (dd->flags & AES_FLAGS_OFB) {
527 valmr |= AES_MR_OPMOD_OFB;
528 } else if (dd->flags & AES_FLAGS_CTR) {
529 valmr |= AES_MR_OPMOD_CTR;
530 } else {
531 valmr |= AES_MR_OPMOD_ECB;
532 }
533
534 if (dd->flags & AES_FLAGS_ENCRYPT)
535 valmr |= AES_MR_CYPHER_ENC;
536
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100537 if (use_dma) {
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200538 valmr |= AES_MR_SMOD_IDATAR0;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100539 if (dd->caps.has_dualbuff)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200540 valmr |= AES_MR_DUALBUFF;
541 } else {
542 valmr |= AES_MR_SMOD_AUTO;
543 }
544
545 atmel_aes_write(dd, AES_CR, valcr);
546 atmel_aes_write(dd, AES_MR, valmr);
547
548 atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
549 dd->ctx->keylen >> 2);
550
551 if (((dd->flags & AES_FLAGS_CBC) || (dd->flags & AES_FLAGS_CFB) ||
552 (dd->flags & AES_FLAGS_OFB) || (dd->flags & AES_FLAGS_CTR)) &&
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100553 iv) {
554 atmel_aes_write_n(dd, AES_IVR(0), iv, 4);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200555 }
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200556}
557
558static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
559 struct ablkcipher_request *req)
560{
561 struct crypto_async_request *async_req, *backlog;
562 struct atmel_aes_ctx *ctx;
563 struct atmel_aes_reqctx *rctx;
564 unsigned long flags;
565 int err, ret = 0;
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100566 bool use_dma;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200567
568 spin_lock_irqsave(&dd->lock, flags);
569 if (req)
570 ret = ablkcipher_enqueue_request(&dd->queue, req);
571 if (dd->flags & AES_FLAGS_BUSY) {
572 spin_unlock_irqrestore(&dd->lock, flags);
573 return ret;
574 }
575 backlog = crypto_get_backlog(&dd->queue);
576 async_req = crypto_dequeue_request(&dd->queue);
577 if (async_req)
578 dd->flags |= AES_FLAGS_BUSY;
579 spin_unlock_irqrestore(&dd->lock, flags);
580
581 if (!async_req)
582 return ret;
583
584 if (backlog)
585 backlog->complete(backlog, -EINPROGRESS);
586
587 req = ablkcipher_request_cast(async_req);
588
589 /* assign new request to device */
590 dd->req = req;
591 dd->total = req->nbytes;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100592 dd->in_offset = 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200593 dd->in_sg = req->src;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100594 dd->out_offset = 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200595 dd->out_sg = req->dst;
596
597 rctx = ablkcipher_request_ctx(req);
598 ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
599 rctx->mode &= AES_FLAGS_MODE_MASK;
600 dd->flags = (dd->flags & ~AES_FLAGS_MODE_MASK) | rctx->mode;
601 dd->ctx = ctx;
602 ctx->dd = dd;
603
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100604 err = atmel_aes_hw_init(dd);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200605 if (!err) {
Cyrille Pitchencdfab4a2015-12-17 17:48:38 +0100606 use_dma = (dd->total > ATMEL_AES_DMA_THRESHOLD);
607 atmel_aes_write_ctrl(dd, use_dma, req->info);
608 if (use_dma)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200609 err = atmel_aes_crypt_dma_start(dd);
610 else
611 err = atmel_aes_crypt_cpu_start(dd);
612 }
613 if (err) {
614 /* aes_task will not finish it, so do it here */
615 atmel_aes_finish_req(dd, err);
616 tasklet_schedule(&dd->queue_task);
617 }
618
619 return ret;
620}
621
622static int atmel_aes_crypt_dma_stop(struct atmel_aes_dev *dd)
623{
624 int err = -EINVAL;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100625 size_t count;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200626
627 if (dd->flags & AES_FLAGS_DMA) {
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200628 err = 0;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100629 if (dd->flags & AES_FLAGS_FAST) {
630 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
631 dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
632 } else {
Leilei Zhao9cd22322015-04-07 17:45:11 +0800633 dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out,
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100634 dd->dma_size, DMA_FROM_DEVICE);
635
636 /* copy data */
637 count = atmel_aes_sg_copy(&dd->out_sg, &dd->out_offset,
638 dd->buf_out, dd->buflen, dd->dma_size, 1);
639 if (count != dd->dma_size) {
640 err = -EINVAL;
Arnd Bergmann20ecae72015-11-17 10:22:06 +0100641 pr_err("not all data converted: %zu\n", count);
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100642 }
643 }
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200644 }
645
646 return err;
647}
648
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100649
650static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
651{
652 int err = -ENOMEM;
653
654 dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, 0);
655 dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, 0);
656 dd->buflen = PAGE_SIZE;
657 dd->buflen &= ~(AES_BLOCK_SIZE - 1);
658
659 if (!dd->buf_in || !dd->buf_out) {
660 dev_err(dd->dev, "unable to alloc pages.\n");
661 goto err_alloc;
662 }
663
664 /* MAP here */
665 dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
666 dd->buflen, DMA_TO_DEVICE);
667 if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
Arnd Bergmann20ecae72015-11-17 10:22:06 +0100668 dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen);
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100669 err = -EINVAL;
670 goto err_map_in;
671 }
672
673 dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
674 dd->buflen, DMA_FROM_DEVICE);
675 if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
Arnd Bergmann20ecae72015-11-17 10:22:06 +0100676 dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen);
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100677 err = -EINVAL;
678 goto err_map_out;
679 }
680
681 return 0;
682
683err_map_out:
684 dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
685 DMA_TO_DEVICE);
686err_map_in:
Christophe Jaillet088f6282015-01-20 08:15:52 +0100687err_alloc:
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100688 free_page((unsigned long)dd->buf_out);
689 free_page((unsigned long)dd->buf_in);
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100690 if (err)
691 pr_err("error: %d\n", err);
692 return err;
693}
694
695static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd)
696{
697 dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
698 DMA_FROM_DEVICE);
699 dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen,
700 DMA_TO_DEVICE);
701 free_page((unsigned long)dd->buf_out);
702 free_page((unsigned long)dd->buf_in);
703}
704
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200705static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
706{
707 struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(
708 crypto_ablkcipher_reqtfm(req));
709 struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
710 struct atmel_aes_dev *dd;
711
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100712 if (mode & AES_FLAGS_CFB8) {
713 if (!IS_ALIGNED(req->nbytes, CFB8_BLOCK_SIZE)) {
714 pr_err("request size is not exact amount of CFB8 blocks\n");
715 return -EINVAL;
716 }
717 ctx->block_size = CFB8_BLOCK_SIZE;
718 } else if (mode & AES_FLAGS_CFB16) {
719 if (!IS_ALIGNED(req->nbytes, CFB16_BLOCK_SIZE)) {
720 pr_err("request size is not exact amount of CFB16 blocks\n");
721 return -EINVAL;
722 }
723 ctx->block_size = CFB16_BLOCK_SIZE;
724 } else if (mode & AES_FLAGS_CFB32) {
725 if (!IS_ALIGNED(req->nbytes, CFB32_BLOCK_SIZE)) {
726 pr_err("request size is not exact amount of CFB32 blocks\n");
727 return -EINVAL;
728 }
729 ctx->block_size = CFB32_BLOCK_SIZE;
Leilei Zhao9f849512014-04-22 15:23:24 +0800730 } else if (mode & AES_FLAGS_CFB64) {
731 if (!IS_ALIGNED(req->nbytes, CFB64_BLOCK_SIZE)) {
732 pr_err("request size is not exact amount of CFB64 blocks\n");
733 return -EINVAL;
734 }
735 ctx->block_size = CFB64_BLOCK_SIZE;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100736 } else {
737 if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
738 pr_err("request size is not exact amount of AES blocks\n");
739 return -EINVAL;
740 }
741 ctx->block_size = AES_BLOCK_SIZE;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200742 }
743
744 dd = atmel_aes_find_dev(ctx);
745 if (!dd)
746 return -ENODEV;
747
748 rctx->mode = mode;
749
750 return atmel_aes_handle_queue(dd, req);
751}
752
753static bool atmel_aes_filter(struct dma_chan *chan, void *slave)
754{
755 struct at_dma_slave *sl = slave;
756
757 if (sl && sl->dma_dev == chan->device->dev) {
758 chan->private = sl;
759 return true;
760 } else {
761 return false;
762 }
763}
764
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100765static int atmel_aes_dma_init(struct atmel_aes_dev *dd,
766 struct crypto_platform_data *pdata)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200767{
768 int err = -ENOMEM;
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200769 dma_cap_mask_t mask;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200770
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200771 dma_cap_zero(mask);
772 dma_cap_set(DMA_SLAVE, mask);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200773
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200774 /* Try to grab 2 DMA channels */
775 dd->dma_lch_in.chan = dma_request_slave_channel_compat(mask,
776 atmel_aes_filter, &pdata->dma_slave->rxdata, dd->dev, "tx");
777 if (!dd->dma_lch_in.chan)
778 goto err_dma_in;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200779
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200780 dd->dma_lch_in.dma_conf.direction = DMA_MEM_TO_DEV;
781 dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base +
782 AES_IDATAR(0);
783 dd->dma_lch_in.dma_conf.src_maxburst = dd->caps.max_burst_size;
784 dd->dma_lch_in.dma_conf.src_addr_width =
785 DMA_SLAVE_BUSWIDTH_4_BYTES;
786 dd->dma_lch_in.dma_conf.dst_maxburst = dd->caps.max_burst_size;
787 dd->dma_lch_in.dma_conf.dst_addr_width =
788 DMA_SLAVE_BUSWIDTH_4_BYTES;
789 dd->dma_lch_in.dma_conf.device_fc = false;
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100790
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200791 dd->dma_lch_out.chan = dma_request_slave_channel_compat(mask,
792 atmel_aes_filter, &pdata->dma_slave->txdata, dd->dev, "rx");
793 if (!dd->dma_lch_out.chan)
794 goto err_dma_out;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200795
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200796 dd->dma_lch_out.dma_conf.direction = DMA_DEV_TO_MEM;
797 dd->dma_lch_out.dma_conf.src_addr = dd->phys_base +
798 AES_ODATAR(0);
799 dd->dma_lch_out.dma_conf.src_maxburst = dd->caps.max_burst_size;
800 dd->dma_lch_out.dma_conf.src_addr_width =
801 DMA_SLAVE_BUSWIDTH_4_BYTES;
802 dd->dma_lch_out.dma_conf.dst_maxburst = dd->caps.max_burst_size;
803 dd->dma_lch_out.dma_conf.dst_addr_width =
804 DMA_SLAVE_BUSWIDTH_4_BYTES;
805 dd->dma_lch_out.dma_conf.device_fc = false;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200806
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200807 return 0;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200808
809err_dma_out:
810 dma_release_channel(dd->dma_lch_in.chan);
811err_dma_in:
Nicolas Ferrebe943c72013-10-14 17:52:38 +0200812 dev_warn(dd->dev, "no DMA channel available\n");
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200813 return err;
814}
815
816static void atmel_aes_dma_cleanup(struct atmel_aes_dev *dd)
817{
818 dma_release_channel(dd->dma_lch_in.chan);
819 dma_release_channel(dd->dma_lch_out.chan);
820}
821
822static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
823 unsigned int keylen)
824{
825 struct atmel_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
826
827 if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
828 keylen != AES_KEYSIZE_256) {
829 crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
830 return -EINVAL;
831 }
832
833 memcpy(ctx->key, key, keylen);
834 ctx->keylen = keylen;
835
836 return 0;
837}
838
839static int atmel_aes_ecb_encrypt(struct ablkcipher_request *req)
840{
841 return atmel_aes_crypt(req,
842 AES_FLAGS_ENCRYPT);
843}
844
845static int atmel_aes_ecb_decrypt(struct ablkcipher_request *req)
846{
847 return atmel_aes_crypt(req,
848 0);
849}
850
851static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req)
852{
853 return atmel_aes_crypt(req,
854 AES_FLAGS_ENCRYPT | AES_FLAGS_CBC);
855}
856
857static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req)
858{
859 return atmel_aes_crypt(req,
860 AES_FLAGS_CBC);
861}
862
863static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req)
864{
865 return atmel_aes_crypt(req,
866 AES_FLAGS_ENCRYPT | AES_FLAGS_OFB);
867}
868
869static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
870{
871 return atmel_aes_crypt(req,
872 AES_FLAGS_OFB);
873}
874
875static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
876{
877 return atmel_aes_crypt(req,
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100878 AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB128);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200879}
880
881static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req)
882{
883 return atmel_aes_crypt(req,
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100884 AES_FLAGS_CFB | AES_FLAGS_CFB128);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200885}
886
887static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req)
888{
889 return atmel_aes_crypt(req,
890 AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB64);
891}
892
893static int atmel_aes_cfb64_decrypt(struct ablkcipher_request *req)
894{
895 return atmel_aes_crypt(req,
896 AES_FLAGS_CFB | AES_FLAGS_CFB64);
897}
898
899static int atmel_aes_cfb32_encrypt(struct ablkcipher_request *req)
900{
901 return atmel_aes_crypt(req,
902 AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB32);
903}
904
905static int atmel_aes_cfb32_decrypt(struct ablkcipher_request *req)
906{
907 return atmel_aes_crypt(req,
908 AES_FLAGS_CFB | AES_FLAGS_CFB32);
909}
910
911static int atmel_aes_cfb16_encrypt(struct ablkcipher_request *req)
912{
913 return atmel_aes_crypt(req,
914 AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB16);
915}
916
917static int atmel_aes_cfb16_decrypt(struct ablkcipher_request *req)
918{
919 return atmel_aes_crypt(req,
920 AES_FLAGS_CFB | AES_FLAGS_CFB16);
921}
922
923static int atmel_aes_cfb8_encrypt(struct ablkcipher_request *req)
924{
925 return atmel_aes_crypt(req,
926 AES_FLAGS_ENCRYPT | AES_FLAGS_CFB | AES_FLAGS_CFB8);
927}
928
929static int atmel_aes_cfb8_decrypt(struct ablkcipher_request *req)
930{
931 return atmel_aes_crypt(req,
932 AES_FLAGS_CFB | AES_FLAGS_CFB8);
933}
934
935static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req)
936{
937 return atmel_aes_crypt(req,
938 AES_FLAGS_ENCRYPT | AES_FLAGS_CTR);
939}
940
941static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req)
942{
943 return atmel_aes_crypt(req,
944 AES_FLAGS_CTR);
945}
946
947static int atmel_aes_cra_init(struct crypto_tfm *tfm)
948{
949 tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx);
950
951 return 0;
952}
953
954static void atmel_aes_cra_exit(struct crypto_tfm *tfm)
955{
956}
957
958static struct crypto_alg aes_algs[] = {
959{
960 .cra_name = "ecb(aes)",
961 .cra_driver_name = "atmel-ecb-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +0100962 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200963 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
964 .cra_blocksize = AES_BLOCK_SIZE,
965 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100966 .cra_alignmask = 0xf,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200967 .cra_type = &crypto_ablkcipher_type,
968 .cra_module = THIS_MODULE,
969 .cra_init = atmel_aes_cra_init,
970 .cra_exit = atmel_aes_cra_exit,
971 .cra_u.ablkcipher = {
972 .min_keysize = AES_MIN_KEY_SIZE,
973 .max_keysize = AES_MAX_KEY_SIZE,
974 .setkey = atmel_aes_setkey,
975 .encrypt = atmel_aes_ecb_encrypt,
976 .decrypt = atmel_aes_ecb_decrypt,
977 }
978},
979{
980 .cra_name = "cbc(aes)",
981 .cra_driver_name = "atmel-cbc-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +0100982 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200983 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
984 .cra_blocksize = AES_BLOCK_SIZE,
985 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +0100986 .cra_alignmask = 0xf,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +0200987 .cra_type = &crypto_ablkcipher_type,
988 .cra_module = THIS_MODULE,
989 .cra_init = atmel_aes_cra_init,
990 .cra_exit = atmel_aes_cra_exit,
991 .cra_u.ablkcipher = {
992 .min_keysize = AES_MIN_KEY_SIZE,
993 .max_keysize = AES_MAX_KEY_SIZE,
994 .ivsize = AES_BLOCK_SIZE,
995 .setkey = atmel_aes_setkey,
996 .encrypt = atmel_aes_cbc_encrypt,
997 .decrypt = atmel_aes_cbc_decrypt,
998 }
999},
1000{
1001 .cra_name = "ofb(aes)",
1002 .cra_driver_name = "atmel-ofb-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001003 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001004 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1005 .cra_blocksize = AES_BLOCK_SIZE,
1006 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001007 .cra_alignmask = 0xf,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001008 .cra_type = &crypto_ablkcipher_type,
1009 .cra_module = THIS_MODULE,
1010 .cra_init = atmel_aes_cra_init,
1011 .cra_exit = atmel_aes_cra_exit,
1012 .cra_u.ablkcipher = {
1013 .min_keysize = AES_MIN_KEY_SIZE,
1014 .max_keysize = AES_MAX_KEY_SIZE,
1015 .ivsize = AES_BLOCK_SIZE,
1016 .setkey = atmel_aes_setkey,
1017 .encrypt = atmel_aes_ofb_encrypt,
1018 .decrypt = atmel_aes_ofb_decrypt,
1019 }
1020},
1021{
1022 .cra_name = "cfb(aes)",
1023 .cra_driver_name = "atmel-cfb-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001024 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001025 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1026 .cra_blocksize = AES_BLOCK_SIZE,
1027 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001028 .cra_alignmask = 0xf,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001029 .cra_type = &crypto_ablkcipher_type,
1030 .cra_module = THIS_MODULE,
1031 .cra_init = atmel_aes_cra_init,
1032 .cra_exit = atmel_aes_cra_exit,
1033 .cra_u.ablkcipher = {
1034 .min_keysize = AES_MIN_KEY_SIZE,
1035 .max_keysize = AES_MAX_KEY_SIZE,
1036 .ivsize = AES_BLOCK_SIZE,
1037 .setkey = atmel_aes_setkey,
1038 .encrypt = atmel_aes_cfb_encrypt,
1039 .decrypt = atmel_aes_cfb_decrypt,
1040 }
1041},
1042{
1043 .cra_name = "cfb32(aes)",
1044 .cra_driver_name = "atmel-cfb32-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001045 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001046 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1047 .cra_blocksize = CFB32_BLOCK_SIZE,
1048 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001049 .cra_alignmask = 0x3,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001050 .cra_type = &crypto_ablkcipher_type,
1051 .cra_module = THIS_MODULE,
1052 .cra_init = atmel_aes_cra_init,
1053 .cra_exit = atmel_aes_cra_exit,
1054 .cra_u.ablkcipher = {
1055 .min_keysize = AES_MIN_KEY_SIZE,
1056 .max_keysize = AES_MAX_KEY_SIZE,
1057 .ivsize = AES_BLOCK_SIZE,
1058 .setkey = atmel_aes_setkey,
1059 .encrypt = atmel_aes_cfb32_encrypt,
1060 .decrypt = atmel_aes_cfb32_decrypt,
1061 }
1062},
1063{
1064 .cra_name = "cfb16(aes)",
1065 .cra_driver_name = "atmel-cfb16-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001066 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001067 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1068 .cra_blocksize = CFB16_BLOCK_SIZE,
1069 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001070 .cra_alignmask = 0x1,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001071 .cra_type = &crypto_ablkcipher_type,
1072 .cra_module = THIS_MODULE,
1073 .cra_init = atmel_aes_cra_init,
1074 .cra_exit = atmel_aes_cra_exit,
1075 .cra_u.ablkcipher = {
1076 .min_keysize = AES_MIN_KEY_SIZE,
1077 .max_keysize = AES_MAX_KEY_SIZE,
1078 .ivsize = AES_BLOCK_SIZE,
1079 .setkey = atmel_aes_setkey,
1080 .encrypt = atmel_aes_cfb16_encrypt,
1081 .decrypt = atmel_aes_cfb16_decrypt,
1082 }
1083},
1084{
1085 .cra_name = "cfb8(aes)",
1086 .cra_driver_name = "atmel-cfb8-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001087 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001088 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
Leilei Zhaoe5d8c962014-04-22 15:23:23 +08001089 .cra_blocksize = CFB8_BLOCK_SIZE,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001090 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
1091 .cra_alignmask = 0x0,
1092 .cra_type = &crypto_ablkcipher_type,
1093 .cra_module = THIS_MODULE,
1094 .cra_init = atmel_aes_cra_init,
1095 .cra_exit = atmel_aes_cra_exit,
1096 .cra_u.ablkcipher = {
1097 .min_keysize = AES_MIN_KEY_SIZE,
1098 .max_keysize = AES_MAX_KEY_SIZE,
1099 .ivsize = AES_BLOCK_SIZE,
1100 .setkey = atmel_aes_setkey,
1101 .encrypt = atmel_aes_cfb8_encrypt,
1102 .decrypt = atmel_aes_cfb8_decrypt,
1103 }
1104},
1105{
1106 .cra_name = "ctr(aes)",
1107 .cra_driver_name = "atmel-ctr-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001108 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001109 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1110 .cra_blocksize = AES_BLOCK_SIZE,
1111 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001112 .cra_alignmask = 0xf,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001113 .cra_type = &crypto_ablkcipher_type,
1114 .cra_module = THIS_MODULE,
1115 .cra_init = atmel_aes_cra_init,
1116 .cra_exit = atmel_aes_cra_exit,
1117 .cra_u.ablkcipher = {
1118 .min_keysize = AES_MIN_KEY_SIZE,
1119 .max_keysize = AES_MAX_KEY_SIZE,
1120 .ivsize = AES_BLOCK_SIZE,
1121 .setkey = atmel_aes_setkey,
1122 .encrypt = atmel_aes_ctr_encrypt,
1123 .decrypt = atmel_aes_ctr_decrypt,
1124 }
1125},
1126};
1127
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001128static struct crypto_alg aes_cfb64_alg = {
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001129 .cra_name = "cfb64(aes)",
1130 .cra_driver_name = "atmel-cfb64-aes",
Cyrille Pitchen88efd9a2015-12-17 17:48:34 +01001131 .cra_priority = ATMEL_AES_PRIORITY,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001132 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1133 .cra_blocksize = CFB64_BLOCK_SIZE,
1134 .cra_ctxsize = sizeof(struct atmel_aes_ctx),
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001135 .cra_alignmask = 0x7,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001136 .cra_type = &crypto_ablkcipher_type,
1137 .cra_module = THIS_MODULE,
1138 .cra_init = atmel_aes_cra_init,
1139 .cra_exit = atmel_aes_cra_exit,
1140 .cra_u.ablkcipher = {
1141 .min_keysize = AES_MIN_KEY_SIZE,
1142 .max_keysize = AES_MAX_KEY_SIZE,
1143 .ivsize = AES_BLOCK_SIZE,
1144 .setkey = atmel_aes_setkey,
1145 .encrypt = atmel_aes_cfb64_encrypt,
1146 .decrypt = atmel_aes_cfb64_decrypt,
1147 }
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001148};
1149
1150static void atmel_aes_queue_task(unsigned long data)
1151{
1152 struct atmel_aes_dev *dd = (struct atmel_aes_dev *)data;
1153
1154 atmel_aes_handle_queue(dd, NULL);
1155}
1156
1157static void atmel_aes_done_task(unsigned long data)
1158{
1159 struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data;
1160 int err;
1161
1162 if (!(dd->flags & AES_FLAGS_DMA)) {
1163 atmel_aes_read_n(dd, AES_ODATAR(0), (u32 *) dd->buf_out,
1164 dd->bufcnt >> 2);
1165
1166 if (sg_copy_from_buffer(dd->out_sg, dd->nb_out_sg,
1167 dd->buf_out, dd->bufcnt))
1168 err = 0;
1169 else
1170 err = -EINVAL;
1171
1172 goto cpu_end;
1173 }
1174
1175 err = atmel_aes_crypt_dma_stop(dd);
1176
1177 err = dd->err ? : err;
1178
1179 if (dd->total && !err) {
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001180 if (dd->flags & AES_FLAGS_FAST) {
1181 dd->in_sg = sg_next(dd->in_sg);
1182 dd->out_sg = sg_next(dd->out_sg);
1183 if (!dd->in_sg || !dd->out_sg)
1184 err = -EINVAL;
1185 }
1186 if (!err)
1187 err = atmel_aes_crypt_dma_start(dd);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001188 if (!err)
1189 return; /* DMA started. Not fininishing. */
1190 }
1191
1192cpu_end:
1193 atmel_aes_finish_req(dd, err);
1194 atmel_aes_handle_queue(dd, NULL);
1195}
1196
1197static irqreturn_t atmel_aes_irq(int irq, void *dev_id)
1198{
1199 struct atmel_aes_dev *aes_dd = dev_id;
1200 u32 reg;
1201
1202 reg = atmel_aes_read(aes_dd, AES_ISR);
1203 if (reg & atmel_aes_read(aes_dd, AES_IMR)) {
1204 atmel_aes_write(aes_dd, AES_IDR, reg);
1205 if (AES_FLAGS_BUSY & aes_dd->flags)
1206 tasklet_schedule(&aes_dd->done_task);
1207 else
1208 dev_warn(aes_dd->dev, "AES interrupt when no active requests.\n");
1209 return IRQ_HANDLED;
1210 }
1211
1212 return IRQ_NONE;
1213}
1214
1215static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
1216{
1217 int i;
1218
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001219 if (dd->caps.has_cfb64)
1220 crypto_unregister_alg(&aes_cfb64_alg);
Cyrille Pitchen924a8bc2015-12-17 17:48:35 +01001221
1222 for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
1223 crypto_unregister_alg(&aes_algs[i]);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001224}
1225
1226static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
1227{
1228 int err, i, j;
1229
1230 for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001231 err = crypto_register_alg(&aes_algs[i]);
1232 if (err)
1233 goto err_aes_algs;
1234 }
1235
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001236 if (dd->caps.has_cfb64) {
1237 err = crypto_register_alg(&aes_cfb64_alg);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001238 if (err)
1239 goto err_aes_cfb64_alg;
1240 }
1241
1242 return 0;
1243
1244err_aes_cfb64_alg:
1245 i = ARRAY_SIZE(aes_algs);
1246err_aes_algs:
1247 for (j = 0; j < i; j++)
1248 crypto_unregister_alg(&aes_algs[j]);
1249
1250 return err;
1251}
1252
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001253static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
1254{
1255 dd->caps.has_dualbuff = 0;
1256 dd->caps.has_cfb64 = 0;
1257 dd->caps.max_burst_size = 1;
1258
1259 /* keep only major version number */
1260 switch (dd->hw_version & 0xff0) {
Leilei Zhao973e2092015-12-17 17:48:32 +01001261 case 0x500:
1262 dd->caps.has_dualbuff = 1;
1263 dd->caps.has_cfb64 = 1;
1264 dd->caps.max_burst_size = 4;
1265 break;
Leilei Zhaocf1f0d12015-04-07 17:45:02 +08001266 case 0x200:
1267 dd->caps.has_dualbuff = 1;
1268 dd->caps.has_cfb64 = 1;
1269 dd->caps.max_burst_size = 4;
1270 break;
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001271 case 0x130:
1272 dd->caps.has_dualbuff = 1;
1273 dd->caps.has_cfb64 = 1;
1274 dd->caps.max_burst_size = 4;
1275 break;
1276 case 0x120:
1277 break;
1278 default:
1279 dev_warn(dd->dev,
1280 "Unmanaged aes version, set minimum capabilities\n");
1281 break;
1282 }
1283}
1284
Nicolas Ferrebe943c72013-10-14 17:52:38 +02001285#if defined(CONFIG_OF)
1286static const struct of_device_id atmel_aes_dt_ids[] = {
1287 { .compatible = "atmel,at91sam9g46-aes" },
1288 { /* sentinel */ }
1289};
1290MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids);
1291
1292static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev)
1293{
1294 struct device_node *np = pdev->dev.of_node;
1295 struct crypto_platform_data *pdata;
1296
1297 if (!np) {
1298 dev_err(&pdev->dev, "device node not found\n");
1299 return ERR_PTR(-EINVAL);
1300 }
1301
1302 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1303 if (!pdata) {
1304 dev_err(&pdev->dev, "could not allocate memory for pdata\n");
1305 return ERR_PTR(-ENOMEM);
1306 }
1307
1308 pdata->dma_slave = devm_kzalloc(&pdev->dev,
1309 sizeof(*(pdata->dma_slave)),
1310 GFP_KERNEL);
1311 if (!pdata->dma_slave) {
1312 dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
1313 devm_kfree(&pdev->dev, pdata);
1314 return ERR_PTR(-ENOMEM);
1315 }
1316
1317 return pdata;
1318}
1319#else
1320static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev)
1321{
1322 return ERR_PTR(-EINVAL);
1323}
1324#endif
1325
Greg Kroah-Hartman49cfe4d2012-12-21 13:14:09 -08001326static int atmel_aes_probe(struct platform_device *pdev)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001327{
1328 struct atmel_aes_dev *aes_dd;
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001329 struct crypto_platform_data *pdata;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001330 struct device *dev = &pdev->dev;
1331 struct resource *aes_res;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001332 int err;
1333
1334 pdata = pdev->dev.platform_data;
1335 if (!pdata) {
Nicolas Ferrebe943c72013-10-14 17:52:38 +02001336 pdata = atmel_aes_of_init(pdev);
1337 if (IS_ERR(pdata)) {
1338 err = PTR_ERR(pdata);
1339 goto aes_dd_err;
1340 }
1341 }
1342
1343 if (!pdata->dma_slave) {
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001344 err = -ENXIO;
1345 goto aes_dd_err;
1346 }
1347
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001348 aes_dd = devm_kzalloc(&pdev->dev, sizeof(*aes_dd), GFP_KERNEL);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001349 if (aes_dd == NULL) {
1350 dev_err(dev, "unable to alloc data struct.\n");
1351 err = -ENOMEM;
1352 goto aes_dd_err;
1353 }
1354
1355 aes_dd->dev = dev;
1356
1357 platform_set_drvdata(pdev, aes_dd);
1358
1359 INIT_LIST_HEAD(&aes_dd->list);
Leilei Zhao8a10eb82015-04-07 17:45:09 +08001360 spin_lock_init(&aes_dd->lock);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001361
1362 tasklet_init(&aes_dd->done_task, atmel_aes_done_task,
1363 (unsigned long)aes_dd);
1364 tasklet_init(&aes_dd->queue_task, atmel_aes_queue_task,
1365 (unsigned long)aes_dd);
1366
1367 crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH);
1368
1369 aes_dd->irq = -1;
1370
1371 /* Get the base address */
1372 aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1373 if (!aes_res) {
1374 dev_err(dev, "no MEM resource info\n");
1375 err = -ENODEV;
1376 goto res_err;
1377 }
1378 aes_dd->phys_base = aes_res->start;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001379
1380 /* Get the IRQ */
1381 aes_dd->irq = platform_get_irq(pdev, 0);
1382 if (aes_dd->irq < 0) {
1383 dev_err(dev, "no IRQ resource info\n");
1384 err = aes_dd->irq;
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001385 goto res_err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001386 }
1387
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001388 err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq,
1389 IRQF_SHARED, "atmel-aes", aes_dd);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001390 if (err) {
1391 dev_err(dev, "unable to request aes irq.\n");
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001392 goto res_err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001393 }
1394
1395 /* Initializing the clock */
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001396 aes_dd->iclk = devm_clk_get(&pdev->dev, "aes_clk");
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001397 if (IS_ERR(aes_dd->iclk)) {
Colin Ian Kingbe208352015-02-28 20:40:10 +00001398 dev_err(dev, "clock initialization failed.\n");
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001399 err = PTR_ERR(aes_dd->iclk);
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001400 goto res_err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001401 }
1402
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001403 aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001404 if (!aes_dd->io_base) {
1405 dev_err(dev, "can't ioremap\n");
1406 err = -ENOMEM;
LABBE Corentinb0e8b342015-10-12 19:47:03 +02001407 goto res_err;
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001408 }
1409
Cyrille Pitchenaab0a392015-12-17 17:48:37 +01001410 err = atmel_aes_hw_version_init(aes_dd);
1411 if (err)
1412 goto res_err;
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001413
1414 atmel_aes_get_cap(aes_dd);
1415
1416 err = atmel_aes_buff_init(aes_dd);
1417 if (err)
1418 goto err_aes_buff;
1419
1420 err = atmel_aes_dma_init(aes_dd, pdata);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001421 if (err)
1422 goto err_aes_dma;
1423
1424 spin_lock(&atmel_aes.lock);
1425 list_add_tail(&aes_dd->list, &atmel_aes.dev_list);
1426 spin_unlock(&atmel_aes.lock);
1427
1428 err = atmel_aes_register_algs(aes_dd);
1429 if (err)
1430 goto err_algs;
1431
Nicolas Ferrebe943c72013-10-14 17:52:38 +02001432 dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n",
1433 dma_chan_name(aes_dd->dma_lch_in.chan),
1434 dma_chan_name(aes_dd->dma_lch_out.chan));
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001435
1436 return 0;
1437
1438err_algs:
1439 spin_lock(&atmel_aes.lock);
1440 list_del(&aes_dd->list);
1441 spin_unlock(&atmel_aes.lock);
1442 atmel_aes_dma_cleanup(aes_dd);
1443err_aes_dma:
Nicolas Royercadc4ab2013-02-20 17:10:24 +01001444 atmel_aes_buff_cleanup(aes_dd);
1445err_aes_buff:
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001446res_err:
1447 tasklet_kill(&aes_dd->done_task);
1448 tasklet_kill(&aes_dd->queue_task);
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001449aes_dd_err:
1450 dev_err(dev, "initialization failed.\n");
1451
1452 return err;
1453}
1454
Greg Kroah-Hartman49cfe4d2012-12-21 13:14:09 -08001455static int atmel_aes_remove(struct platform_device *pdev)
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001456{
1457 static struct atmel_aes_dev *aes_dd;
1458
1459 aes_dd = platform_get_drvdata(pdev);
1460 if (!aes_dd)
1461 return -ENODEV;
1462 spin_lock(&atmel_aes.lock);
1463 list_del(&aes_dd->list);
1464 spin_unlock(&atmel_aes.lock);
1465
1466 atmel_aes_unregister_algs(aes_dd);
1467
1468 tasklet_kill(&aes_dd->done_task);
1469 tasklet_kill(&aes_dd->queue_task);
1470
1471 atmel_aes_dma_cleanup(aes_dd);
1472
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001473 return 0;
1474}
1475
1476static struct platform_driver atmel_aes_driver = {
1477 .probe = atmel_aes_probe,
Greg Kroah-Hartman49cfe4d2012-12-21 13:14:09 -08001478 .remove = atmel_aes_remove,
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001479 .driver = {
1480 .name = "atmel_aes",
Nicolas Ferrebe943c72013-10-14 17:52:38 +02001481 .of_match_table = of_match_ptr(atmel_aes_dt_ids),
Nicolas Royerbd3c7b52012-07-01 19:19:44 +02001482 },
1483};
1484
1485module_platform_driver(atmel_aes_driver);
1486
1487MODULE_DESCRIPTION("Atmel AES hw acceleration support.");
1488MODULE_LICENSE("GPL v2");
1489MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");