xref: /openbmc/linux/drivers/crypto/atmel-aes.c (revision bbe628ed)
1bd3c7b5cSNicolas Royer /*
2bd3c7b5cSNicolas Royer  * Cryptographic API.
3bd3c7b5cSNicolas Royer  *
4bd3c7b5cSNicolas Royer  * Support for ATMEL AES HW acceleration.
5bd3c7b5cSNicolas Royer  *
6bd3c7b5cSNicolas Royer  * Copyright (c) 2012 Eukréa Electromatique - ATMEL
7bd3c7b5cSNicolas Royer  * Author: Nicolas Royer <nicolas@eukrea.com>
8bd3c7b5cSNicolas Royer  *
9bd3c7b5cSNicolas Royer  * This program is free software; you can redistribute it and/or modify
10bd3c7b5cSNicolas Royer  * it under the terms of the GNU General Public License version 2 as published
11bd3c7b5cSNicolas Royer  * by the Free Software Foundation.
12bd3c7b5cSNicolas Royer  *
13bd3c7b5cSNicolas Royer  * Some ideas are from omap-aes.c driver.
14bd3c7b5cSNicolas Royer  */
15bd3c7b5cSNicolas Royer 
16bd3c7b5cSNicolas Royer 
17bd3c7b5cSNicolas Royer #include <linux/kernel.h>
18bd3c7b5cSNicolas Royer #include <linux/module.h>
19bd3c7b5cSNicolas Royer #include <linux/slab.h>
20bd3c7b5cSNicolas Royer #include <linux/err.h>
21bd3c7b5cSNicolas Royer #include <linux/clk.h>
22bd3c7b5cSNicolas Royer #include <linux/io.h>
23bd3c7b5cSNicolas Royer #include <linux/hw_random.h>
24bd3c7b5cSNicolas Royer #include <linux/platform_device.h>
25bd3c7b5cSNicolas Royer 
26bd3c7b5cSNicolas Royer #include <linux/device.h>
27bd3c7b5cSNicolas Royer #include <linux/init.h>
28bd3c7b5cSNicolas Royer #include <linux/errno.h>
29bd3c7b5cSNicolas Royer #include <linux/interrupt.h>
30bd3c7b5cSNicolas Royer #include <linux/irq.h>
31bd3c7b5cSNicolas Royer #include <linux/scatterlist.h>
32bd3c7b5cSNicolas Royer #include <linux/dma-mapping.h>
33be943c7dSNicolas Ferre #include <linux/of_device.h>
34bd3c7b5cSNicolas Royer #include <linux/delay.h>
35bd3c7b5cSNicolas Royer #include <linux/crypto.h>
36bd3c7b5cSNicolas Royer #include <crypto/scatterwalk.h>
37bd3c7b5cSNicolas Royer #include <crypto/algapi.h>
38bd3c7b5cSNicolas Royer #include <crypto/aes.h>
39cadc4ab8SNicolas Royer #include <linux/platform_data/crypto-atmel.h>
40be943c7dSNicolas Ferre #include <dt-bindings/dma/at91.h>
41bd3c7b5cSNicolas Royer #include "atmel-aes-regs.h"
42bd3c7b5cSNicolas Royer 
4388efd9a9SCyrille Pitchen #define ATMEL_AES_PRIORITY	300
4488efd9a9SCyrille Pitchen 
45bbe628edSCyrille Pitchen #define ATMEL_AES_BUFFER_ORDER	2
46bbe628edSCyrille Pitchen #define ATMEL_AES_BUFFER_SIZE	(PAGE_SIZE << ATMEL_AES_BUFFER_ORDER)
47bbe628edSCyrille Pitchen 
48bd3c7b5cSNicolas Royer #define CFB8_BLOCK_SIZE		1
49bd3c7b5cSNicolas Royer #define CFB16_BLOCK_SIZE	2
50bd3c7b5cSNicolas Royer #define CFB32_BLOCK_SIZE	4
51bd3c7b5cSNicolas Royer #define CFB64_BLOCK_SIZE	8
52bd3c7b5cSNicolas Royer 
53bbe628edSCyrille Pitchen #define SIZE_IN_WORDS(x)	((x) >> 2)
54bbe628edSCyrille Pitchen 
55bd3c7b5cSNicolas Royer /* AES flags */
5677dacf5fSCyrille Pitchen /* Reserve bits [18:16] [14:12] [0] for mode (same as for AES_MR) */
5777dacf5fSCyrille Pitchen #define AES_FLAGS_ENCRYPT	AES_MR_CYPHER_ENC
5877dacf5fSCyrille Pitchen #define AES_FLAGS_OPMODE_MASK	(AES_MR_OPMOD_MASK | AES_MR_CFBS_MASK)
5977dacf5fSCyrille Pitchen #define AES_FLAGS_ECB		AES_MR_OPMOD_ECB
6077dacf5fSCyrille Pitchen #define AES_FLAGS_CBC		AES_MR_OPMOD_CBC
6177dacf5fSCyrille Pitchen #define AES_FLAGS_OFB		AES_MR_OPMOD_OFB
6277dacf5fSCyrille Pitchen #define AES_FLAGS_CFB128	(AES_MR_OPMOD_CFB | AES_MR_CFBS_128b)
6377dacf5fSCyrille Pitchen #define AES_FLAGS_CFB64		(AES_MR_OPMOD_CFB | AES_MR_CFBS_64b)
6477dacf5fSCyrille Pitchen #define AES_FLAGS_CFB32		(AES_MR_OPMOD_CFB | AES_MR_CFBS_32b)
6577dacf5fSCyrille Pitchen #define AES_FLAGS_CFB16		(AES_MR_OPMOD_CFB | AES_MR_CFBS_16b)
6677dacf5fSCyrille Pitchen #define AES_FLAGS_CFB8		(AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
6777dacf5fSCyrille Pitchen #define AES_FLAGS_CTR		AES_MR_OPMOD_CTR
68bd3c7b5cSNicolas Royer 
6977dacf5fSCyrille Pitchen #define AES_FLAGS_MODE_MASK	(AES_FLAGS_OPMODE_MASK |	\
7077dacf5fSCyrille Pitchen 				 AES_FLAGS_ENCRYPT)
7177dacf5fSCyrille Pitchen 
7277dacf5fSCyrille Pitchen #define AES_FLAGS_INIT		BIT(2)
7377dacf5fSCyrille Pitchen #define AES_FLAGS_BUSY		BIT(3)
7477dacf5fSCyrille Pitchen 
7577dacf5fSCyrille Pitchen #define AES_FLAGS_PERSISTENT	(AES_FLAGS_INIT | AES_FLAGS_BUSY)
76bd3c7b5cSNicolas Royer 
77cadc4ab8SNicolas Royer #define ATMEL_AES_QUEUE_LENGTH	50
78bd3c7b5cSNicolas Royer 
79bd3c7b5cSNicolas Royer #define ATMEL_AES_DMA_THRESHOLD		16
80bd3c7b5cSNicolas Royer 
81bd3c7b5cSNicolas Royer 
82cadc4ab8SNicolas Royer struct atmel_aes_caps {
83cadc4ab8SNicolas Royer 	bool	has_dualbuff;
84cadc4ab8SNicolas Royer 	bool	has_cfb64;
85cadc4ab8SNicolas Royer 	u32		max_burst_size;
86cadc4ab8SNicolas Royer };
87cadc4ab8SNicolas Royer 
88bd3c7b5cSNicolas Royer struct atmel_aes_dev;
89bd3c7b5cSNicolas Royer 
90ccbf7298SCyrille Pitchen 
91ccbf7298SCyrille Pitchen typedef int (*atmel_aes_fn_t)(struct atmel_aes_dev *);
92ccbf7298SCyrille Pitchen 
93ccbf7298SCyrille Pitchen 
94ccbf7298SCyrille Pitchen struct atmel_aes_base_ctx {
95bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *dd;
96ccbf7298SCyrille Pitchen 	atmel_aes_fn_t	start;
97bd3c7b5cSNicolas Royer 
98bd3c7b5cSNicolas Royer 	int		keylen;
99bd3c7b5cSNicolas Royer 	u32		key[AES_KEYSIZE_256 / sizeof(u32)];
100cadc4ab8SNicolas Royer 
101cadc4ab8SNicolas Royer 	u16		block_size;
102bd3c7b5cSNicolas Royer };
103bd3c7b5cSNicolas Royer 
104ccbf7298SCyrille Pitchen struct atmel_aes_ctx {
105ccbf7298SCyrille Pitchen 	struct atmel_aes_base_ctx	base;
106ccbf7298SCyrille Pitchen };
107ccbf7298SCyrille Pitchen 
108bd3c7b5cSNicolas Royer struct atmel_aes_reqctx {
109bd3c7b5cSNicolas Royer 	unsigned long mode;
110bd3c7b5cSNicolas Royer };
111bd3c7b5cSNicolas Royer 
112bd3c7b5cSNicolas Royer struct atmel_aes_dma {
113bd3c7b5cSNicolas Royer 	struct dma_chan		*chan;
114bbe628edSCyrille Pitchen 	struct scatterlist	*sg;
115bbe628edSCyrille Pitchen 	int			nents;
116bbe628edSCyrille Pitchen 	unsigned int		remainder;
117bbe628edSCyrille Pitchen 	unsigned int		sg_len;
118bd3c7b5cSNicolas Royer };
119bd3c7b5cSNicolas Royer 
120bd3c7b5cSNicolas Royer struct atmel_aes_dev {
121bd3c7b5cSNicolas Royer 	struct list_head	list;
122bd3c7b5cSNicolas Royer 	unsigned long		phys_base;
123bd3c7b5cSNicolas Royer 	void __iomem		*io_base;
124bd3c7b5cSNicolas Royer 
125ccbf7298SCyrille Pitchen 	struct crypto_async_request	*areq;
126ccbf7298SCyrille Pitchen 	struct atmel_aes_base_ctx	*ctx;
127ccbf7298SCyrille Pitchen 
12810f12c1bSCyrille Pitchen 	bool			is_async;
12910f12c1bSCyrille Pitchen 	atmel_aes_fn_t		resume;
130bbe628edSCyrille Pitchen 	atmel_aes_fn_t		cpu_transfer_complete;
13110f12c1bSCyrille Pitchen 
132bd3c7b5cSNicolas Royer 	struct device		*dev;
133bd3c7b5cSNicolas Royer 	struct clk		*iclk;
134bd3c7b5cSNicolas Royer 	int	irq;
135bd3c7b5cSNicolas Royer 
136bd3c7b5cSNicolas Royer 	unsigned long		flags;
137bd3c7b5cSNicolas Royer 
138bd3c7b5cSNicolas Royer 	spinlock_t		lock;
139bd3c7b5cSNicolas Royer 	struct crypto_queue	queue;
140bd3c7b5cSNicolas Royer 
141bd3c7b5cSNicolas Royer 	struct tasklet_struct	done_task;
142bd3c7b5cSNicolas Royer 	struct tasklet_struct	queue_task;
143bd3c7b5cSNicolas Royer 
144bd3c7b5cSNicolas Royer 	size_t			total;
145bbe628edSCyrille Pitchen 	size_t			datalen;
146bbe628edSCyrille Pitchen 	u32			*data;
147bd3c7b5cSNicolas Royer 
148bbe628edSCyrille Pitchen 	struct atmel_aes_dma	src;
149bbe628edSCyrille Pitchen 	struct atmel_aes_dma	dst;
150bd3c7b5cSNicolas Royer 
151cadc4ab8SNicolas Royer 	size_t			buflen;
152bbe628edSCyrille Pitchen 	void			*buf;
153bbe628edSCyrille Pitchen 	struct scatterlist	aligned_sg;
154bbe628edSCyrille Pitchen 	struct scatterlist	*real_dst;
155bd3c7b5cSNicolas Royer 
156cadc4ab8SNicolas Royer 	struct atmel_aes_caps	caps;
157cadc4ab8SNicolas Royer 
158bd3c7b5cSNicolas Royer 	u32	hw_version;
159bd3c7b5cSNicolas Royer };
160bd3c7b5cSNicolas Royer 
161bd3c7b5cSNicolas Royer struct atmel_aes_drv {
162bd3c7b5cSNicolas Royer 	struct list_head	dev_list;
163bd3c7b5cSNicolas Royer 	spinlock_t		lock;
164bd3c7b5cSNicolas Royer };
165bd3c7b5cSNicolas Royer 
166bd3c7b5cSNicolas Royer static struct atmel_aes_drv atmel_aes = {
167bd3c7b5cSNicolas Royer 	.dev_list = LIST_HEAD_INIT(atmel_aes.dev_list),
168bd3c7b5cSNicolas Royer 	.lock = __SPIN_LOCK_UNLOCKED(atmel_aes.lock),
169bd3c7b5cSNicolas Royer };
170bd3c7b5cSNicolas Royer 
171cadc4ab8SNicolas Royer 
172bd3c7b5cSNicolas Royer static inline u32 atmel_aes_read(struct atmel_aes_dev *dd, u32 offset)
173bd3c7b5cSNicolas Royer {
174bd3c7b5cSNicolas Royer 	return readl_relaxed(dd->io_base + offset);
175bd3c7b5cSNicolas Royer }
176bd3c7b5cSNicolas Royer 
177bd3c7b5cSNicolas Royer static inline void atmel_aes_write(struct atmel_aes_dev *dd,
178bd3c7b5cSNicolas Royer 					u32 offset, u32 value)
179bd3c7b5cSNicolas Royer {
180bd3c7b5cSNicolas Royer 	writel_relaxed(value, dd->io_base + offset);
181bd3c7b5cSNicolas Royer }
182bd3c7b5cSNicolas Royer 
183bd3c7b5cSNicolas Royer static void atmel_aes_read_n(struct atmel_aes_dev *dd, u32 offset,
184bd3c7b5cSNicolas Royer 					u32 *value, int count)
185bd3c7b5cSNicolas Royer {
186bd3c7b5cSNicolas Royer 	for (; count--; value++, offset += 4)
187bd3c7b5cSNicolas Royer 		*value = atmel_aes_read(dd, offset);
188bd3c7b5cSNicolas Royer }
189bd3c7b5cSNicolas Royer 
190bd3c7b5cSNicolas Royer static void atmel_aes_write_n(struct atmel_aes_dev *dd, u32 offset,
191c0b28d8cSCyrille Pitchen 			      const u32 *value, int count)
192bd3c7b5cSNicolas Royer {
193bd3c7b5cSNicolas Royer 	for (; count--; value++, offset += 4)
194bd3c7b5cSNicolas Royer 		atmel_aes_write(dd, offset, *value);
195bd3c7b5cSNicolas Royer }
196bd3c7b5cSNicolas Royer 
197bbe628edSCyrille Pitchen static inline void atmel_aes_read_block(struct atmel_aes_dev *dd, u32 offset,
198bbe628edSCyrille Pitchen 					u32 *value)
199bbe628edSCyrille Pitchen {
200bbe628edSCyrille Pitchen 	atmel_aes_read_n(dd, offset, value, SIZE_IN_WORDS(AES_BLOCK_SIZE));
201bbe628edSCyrille Pitchen }
202bbe628edSCyrille Pitchen 
203bbe628edSCyrille Pitchen static inline void atmel_aes_write_block(struct atmel_aes_dev *dd, u32 offset,
204bbe628edSCyrille Pitchen 					 const u32 *value)
205bbe628edSCyrille Pitchen {
206bbe628edSCyrille Pitchen 	atmel_aes_write_n(dd, offset, value, SIZE_IN_WORDS(AES_BLOCK_SIZE));
207bbe628edSCyrille Pitchen }
208bbe628edSCyrille Pitchen 
209bbe628edSCyrille Pitchen static inline int atmel_aes_wait_for_data_ready(struct atmel_aes_dev *dd,
210bbe628edSCyrille Pitchen 						atmel_aes_fn_t resume)
211bbe628edSCyrille Pitchen {
212bbe628edSCyrille Pitchen 	u32 isr = atmel_aes_read(dd, AES_ISR);
213bbe628edSCyrille Pitchen 
214bbe628edSCyrille Pitchen 	if (unlikely(isr & AES_INT_DATARDY))
215bbe628edSCyrille Pitchen 		return resume(dd);
216bbe628edSCyrille Pitchen 
217bbe628edSCyrille Pitchen 	dd->resume = resume;
218bbe628edSCyrille Pitchen 	atmel_aes_write(dd, AES_IER, AES_INT_DATARDY);
219bbe628edSCyrille Pitchen 	return -EINPROGRESS;
220bbe628edSCyrille Pitchen }
221bbe628edSCyrille Pitchen 
222bbe628edSCyrille Pitchen static inline size_t atmel_aes_padlen(size_t len, size_t block_size)
223bbe628edSCyrille Pitchen {
224bbe628edSCyrille Pitchen 	len &= block_size - 1;
225bbe628edSCyrille Pitchen 	return len ? block_size - len : 0;
226bbe628edSCyrille Pitchen }
227bbe628edSCyrille Pitchen 
228ccbf7298SCyrille Pitchen static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_base_ctx *ctx)
229bd3c7b5cSNicolas Royer {
230bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *aes_dd = NULL;
231bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *tmp;
232bd3c7b5cSNicolas Royer 
233bd3c7b5cSNicolas Royer 	spin_lock_bh(&atmel_aes.lock);
234bd3c7b5cSNicolas Royer 	if (!ctx->dd) {
235bd3c7b5cSNicolas Royer 		list_for_each_entry(tmp, &atmel_aes.dev_list, list) {
236bd3c7b5cSNicolas Royer 			aes_dd = tmp;
237bd3c7b5cSNicolas Royer 			break;
238bd3c7b5cSNicolas Royer 		}
239bd3c7b5cSNicolas Royer 		ctx->dd = aes_dd;
240bd3c7b5cSNicolas Royer 	} else {
241bd3c7b5cSNicolas Royer 		aes_dd = ctx->dd;
242bd3c7b5cSNicolas Royer 	}
243bd3c7b5cSNicolas Royer 
244bd3c7b5cSNicolas Royer 	spin_unlock_bh(&atmel_aes.lock);
245bd3c7b5cSNicolas Royer 
246bd3c7b5cSNicolas Royer 	return aes_dd;
247bd3c7b5cSNicolas Royer }
248bd3c7b5cSNicolas Royer 
249bd3c7b5cSNicolas Royer static int atmel_aes_hw_init(struct atmel_aes_dev *dd)
250bd3c7b5cSNicolas Royer {
2519d83d299SLABBE Corentin 	int err;
2529d83d299SLABBE Corentin 
2539d83d299SLABBE Corentin 	err = clk_prepare_enable(dd->iclk);
2549d83d299SLABBE Corentin 	if (err)
2559d83d299SLABBE Corentin 		return err;
256bd3c7b5cSNicolas Royer 
257bd3c7b5cSNicolas Royer 	if (!(dd->flags & AES_FLAGS_INIT)) {
258bd3c7b5cSNicolas Royer 		atmel_aes_write(dd, AES_CR, AES_CR_SWRST);
259cadc4ab8SNicolas Royer 		atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET);
260bd3c7b5cSNicolas Royer 		dd->flags |= AES_FLAGS_INIT;
261bd3c7b5cSNicolas Royer 	}
262bd3c7b5cSNicolas Royer 
263bd3c7b5cSNicolas Royer 	return 0;
264bd3c7b5cSNicolas Royer }
265bd3c7b5cSNicolas Royer 
266cadc4ab8SNicolas Royer static inline unsigned int atmel_aes_get_version(struct atmel_aes_dev *dd)
267cadc4ab8SNicolas Royer {
268cadc4ab8SNicolas Royer 	return atmel_aes_read(dd, AES_HW_VERSION) & 0x00000fff;
269cadc4ab8SNicolas Royer }
270cadc4ab8SNicolas Royer 
271aab0a39bSCyrille Pitchen static int atmel_aes_hw_version_init(struct atmel_aes_dev *dd)
272bd3c7b5cSNicolas Royer {
273aab0a39bSCyrille Pitchen 	int err;
274aab0a39bSCyrille Pitchen 
275aab0a39bSCyrille Pitchen 	err = atmel_aes_hw_init(dd);
276aab0a39bSCyrille Pitchen 	if (err)
277aab0a39bSCyrille Pitchen 		return err;
278bd3c7b5cSNicolas Royer 
279cadc4ab8SNicolas Royer 	dd->hw_version = atmel_aes_get_version(dd);
280cadc4ab8SNicolas Royer 
281aab0a39bSCyrille Pitchen 	dev_info(dd->dev, "version: 0x%x\n", dd->hw_version);
282bd3c7b5cSNicolas Royer 
283bd3c7b5cSNicolas Royer 	clk_disable_unprepare(dd->iclk);
284aab0a39bSCyrille Pitchen 	return 0;
285bd3c7b5cSNicolas Royer }
286bd3c7b5cSNicolas Royer 
28777dacf5fSCyrille Pitchen static inline void atmel_aes_set_mode(struct atmel_aes_dev *dd,
28877dacf5fSCyrille Pitchen 				      const struct atmel_aes_reqctx *rctx)
28977dacf5fSCyrille Pitchen {
29077dacf5fSCyrille Pitchen 	/* Clear all but persistent flags and set request flags. */
29177dacf5fSCyrille Pitchen 	dd->flags = (dd->flags & AES_FLAGS_PERSISTENT) | rctx->mode;
29277dacf5fSCyrille Pitchen }
29377dacf5fSCyrille Pitchen 
29410f12c1bSCyrille Pitchen static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
295bd3c7b5cSNicolas Royer {
296bd3c7b5cSNicolas Royer 	clk_disable_unprepare(dd->iclk);
297bd3c7b5cSNicolas Royer 	dd->flags &= ~AES_FLAGS_BUSY;
298bd3c7b5cSNicolas Royer 
29910f12c1bSCyrille Pitchen 	if (dd->is_async)
30010f12c1bSCyrille Pitchen 		dd->areq->complete(dd->areq, err);
30110f12c1bSCyrille Pitchen 
30210f12c1bSCyrille Pitchen 	tasklet_schedule(&dd->queue_task);
30310f12c1bSCyrille Pitchen 
30410f12c1bSCyrille Pitchen 	return err;
305bd3c7b5cSNicolas Royer }
306bd3c7b5cSNicolas Royer 
307bd3c7b5cSNicolas Royer 
308bbe628edSCyrille Pitchen /* CPU transfer */
309bbe628edSCyrille Pitchen 
310bbe628edSCyrille Pitchen static int atmel_aes_cpu_transfer(struct atmel_aes_dev *dd)
311bbe628edSCyrille Pitchen {
312bbe628edSCyrille Pitchen 	int err = 0;
313bbe628edSCyrille Pitchen 	u32 isr;
314bbe628edSCyrille Pitchen 
315bbe628edSCyrille Pitchen 	for (;;) {
316bbe628edSCyrille Pitchen 		atmel_aes_read_block(dd, AES_ODATAR(0), dd->data);
317bbe628edSCyrille Pitchen 		dd->data += 4;
318bbe628edSCyrille Pitchen 		dd->datalen -= AES_BLOCK_SIZE;
319bbe628edSCyrille Pitchen 
320bbe628edSCyrille Pitchen 		if (dd->datalen < AES_BLOCK_SIZE)
321bbe628edSCyrille Pitchen 			break;
322bbe628edSCyrille Pitchen 
323bbe628edSCyrille Pitchen 		atmel_aes_write_block(dd, AES_IDATAR(0), dd->data);
324bbe628edSCyrille Pitchen 
325bbe628edSCyrille Pitchen 		isr = atmel_aes_read(dd, AES_ISR);
326bbe628edSCyrille Pitchen 		if (!(isr & AES_INT_DATARDY)) {
327bbe628edSCyrille Pitchen 			dd->resume = atmel_aes_cpu_transfer;
328bbe628edSCyrille Pitchen 			atmel_aes_write(dd, AES_IER, AES_INT_DATARDY);
329bbe628edSCyrille Pitchen 			return -EINPROGRESS;
330bbe628edSCyrille Pitchen 		}
331bd3c7b5cSNicolas Royer 	}
332bd3c7b5cSNicolas Royer 
333bbe628edSCyrille Pitchen 	if (!sg_copy_from_buffer(dd->real_dst, sg_nents(dd->real_dst),
334bbe628edSCyrille Pitchen 				 dd->buf, dd->total))
335bbe628edSCyrille Pitchen 		err = -EINVAL;
336bbe628edSCyrille Pitchen 
337bbe628edSCyrille Pitchen 	if (err)
338bbe628edSCyrille Pitchen 		return atmel_aes_complete(dd, err);
339bbe628edSCyrille Pitchen 
340bbe628edSCyrille Pitchen 	return dd->cpu_transfer_complete(dd);
341bbe628edSCyrille Pitchen }
342bbe628edSCyrille Pitchen 
343bbe628edSCyrille Pitchen static int atmel_aes_cpu_start(struct atmel_aes_dev *dd,
344bbe628edSCyrille Pitchen 			       struct scatterlist *src,
345bbe628edSCyrille Pitchen 			       struct scatterlist *dst,
346bbe628edSCyrille Pitchen 			       size_t len,
347bbe628edSCyrille Pitchen 			       atmel_aes_fn_t resume)
348bd3c7b5cSNicolas Royer {
349bbe628edSCyrille Pitchen 	size_t padlen = atmel_aes_padlen(len, AES_BLOCK_SIZE);
350bbe628edSCyrille Pitchen 
351bbe628edSCyrille Pitchen 	if (unlikely(len == 0))
352bbe628edSCyrille Pitchen 		return -EINVAL;
353bbe628edSCyrille Pitchen 
354bbe628edSCyrille Pitchen 	sg_copy_to_buffer(src, sg_nents(src), dd->buf, len);
355bbe628edSCyrille Pitchen 
356bbe628edSCyrille Pitchen 	dd->total = len;
357bbe628edSCyrille Pitchen 	dd->real_dst = dst;
358bbe628edSCyrille Pitchen 	dd->cpu_transfer_complete = resume;
359bbe628edSCyrille Pitchen 	dd->datalen = len + padlen;
360bbe628edSCyrille Pitchen 	dd->data = (u32 *)dd->buf;
361bbe628edSCyrille Pitchen 	atmel_aes_write_block(dd, AES_IDATAR(0), dd->data);
362bbe628edSCyrille Pitchen 	return atmel_aes_wait_for_data_ready(dd, atmel_aes_cpu_transfer);
363bbe628edSCyrille Pitchen }
364bbe628edSCyrille Pitchen 
365bbe628edSCyrille Pitchen 
366bbe628edSCyrille Pitchen /* DMA transfer */
367bbe628edSCyrille Pitchen 
368bbe628edSCyrille Pitchen static void atmel_aes_dma_callback(void *data);
369bbe628edSCyrille Pitchen 
370bbe628edSCyrille Pitchen static bool atmel_aes_check_aligned(struct atmel_aes_dev *dd,
371bbe628edSCyrille Pitchen 				    struct scatterlist *sg,
372bbe628edSCyrille Pitchen 				    size_t len,
373bbe628edSCyrille Pitchen 				    struct atmel_aes_dma *dma)
374bbe628edSCyrille Pitchen {
375bbe628edSCyrille Pitchen 	int nents;
376bbe628edSCyrille Pitchen 
377bbe628edSCyrille Pitchen 	if (!IS_ALIGNED(len, dd->ctx->block_size))
378bbe628edSCyrille Pitchen 		return false;
379bbe628edSCyrille Pitchen 
380bbe628edSCyrille Pitchen 	for (nents = 0; sg; sg = sg_next(sg), ++nents) {
381bbe628edSCyrille Pitchen 		if (!IS_ALIGNED(sg->offset, sizeof(u32)))
382bbe628edSCyrille Pitchen 			return false;
383bbe628edSCyrille Pitchen 
384bbe628edSCyrille Pitchen 		if (len <= sg->length) {
385bbe628edSCyrille Pitchen 			if (!IS_ALIGNED(len, dd->ctx->block_size))
386bbe628edSCyrille Pitchen 				return false;
387bbe628edSCyrille Pitchen 
388bbe628edSCyrille Pitchen 			dma->nents = nents+1;
389bbe628edSCyrille Pitchen 			dma->remainder = sg->length - len;
390bbe628edSCyrille Pitchen 			sg->length = len;
391bbe628edSCyrille Pitchen 			return true;
392bbe628edSCyrille Pitchen 		}
393bbe628edSCyrille Pitchen 
394bbe628edSCyrille Pitchen 		if (!IS_ALIGNED(sg->length, dd->ctx->block_size))
395bbe628edSCyrille Pitchen 			return false;
396bbe628edSCyrille Pitchen 
397bbe628edSCyrille Pitchen 		len -= sg->length;
398bbe628edSCyrille Pitchen 	}
399bbe628edSCyrille Pitchen 
400bbe628edSCyrille Pitchen 	return false;
401bbe628edSCyrille Pitchen }
402bbe628edSCyrille Pitchen 
403bbe628edSCyrille Pitchen static inline void atmel_aes_restore_sg(const struct atmel_aes_dma *dma)
404bbe628edSCyrille Pitchen {
405bbe628edSCyrille Pitchen 	struct scatterlist *sg = dma->sg;
406bbe628edSCyrille Pitchen 	int nents = dma->nents;
407bbe628edSCyrille Pitchen 
408bbe628edSCyrille Pitchen 	if (!dma->remainder)
409bbe628edSCyrille Pitchen 		return;
410bbe628edSCyrille Pitchen 
411bbe628edSCyrille Pitchen 	while (--nents > 0 && sg)
412bbe628edSCyrille Pitchen 		sg = sg_next(sg);
413bbe628edSCyrille Pitchen 
414bbe628edSCyrille Pitchen 	if (!sg)
415bbe628edSCyrille Pitchen 		return;
416bbe628edSCyrille Pitchen 
417bbe628edSCyrille Pitchen 	sg->length += dma->remainder;
418bbe628edSCyrille Pitchen }
419bbe628edSCyrille Pitchen 
420bbe628edSCyrille Pitchen static int atmel_aes_map(struct atmel_aes_dev *dd,
421bbe628edSCyrille Pitchen 			 struct scatterlist *src,
422bbe628edSCyrille Pitchen 			 struct scatterlist *dst,
423bbe628edSCyrille Pitchen 			 size_t len)
424bbe628edSCyrille Pitchen {
425bbe628edSCyrille Pitchen 	bool src_aligned, dst_aligned;
426bbe628edSCyrille Pitchen 	size_t padlen;
427bbe628edSCyrille Pitchen 
428bbe628edSCyrille Pitchen 	dd->total = len;
429bbe628edSCyrille Pitchen 	dd->src.sg = src;
430bbe628edSCyrille Pitchen 	dd->dst.sg = dst;
431bbe628edSCyrille Pitchen 	dd->real_dst = dst;
432bbe628edSCyrille Pitchen 
433bbe628edSCyrille Pitchen 	src_aligned = atmel_aes_check_aligned(dd, src, len, &dd->src);
434bbe628edSCyrille Pitchen 	if (src == dst)
435bbe628edSCyrille Pitchen 		dst_aligned = src_aligned;
436bbe628edSCyrille Pitchen 	else
437bbe628edSCyrille Pitchen 		dst_aligned = atmel_aes_check_aligned(dd, dst, len, &dd->dst);
438bbe628edSCyrille Pitchen 	if (!src_aligned || !dst_aligned) {
439bbe628edSCyrille Pitchen 		padlen = atmel_aes_padlen(len, dd->ctx->block_size);
440bbe628edSCyrille Pitchen 
441bbe628edSCyrille Pitchen 		if (dd->buflen < len + padlen)
442bbe628edSCyrille Pitchen 			return -ENOMEM;
443bbe628edSCyrille Pitchen 
444bbe628edSCyrille Pitchen 		if (!src_aligned) {
445bbe628edSCyrille Pitchen 			sg_copy_to_buffer(src, sg_nents(src), dd->buf, len);
446bbe628edSCyrille Pitchen 			dd->src.sg = &dd->aligned_sg;
447bbe628edSCyrille Pitchen 			dd->src.nents = 1;
448bbe628edSCyrille Pitchen 			dd->src.remainder = 0;
449bbe628edSCyrille Pitchen 		}
450bbe628edSCyrille Pitchen 
451bbe628edSCyrille Pitchen 		if (!dst_aligned) {
452bbe628edSCyrille Pitchen 			dd->dst.sg = &dd->aligned_sg;
453bbe628edSCyrille Pitchen 			dd->dst.nents = 1;
454bbe628edSCyrille Pitchen 			dd->dst.remainder = 0;
455bbe628edSCyrille Pitchen 		}
456bbe628edSCyrille Pitchen 
457bbe628edSCyrille Pitchen 		sg_init_table(&dd->aligned_sg, 1);
458bbe628edSCyrille Pitchen 		sg_set_buf(&dd->aligned_sg, dd->buf, len + padlen);
459bbe628edSCyrille Pitchen 	}
460bbe628edSCyrille Pitchen 
461bbe628edSCyrille Pitchen 	if (dd->src.sg == dd->dst.sg) {
462bbe628edSCyrille Pitchen 		dd->src.sg_len = dma_map_sg(dd->dev, dd->src.sg, dd->src.nents,
463bbe628edSCyrille Pitchen 					    DMA_BIDIRECTIONAL);
464bbe628edSCyrille Pitchen 		dd->dst.sg_len = dd->src.sg_len;
465bbe628edSCyrille Pitchen 		if (!dd->src.sg_len)
466bbe628edSCyrille Pitchen 			return -EFAULT;
467bbe628edSCyrille Pitchen 	} else {
468bbe628edSCyrille Pitchen 		dd->src.sg_len = dma_map_sg(dd->dev, dd->src.sg, dd->src.nents,
469bbe628edSCyrille Pitchen 					    DMA_TO_DEVICE);
470bbe628edSCyrille Pitchen 		if (!dd->src.sg_len)
471bbe628edSCyrille Pitchen 			return -EFAULT;
472bbe628edSCyrille Pitchen 
473bbe628edSCyrille Pitchen 		dd->dst.sg_len = dma_map_sg(dd->dev, dd->dst.sg, dd->dst.nents,
474bbe628edSCyrille Pitchen 					    DMA_FROM_DEVICE);
475bbe628edSCyrille Pitchen 		if (!dd->dst.sg_len) {
476bbe628edSCyrille Pitchen 			dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents,
477bbe628edSCyrille Pitchen 				     DMA_TO_DEVICE);
478bbe628edSCyrille Pitchen 			return -EFAULT;
479bbe628edSCyrille Pitchen 		}
480bbe628edSCyrille Pitchen 	}
481bbe628edSCyrille Pitchen 
482bbe628edSCyrille Pitchen 	return 0;
483bbe628edSCyrille Pitchen }
484bbe628edSCyrille Pitchen 
485bbe628edSCyrille Pitchen static void atmel_aes_unmap(struct atmel_aes_dev *dd)
486bbe628edSCyrille Pitchen {
487bbe628edSCyrille Pitchen 	if (dd->src.sg == dd->dst.sg) {
488bbe628edSCyrille Pitchen 		dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents,
489bbe628edSCyrille Pitchen 			     DMA_BIDIRECTIONAL);
490bbe628edSCyrille Pitchen 
491bbe628edSCyrille Pitchen 		if (dd->src.sg != &dd->aligned_sg)
492bbe628edSCyrille Pitchen 			atmel_aes_restore_sg(&dd->src);
493bbe628edSCyrille Pitchen 	} else {
494bbe628edSCyrille Pitchen 		dma_unmap_sg(dd->dev, dd->dst.sg, dd->dst.nents,
495bbe628edSCyrille Pitchen 			     DMA_FROM_DEVICE);
496bbe628edSCyrille Pitchen 
497bbe628edSCyrille Pitchen 		if (dd->dst.sg != &dd->aligned_sg)
498bbe628edSCyrille Pitchen 			atmel_aes_restore_sg(&dd->dst);
499bbe628edSCyrille Pitchen 
500bbe628edSCyrille Pitchen 		dma_unmap_sg(dd->dev, dd->src.sg, dd->src.nents,
501bbe628edSCyrille Pitchen 			     DMA_TO_DEVICE);
502bbe628edSCyrille Pitchen 
503bbe628edSCyrille Pitchen 		if (dd->src.sg != &dd->aligned_sg)
504bbe628edSCyrille Pitchen 			atmel_aes_restore_sg(&dd->src);
505bbe628edSCyrille Pitchen 	}
506bbe628edSCyrille Pitchen 
507bbe628edSCyrille Pitchen 	if (dd->dst.sg == &dd->aligned_sg)
508bbe628edSCyrille Pitchen 		sg_copy_from_buffer(dd->real_dst, sg_nents(dd->real_dst),
509bbe628edSCyrille Pitchen 				    dd->buf, dd->total);
510bbe628edSCyrille Pitchen }
511bbe628edSCyrille Pitchen 
512bbe628edSCyrille Pitchen static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
513bbe628edSCyrille Pitchen 					enum dma_slave_buswidth addr_width,
514bbe628edSCyrille Pitchen 					enum dma_transfer_direction dir,
515bbe628edSCyrille Pitchen 					u32 maxburst)
516bbe628edSCyrille Pitchen {
517bbe628edSCyrille Pitchen 	struct dma_async_tx_descriptor *desc;
518bbe628edSCyrille Pitchen 	struct dma_slave_config config;
519bbe628edSCyrille Pitchen 	dma_async_tx_callback callback;
520bbe628edSCyrille Pitchen 	struct atmel_aes_dma *dma;
521bbe628edSCyrille Pitchen 	int err;
522bbe628edSCyrille Pitchen 
523bbe628edSCyrille Pitchen 	memset(&config, 0, sizeof(config));
524bbe628edSCyrille Pitchen 	config.direction = dir;
525bbe628edSCyrille Pitchen 	config.src_addr_width = addr_width;
526bbe628edSCyrille Pitchen 	config.dst_addr_width = addr_width;
527bbe628edSCyrille Pitchen 	config.src_maxburst = maxburst;
528bbe628edSCyrille Pitchen 	config.dst_maxburst = maxburst;
529bbe628edSCyrille Pitchen 
530bbe628edSCyrille Pitchen 	switch (dir) {
531bbe628edSCyrille Pitchen 	case DMA_MEM_TO_DEV:
532bbe628edSCyrille Pitchen 		dma = &dd->src;
533bbe628edSCyrille Pitchen 		callback = NULL;
534bbe628edSCyrille Pitchen 		config.dst_addr = dd->phys_base + AES_IDATAR(0);
535bbe628edSCyrille Pitchen 		break;
536bbe628edSCyrille Pitchen 
537bbe628edSCyrille Pitchen 	case DMA_DEV_TO_MEM:
538bbe628edSCyrille Pitchen 		dma = &dd->dst;
539bbe628edSCyrille Pitchen 		callback = atmel_aes_dma_callback;
540bbe628edSCyrille Pitchen 		config.src_addr = dd->phys_base + AES_ODATAR(0);
541bbe628edSCyrille Pitchen 		break;
542bbe628edSCyrille Pitchen 
543bbe628edSCyrille Pitchen 	default:
544bbe628edSCyrille Pitchen 		return -EINVAL;
545bbe628edSCyrille Pitchen 	}
546bbe628edSCyrille Pitchen 
547bbe628edSCyrille Pitchen 	err = dmaengine_slave_config(dma->chan, &config);
548bbe628edSCyrille Pitchen 	if (err)
549bbe628edSCyrille Pitchen 		return err;
550bbe628edSCyrille Pitchen 
551bbe628edSCyrille Pitchen 	desc = dmaengine_prep_slave_sg(dma->chan, dma->sg, dma->sg_len, dir,
552bbe628edSCyrille Pitchen 				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
553bbe628edSCyrille Pitchen 	if (!desc)
554bbe628edSCyrille Pitchen 		return -ENOMEM;
555bbe628edSCyrille Pitchen 
556bbe628edSCyrille Pitchen 	desc->callback = callback;
557bbe628edSCyrille Pitchen 	desc->callback_param = dd;
558bbe628edSCyrille Pitchen 	dmaengine_submit(desc);
559bbe628edSCyrille Pitchen 	dma_async_issue_pending(dma->chan);
560bbe628edSCyrille Pitchen 
561bbe628edSCyrille Pitchen 	return 0;
562bbe628edSCyrille Pitchen }
563bbe628edSCyrille Pitchen 
564bbe628edSCyrille Pitchen static void atmel_aes_dma_transfer_stop(struct atmel_aes_dev *dd,
565bbe628edSCyrille Pitchen 					enum dma_transfer_direction dir)
566bbe628edSCyrille Pitchen {
567bbe628edSCyrille Pitchen 	struct atmel_aes_dma *dma;
568bbe628edSCyrille Pitchen 
569bbe628edSCyrille Pitchen 	switch (dir) {
570bbe628edSCyrille Pitchen 	case DMA_MEM_TO_DEV:
571bbe628edSCyrille Pitchen 		dma = &dd->src;
572bbe628edSCyrille Pitchen 		break;
573bbe628edSCyrille Pitchen 
574bbe628edSCyrille Pitchen 	case DMA_DEV_TO_MEM:
575bbe628edSCyrille Pitchen 		dma = &dd->dst;
576bbe628edSCyrille Pitchen 		break;
577bbe628edSCyrille Pitchen 
578bbe628edSCyrille Pitchen 	default:
579bbe628edSCyrille Pitchen 		return;
580bbe628edSCyrille Pitchen 	}
581bbe628edSCyrille Pitchen 
582bbe628edSCyrille Pitchen 	dmaengine_terminate_all(dma->chan);
583bbe628edSCyrille Pitchen }
584bbe628edSCyrille Pitchen 
585bbe628edSCyrille Pitchen static int atmel_aes_dma_start(struct atmel_aes_dev *dd,
586bbe628edSCyrille Pitchen 			       struct scatterlist *src,
587bbe628edSCyrille Pitchen 			       struct scatterlist *dst,
588bbe628edSCyrille Pitchen 			       size_t len,
589bbe628edSCyrille Pitchen 			       atmel_aes_fn_t resume)
590bbe628edSCyrille Pitchen {
59177dacf5fSCyrille Pitchen 	enum dma_slave_buswidth addr_width;
59277dacf5fSCyrille Pitchen 	u32 maxburst;
593bbe628edSCyrille Pitchen 	int err;
59477dacf5fSCyrille Pitchen 
59577dacf5fSCyrille Pitchen 	switch (dd->ctx->block_size) {
59677dacf5fSCyrille Pitchen 	case CFB8_BLOCK_SIZE:
59777dacf5fSCyrille Pitchen 		addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
59877dacf5fSCyrille Pitchen 		maxburst = 1;
59977dacf5fSCyrille Pitchen 		break;
60077dacf5fSCyrille Pitchen 
60177dacf5fSCyrille Pitchen 	case CFB16_BLOCK_SIZE:
60277dacf5fSCyrille Pitchen 		addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
60377dacf5fSCyrille Pitchen 		maxburst = 1;
60477dacf5fSCyrille Pitchen 		break;
60577dacf5fSCyrille Pitchen 
60677dacf5fSCyrille Pitchen 	case CFB32_BLOCK_SIZE:
60777dacf5fSCyrille Pitchen 	case CFB64_BLOCK_SIZE:
60877dacf5fSCyrille Pitchen 		addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
60977dacf5fSCyrille Pitchen 		maxburst = 1;
61077dacf5fSCyrille Pitchen 		break;
61177dacf5fSCyrille Pitchen 
61277dacf5fSCyrille Pitchen 	case AES_BLOCK_SIZE:
61377dacf5fSCyrille Pitchen 		addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
61477dacf5fSCyrille Pitchen 		maxburst = dd->caps.max_burst_size;
61577dacf5fSCyrille Pitchen 		break;
61677dacf5fSCyrille Pitchen 
61777dacf5fSCyrille Pitchen 	default:
618bbe628edSCyrille Pitchen 		err = -EINVAL;
619bbe628edSCyrille Pitchen 		goto exit;
62077dacf5fSCyrille Pitchen 	}
621bd3c7b5cSNicolas Royer 
622bbe628edSCyrille Pitchen 	err = atmel_aes_map(dd, src, dst, len);
623bbe628edSCyrille Pitchen 	if (err)
624bbe628edSCyrille Pitchen 		goto exit;
625bd3c7b5cSNicolas Royer 
626bbe628edSCyrille Pitchen 	dd->resume = resume;
627bd3c7b5cSNicolas Royer 
628bbe628edSCyrille Pitchen 	/* Set output DMA transfer first */
629bbe628edSCyrille Pitchen 	err = atmel_aes_dma_transfer_start(dd, addr_width, DMA_DEV_TO_MEM,
630bbe628edSCyrille Pitchen 					   maxburst);
631bbe628edSCyrille Pitchen 	if (err)
632bbe628edSCyrille Pitchen 		goto unmap;
633cadc4ab8SNicolas Royer 
634bbe628edSCyrille Pitchen 	/* Then set input DMA transfer */
635bbe628edSCyrille Pitchen 	err = atmel_aes_dma_transfer_start(dd, addr_width, DMA_MEM_TO_DEV,
636bbe628edSCyrille Pitchen 					   maxburst);
637bbe628edSCyrille Pitchen 	if (err)
638bbe628edSCyrille Pitchen 		goto output_transfer_stop;
639cadc4ab8SNicolas Royer 
64010f12c1bSCyrille Pitchen 	return -EINPROGRESS;
641bbe628edSCyrille Pitchen 
642bbe628edSCyrille Pitchen output_transfer_stop:
643bbe628edSCyrille Pitchen 	atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM);
644bbe628edSCyrille Pitchen unmap:
645bbe628edSCyrille Pitchen 	atmel_aes_unmap(dd);
646bbe628edSCyrille Pitchen exit:
647bbe628edSCyrille Pitchen 	return atmel_aes_complete(dd, err);
648bd3c7b5cSNicolas Royer }
649bd3c7b5cSNicolas Royer 
650bbe628edSCyrille Pitchen static void atmel_aes_dma_stop(struct atmel_aes_dev *dd)
651bd3c7b5cSNicolas Royer {
652bbe628edSCyrille Pitchen 	atmel_aes_dma_transfer_stop(dd, DMA_MEM_TO_DEV);
653bbe628edSCyrille Pitchen 	atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM);
654bbe628edSCyrille Pitchen 	atmel_aes_unmap(dd);
655bd3c7b5cSNicolas Royer }
656bd3c7b5cSNicolas Royer 
657bbe628edSCyrille Pitchen static void atmel_aes_dma_callback(void *data)
658bbe628edSCyrille Pitchen {
659bbe628edSCyrille Pitchen 	struct atmel_aes_dev *dd = data;
660bd3c7b5cSNicolas Royer 
661bbe628edSCyrille Pitchen 	atmel_aes_dma_stop(dd);
662bbe628edSCyrille Pitchen 	dd->is_async = true;
663bbe628edSCyrille Pitchen 	(void)dd->resume(dd);
664bd3c7b5cSNicolas Royer }
665bd3c7b5cSNicolas Royer 
666cdfab4a7SCyrille Pitchen static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
667cdfab4a7SCyrille Pitchen 				 const u32 *iv)
668bd3c7b5cSNicolas Royer {
669794595d2SCyrille Pitchen 	u32 valmr = 0;
670bd3c7b5cSNicolas Royer 
671bd3c7b5cSNicolas Royer 	/* MR register must be set before IV registers */
672bd3c7b5cSNicolas Royer 	if (dd->ctx->keylen == AES_KEYSIZE_128)
673bd3c7b5cSNicolas Royer 		valmr |= AES_MR_KEYSIZE_128;
674bd3c7b5cSNicolas Royer 	else if (dd->ctx->keylen == AES_KEYSIZE_192)
675bd3c7b5cSNicolas Royer 		valmr |= AES_MR_KEYSIZE_192;
676bd3c7b5cSNicolas Royer 	else
677bd3c7b5cSNicolas Royer 		valmr |= AES_MR_KEYSIZE_256;
678bd3c7b5cSNicolas Royer 
67977dacf5fSCyrille Pitchen 	valmr |= dd->flags & AES_FLAGS_MODE_MASK;
680bd3c7b5cSNicolas Royer 
681cdfab4a7SCyrille Pitchen 	if (use_dma) {
682bd3c7b5cSNicolas Royer 		valmr |= AES_MR_SMOD_IDATAR0;
683cadc4ab8SNicolas Royer 		if (dd->caps.has_dualbuff)
684bd3c7b5cSNicolas Royer 			valmr |= AES_MR_DUALBUFF;
685bd3c7b5cSNicolas Royer 	} else {
686bd3c7b5cSNicolas Royer 		valmr |= AES_MR_SMOD_AUTO;
687bd3c7b5cSNicolas Royer 	}
688bd3c7b5cSNicolas Royer 
689bd3c7b5cSNicolas Royer 	atmel_aes_write(dd, AES_MR, valmr);
690bd3c7b5cSNicolas Royer 
691bd3c7b5cSNicolas Royer 	atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
692bd3c7b5cSNicolas Royer 						dd->ctx->keylen >> 2);
693bd3c7b5cSNicolas Royer 
69477dacf5fSCyrille Pitchen 	if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
695cdfab4a7SCyrille Pitchen 		atmel_aes_write_n(dd, AES_IVR(0), iv, 4);
696bd3c7b5cSNicolas Royer }
697bd3c7b5cSNicolas Royer 
698bd3c7b5cSNicolas Royer static int atmel_aes_handle_queue(struct atmel_aes_dev *dd,
699ccbf7298SCyrille Pitchen 				  struct crypto_async_request *new_areq)
700bd3c7b5cSNicolas Royer {
701ccbf7298SCyrille Pitchen 	struct crypto_async_request *areq, *backlog;
702ccbf7298SCyrille Pitchen 	struct atmel_aes_base_ctx *ctx;
703bd3c7b5cSNicolas Royer 	unsigned long flags;
704bd3c7b5cSNicolas Royer 	int err, ret = 0;
705bd3c7b5cSNicolas Royer 
706bd3c7b5cSNicolas Royer 	spin_lock_irqsave(&dd->lock, flags);
707ccbf7298SCyrille Pitchen 	if (new_areq)
708ccbf7298SCyrille Pitchen 		ret = crypto_enqueue_request(&dd->queue, new_areq);
709bd3c7b5cSNicolas Royer 	if (dd->flags & AES_FLAGS_BUSY) {
710bd3c7b5cSNicolas Royer 		spin_unlock_irqrestore(&dd->lock, flags);
711bd3c7b5cSNicolas Royer 		return ret;
712bd3c7b5cSNicolas Royer 	}
713bd3c7b5cSNicolas Royer 	backlog = crypto_get_backlog(&dd->queue);
714ccbf7298SCyrille Pitchen 	areq = crypto_dequeue_request(&dd->queue);
715ccbf7298SCyrille Pitchen 	if (areq)
716bd3c7b5cSNicolas Royer 		dd->flags |= AES_FLAGS_BUSY;
717bd3c7b5cSNicolas Royer 	spin_unlock_irqrestore(&dd->lock, flags);
718bd3c7b5cSNicolas Royer 
719ccbf7298SCyrille Pitchen 	if (!areq)
720bd3c7b5cSNicolas Royer 		return ret;
721bd3c7b5cSNicolas Royer 
722bd3c7b5cSNicolas Royer 	if (backlog)
723bd3c7b5cSNicolas Royer 		backlog->complete(backlog, -EINPROGRESS);
724bd3c7b5cSNicolas Royer 
725ccbf7298SCyrille Pitchen 	ctx = crypto_tfm_ctx(areq->tfm);
726ccbf7298SCyrille Pitchen 
727ccbf7298SCyrille Pitchen 	dd->areq = areq;
728ccbf7298SCyrille Pitchen 	dd->ctx = ctx;
72910f12c1bSCyrille Pitchen 	dd->is_async = (areq != new_areq);
730ccbf7298SCyrille Pitchen 
731ccbf7298SCyrille Pitchen 	err = ctx->start(dd);
73210f12c1bSCyrille Pitchen 	return (dd->is_async) ? ret : err;
733ccbf7298SCyrille Pitchen }
734ccbf7298SCyrille Pitchen 
735bbe628edSCyrille Pitchen static int atmel_aes_transfer_complete(struct atmel_aes_dev *dd)
736bbe628edSCyrille Pitchen {
737bbe628edSCyrille Pitchen 	return atmel_aes_complete(dd, 0);
738bbe628edSCyrille Pitchen }
739bbe628edSCyrille Pitchen 
740ccbf7298SCyrille Pitchen static int atmel_aes_start(struct atmel_aes_dev *dd)
741ccbf7298SCyrille Pitchen {
742ccbf7298SCyrille Pitchen 	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
743bbe628edSCyrille Pitchen 	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
744bbe628edSCyrille Pitchen 	bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD ||
745bbe628edSCyrille Pitchen 			dd->ctx->block_size != AES_BLOCK_SIZE);
746ccbf7298SCyrille Pitchen 	int err;
747bd3c7b5cSNicolas Royer 
74877dacf5fSCyrille Pitchen 	atmel_aes_set_mode(dd, rctx);
749bd3c7b5cSNicolas Royer 
750cdfab4a7SCyrille Pitchen 	err = atmel_aes_hw_init(dd);
751bbe628edSCyrille Pitchen 	if (err)
752bbe628edSCyrille Pitchen 		return atmel_aes_complete(dd, err);
753bbe628edSCyrille Pitchen 
754cdfab4a7SCyrille Pitchen 	atmel_aes_write_ctrl(dd, use_dma, req->info);
755cdfab4a7SCyrille Pitchen 	if (use_dma)
756bbe628edSCyrille Pitchen 		return atmel_aes_dma_start(dd, req->src, req->dst, req->nbytes,
757bbe628edSCyrille Pitchen 					   atmel_aes_transfer_complete);
758bd3c7b5cSNicolas Royer 
759bbe628edSCyrille Pitchen 	return atmel_aes_cpu_start(dd, req->src, req->dst, req->nbytes,
760bbe628edSCyrille Pitchen 				   atmel_aes_transfer_complete);
761bd3c7b5cSNicolas Royer }
762bd3c7b5cSNicolas Royer 
763cadc4ab8SNicolas Royer 
764cadc4ab8SNicolas Royer static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
765cadc4ab8SNicolas Royer {
766bbe628edSCyrille Pitchen 	dd->buf = (void *)__get_free_pages(GFP_KERNEL, ATMEL_AES_BUFFER_ORDER);
767bbe628edSCyrille Pitchen 	dd->buflen = ATMEL_AES_BUFFER_SIZE;
768cadc4ab8SNicolas Royer 	dd->buflen &= ~(AES_BLOCK_SIZE - 1);
769cadc4ab8SNicolas Royer 
770bbe628edSCyrille Pitchen 	if (!dd->buf) {
771cadc4ab8SNicolas Royer 		dev_err(dd->dev, "unable to alloc pages.\n");
772bbe628edSCyrille Pitchen 		return -ENOMEM;
773cadc4ab8SNicolas Royer 	}
774cadc4ab8SNicolas Royer 
775cadc4ab8SNicolas Royer 	return 0;
776cadc4ab8SNicolas Royer }
777cadc4ab8SNicolas Royer 
778cadc4ab8SNicolas Royer static void atmel_aes_buff_cleanup(struct atmel_aes_dev *dd)
779cadc4ab8SNicolas Royer {
780bbe628edSCyrille Pitchen 	free_page((unsigned long)dd->buf);
781cadc4ab8SNicolas Royer }
782cadc4ab8SNicolas Royer 
783bd3c7b5cSNicolas Royer static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
784bd3c7b5cSNicolas Royer {
785ccbf7298SCyrille Pitchen 	struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(
786bd3c7b5cSNicolas Royer 			crypto_ablkcipher_reqtfm(req));
787bd3c7b5cSNicolas Royer 	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
788bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *dd;
789bd3c7b5cSNicolas Royer 
79077dacf5fSCyrille Pitchen 	switch (mode & AES_FLAGS_OPMODE_MASK) {
79177dacf5fSCyrille Pitchen 	case AES_FLAGS_CFB8:
792cadc4ab8SNicolas Royer 		ctx->block_size = CFB8_BLOCK_SIZE;
79377dacf5fSCyrille Pitchen 		break;
79477dacf5fSCyrille Pitchen 
79577dacf5fSCyrille Pitchen 	case AES_FLAGS_CFB16:
796cadc4ab8SNicolas Royer 		ctx->block_size = CFB16_BLOCK_SIZE;
79777dacf5fSCyrille Pitchen 		break;
79877dacf5fSCyrille Pitchen 
79977dacf5fSCyrille Pitchen 	case AES_FLAGS_CFB32:
800cadc4ab8SNicolas Royer 		ctx->block_size = CFB32_BLOCK_SIZE;
80177dacf5fSCyrille Pitchen 		break;
80277dacf5fSCyrille Pitchen 
80377dacf5fSCyrille Pitchen 	case AES_FLAGS_CFB64:
8049f84951fSLeilei Zhao 		ctx->block_size = CFB64_BLOCK_SIZE;
80577dacf5fSCyrille Pitchen 		break;
80677dacf5fSCyrille Pitchen 
80777dacf5fSCyrille Pitchen 	default:
808cadc4ab8SNicolas Royer 		ctx->block_size = AES_BLOCK_SIZE;
80977dacf5fSCyrille Pitchen 		break;
810cadc4ab8SNicolas Royer 	}
811bd3c7b5cSNicolas Royer 
812bd3c7b5cSNicolas Royer 	dd = atmel_aes_find_dev(ctx);
813bd3c7b5cSNicolas Royer 	if (!dd)
814bd3c7b5cSNicolas Royer 		return -ENODEV;
815bd3c7b5cSNicolas Royer 
816bd3c7b5cSNicolas Royer 	rctx->mode = mode;
817bd3c7b5cSNicolas Royer 
818ccbf7298SCyrille Pitchen 	return atmel_aes_handle_queue(dd, &req->base);
819bd3c7b5cSNicolas Royer }
820bd3c7b5cSNicolas Royer 
821bd3c7b5cSNicolas Royer static bool atmel_aes_filter(struct dma_chan *chan, void *slave)
822bd3c7b5cSNicolas Royer {
823bd3c7b5cSNicolas Royer 	struct at_dma_slave	*sl = slave;
824bd3c7b5cSNicolas Royer 
825bd3c7b5cSNicolas Royer 	if (sl && sl->dma_dev == chan->device->dev) {
826bd3c7b5cSNicolas Royer 		chan->private = sl;
827bd3c7b5cSNicolas Royer 		return true;
828bd3c7b5cSNicolas Royer 	} else {
829bd3c7b5cSNicolas Royer 		return false;
830bd3c7b5cSNicolas Royer 	}
831bd3c7b5cSNicolas Royer }
832bd3c7b5cSNicolas Royer 
833cadc4ab8SNicolas Royer static int atmel_aes_dma_init(struct atmel_aes_dev *dd,
834cadc4ab8SNicolas Royer 			      struct crypto_platform_data *pdata)
835bd3c7b5cSNicolas Royer {
836bbe628edSCyrille Pitchen 	struct at_dma_slave *slave;
837bd3c7b5cSNicolas Royer 	int err = -ENOMEM;
838be943c7dSNicolas Ferre 	dma_cap_mask_t mask;
839bd3c7b5cSNicolas Royer 
840be943c7dSNicolas Ferre 	dma_cap_zero(mask);
841be943c7dSNicolas Ferre 	dma_cap_set(DMA_SLAVE, mask);
842bd3c7b5cSNicolas Royer 
843bd3c7b5cSNicolas Royer 	/* Try to grab 2 DMA channels */
844bbe628edSCyrille Pitchen 	slave = &pdata->dma_slave->rxdata;
845bbe628edSCyrille Pitchen 	dd->src.chan = dma_request_slave_channel_compat(mask, atmel_aes_filter,
846bbe628edSCyrille Pitchen 							slave, dd->dev, "tx");
847bbe628edSCyrille Pitchen 	if (!dd->src.chan)
848bd3c7b5cSNicolas Royer 		goto err_dma_in;
849bd3c7b5cSNicolas Royer 
850bbe628edSCyrille Pitchen 	slave = &pdata->dma_slave->txdata;
851bbe628edSCyrille Pitchen 	dd->dst.chan = dma_request_slave_channel_compat(mask, atmel_aes_filter,
852bbe628edSCyrille Pitchen 							slave, dd->dev, "rx");
853bbe628edSCyrille Pitchen 	if (!dd->dst.chan)
854bd3c7b5cSNicolas Royer 		goto err_dma_out;
855bd3c7b5cSNicolas Royer 
856bd3c7b5cSNicolas Royer 	return 0;
857bd3c7b5cSNicolas Royer 
858bd3c7b5cSNicolas Royer err_dma_out:
859bbe628edSCyrille Pitchen 	dma_release_channel(dd->src.chan);
860bd3c7b5cSNicolas Royer err_dma_in:
861be943c7dSNicolas Ferre 	dev_warn(dd->dev, "no DMA channel available\n");
862bd3c7b5cSNicolas Royer 	return err;
863bd3c7b5cSNicolas Royer }
864bd3c7b5cSNicolas Royer 
865bd3c7b5cSNicolas Royer static void atmel_aes_dma_cleanup(struct atmel_aes_dev *dd)
866bd3c7b5cSNicolas Royer {
867bbe628edSCyrille Pitchen 	dma_release_channel(dd->dst.chan);
868bbe628edSCyrille Pitchen 	dma_release_channel(dd->src.chan);
869bd3c7b5cSNicolas Royer }
870bd3c7b5cSNicolas Royer 
871bd3c7b5cSNicolas Royer static int atmel_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
872bd3c7b5cSNicolas Royer 			   unsigned int keylen)
873bd3c7b5cSNicolas Royer {
874ccbf7298SCyrille Pitchen 	struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(tfm);
875bd3c7b5cSNicolas Royer 
876bd3c7b5cSNicolas Royer 	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
877bd3c7b5cSNicolas Royer 		   keylen != AES_KEYSIZE_256) {
878bd3c7b5cSNicolas Royer 		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
879bd3c7b5cSNicolas Royer 		return -EINVAL;
880bd3c7b5cSNicolas Royer 	}
881bd3c7b5cSNicolas Royer 
882bd3c7b5cSNicolas Royer 	memcpy(ctx->key, key, keylen);
883bd3c7b5cSNicolas Royer 	ctx->keylen = keylen;
884bd3c7b5cSNicolas Royer 
885bd3c7b5cSNicolas Royer 	return 0;
886bd3c7b5cSNicolas Royer }
887bd3c7b5cSNicolas Royer 
888bd3c7b5cSNicolas Royer static int atmel_aes_ecb_encrypt(struct ablkcipher_request *req)
889bd3c7b5cSNicolas Royer {
89077dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_ECB | AES_FLAGS_ENCRYPT);
891bd3c7b5cSNicolas Royer }
892bd3c7b5cSNicolas Royer 
893bd3c7b5cSNicolas Royer static int atmel_aes_ecb_decrypt(struct ablkcipher_request *req)
894bd3c7b5cSNicolas Royer {
89577dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_ECB);
896bd3c7b5cSNicolas Royer }
897bd3c7b5cSNicolas Royer 
898bd3c7b5cSNicolas Royer static int atmel_aes_cbc_encrypt(struct ablkcipher_request *req)
899bd3c7b5cSNicolas Royer {
900bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
901bd3c7b5cSNicolas Royer 		AES_FLAGS_ENCRYPT | AES_FLAGS_CBC);
902bd3c7b5cSNicolas Royer }
903bd3c7b5cSNicolas Royer 
904bd3c7b5cSNicolas Royer static int atmel_aes_cbc_decrypt(struct ablkcipher_request *req)
905bd3c7b5cSNicolas Royer {
906bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
907bd3c7b5cSNicolas Royer 		AES_FLAGS_CBC);
908bd3c7b5cSNicolas Royer }
909bd3c7b5cSNicolas Royer 
910bd3c7b5cSNicolas Royer static int atmel_aes_ofb_encrypt(struct ablkcipher_request *req)
911bd3c7b5cSNicolas Royer {
912bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
913bd3c7b5cSNicolas Royer 		AES_FLAGS_ENCRYPT | AES_FLAGS_OFB);
914bd3c7b5cSNicolas Royer }
915bd3c7b5cSNicolas Royer 
916bd3c7b5cSNicolas Royer static int atmel_aes_ofb_decrypt(struct ablkcipher_request *req)
917bd3c7b5cSNicolas Royer {
918bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
919bd3c7b5cSNicolas Royer 		AES_FLAGS_OFB);
920bd3c7b5cSNicolas Royer }
921bd3c7b5cSNicolas Royer 
922bd3c7b5cSNicolas Royer static int atmel_aes_cfb_encrypt(struct ablkcipher_request *req)
923bd3c7b5cSNicolas Royer {
92477dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB128 | AES_FLAGS_ENCRYPT);
925bd3c7b5cSNicolas Royer }
926bd3c7b5cSNicolas Royer 
927bd3c7b5cSNicolas Royer static int atmel_aes_cfb_decrypt(struct ablkcipher_request *req)
928bd3c7b5cSNicolas Royer {
92977dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB128);
930bd3c7b5cSNicolas Royer }
931bd3c7b5cSNicolas Royer 
932bd3c7b5cSNicolas Royer static int atmel_aes_cfb64_encrypt(struct ablkcipher_request *req)
933bd3c7b5cSNicolas Royer {
93477dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB64 | AES_FLAGS_ENCRYPT);
935bd3c7b5cSNicolas Royer }
936bd3c7b5cSNicolas Royer 
937bd3c7b5cSNicolas Royer static int atmel_aes_cfb64_decrypt(struct ablkcipher_request *req)
938bd3c7b5cSNicolas Royer {
93977dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB64);
940bd3c7b5cSNicolas Royer }
941bd3c7b5cSNicolas Royer 
942bd3c7b5cSNicolas Royer static int atmel_aes_cfb32_encrypt(struct ablkcipher_request *req)
943bd3c7b5cSNicolas Royer {
94477dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB32 | AES_FLAGS_ENCRYPT);
945bd3c7b5cSNicolas Royer }
946bd3c7b5cSNicolas Royer 
947bd3c7b5cSNicolas Royer static int atmel_aes_cfb32_decrypt(struct ablkcipher_request *req)
948bd3c7b5cSNicolas Royer {
94977dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB32);
950bd3c7b5cSNicolas Royer }
951bd3c7b5cSNicolas Royer 
952bd3c7b5cSNicolas Royer static int atmel_aes_cfb16_encrypt(struct ablkcipher_request *req)
953bd3c7b5cSNicolas Royer {
95477dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB16 | AES_FLAGS_ENCRYPT);
955bd3c7b5cSNicolas Royer }
956bd3c7b5cSNicolas Royer 
957bd3c7b5cSNicolas Royer static int atmel_aes_cfb16_decrypt(struct ablkcipher_request *req)
958bd3c7b5cSNicolas Royer {
95977dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB16);
960bd3c7b5cSNicolas Royer }
961bd3c7b5cSNicolas Royer 
962bd3c7b5cSNicolas Royer static int atmel_aes_cfb8_encrypt(struct ablkcipher_request *req)
963bd3c7b5cSNicolas Royer {
96477dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB8 | AES_FLAGS_ENCRYPT);
965bd3c7b5cSNicolas Royer }
966bd3c7b5cSNicolas Royer 
967bd3c7b5cSNicolas Royer static int atmel_aes_cfb8_decrypt(struct ablkcipher_request *req)
968bd3c7b5cSNicolas Royer {
96977dacf5fSCyrille Pitchen 	return atmel_aes_crypt(req, AES_FLAGS_CFB8);
970bd3c7b5cSNicolas Royer }
971bd3c7b5cSNicolas Royer 
972bd3c7b5cSNicolas Royer static int atmel_aes_ctr_encrypt(struct ablkcipher_request *req)
973bd3c7b5cSNicolas Royer {
974bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
975bd3c7b5cSNicolas Royer 		AES_FLAGS_ENCRYPT | AES_FLAGS_CTR);
976bd3c7b5cSNicolas Royer }
977bd3c7b5cSNicolas Royer 
978bd3c7b5cSNicolas Royer static int atmel_aes_ctr_decrypt(struct ablkcipher_request *req)
979bd3c7b5cSNicolas Royer {
980bd3c7b5cSNicolas Royer 	return atmel_aes_crypt(req,
981bd3c7b5cSNicolas Royer 		AES_FLAGS_CTR);
982bd3c7b5cSNicolas Royer }
983bd3c7b5cSNicolas Royer 
984bd3c7b5cSNicolas Royer static int atmel_aes_cra_init(struct crypto_tfm *tfm)
985bd3c7b5cSNicolas Royer {
986ccbf7298SCyrille Pitchen 	struct atmel_aes_ctx *ctx = crypto_tfm_ctx(tfm);
987ccbf7298SCyrille Pitchen 
988bd3c7b5cSNicolas Royer 	tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx);
989ccbf7298SCyrille Pitchen 	ctx->base.start = atmel_aes_start;
990bd3c7b5cSNicolas Royer 
991bd3c7b5cSNicolas Royer 	return 0;
992bd3c7b5cSNicolas Royer }
993bd3c7b5cSNicolas Royer 
994bd3c7b5cSNicolas Royer static void atmel_aes_cra_exit(struct crypto_tfm *tfm)
995bd3c7b5cSNicolas Royer {
996bd3c7b5cSNicolas Royer }
997bd3c7b5cSNicolas Royer 
998bd3c7b5cSNicolas Royer static struct crypto_alg aes_algs[] = {
999bd3c7b5cSNicolas Royer {
1000bd3c7b5cSNicolas Royer 	.cra_name		= "ecb(aes)",
1001bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-ecb-aes",
100288efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1003bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1004bd3c7b5cSNicolas Royer 	.cra_blocksize		= AES_BLOCK_SIZE,
1005bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1006cadc4ab8SNicolas Royer 	.cra_alignmask		= 0xf,
1007bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1008bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1009bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1010bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1011bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1012bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1013bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1014bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1015bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_ecb_encrypt,
1016bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_ecb_decrypt,
1017bd3c7b5cSNicolas Royer 	}
1018bd3c7b5cSNicolas Royer },
1019bd3c7b5cSNicolas Royer {
1020bd3c7b5cSNicolas Royer 	.cra_name		= "cbc(aes)",
1021bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cbc-aes",
102288efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1023bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1024bd3c7b5cSNicolas Royer 	.cra_blocksize		= AES_BLOCK_SIZE,
1025bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1026cadc4ab8SNicolas Royer 	.cra_alignmask		= 0xf,
1027bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1028bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1029bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1030bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1031bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1032bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1033bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1034bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1035bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1036bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cbc_encrypt,
1037bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cbc_decrypt,
1038bd3c7b5cSNicolas Royer 	}
1039bd3c7b5cSNicolas Royer },
1040bd3c7b5cSNicolas Royer {
1041bd3c7b5cSNicolas Royer 	.cra_name		= "ofb(aes)",
1042bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-ofb-aes",
104388efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1044bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1045bd3c7b5cSNicolas Royer 	.cra_blocksize		= AES_BLOCK_SIZE,
1046bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1047cadc4ab8SNicolas Royer 	.cra_alignmask		= 0xf,
1048bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1049bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1050bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1051bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1052bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1053bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1054bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1055bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1056bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1057bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_ofb_encrypt,
1058bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_ofb_decrypt,
1059bd3c7b5cSNicolas Royer 	}
1060bd3c7b5cSNicolas Royer },
1061bd3c7b5cSNicolas Royer {
1062bd3c7b5cSNicolas Royer 	.cra_name		= "cfb(aes)",
1063bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cfb-aes",
106488efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1065bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1066bd3c7b5cSNicolas Royer 	.cra_blocksize		= AES_BLOCK_SIZE,
1067bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1068cadc4ab8SNicolas Royer 	.cra_alignmask		= 0xf,
1069bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1070bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1071bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1072bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1073bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1074bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1075bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1076bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1077bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1078bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cfb_encrypt,
1079bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cfb_decrypt,
1080bd3c7b5cSNicolas Royer 	}
1081bd3c7b5cSNicolas Royer },
1082bd3c7b5cSNicolas Royer {
1083bd3c7b5cSNicolas Royer 	.cra_name		= "cfb32(aes)",
1084bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cfb32-aes",
108588efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1086bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1087bd3c7b5cSNicolas Royer 	.cra_blocksize		= CFB32_BLOCK_SIZE,
1088bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1089cadc4ab8SNicolas Royer 	.cra_alignmask		= 0x3,
1090bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1091bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1092bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1093bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1094bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1095bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1096bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1097bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1098bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1099bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cfb32_encrypt,
1100bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cfb32_decrypt,
1101bd3c7b5cSNicolas Royer 	}
1102bd3c7b5cSNicolas Royer },
1103bd3c7b5cSNicolas Royer {
1104bd3c7b5cSNicolas Royer 	.cra_name		= "cfb16(aes)",
1105bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cfb16-aes",
110688efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1107bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1108bd3c7b5cSNicolas Royer 	.cra_blocksize		= CFB16_BLOCK_SIZE,
1109bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1110cadc4ab8SNicolas Royer 	.cra_alignmask		= 0x1,
1111bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1112bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1113bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1114bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1115bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1116bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1117bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1118bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1119bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1120bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cfb16_encrypt,
1121bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cfb16_decrypt,
1122bd3c7b5cSNicolas Royer 	}
1123bd3c7b5cSNicolas Royer },
1124bd3c7b5cSNicolas Royer {
1125bd3c7b5cSNicolas Royer 	.cra_name		= "cfb8(aes)",
1126bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cfb8-aes",
112788efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1128bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1129e5d8c961SLeilei Zhao 	.cra_blocksize		= CFB8_BLOCK_SIZE,
1130bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1131bd3c7b5cSNicolas Royer 	.cra_alignmask		= 0x0,
1132bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1133bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1134bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1135bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1136bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1137bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1138bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1139bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1140bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1141bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cfb8_encrypt,
1142bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cfb8_decrypt,
1143bd3c7b5cSNicolas Royer 	}
1144bd3c7b5cSNicolas Royer },
1145bd3c7b5cSNicolas Royer {
1146bd3c7b5cSNicolas Royer 	.cra_name		= "ctr(aes)",
1147bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-ctr-aes",
114888efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1149bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1150bd3c7b5cSNicolas Royer 	.cra_blocksize		= AES_BLOCK_SIZE,
1151bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1152cadc4ab8SNicolas Royer 	.cra_alignmask		= 0xf,
1153bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1154bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1155bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1156bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1157bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1158bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1159bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1160bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1161bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1162bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_ctr_encrypt,
1163bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_ctr_decrypt,
1164bd3c7b5cSNicolas Royer 	}
1165bd3c7b5cSNicolas Royer },
1166bd3c7b5cSNicolas Royer };
1167bd3c7b5cSNicolas Royer 
1168cadc4ab8SNicolas Royer static struct crypto_alg aes_cfb64_alg = {
1169bd3c7b5cSNicolas Royer 	.cra_name		= "cfb64(aes)",
1170bd3c7b5cSNicolas Royer 	.cra_driver_name	= "atmel-cfb64-aes",
117188efd9a9SCyrille Pitchen 	.cra_priority		= ATMEL_AES_PRIORITY,
1172bd3c7b5cSNicolas Royer 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
1173bd3c7b5cSNicolas Royer 	.cra_blocksize		= CFB64_BLOCK_SIZE,
1174bd3c7b5cSNicolas Royer 	.cra_ctxsize		= sizeof(struct atmel_aes_ctx),
1175cadc4ab8SNicolas Royer 	.cra_alignmask		= 0x7,
1176bd3c7b5cSNicolas Royer 	.cra_type		= &crypto_ablkcipher_type,
1177bd3c7b5cSNicolas Royer 	.cra_module		= THIS_MODULE,
1178bd3c7b5cSNicolas Royer 	.cra_init		= atmel_aes_cra_init,
1179bd3c7b5cSNicolas Royer 	.cra_exit		= atmel_aes_cra_exit,
1180bd3c7b5cSNicolas Royer 	.cra_u.ablkcipher = {
1181bd3c7b5cSNicolas Royer 		.min_keysize	= AES_MIN_KEY_SIZE,
1182bd3c7b5cSNicolas Royer 		.max_keysize	= AES_MAX_KEY_SIZE,
1183bd3c7b5cSNicolas Royer 		.ivsize		= AES_BLOCK_SIZE,
1184bd3c7b5cSNicolas Royer 		.setkey		= atmel_aes_setkey,
1185bd3c7b5cSNicolas Royer 		.encrypt	= atmel_aes_cfb64_encrypt,
1186bd3c7b5cSNicolas Royer 		.decrypt	= atmel_aes_cfb64_decrypt,
1187bd3c7b5cSNicolas Royer 	}
1188bd3c7b5cSNicolas Royer };
1189bd3c7b5cSNicolas Royer 
1190bd3c7b5cSNicolas Royer static void atmel_aes_queue_task(unsigned long data)
1191bd3c7b5cSNicolas Royer {
1192bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *dd = (struct atmel_aes_dev *)data;
1193bd3c7b5cSNicolas Royer 
1194bd3c7b5cSNicolas Royer 	atmel_aes_handle_queue(dd, NULL);
1195bd3c7b5cSNicolas Royer }
1196bd3c7b5cSNicolas Royer 
1197bd3c7b5cSNicolas Royer static void atmel_aes_done_task(unsigned long data)
1198bd3c7b5cSNicolas Royer {
1199bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *dd = (struct atmel_aes_dev *) data;
1200bd3c7b5cSNicolas Royer 
120110f12c1bSCyrille Pitchen 	dd->is_async = true;
120210f12c1bSCyrille Pitchen 	(void)dd->resume(dd);
1203bd3c7b5cSNicolas Royer }
1204bd3c7b5cSNicolas Royer 
1205bd3c7b5cSNicolas Royer static irqreturn_t atmel_aes_irq(int irq, void *dev_id)
1206bd3c7b5cSNicolas Royer {
1207bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *aes_dd = dev_id;
1208bd3c7b5cSNicolas Royer 	u32 reg;
1209bd3c7b5cSNicolas Royer 
1210bd3c7b5cSNicolas Royer 	reg = atmel_aes_read(aes_dd, AES_ISR);
1211bd3c7b5cSNicolas Royer 	if (reg & atmel_aes_read(aes_dd, AES_IMR)) {
1212bd3c7b5cSNicolas Royer 		atmel_aes_write(aes_dd, AES_IDR, reg);
1213bd3c7b5cSNicolas Royer 		if (AES_FLAGS_BUSY & aes_dd->flags)
1214bd3c7b5cSNicolas Royer 			tasklet_schedule(&aes_dd->done_task);
1215bd3c7b5cSNicolas Royer 		else
1216bd3c7b5cSNicolas Royer 			dev_warn(aes_dd->dev, "AES interrupt when no active requests.\n");
1217bd3c7b5cSNicolas Royer 		return IRQ_HANDLED;
1218bd3c7b5cSNicolas Royer 	}
1219bd3c7b5cSNicolas Royer 
1220bd3c7b5cSNicolas Royer 	return IRQ_NONE;
1221bd3c7b5cSNicolas Royer }
1222bd3c7b5cSNicolas Royer 
1223bd3c7b5cSNicolas Royer static void atmel_aes_unregister_algs(struct atmel_aes_dev *dd)
1224bd3c7b5cSNicolas Royer {
1225bd3c7b5cSNicolas Royer 	int i;
1226bd3c7b5cSNicolas Royer 
1227cadc4ab8SNicolas Royer 	if (dd->caps.has_cfb64)
1228cadc4ab8SNicolas Royer 		crypto_unregister_alg(&aes_cfb64_alg);
1229924a8bc7SCyrille Pitchen 
1230924a8bc7SCyrille Pitchen 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
1231924a8bc7SCyrille Pitchen 		crypto_unregister_alg(&aes_algs[i]);
1232bd3c7b5cSNicolas Royer }
1233bd3c7b5cSNicolas Royer 
1234bd3c7b5cSNicolas Royer static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
1235bd3c7b5cSNicolas Royer {
1236bd3c7b5cSNicolas Royer 	int err, i, j;
1237bd3c7b5cSNicolas Royer 
1238bd3c7b5cSNicolas Royer 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
1239bd3c7b5cSNicolas Royer 		err = crypto_register_alg(&aes_algs[i]);
1240bd3c7b5cSNicolas Royer 		if (err)
1241bd3c7b5cSNicolas Royer 			goto err_aes_algs;
1242bd3c7b5cSNicolas Royer 	}
1243bd3c7b5cSNicolas Royer 
1244cadc4ab8SNicolas Royer 	if (dd->caps.has_cfb64) {
1245cadc4ab8SNicolas Royer 		err = crypto_register_alg(&aes_cfb64_alg);
1246bd3c7b5cSNicolas Royer 		if (err)
1247bd3c7b5cSNicolas Royer 			goto err_aes_cfb64_alg;
1248bd3c7b5cSNicolas Royer 	}
1249bd3c7b5cSNicolas Royer 
1250bd3c7b5cSNicolas Royer 	return 0;
1251bd3c7b5cSNicolas Royer 
1252bd3c7b5cSNicolas Royer err_aes_cfb64_alg:
1253bd3c7b5cSNicolas Royer 	i = ARRAY_SIZE(aes_algs);
1254bd3c7b5cSNicolas Royer err_aes_algs:
1255bd3c7b5cSNicolas Royer 	for (j = 0; j < i; j++)
1256bd3c7b5cSNicolas Royer 		crypto_unregister_alg(&aes_algs[j]);
1257bd3c7b5cSNicolas Royer 
1258bd3c7b5cSNicolas Royer 	return err;
1259bd3c7b5cSNicolas Royer }
1260bd3c7b5cSNicolas Royer 
1261cadc4ab8SNicolas Royer static void atmel_aes_get_cap(struct atmel_aes_dev *dd)
1262cadc4ab8SNicolas Royer {
1263cadc4ab8SNicolas Royer 	dd->caps.has_dualbuff = 0;
1264cadc4ab8SNicolas Royer 	dd->caps.has_cfb64 = 0;
1265cadc4ab8SNicolas Royer 	dd->caps.max_burst_size = 1;
1266cadc4ab8SNicolas Royer 
1267cadc4ab8SNicolas Royer 	/* keep only major version number */
1268cadc4ab8SNicolas Royer 	switch (dd->hw_version & 0xff0) {
1269973e209dSLeilei Zhao 	case 0x500:
1270973e209dSLeilei Zhao 		dd->caps.has_dualbuff = 1;
1271973e209dSLeilei Zhao 		dd->caps.has_cfb64 = 1;
1272973e209dSLeilei Zhao 		dd->caps.max_burst_size = 4;
1273973e209dSLeilei Zhao 		break;
1274cf1f0d12SLeilei Zhao 	case 0x200:
1275cf1f0d12SLeilei Zhao 		dd->caps.has_dualbuff = 1;
1276cf1f0d12SLeilei Zhao 		dd->caps.has_cfb64 = 1;
1277cf1f0d12SLeilei Zhao 		dd->caps.max_burst_size = 4;
1278cf1f0d12SLeilei Zhao 		break;
1279cadc4ab8SNicolas Royer 	case 0x130:
1280cadc4ab8SNicolas Royer 		dd->caps.has_dualbuff = 1;
1281cadc4ab8SNicolas Royer 		dd->caps.has_cfb64 = 1;
1282cadc4ab8SNicolas Royer 		dd->caps.max_burst_size = 4;
1283cadc4ab8SNicolas Royer 		break;
1284cadc4ab8SNicolas Royer 	case 0x120:
1285cadc4ab8SNicolas Royer 		break;
1286cadc4ab8SNicolas Royer 	default:
1287cadc4ab8SNicolas Royer 		dev_warn(dd->dev,
1288cadc4ab8SNicolas Royer 				"Unmanaged aes version, set minimum capabilities\n");
1289cadc4ab8SNicolas Royer 		break;
1290cadc4ab8SNicolas Royer 	}
1291cadc4ab8SNicolas Royer }
1292cadc4ab8SNicolas Royer 
1293be943c7dSNicolas Ferre #if defined(CONFIG_OF)
1294be943c7dSNicolas Ferre static const struct of_device_id atmel_aes_dt_ids[] = {
1295be943c7dSNicolas Ferre 	{ .compatible = "atmel,at91sam9g46-aes" },
1296be943c7dSNicolas Ferre 	{ /* sentinel */ }
1297be943c7dSNicolas Ferre };
1298be943c7dSNicolas Ferre MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids);
1299be943c7dSNicolas Ferre 
1300be943c7dSNicolas Ferre static struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev)
1301be943c7dSNicolas Ferre {
1302be943c7dSNicolas Ferre 	struct device_node *np = pdev->dev.of_node;
1303be943c7dSNicolas Ferre 	struct crypto_platform_data *pdata;
1304be943c7dSNicolas Ferre 
1305be943c7dSNicolas Ferre 	if (!np) {
1306be943c7dSNicolas Ferre 		dev_err(&pdev->dev, "device node not found\n");
1307be943c7dSNicolas Ferre 		return ERR_PTR(-EINVAL);
1308be943c7dSNicolas Ferre 	}
1309be943c7dSNicolas Ferre 
1310be943c7dSNicolas Ferre 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
1311be943c7dSNicolas Ferre 	if (!pdata) {
1312be943c7dSNicolas Ferre 		dev_err(&pdev->dev, "could not allocate memory for pdata\n");
1313be943c7dSNicolas Ferre 		return ERR_PTR(-ENOMEM);
1314be943c7dSNicolas Ferre 	}
1315be943c7dSNicolas Ferre 
1316be943c7dSNicolas Ferre 	pdata->dma_slave = devm_kzalloc(&pdev->dev,
1317be943c7dSNicolas Ferre 					sizeof(*(pdata->dma_slave)),
1318be943c7dSNicolas Ferre 					GFP_KERNEL);
1319be943c7dSNicolas Ferre 	if (!pdata->dma_slave) {
1320be943c7dSNicolas Ferre 		dev_err(&pdev->dev, "could not allocate memory for dma_slave\n");
1321be943c7dSNicolas Ferre 		devm_kfree(&pdev->dev, pdata);
1322be943c7dSNicolas Ferre 		return ERR_PTR(-ENOMEM);
1323be943c7dSNicolas Ferre 	}
1324be943c7dSNicolas Ferre 
1325be943c7dSNicolas Ferre 	return pdata;
1326be943c7dSNicolas Ferre }
1327be943c7dSNicolas Ferre #else
1328be943c7dSNicolas Ferre static inline struct crypto_platform_data *atmel_aes_of_init(struct platform_device *pdev)
1329be943c7dSNicolas Ferre {
1330be943c7dSNicolas Ferre 	return ERR_PTR(-EINVAL);
1331be943c7dSNicolas Ferre }
1332be943c7dSNicolas Ferre #endif
1333be943c7dSNicolas Ferre 
133449cfe4dbSGreg Kroah-Hartman static int atmel_aes_probe(struct platform_device *pdev)
1335bd3c7b5cSNicolas Royer {
1336bd3c7b5cSNicolas Royer 	struct atmel_aes_dev *aes_dd;
1337cadc4ab8SNicolas Royer 	struct crypto_platform_data *pdata;
1338bd3c7b5cSNicolas Royer 	struct device *dev = &pdev->dev;
1339bd3c7b5cSNicolas Royer 	struct resource *aes_res;
1340bd3c7b5cSNicolas Royer 	int err;
1341bd3c7b5cSNicolas Royer 
1342bd3c7b5cSNicolas Royer 	pdata = pdev->dev.platform_data;
1343bd3c7b5cSNicolas Royer 	if (!pdata) {
1344be943c7dSNicolas Ferre 		pdata = atmel_aes_of_init(pdev);
1345be943c7dSNicolas Ferre 		if (IS_ERR(pdata)) {
1346be943c7dSNicolas Ferre 			err = PTR_ERR(pdata);
1347be943c7dSNicolas Ferre 			goto aes_dd_err;
1348be943c7dSNicolas Ferre 		}
1349be943c7dSNicolas Ferre 	}
1350be943c7dSNicolas Ferre 
1351be943c7dSNicolas Ferre 	if (!pdata->dma_slave) {
1352bd3c7b5cSNicolas Royer 		err = -ENXIO;
1353bd3c7b5cSNicolas Royer 		goto aes_dd_err;
1354bd3c7b5cSNicolas Royer 	}
1355bd3c7b5cSNicolas Royer 
1356b0e8b341SLABBE Corentin 	aes_dd = devm_kzalloc(&pdev->dev, sizeof(*aes_dd), GFP_KERNEL);
1357bd3c7b5cSNicolas Royer 	if (aes_dd == NULL) {
1358bd3c7b5cSNicolas Royer 		dev_err(dev, "unable to alloc data struct.\n");
1359bd3c7b5cSNicolas Royer 		err = -ENOMEM;
1360bd3c7b5cSNicolas Royer 		goto aes_dd_err;
1361bd3c7b5cSNicolas Royer 	}
1362bd3c7b5cSNicolas Royer 
1363bd3c7b5cSNicolas Royer 	aes_dd->dev = dev;
1364bd3c7b5cSNicolas Royer 
1365bd3c7b5cSNicolas Royer 	platform_set_drvdata(pdev, aes_dd);
1366bd3c7b5cSNicolas Royer 
1367bd3c7b5cSNicolas Royer 	INIT_LIST_HEAD(&aes_dd->list);
13688a10eb8dSLeilei Zhao 	spin_lock_init(&aes_dd->lock);
1369bd3c7b5cSNicolas Royer 
1370bd3c7b5cSNicolas Royer 	tasklet_init(&aes_dd->done_task, atmel_aes_done_task,
1371bd3c7b5cSNicolas Royer 					(unsigned long)aes_dd);
1372bd3c7b5cSNicolas Royer 	tasklet_init(&aes_dd->queue_task, atmel_aes_queue_task,
1373bd3c7b5cSNicolas Royer 					(unsigned long)aes_dd);
1374bd3c7b5cSNicolas Royer 
1375bd3c7b5cSNicolas Royer 	crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH);
1376bd3c7b5cSNicolas Royer 
1377bd3c7b5cSNicolas Royer 	aes_dd->irq = -1;
1378bd3c7b5cSNicolas Royer 
1379bd3c7b5cSNicolas Royer 	/* Get the base address */
1380bd3c7b5cSNicolas Royer 	aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1381bd3c7b5cSNicolas Royer 	if (!aes_res) {
1382bd3c7b5cSNicolas Royer 		dev_err(dev, "no MEM resource info\n");
1383bd3c7b5cSNicolas Royer 		err = -ENODEV;
1384bd3c7b5cSNicolas Royer 		goto res_err;
1385bd3c7b5cSNicolas Royer 	}
1386bd3c7b5cSNicolas Royer 	aes_dd->phys_base = aes_res->start;
1387bd3c7b5cSNicolas Royer 
1388bd3c7b5cSNicolas Royer 	/* Get the IRQ */
1389bd3c7b5cSNicolas Royer 	aes_dd->irq = platform_get_irq(pdev,  0);
1390bd3c7b5cSNicolas Royer 	if (aes_dd->irq < 0) {
1391bd3c7b5cSNicolas Royer 		dev_err(dev, "no IRQ resource info\n");
1392bd3c7b5cSNicolas Royer 		err = aes_dd->irq;
1393b0e8b341SLABBE Corentin 		goto res_err;
1394bd3c7b5cSNicolas Royer 	}
1395bd3c7b5cSNicolas Royer 
1396b0e8b341SLABBE Corentin 	err = devm_request_irq(&pdev->dev, aes_dd->irq, atmel_aes_irq,
1397b0e8b341SLABBE Corentin 			       IRQF_SHARED, "atmel-aes", aes_dd);
1398bd3c7b5cSNicolas Royer 	if (err) {
1399bd3c7b5cSNicolas Royer 		dev_err(dev, "unable to request aes irq.\n");
1400b0e8b341SLABBE Corentin 		goto res_err;
1401bd3c7b5cSNicolas Royer 	}
1402bd3c7b5cSNicolas Royer 
1403bd3c7b5cSNicolas Royer 	/* Initializing the clock */
1404b0e8b341SLABBE Corentin 	aes_dd->iclk = devm_clk_get(&pdev->dev, "aes_clk");
1405bd3c7b5cSNicolas Royer 	if (IS_ERR(aes_dd->iclk)) {
1406be208356SColin Ian King 		dev_err(dev, "clock initialization failed.\n");
1407bd3c7b5cSNicolas Royer 		err = PTR_ERR(aes_dd->iclk);
1408b0e8b341SLABBE Corentin 		goto res_err;
1409bd3c7b5cSNicolas Royer 	}
1410bd3c7b5cSNicolas Royer 
1411b0e8b341SLABBE Corentin 	aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
1412bd3c7b5cSNicolas Royer 	if (!aes_dd->io_base) {
1413bd3c7b5cSNicolas Royer 		dev_err(dev, "can't ioremap\n");
1414bd3c7b5cSNicolas Royer 		err = -ENOMEM;
1415b0e8b341SLABBE Corentin 		goto res_err;
1416bd3c7b5cSNicolas Royer 	}
1417bd3c7b5cSNicolas Royer 
1418aab0a39bSCyrille Pitchen 	err = atmel_aes_hw_version_init(aes_dd);
1419aab0a39bSCyrille Pitchen 	if (err)
1420aab0a39bSCyrille Pitchen 		goto res_err;
1421cadc4ab8SNicolas Royer 
1422cadc4ab8SNicolas Royer 	atmel_aes_get_cap(aes_dd);
1423cadc4ab8SNicolas Royer 
1424cadc4ab8SNicolas Royer 	err = atmel_aes_buff_init(aes_dd);
1425cadc4ab8SNicolas Royer 	if (err)
1426cadc4ab8SNicolas Royer 		goto err_aes_buff;
1427cadc4ab8SNicolas Royer 
1428cadc4ab8SNicolas Royer 	err = atmel_aes_dma_init(aes_dd, pdata);
1429bd3c7b5cSNicolas Royer 	if (err)
1430bd3c7b5cSNicolas Royer 		goto err_aes_dma;
1431bd3c7b5cSNicolas Royer 
1432bd3c7b5cSNicolas Royer 	spin_lock(&atmel_aes.lock);
1433bd3c7b5cSNicolas Royer 	list_add_tail(&aes_dd->list, &atmel_aes.dev_list);
1434bd3c7b5cSNicolas Royer 	spin_unlock(&atmel_aes.lock);
1435bd3c7b5cSNicolas Royer 
1436bd3c7b5cSNicolas Royer 	err = atmel_aes_register_algs(aes_dd);
1437bd3c7b5cSNicolas Royer 	if (err)
1438bd3c7b5cSNicolas Royer 		goto err_algs;
1439bd3c7b5cSNicolas Royer 
1440be943c7dSNicolas Ferre 	dev_info(dev, "Atmel AES - Using %s, %s for DMA transfers\n",
1441bbe628edSCyrille Pitchen 			dma_chan_name(aes_dd->src.chan),
1442bbe628edSCyrille Pitchen 			dma_chan_name(aes_dd->dst.chan));
1443bd3c7b5cSNicolas Royer 
1444bd3c7b5cSNicolas Royer 	return 0;
1445bd3c7b5cSNicolas Royer 
1446bd3c7b5cSNicolas Royer err_algs:
1447bd3c7b5cSNicolas Royer 	spin_lock(&atmel_aes.lock);
1448bd3c7b5cSNicolas Royer 	list_del(&aes_dd->list);
1449bd3c7b5cSNicolas Royer 	spin_unlock(&atmel_aes.lock);
1450bd3c7b5cSNicolas Royer 	atmel_aes_dma_cleanup(aes_dd);
1451bd3c7b5cSNicolas Royer err_aes_dma:
1452cadc4ab8SNicolas Royer 	atmel_aes_buff_cleanup(aes_dd);
1453cadc4ab8SNicolas Royer err_aes_buff:
1454bd3c7b5cSNicolas Royer res_err:
1455bd3c7b5cSNicolas Royer 	tasklet_kill(&aes_dd->done_task);
1456bd3c7b5cSNicolas Royer 	tasklet_kill(&aes_dd->queue_task);
1457bd3c7b5cSNicolas Royer aes_dd_err:
1458bd3c7b5cSNicolas Royer 	dev_err(dev, "initialization failed.\n");
1459bd3c7b5cSNicolas Royer 
1460bd3c7b5cSNicolas Royer 	return err;
1461bd3c7b5cSNicolas Royer }
1462bd3c7b5cSNicolas Royer 
146349cfe4dbSGreg Kroah-Hartman static int atmel_aes_remove(struct platform_device *pdev)
1464bd3c7b5cSNicolas Royer {
1465bd3c7b5cSNicolas Royer 	static struct atmel_aes_dev *aes_dd;
1466bd3c7b5cSNicolas Royer 
1467bd3c7b5cSNicolas Royer 	aes_dd = platform_get_drvdata(pdev);
1468bd3c7b5cSNicolas Royer 	if (!aes_dd)
1469bd3c7b5cSNicolas Royer 		return -ENODEV;
1470bd3c7b5cSNicolas Royer 	spin_lock(&atmel_aes.lock);
1471bd3c7b5cSNicolas Royer 	list_del(&aes_dd->list);
1472bd3c7b5cSNicolas Royer 	spin_unlock(&atmel_aes.lock);
1473bd3c7b5cSNicolas Royer 
1474bd3c7b5cSNicolas Royer 	atmel_aes_unregister_algs(aes_dd);
1475bd3c7b5cSNicolas Royer 
1476bd3c7b5cSNicolas Royer 	tasklet_kill(&aes_dd->done_task);
1477bd3c7b5cSNicolas Royer 	tasklet_kill(&aes_dd->queue_task);
1478bd3c7b5cSNicolas Royer 
1479bd3c7b5cSNicolas Royer 	atmel_aes_dma_cleanup(aes_dd);
14802a377828SCyrille Pitchen 	atmel_aes_buff_cleanup(aes_dd);
1481bd3c7b5cSNicolas Royer 
1482bd3c7b5cSNicolas Royer 	return 0;
1483bd3c7b5cSNicolas Royer }
1484bd3c7b5cSNicolas Royer 
1485bd3c7b5cSNicolas Royer static struct platform_driver atmel_aes_driver = {
1486bd3c7b5cSNicolas Royer 	.probe		= atmel_aes_probe,
148749cfe4dbSGreg Kroah-Hartman 	.remove		= atmel_aes_remove,
1488bd3c7b5cSNicolas Royer 	.driver		= {
1489bd3c7b5cSNicolas Royer 		.name	= "atmel_aes",
1490be943c7dSNicolas Ferre 		.of_match_table = of_match_ptr(atmel_aes_dt_ids),
1491bd3c7b5cSNicolas Royer 	},
1492bd3c7b5cSNicolas Royer };
1493bd3c7b5cSNicolas Royer 
1494bd3c7b5cSNicolas Royer module_platform_driver(atmel_aes_driver);
1495bd3c7b5cSNicolas Royer 
1496bd3c7b5cSNicolas Royer MODULE_DESCRIPTION("Atmel AES hw acceleration support.");
1497bd3c7b5cSNicolas Royer MODULE_LICENSE("GPL v2");
1498bd3c7b5cSNicolas Royer MODULE_AUTHOR("Nicolas Royer - Eukréa Electromatique");
1499