omap-aes.c revision eeb2b202c5b886b76c3bfa76f47e450fa69389fb
1537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/*
2537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Cryptographic API.
3537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *
4537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Support for OMAP AES HW acceleration.
5537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *
6537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Copyright (c) 2010 Nokia Corporation
7537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
8537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *
9537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * This program is free software; you can redistribute it and/or modify
10537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * it under the terms of the GNU General Public License version 2 as published
11537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin * by the Free Software Foundation.
12537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin *
13537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin */
14537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
15537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define pr_fmt(fmt) "%s: " fmt, __func__
16537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
17537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/err.h>
18537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/module.h>
19537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/init.h>
20537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/errno.h>
21537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/kernel.h>
22537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/clk.h>
23537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/platform_device.h>
24537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/scatterlist.h>
25537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/dma-mapping.h>
26537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/io.h>
27537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/crypto.h>
28537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <linux/interrupt.h>
29537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <crypto/scatterwalk.h>
30537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <crypto/aes.h>
31537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
32537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <plat/cpu.h>
33537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#include <plat/dma.h>
34537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
35537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* OMAP TRM gives bitfields as start:end, where start is the higher bit
36537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin   number. For example 7:0 */
37537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
38537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
39537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
40537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_KEY(x)			(0x1C - ((x ^ 0x01) * 0x04))
41537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_IV(x)			(0x20 + ((x) * 0x04))
42537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
43537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL			0x30
44537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CTR_WIDTH		(1 << 7)
45537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CTR		(1 << 6)
46537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_CBC		(1 << 5)
47537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_KEY_SIZE		(3 << 3)
48537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_DIRECTION		(1 << 2)
49537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_INPUT_READY	(1 << 1)
50537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_CTRL_OUTPUT_READY	(1 << 0)
51537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
52537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_DATA			0x34
53537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_DATA_N(x)		(0x34 + ((x) * 0x04))
54537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
55537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV			0x44
56537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV_MAJOR		0xF0
57537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_REV_MINOR		0x0F
58537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
59537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK			0x48
60537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_SIDLE		(1 << 6)
61537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_START		(1 << 5)
62537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_DMA_OUT_EN		(1 << 3)
63537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_DMA_IN_EN		(1 << 2)
64537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_MASK_SOFTRESET		(1 << 1)
65537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_AUTOIDLE		(1 << 0)
66537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
67537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_SYSSTATUS		0x4C
68537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define AES_REG_SYSSTATUS_RESETDONE	(1 << 0)
69537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
70537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define DEFAULT_TIMEOUT		(5*HZ)
71537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
72537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_MODE_MASK		0x000f
73537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_ENCRYPT		BIT(0)
74537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_CBC		BIT(1)
75537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_GIV		BIT(2)
76537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
77537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_NEW_KEY		BIT(4)
78537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_NEW_IV		BIT(5)
79537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_INIT		BIT(6)
80537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define FLAGS_FAST		BIT(7)
81eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin#define FLAGS_BUSY		BIT(8)
82537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
83537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_ctx {
84537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd;
85537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
86537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int		keylen;
87537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32		key[AES_KEYSIZE_256 / sizeof(u32)];
88537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long	flags;
89537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin};
90537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
91537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_reqctx {
92537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long mode;
93537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin};
94537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
95537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define OMAP_AES_QUEUE_LENGTH	1
96537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin#define OMAP_AES_CACHE_SIZE	0
97537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
98537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstruct omap_aes_dev {
99537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct list_head	list;
100537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long		phys_base;
101537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	void __iomem 		*io_base;
102537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct clk		*iclk;
103537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx	*ctx;
104537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct device		*dev;
105537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long		flags;
106537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
107537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32			*iv;
108537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32			ctrl;
109537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
110537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spinlock_t			lock;
111537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct crypto_queue		queue;
112537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
113537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct tasklet_struct		task;
114537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
115537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct ablkcipher_request	*req;
116537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t				total;
117537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct scatterlist		*in_sg;
118537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t				in_offset;
119537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct scatterlist		*out_sg;
120537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t				out_offset;
121537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
122537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t			buflen;
123537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	void			*buf_in;
124537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t			dma_size;
125537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int			dma_in;
126537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int			dma_lch_in;
127537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_addr_t		dma_addr_in;
128537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	void			*buf_out;
129537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int			dma_out;
130537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int			dma_lch_out;
131537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_addr_t		dma_addr_out;
132537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin};
133537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
134537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* keep registered devices data here */
135537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic LIST_HEAD(dev_list);
136537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic DEFINE_SPINLOCK(list_lock);
137537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
138537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline u32 omap_aes_read(struct omap_aes_dev *dd, u32 offset)
139537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
140537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return __raw_readl(dd->io_base + offset);
141537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
142537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
143537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline void omap_aes_write(struct omap_aes_dev *dd, u32 offset,
144537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				  u32 value)
145537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
146537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	__raw_writel(value, dd->io_base + offset);
147537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
148537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
149537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic inline void omap_aes_write_mask(struct omap_aes_dev *dd, u32 offset,
150537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					u32 value, u32 mask)
151537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
152537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32 val;
153537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
154537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	val = omap_aes_read(dd, offset);
155537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	val &= ~mask;
156537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	val |= value;
157537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write(dd, offset, val);
158537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
159537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
160537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset,
161537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					u32 *value, int count)
162537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
163537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	for (; count--; value++, offset += 4)
164537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		omap_aes_write(dd, offset, *value);
165537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
166537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
167537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit)
168537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
169537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long timeout = jiffies + DEFAULT_TIMEOUT;
170537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
171537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	while (!(omap_aes_read(dd, offset) & bit)) {
172537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (time_is_before_jiffies(timeout)) {
173537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			dev_err(dd->dev, "omap-aes timeout\n");
174537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			return -ETIMEDOUT;
175537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
176537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
177537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
178537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
179537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
180537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_hw_init(struct omap_aes_dev *dd)
181537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
182537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	clk_enable(dd->iclk);
183eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin
184537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!(dd->flags & FLAGS_INIT)) {
185537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* is it necessary to reset before every operation? */
186537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
187537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					AES_REG_MASK_SOFTRESET);
188537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/*
189537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		 * prevent OCP bus error (SRESP) in case an access to the module
190537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		 * is performed while the module is coming out of soft reset
191537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		 */
192537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		__asm__ __volatile__("nop");
193537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		__asm__ __volatile__("nop");
194537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
195eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
196eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin				AES_REG_SYSSTATUS_RESETDONE)) {
197eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin			clk_disable(dd->iclk);
198eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin			return -ETIMEDOUT;
199eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		}
200eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		dd->flags |= FLAGS_INIT;
201537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
202537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
203eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	return 0;
204537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
205537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
206537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_write_ctrl(struct omap_aes_dev *dd)
207537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
208537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned int key32;
209537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int i;
210537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32 val, mask;
211537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
212537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
213537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->flags & FLAGS_CBC)
214537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		val |= AES_REG_CTRL_CBC;
215537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->flags & FLAGS_ENCRYPT)
216537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		val |= AES_REG_CTRL_DIRECTION;
217537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
218537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) &&
219537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		   !(dd->ctx->flags & FLAGS_NEW_KEY))
220537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto out;
221537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
222537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* only need to write control registers for new settings */
223537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
224537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->ctrl = val;
225537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
226537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	val = 0;
227537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->dma_lch_out >= 0)
228537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		val |= AES_REG_MASK_DMA_OUT_EN;
229537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->dma_lch_in >= 0)
230537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		val |= AES_REG_MASK_DMA_IN_EN;
231537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
232537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
233537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
234537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write_mask(dd, AES_REG_MASK, val, mask);
235537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
236537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("Set key\n");
237537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	key32 = dd->ctx->keylen / sizeof(u32);
238537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* set a key */
239537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	for (i = 0; i < key32; i++) {
240537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		omap_aes_write(dd, AES_REG_KEY(i),
241537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			__le32_to_cpu(dd->ctx->key[i]));
242537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
243537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->ctx->flags &= ~FLAGS_NEW_KEY;
244537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
245537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->flags & FLAGS_NEW_IV) {
246537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_debug("Set IV\n");
247537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		omap_aes_write_n(dd, AES_REG_IV(0), dd->iv, 4);
248537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->flags &= ~FLAGS_NEW_IV;
249537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
250537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
251537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
252537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			AES_REG_CTRL_KEY_SIZE;
253537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
254537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write_mask(dd, AES_REG_CTRL, dd->ctrl, mask);
255537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
256537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinout:
257537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* start DMA or disable idle mode */
258537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
259537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			    AES_REG_MASK_START);
260537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
261537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
262537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
263537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
264537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd = NULL, *tmp;
265537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
266537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_lock_bh(&list_lock);
267537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!ctx->dd) {
268537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		list_for_each_entry(tmp, &dev_list, list) {
269537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			/* FIXME: take fist available aes core */
270537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			dd = tmp;
271537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			break;
272537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
273537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		ctx->dd = dd;
274537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	} else {
275537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* already found before */
276537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd = ctx->dd;
277537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
278537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_unlock_bh(&list_lock);
279537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
280537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return dd;
281537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
282537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
283537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
284537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
285537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd = data;
286537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
287537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (lch == dd->dma_lch_out)
288537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		tasklet_schedule(&dd->task);
289537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
290537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
291537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_dma_init(struct omap_aes_dev *dd)
292537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
293537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int err = -ENOMEM;
294537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
295537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dma_lch_out = -1;
296537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dma_lch_in = -1;
297537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
298537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
299537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
300537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->buflen = PAGE_SIZE << OMAP_AES_CACHE_SIZE;
301537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->buflen &= ~(AES_BLOCK_SIZE - 1);
302537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
303537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd->buf_in || !dd->buf_out) {
304537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dd->dev, "unable to alloc pages.\n");
305537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_alloc;
306537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
307537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
308537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* MAP here */
309537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->buflen,
310537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					 DMA_TO_DEVICE);
311537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dma_mapping_error(dd->dev, dd->dma_addr_in)) {
312537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
313537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = -EINVAL;
314537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_map_in;
315537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
316537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
317537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->buflen,
318537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					  DMA_FROM_DEVICE);
319537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dma_mapping_error(dd->dev, dd->dma_addr_out)) {
320537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dd->dev, "dma %d bytes error\n", dd->buflen);
321537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = -EINVAL;
322537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_map_out;
323537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
324537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
325537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	err = omap_request_dma(dd->dma_in, "omap-aes-rx",
326537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			       omap_aes_dma_callback, dd, &dd->dma_lch_in);
327537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (err) {
328537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dd->dev, "Unable to request DMA channel\n");
329537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_dma_in;
330537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
331537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	err = omap_request_dma(dd->dma_out, "omap-aes-tx",
332537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			       omap_aes_dma_callback, dd, &dd->dma_lch_out);
333537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (err) {
334537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dd->dev, "Unable to request DMA channel\n");
335537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_dma_out;
336537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
337537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
338537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
339537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
340537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma_out:
341537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_free_dma(dd->dma_lch_in);
342537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma_in:
343537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
344537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			 DMA_FROM_DEVICE);
345537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_map_out:
346537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
347537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_map_in:
348537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	free_pages((unsigned long)dd->buf_out, OMAP_AES_CACHE_SIZE);
349537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	free_pages((unsigned long)dd->buf_in, OMAP_AES_CACHE_SIZE);
350537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_alloc:
351537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (err)
352537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_err("error: %d\n", err);
353537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return err;
354537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
355537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
356537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
357537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
358537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_free_dma(dd->dma_lch_out);
359537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_free_dma(dd->dma_lch_in);
360537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
361537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			 DMA_FROM_DEVICE);
362537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
363537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	free_pages((unsigned long)dd->buf_out, OMAP_AES_CACHE_SIZE);
364537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	free_pages((unsigned long)dd->buf_in, OMAP_AES_CACHE_SIZE);
365537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
366537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
367537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void sg_copy_buf(void *buf, struct scatterlist *sg,
368537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			      unsigned int start, unsigned int nbytes, int out)
369537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
370537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct scatter_walk walk;
371537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
372537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!nbytes)
373537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return;
374537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
375537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	scatterwalk_start(&walk, sg);
376537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	scatterwalk_advance(&walk, start);
377537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	scatterwalk_copychunks(buf, &walk, nbytes, out);
378537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	scatterwalk_done(&walk, out, 0);
379537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
380537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
381537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
382537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		   size_t buflen, size_t total, int out)
383537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
384537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned int count, off = 0;
385537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
386537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	while (buflen && total) {
387537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = min((*sg)->length - *offset, total);
388537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = min(count, buflen);
389537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
390537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (!count)
391537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			return off;
392537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
393537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		sg_copy_buf(buf + off, *sg, *offset, count, out);
394537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
395537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		off += count;
396537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		buflen -= count;
397537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		*offset += count;
398537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		total -= count;
399537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
400537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (*offset == (*sg)->length) {
401537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			*sg = sg_next(*sg);
402537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			if (*sg)
403537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				*offset = 0;
404537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			else
405537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				total = 0;
406537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
407537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
408537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
409537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return off;
410537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
411537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
412537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
413537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			       dma_addr_t dma_addr_out, int length)
414537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
415537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
416537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd = ctx->dd;
417537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int len32;
418537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
419537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("len: %d\n", length);
420537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
421537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dma_size = length;
422537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
423537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!(dd->flags & FLAGS_FAST))
424537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dma_sync_single_for_device(dd->dev, dma_addr_in, length,
425537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					   DMA_TO_DEVICE);
426537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
427537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	len32 = DIV_ROUND_UP(length, sizeof(u32));
428537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
429537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* IN */
4303bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
4313bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin				 dd->phys_base + AES_REG_DATA, 0, 4);
4323bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin
4333bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
4343bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
4353bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin
436537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
437537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				     len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
438537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					OMAP_DMA_DST_SYNC);
439537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
440537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_set_dma_src_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_POST_INC,
441537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				dma_addr_in, 0, 0);
442537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
443537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* OUT */
4443bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
4453bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin				dd->phys_base + AES_REG_DATA, 0, 4);
4463bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin
4473bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
4483bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin	omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
4493bd2e2216bc82a83fc5048f8e61d2d22dd5d9cdaDmitry Kasatkin
450537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
451537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				     len32, 1, OMAP_DMA_SYNC_PACKET,
452537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					dd->dma_out, OMAP_DMA_SRC_SYNC);
453537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
454537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC,
455537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				 dma_addr_out, 0, 0);
456537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
457537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_start_dma(dd->dma_lch_in);
458537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_start_dma(dd->dma_lch_out);
459537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
460537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write_ctrl(dd);
461537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
462537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
463537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
464537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
465537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
466537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
467537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
468537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					crypto_ablkcipher_reqtfm(dd->req));
469537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int err, fast = 0, in, out;
470537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t count;
471537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dma_addr_t addr_in, addr_out;
472537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
473537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("total: %d\n", dd->total);
474537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
475537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
476537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* check for alignment */
477537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
478537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
479537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
480537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		fast = in && out;
481537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
482537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
483537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (fast)  {
484537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = min(dd->total, sg_dma_len(dd->in_sg));
485537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = min(count, sg_dma_len(dd->out_sg));
486537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
487537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (count != dd->total)
488537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			return -EINVAL;
489537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
490537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_debug("fast\n");
491537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
492537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
493537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (!err) {
494537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			dev_err(dd->dev, "dma_map_sg() error\n");
495537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			return -EINVAL;
496537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
497537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
498537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = dma_map_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
499537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (!err) {
500537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			dev_err(dd->dev, "dma_map_sg() error\n");
501537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
502537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			return -EINVAL;
503537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
504537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
505537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		addr_in = sg_dma_address(dd->in_sg);
506537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		addr_out = sg_dma_address(dd->out_sg);
507537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
508537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->flags |= FLAGS_FAST;
509537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
510537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	} else {
511537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* use cache buffers */
512537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
513537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				 dd->buflen, dd->total, 0);
514537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
515537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		addr_in = dd->dma_addr_in;
516537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		addr_out = dd->dma_addr_out;
517537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
518537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->flags &= ~FLAGS_FAST;
519537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
520537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
521537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
522537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->total -= count;
523537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
524537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	err = omap_aes_hw_init(dd);
525537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
526537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
527537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
528537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return err;
529537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
530537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
531537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
532537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
533537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx *ctx;
534537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
535537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("err: %d\n", err);
536537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
537eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	dd->flags &= ~FLAGS_BUSY;
538eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin
539537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req));
540537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
541537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd->total)
542537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->req->base.complete(&dd->req->base, err);
543537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
544537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
545537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
546537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
547537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int err = 0;
548537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	size_t count;
549537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
550537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("total: %d\n", dd->total);
551537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
552537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
553537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
554eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	clk_disable(dd->iclk);
555537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
556537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_stop_dma(dd->dma_lch_in);
557537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_stop_dma(dd->dma_lch_out);
558537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
559537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->flags & FLAGS_FAST) {
560537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
561537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
562537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	} else {
563537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
564537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin					   dd->dma_size, DMA_FROM_DEVICE);
565537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
566537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* copy data */
567537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		count = sg_copy(&dd->out_sg, &dd->out_offset, dd->buf_out,
568537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin				 dd->buflen, dd->dma_size, 1);
569537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (count != dd->dma_size) {
570537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			err = -EINVAL;
571537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			pr_err("not all data converted: %u\n", count);
572537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		}
573537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
574537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
575537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (err || !dd->total)
576537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		omap_aes_finish_req(dd, err);
577537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
578537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return err;
579537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
580537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
581eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkinstatic int omap_aes_handle_req(struct omap_aes_dev *dd,
582eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin			       struct ablkcipher_request *req)
583537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
584537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct crypto_async_request *async_req, *backlog;
585537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx *ctx;
586537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_reqctx *rctx;
587537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	unsigned long flags;
588eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	int err = 0;
589537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
590537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_lock_irqsave(&dd->lock, flags);
591eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	if (req)
592eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		err = ablkcipher_enqueue_request(&dd->queue, req);
593eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	if (dd->flags & FLAGS_BUSY) {
594eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		spin_unlock_irqrestore(&dd->lock, flags);
595eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		return err;
596eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	}
597537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	backlog = crypto_get_backlog(&dd->queue);
598537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	async_req = crypto_dequeue_request(&dd->queue);
599eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	if (async_req)
600eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		dd->flags |= FLAGS_BUSY;
601537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_unlock_irqrestore(&dd->lock, flags);
602537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
603537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!async_req)
604537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return 0;
605537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
606537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (backlog)
607537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		backlog->complete(backlog, -EINPROGRESS);
608537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
609537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	req = ablkcipher_request_cast(async_req);
610537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
611537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("get new req\n");
612537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
613537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* assign new request to device */
614537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->req = req;
615537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->total = req->nbytes;
616537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->in_offset = 0;
617537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->in_sg = req->src;
618537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->out_offset = 0;
619537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->out_sg = req->dst;
620537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
621537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	rctx = ablkcipher_request_ctx(req);
622537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
623537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	rctx->mode &= FLAGS_MODE_MASK;
624537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
625537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
626537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->iv = req->info;
627537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if ((dd->flags & FLAGS_CBC) && dd->iv)
628537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->flags |= FLAGS_NEW_IV;
629537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	else
630537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->flags &= ~FLAGS_NEW_IV;
631537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
632537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	ctx->dd = dd;
633537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd->ctx != ctx) {
634537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		/* assign new context to device */
635537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->ctx = ctx;
636537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		ctx->flags |= FLAGS_NEW_KEY;
637537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
638537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
639537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
640537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_err("request size is not exact amount of AES blocks\n");
641537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
642eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	omap_aes_crypt_dma_start(dd);
643eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin
644eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	return err;
645537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
646537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
647537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_task(unsigned long data)
648537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
649537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
650537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
651537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("enter\n");
652537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
653eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	omap_aes_crypt_dma_stop(dd);
654537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
655eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	if (dd->total)
656eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		omap_aes_crypt_dma_start(dd);
657eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	else
658eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin		omap_aes_handle_req(dd, NULL);
659537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
660537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("exit\n");
661537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
662537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
663537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
664537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
665537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
666537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			crypto_ablkcipher_reqtfm(req));
667537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
668537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd;
669537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
670537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
671537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		  !!(mode & FLAGS_ENCRYPT),
672537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		  !!(mode & FLAGS_CBC));
673537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
674537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd = omap_aes_find_dev(ctx);
675537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd)
676537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return -ENODEV;
677537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
678537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	rctx->mode = mode;
679537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
680eeb2b202c5b886b76c3bfa76f47e450fa69389fbDmitry Kasatkin	return omap_aes_handle_req(dd, req);
681537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
682537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
683537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* ********************** ALG API ************************************ */
684537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
685537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
686537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			   unsigned int keylen)
687537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
688537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
689537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
690537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
691537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		   keylen != AES_KEYSIZE_256)
692537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return -EINVAL;
693537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
694537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("enter, keylen: %d\n", keylen);
695537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
696537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	memcpy(ctx->key, key, keylen);
697537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	ctx->keylen = keylen;
698537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	ctx->flags |= FLAGS_NEW_KEY;
699537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
700537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
701537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
702537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
703537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_ecb_encrypt(struct ablkcipher_request *req)
704537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
705537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return omap_aes_crypt(req, FLAGS_ENCRYPT);
706537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
707537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
708537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_ecb_decrypt(struct ablkcipher_request *req)
709537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
710537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return omap_aes_crypt(req, 0);
711537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
712537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
713537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cbc_encrypt(struct ablkcipher_request *req)
714537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
715537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
716537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
717537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
718537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cbc_decrypt(struct ablkcipher_request *req)
719537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
720537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return omap_aes_crypt(req, FLAGS_CBC);
721537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
722537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
723537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_cra_init(struct crypto_tfm *tfm)
724537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
725537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("enter\n");
726537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
727537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
728537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
729537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
730537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
731537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
732537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void omap_aes_cra_exit(struct crypto_tfm *tfm)
733537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
734537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_debug("enter\n");
735537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
736537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
737537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin/* ********************** ALGS ************************************ */
738537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
739537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct crypto_alg algs[] = {
740537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
741537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_name		= "ecb(aes)",
742537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_driver_name	= "ecb-aes-omap",
743537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_priority		= 100,
744537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
745537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_blocksize		= AES_BLOCK_SIZE,
746537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
747537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_alignmask	 	= 0,
748537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_type		= &crypto_ablkcipher_type,
749537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_module		= THIS_MODULE,
750537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_init		= omap_aes_cra_init,
751537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_exit		= omap_aes_cra_exit,
752537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_u.ablkcipher = {
753537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.min_keysize	= AES_MIN_KEY_SIZE,
754537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.max_keysize	= AES_MAX_KEY_SIZE,
755537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.setkey		= omap_aes_setkey,
756537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.encrypt	= omap_aes_ecb_encrypt,
757537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.decrypt	= omap_aes_ecb_decrypt,
758537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
759537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin},
760537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
761537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_name		= "cbc(aes)",
762537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_driver_name	= "cbc-aes-omap",
763537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_priority		= 100,
764537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
765537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_blocksize		= AES_BLOCK_SIZE,
766537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
767537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_alignmask	 	= 0,
768537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_type		= &crypto_ablkcipher_type,
769537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_module		= THIS_MODULE,
770537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_init		= omap_aes_cra_init,
771537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_exit		= omap_aes_cra_exit,
772537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.cra_u.ablkcipher = {
773537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.min_keysize	= AES_MIN_KEY_SIZE,
774537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.max_keysize	= AES_MAX_KEY_SIZE,
775537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.ivsize		= AES_BLOCK_SIZE,
776537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.setkey		= omap_aes_setkey,
777537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.encrypt	= omap_aes_cbc_encrypt,
778537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.decrypt	= omap_aes_cbc_decrypt,
779537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
780537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
781537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin};
782537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
783537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_probe(struct platform_device *pdev)
784537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
785537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct device *dev = &pdev->dev;
786537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd;
787537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct resource *res;
788537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int err = -ENOMEM, i, j;
789537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	u32 reg;
790537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
791537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd = kzalloc(sizeof(struct omap_aes_dev), GFP_KERNEL);
792537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (dd == NULL) {
793537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dev, "unable to alloc data struct.\n");
794537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_data;
795537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
796537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->dev = dev;
797537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	platform_set_drvdata(pdev, dd);
798537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
799537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_lock_init(&dd->lock);
800537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH);
801537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
802537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* Get the base address */
803537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
804537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!res) {
805537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dev, "invalid resource type\n");
806537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = -ENODEV;
807537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_res;
808537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
809537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->phys_base = res->start;
810537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
811537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* Get the DMA */
812537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
813537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!res)
814537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_info(dev, "no DMA info\n");
815537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	else
816537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->dma_out = res->start;
817537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
818537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* Get the DMA */
819537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
820537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!res)
821537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_info(dev, "no DMA info\n");
822537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	else
823537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dd->dma_in = res->start;
824537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
825537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	/* Initializing the clock */
826537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->iclk = clk_get(dev, "ick");
827537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd->iclk) {
828537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dev, "clock intialization failed.\n");
829537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = -ENODEV;
830537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_res;
831537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
832537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
833537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd->io_base = ioremap(dd->phys_base, SZ_4K);
834537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd->io_base) {
835537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		dev_err(dev, "can't ioremap\n");
836537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = -ENOMEM;
837537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_io;
838537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
839537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
840537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	clk_enable(dd->iclk);
841537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	reg = omap_aes_read(dd, AES_REG_REV);
842537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
843537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		 (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
844537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	clk_disable(dd->iclk);
845537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
846537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	tasklet_init(&dd->task, omap_aes_task, (unsigned long)dd);
847537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
848537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	err = omap_aes_dma_init(dd);
849537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (err)
850537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		goto err_dma;
851537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
852537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	INIT_LIST_HEAD(&dd->list);
853537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_lock(&list_lock);
854537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	list_add_tail(&dd->list, &dev_list);
855537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_unlock(&list_lock);
856537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
857537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	for (i = 0; i < ARRAY_SIZE(algs); i++) {
858537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_debug("i: %d\n", i);
859537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		INIT_LIST_HEAD(&algs[i].cra_list);
860537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		err = crypto_register_alg(&algs[i]);
861537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		if (err)
862537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin			goto err_algs;
863537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
864537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
865537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_info("probe() done\n");
866537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
867537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
868537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_algs:
869537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	for (j = 0; j < i; j++)
870537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		crypto_unregister_alg(&algs[j]);
871537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_dma_cleanup(dd);
872537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_dma:
873537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	tasklet_kill(&dd->task);
874537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	iounmap(dd->io_base);
875537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_io:
876537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	clk_put(dd->iclk);
877537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_res:
878537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	kfree(dd);
879537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd = NULL;
880537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinerr_data:
881537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dev_err(dev, "initialization failed.\n");
882537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return err;
883537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
884537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
885537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int omap_aes_remove(struct platform_device *pdev)
886537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
887537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	struct omap_aes_dev *dd = platform_get_drvdata(pdev);
888537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	int i;
889537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
890537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!dd)
891537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return -ENODEV;
892537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
893537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_lock(&list_lock);
894537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	list_del(&dd->list);
895537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	spin_unlock(&list_lock);
896537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
897537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	for (i = 0; i < ARRAY_SIZE(algs); i++)
898537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		crypto_unregister_alg(&algs[i]);
899537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
900537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	tasklet_kill(&dd->task);
901537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	omap_aes_dma_cleanup(dd);
902537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	iounmap(dd->io_base);
903537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	clk_put(dd->iclk);
904537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	kfree(dd);
905537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	dd = NULL;
906537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
907537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return 0;
908537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
909537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
910537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic struct platform_driver omap_aes_driver = {
911537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.probe	= omap_aes_probe,
912537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.remove	= omap_aes_remove,
913537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	.driver	= {
914537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.name	= "omap-aes",
915537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		.owner	= THIS_MODULE,
916537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	},
917537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin};
918537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
919537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic int __init omap_aes_mod_init(void)
920537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
921537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	pr_info("loading %s driver\n", "omap-aes");
922537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
923537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	if (!cpu_class_is_omap2() || omap_type() != OMAP2_DEVICE_TYPE_SEC) {
924537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		pr_err("Unsupported cpu\n");
925537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin		return -ENODEV;
926537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	}
927537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
928537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	return  platform_driver_register(&omap_aes_driver);
929537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
930537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
931537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinstatic void __exit omap_aes_mod_exit(void)
932537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin{
933537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin	platform_driver_unregister(&omap_aes_driver);
934537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin}
935537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
936537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinmodule_init(omap_aes_mod_init);
937537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkinmodule_exit(omap_aes_mod_exit);
938537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
939537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_DESCRIPTION("OMAP AES hw acceleration support.");
940537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_LICENSE("GPL v2");
941537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry KasatkinMODULE_AUTHOR("Dmitry Kasatkin");
942537559a5b3ef854772bd89fbb43aa77d0bbfb721Dmitry Kasatkin
943