Blame view

drivers/crypto/omap-sham.c 51.9 KB
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1
2
3
4
5
6
7
  /*
   * Cryptographic API.
   *
   * Support for OMAP SHA1/MD5 HW acceleration.
   *
   * Copyright (c) 2010 Nokia Corporation
   * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
0d373d603   Mark A. Greer   crypto: omap-sham...
8
   * Copyright (c) 2011 Texas Instruments Incorporated
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
9
10
11
12
13
14
15
16
17
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as published
   * by the Free Software Foundation.
   *
   * Some ideas are from old omap-sha1-md5.c driver.
   */
  
  #define pr_fmt(fmt) "%s: " fmt, __func__
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
18
19
20
21
22
23
24
  #include <linux/err.h>
  #include <linux/device.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/kernel.h>
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
25
26
27
28
29
  #include <linux/irq.h>
  #include <linux/io.h>
  #include <linux/platform_device.h>
  #include <linux/scatterlist.h>
  #include <linux/dma-mapping.h>
dfd061d5a   Mark A. Greer   crypto: omap-sham...
30
  #include <linux/dmaengine.h>
b359f034c   Mark A. Greer   crypto: omap-sham...
31
  #include <linux/pm_runtime.h>
03feec9cc   Mark A. Greer   crypto: omap-sham...
32
33
34
35
  #include <linux/of.h>
  #include <linux/of_device.h>
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
36
37
38
39
40
41
42
43
  #include <linux/delay.h>
  #include <linux/crypto.h>
  #include <linux/cryptohash.h>
  #include <crypto/scatterwalk.h>
  #include <crypto/algapi.h>
  #include <crypto/sha.h>
  #include <crypto/hash.h>
  #include <crypto/internal/hash.h>
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
44
  #define MD5_DIGEST_SIZE			16
0d373d603   Mark A. Greer   crypto: omap-sham...
45
46
47
  #define SHA_REG_IDIGEST(dd, x)		((dd)->pdata->idigest_ofs + ((x)*0x04))
  #define SHA_REG_DIN(dd, x)		((dd)->pdata->din_ofs + ((x) * 0x04))
  #define SHA_REG_DIGCNT(dd)		((dd)->pdata->digcnt_ofs)
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
48
  #define SHA_REG_ODIGEST(dd, x)		((dd)->pdata->odigest_ofs + (x * 0x04))
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
49
50
51
52
53
54
55
56
  
  #define SHA_REG_CTRL			0x18
  #define SHA_REG_CTRL_LENGTH		(0xFFFFFFFF << 5)
  #define SHA_REG_CTRL_CLOSE_HASH		(1 << 4)
  #define SHA_REG_CTRL_ALGO_CONST		(1 << 3)
  #define SHA_REG_CTRL_ALGO		(1 << 2)
  #define SHA_REG_CTRL_INPUT_READY	(1 << 1)
  #define SHA_REG_CTRL_OUTPUT_READY	(1 << 0)
0d373d603   Mark A. Greer   crypto: omap-sham...
57
  #define SHA_REG_REV(dd)			((dd)->pdata->rev_ofs)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
58

0d373d603   Mark A. Greer   crypto: omap-sham...
59
  #define SHA_REG_MASK(dd)		((dd)->pdata->mask_ofs)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
60
61
62
63
  #define SHA_REG_MASK_DMA_EN		(1 << 3)
  #define SHA_REG_MASK_IT_EN		(1 << 2)
  #define SHA_REG_MASK_SOFTRESET		(1 << 1)
  #define SHA_REG_AUTOIDLE		(1 << 0)
0d373d603   Mark A. Greer   crypto: omap-sham...
64
  #define SHA_REG_SYSSTATUS(dd)		((dd)->pdata->sysstatus_ofs)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
65
  #define SHA_REG_SYSSTATUS_RESETDONE	(1 << 0)
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
66
  #define SHA_REG_MODE(dd)		((dd)->pdata->mode_ofs)
0d373d603   Mark A. Greer   crypto: omap-sham...
67
68
69
70
  #define SHA_REG_MODE_HMAC_OUTER_HASH	(1 << 7)
  #define SHA_REG_MODE_HMAC_KEY_PROC	(1 << 5)
  #define SHA_REG_MODE_CLOSE_HASH		(1 << 4)
  #define SHA_REG_MODE_ALGO_CONSTANT	(1 << 3)
0d373d603   Mark A. Greer   crypto: omap-sham...
71

eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
72
73
74
75
76
77
78
79
80
  #define SHA_REG_MODE_ALGO_MASK		(7 << 0)
  #define SHA_REG_MODE_ALGO_MD5_128	(0 << 1)
  #define SHA_REG_MODE_ALGO_SHA1_160	(1 << 1)
  #define SHA_REG_MODE_ALGO_SHA2_224	(2 << 1)
  #define SHA_REG_MODE_ALGO_SHA2_256	(3 << 1)
  #define SHA_REG_MODE_ALGO_SHA2_384	(1 << 0)
  #define SHA_REG_MODE_ALGO_SHA2_512	(3 << 0)
  
  #define SHA_REG_LENGTH(dd)		((dd)->pdata->length_ofs)
0d373d603   Mark A. Greer   crypto: omap-sham...
81
82
83
84
85
86
87
88
89
90
91
92
  
  #define SHA_REG_IRQSTATUS		0x118
  #define SHA_REG_IRQSTATUS_CTX_RDY	(1 << 3)
  #define SHA_REG_IRQSTATUS_PARTHASH_RDY (1 << 2)
  #define SHA_REG_IRQSTATUS_INPUT_RDY	(1 << 1)
  #define SHA_REG_IRQSTATUS_OUTPUT_RDY	(1 << 0)
  
  #define SHA_REG_IRQENA			0x11C
  #define SHA_REG_IRQENA_CTX_RDY		(1 << 3)
  #define SHA_REG_IRQENA_PARTHASH_RDY	(1 << 2)
  #define SHA_REG_IRQENA_INPUT_RDY	(1 << 1)
  #define SHA_REG_IRQENA_OUTPUT_RDY	(1 << 0)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
93
  #define DEFAULT_TIMEOUT_INTERVAL	HZ
e93f767be   Tero Kristo   crypto: omap-sham...
94
  #define DEFAULT_AUTOSUSPEND_DELAY	1000
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
95
96
97
98
99
100
101
  /* mostly device flags */
  #define FLAGS_BUSY		0
  #define FLAGS_FINAL		1
  #define FLAGS_DMA_ACTIVE	2
  #define FLAGS_OUTPUT_READY	3
  #define FLAGS_INIT		4
  #define FLAGS_CPU		5
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
102
  #define FLAGS_DMA_READY		6
0d373d603   Mark A. Greer   crypto: omap-sham...
103
104
  #define FLAGS_AUTO_XOR		7
  #define FLAGS_BE32_SHA1		8
f19de1bc6   Tero Kristo   crypto: omap-sham...
105
106
  #define FLAGS_SGS_COPIED	9
  #define FLAGS_SGS_ALLOCED	10
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
107
108
  /* context flags */
  #define FLAGS_FINUP		16
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
109

0d373d603   Mark A. Greer   crypto: omap-sham...
110
  #define FLAGS_MODE_SHIFT	18
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
111
112
113
114
115
116
117
118
119
120
  #define FLAGS_MODE_MASK		(SHA_REG_MODE_ALGO_MASK	<< FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_MD5		(SHA_REG_MODE_ALGO_MD5_128 << FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_SHA1		(SHA_REG_MODE_ALGO_SHA1_160 << FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_SHA224	(SHA_REG_MODE_ALGO_SHA2_224 << FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_SHA256	(SHA_REG_MODE_ALGO_SHA2_256 << FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_SHA384	(SHA_REG_MODE_ALGO_SHA2_384 << FLAGS_MODE_SHIFT)
  #define FLAGS_MODE_SHA512	(SHA_REG_MODE_ALGO_SHA2_512 << FLAGS_MODE_SHIFT)
  
  #define FLAGS_HMAC		21
  #define FLAGS_ERROR		22
0d373d603   Mark A. Greer   crypto: omap-sham...
121
122
123
  
  #define OP_UPDATE		1
  #define OP_FINAL		2
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
124

798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
125
126
  #define OMAP_ALIGN_MASK		(sizeof(u32)-1)
  #define OMAP_ALIGNED		__attribute__((aligned(sizeof(u32))))
182e283f3   Tero Kristo   crypto: omap-sham...
127
  #define BUFLEN			SHA512_BLOCK_SIZE
2c5bd1ef1   Tero Kristo   crypto: omap-sham...
128
  #define OMAP_SHA_DMA_THRESHOLD	256
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
129

8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
130
131
132
133
134
135
  struct omap_sham_dev;
  
  struct omap_sham_reqctx {
  	struct omap_sham_dev	*dd;
  	unsigned long		flags;
  	unsigned long		op;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
136
  	u8			digest[SHA512_DIGEST_SIZE] OMAP_ALIGNED;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
137
  	size_t			digcnt;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
138
139
  	size_t			bufcnt;
  	size_t			buflen;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
140
141
142
  
  	/* walk state */
  	struct scatterlist	*sg;
f19de1bc6   Tero Kristo   crypto: omap-sham...
143
  	struct scatterlist	sgl[2];
8043bb1ae   Tero Kristo   crypto: omap-sham...
144
  	int			offset;	/* offset in current sg */
f19de1bc6   Tero Kristo   crypto: omap-sham...
145
  	int			sg_len;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
146
  	unsigned int		total;	/* total request */
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
147
148
  
  	u8			buffer[0] OMAP_ALIGNED;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
149
150
151
152
  };
  
  struct omap_sham_hmac_ctx {
  	struct crypto_shash	*shash;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
153
154
  	u8			ipad[SHA512_BLOCK_SIZE] OMAP_ALIGNED;
  	u8			opad[SHA512_BLOCK_SIZE] OMAP_ALIGNED;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
155
156
157
158
159
160
161
162
163
164
165
166
  };
  
  struct omap_sham_ctx {
  	struct omap_sham_dev	*dd;
  
  	unsigned long		flags;
  
  	/* fallback stuff */
  	struct crypto_shash	*fallback;
  
  	struct omap_sham_hmac_ctx base[0];
  };
65e7a549a   Tero Kristo   crypto: omap-sham...
167
  #define OMAP_SHAM_QUEUE_LENGTH	10
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
168

d20fb18be   Mark A. Greer   crypto: omap-sham...
169
170
171
172
173
  struct omap_sham_algs_info {
  	struct ahash_alg	*algs_list;
  	unsigned int		size;
  	unsigned int		registered;
  };
0d373d603   Mark A. Greer   crypto: omap-sham...
174
  struct omap_sham_pdata {
d20fb18be   Mark A. Greer   crypto: omap-sham...
175
176
  	struct omap_sham_algs_info	*algs_info;
  	unsigned int	algs_info_size;
0d373d603   Mark A. Greer   crypto: omap-sham...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  	unsigned long	flags;
  	int		digest_size;
  
  	void		(*copy_hash)(struct ahash_request *req, int out);
  	void		(*write_ctrl)(struct omap_sham_dev *dd, size_t length,
  				      int final, int dma);
  	void		(*trigger)(struct omap_sham_dev *dd, size_t length);
  	int		(*poll_irq)(struct omap_sham_dev *dd);
  	irqreturn_t	(*intr_hdlr)(int irq, void *dev_id);
  
  	u32		odigest_ofs;
  	u32		idigest_ofs;
  	u32		din_ofs;
  	u32		digcnt_ofs;
  	u32		rev_ofs;
  	u32		mask_ofs;
  	u32		sysstatus_ofs;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
194
195
  	u32		mode_ofs;
  	u32		length_ofs;
0d373d603   Mark A. Greer   crypto: omap-sham...
196
197
198
199
200
201
  
  	u32		major_mask;
  	u32		major_shift;
  	u32		minor_mask;
  	u32		minor_shift;
  };
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
202
203
204
205
206
207
  struct omap_sham_dev {
  	struct list_head	list;
  	unsigned long		phys_base;
  	struct device		*dev;
  	void __iomem		*io_base;
  	int			irq;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
208
  	spinlock_t		lock;
3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
209
  	int			err;
dfd061d5a   Mark A. Greer   crypto: omap-sham...
210
  	struct dma_chan		*dma_lch;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
211
  	struct tasklet_struct	done_task;
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
212
  	u8			polling_mode;
f19de1bc6   Tero Kristo   crypto: omap-sham...
213
  	u8			xmit_buf[BUFLEN];
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
214
215
216
217
  
  	unsigned long		flags;
  	struct crypto_queue	queue;
  	struct ahash_request	*req;
0d373d603   Mark A. Greer   crypto: omap-sham...
218
219
  
  	const struct omap_sham_pdata	*pdata;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  };
  
  struct omap_sham_drv {
  	struct list_head	dev_list;
  	spinlock_t		lock;
  	unsigned long		flags;
  };
  
  static struct omap_sham_drv sham = {
  	.dev_list = LIST_HEAD_INIT(sham.dev_list),
  	.lock = __SPIN_LOCK_UNLOCKED(sham.lock),
  };
  
  static inline u32 omap_sham_read(struct omap_sham_dev *dd, u32 offset)
  {
  	return __raw_readl(dd->io_base + offset);
  }
  
  static inline void omap_sham_write(struct omap_sham_dev *dd,
  					u32 offset, u32 value)
  {
  	__raw_writel(value, dd->io_base + offset);
  }
  
  static inline void omap_sham_write_mask(struct omap_sham_dev *dd, u32 address,
  					u32 value, u32 mask)
  {
  	u32 val;
  
  	val = omap_sham_read(dd, address);
  	val &= ~mask;
  	val |= value;
  	omap_sham_write(dd, address, val);
  }
  
  static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit)
  {
  	unsigned long timeout = jiffies + DEFAULT_TIMEOUT_INTERVAL;
  
  	while (!(omap_sham_read(dd, offset) & bit)) {
  		if (time_is_before_jiffies(timeout))
  			return -ETIMEDOUT;
  	}
  
  	return 0;
  }
0d373d603   Mark A. Greer   crypto: omap-sham...
266
  static void omap_sham_copy_hash_omap2(struct ahash_request *req, int out)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
267
268
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
0d373d603   Mark A. Greer   crypto: omap-sham...
269
  	struct omap_sham_dev *dd = ctx->dd;
0c3cf4cc9   Dmitry Kasatkin   crypto: omap-sham...
270
  	u32 *hash = (u32 *)ctx->digest;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
271
  	int i;
0d373d603   Mark A. Greer   crypto: omap-sham...
272
  	for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
273
  		if (out)
0d373d603   Mark A. Greer   crypto: omap-sham...
274
  			hash[i] = omap_sham_read(dd, SHA_REG_IDIGEST(dd, i));
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
275
  		else
0d373d603   Mark A. Greer   crypto: omap-sham...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  			omap_sham_write(dd, SHA_REG_IDIGEST(dd, i), hash[i]);
  	}
  }
  
  static void omap_sham_copy_hash_omap4(struct ahash_request *req, int out)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	struct omap_sham_dev *dd = ctx->dd;
  	int i;
  
  	if (ctx->flags & BIT(FLAGS_HMAC)) {
  		struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
  		struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
  		struct omap_sham_hmac_ctx *bctx = tctx->base;
  		u32 *opad = (u32 *)bctx->opad;
  
  		for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
  			if (out)
  				opad[i] = omap_sham_read(dd,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
295
  						SHA_REG_ODIGEST(dd, i));
0d373d603   Mark A. Greer   crypto: omap-sham...
296
  			else
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
297
  				omap_sham_write(dd, SHA_REG_ODIGEST(dd, i),
0d373d603   Mark A. Greer   crypto: omap-sham...
298
299
  						opad[i]);
  		}
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
300
  	}
0d373d603   Mark A. Greer   crypto: omap-sham...
301
302
  
  	omap_sham_copy_hash_omap2(req, out);
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
303
304
305
306
307
308
309
  }
  
  static void omap_sham_copy_ready_hash(struct ahash_request *req)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	u32 *in = (u32 *)ctx->digest;
  	u32 *hash = (u32 *)req->result;
0d373d603   Mark A. Greer   crypto: omap-sham...
310
  	int i, d, big_endian = 0;
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
311
312
313
  
  	if (!hash)
  		return;
0d373d603   Mark A. Greer   crypto: omap-sham...
314
315
316
317
318
319
320
321
322
323
  	switch (ctx->flags & FLAGS_MODE_MASK) {
  	case FLAGS_MODE_MD5:
  		d = MD5_DIGEST_SIZE / sizeof(u32);
  		break;
  	case FLAGS_MODE_SHA1:
  		/* OMAP2 SHA1 is big endian */
  		if (test_bit(FLAGS_BE32_SHA1, &ctx->dd->flags))
  			big_endian = 1;
  		d = SHA1_DIGEST_SIZE / sizeof(u32);
  		break;
d20fb18be   Mark A. Greer   crypto: omap-sham...
324
325
326
327
328
329
  	case FLAGS_MODE_SHA224:
  		d = SHA224_DIGEST_SIZE / sizeof(u32);
  		break;
  	case FLAGS_MODE_SHA256:
  		d = SHA256_DIGEST_SIZE / sizeof(u32);
  		break;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
330
331
332
333
334
335
  	case FLAGS_MODE_SHA384:
  		d = SHA384_DIGEST_SIZE / sizeof(u32);
  		break;
  	case FLAGS_MODE_SHA512:
  		d = SHA512_DIGEST_SIZE / sizeof(u32);
  		break;
0d373d603   Mark A. Greer   crypto: omap-sham...
336
337
338
339
340
341
  	default:
  		d = 0;
  	}
  
  	if (big_endian)
  		for (i = 0; i < d; i++)
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
342
  			hash[i] = be32_to_cpu(in[i]);
0d373d603   Mark A. Greer   crypto: omap-sham...
343
344
  	else
  		for (i = 0; i < d; i++)
3c8d758ab   Dmitry Kasatkin   crypto: omap-sham...
345
  			hash[i] = le32_to_cpu(in[i]);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
346
  }
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
347
  static int omap_sham_hw_init(struct omap_sham_dev *dd)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
348
  {
604c31039   Pali Rohár   crypto: omap-sham...
349
350
351
352
353
354
355
356
  	int err;
  
  	err = pm_runtime_get_sync(dd->dev);
  	if (err < 0) {
  		dev_err(dd->dev, "failed to get sync: %d
  ", err);
  		return err;
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
357

a929cbeef   Dmitry Kasatkin   crypto: omap-sham...
358
  	if (!test_bit(FLAGS_INIT, &dd->flags)) {
a929cbeef   Dmitry Kasatkin   crypto: omap-sham...
359
  		set_bit(FLAGS_INIT, &dd->flags);
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
360
361
  		dd->err = 0;
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
362

798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
363
364
  	return 0;
  }
0d373d603   Mark A. Greer   crypto: omap-sham...
365
  static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
366
367
368
369
370
371
  				 int final, int dma)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
  	u32 val = length << 5, mask;
  
  	if (likely(ctx->digcnt))
0d373d603   Mark A. Greer   crypto: omap-sham...
372
  		omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
373

0d373d603   Mark A. Greer   crypto: omap-sham...
374
  	omap_sham_write_mask(dd, SHA_REG_MASK(dd),
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
375
376
377
378
379
380
  		SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0),
  		SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
  	/*
  	 * Setting ALGO_CONST only for the first iteration
  	 * and CLOSE_HASH only for the last one.
  	 */
0d373d603   Mark A. Greer   crypto: omap-sham...
381
  	if ((ctx->flags & FLAGS_MODE_MASK) == FLAGS_MODE_SHA1)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
382
383
384
385
386
387
388
389
390
391
  		val |= SHA_REG_CTRL_ALGO;
  	if (!ctx->digcnt)
  		val |= SHA_REG_CTRL_ALGO_CONST;
  	if (final)
  		val |= SHA_REG_CTRL_CLOSE_HASH;
  
  	mask = SHA_REG_CTRL_ALGO_CONST | SHA_REG_CTRL_CLOSE_HASH |
  			SHA_REG_CTRL_ALGO | SHA_REG_CTRL_LENGTH;
  
  	omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
392
  }
0d373d603   Mark A. Greer   crypto: omap-sham...
393
394
395
396
397
398
399
400
  static void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length)
  {
  }
  
  static int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd)
  {
  	return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY);
  }
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
  static int get_block_size(struct omap_sham_reqctx *ctx)
  {
  	int d;
  
  	switch (ctx->flags & FLAGS_MODE_MASK) {
  	case FLAGS_MODE_MD5:
  	case FLAGS_MODE_SHA1:
  		d = SHA1_BLOCK_SIZE;
  		break;
  	case FLAGS_MODE_SHA224:
  	case FLAGS_MODE_SHA256:
  		d = SHA256_BLOCK_SIZE;
  		break;
  	case FLAGS_MODE_SHA384:
  	case FLAGS_MODE_SHA512:
  		d = SHA512_BLOCK_SIZE;
  		break;
  	default:
  		d = 0;
  	}
  
  	return d;
  }
0d373d603   Mark A. Greer   crypto: omap-sham...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  static void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset,
  				    u32 *value, int count)
  {
  	for (; count--; value++, offset += 4)
  		omap_sham_write(dd, offset, *value);
  }
  
  static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
  				 int final, int dma)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
  	u32 val, mask;
  
  	/*
  	 * Setting ALGO_CONST only for the first iteration and
  	 * CLOSE_HASH only for the last one. Note that flags mode bits
  	 * correspond to algorithm encoding in mode register.
  	 */
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
442
  	val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT);
0d373d603   Mark A. Greer   crypto: omap-sham...
443
444
445
446
  	if (!ctx->digcnt) {
  		struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
  		struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
  		struct omap_sham_hmac_ctx *bctx = tctx->base;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
447
  		int bs, nr_dr;
0d373d603   Mark A. Greer   crypto: omap-sham...
448
449
450
451
  
  		val |= SHA_REG_MODE_ALGO_CONSTANT;
  
  		if (ctx->flags & BIT(FLAGS_HMAC)) {
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
452
453
  			bs = get_block_size(ctx);
  			nr_dr = bs / (2 * sizeof(u32));
0d373d603   Mark A. Greer   crypto: omap-sham...
454
  			val |= SHA_REG_MODE_HMAC_KEY_PROC;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
455
456
457
458
459
  			omap_sham_write_n(dd, SHA_REG_ODIGEST(dd, 0),
  					  (u32 *)bctx->ipad, nr_dr);
  			omap_sham_write_n(dd, SHA_REG_IDIGEST(dd, 0),
  					  (u32 *)bctx->ipad + nr_dr, nr_dr);
  			ctx->digcnt += bs;
0d373d603   Mark A. Greer   crypto: omap-sham...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
  		}
  	}
  
  	if (final) {
  		val |= SHA_REG_MODE_CLOSE_HASH;
  
  		if (ctx->flags & BIT(FLAGS_HMAC))
  			val |= SHA_REG_MODE_HMAC_OUTER_HASH;
  	}
  
  	mask = SHA_REG_MODE_ALGO_CONSTANT | SHA_REG_MODE_CLOSE_HASH |
  	       SHA_REG_MODE_ALGO_MASK | SHA_REG_MODE_HMAC_OUTER_HASH |
  	       SHA_REG_MODE_HMAC_KEY_PROC;
  
  	dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx
  ", val, ctx->flags);
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
476
  	omap_sham_write_mask(dd, SHA_REG_MODE(dd), val, mask);
0d373d603   Mark A. Greer   crypto: omap-sham...
477
478
479
480
481
482
483
484
485
  	omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY);
  	omap_sham_write_mask(dd, SHA_REG_MASK(dd),
  			     SHA_REG_MASK_IT_EN |
  				     (dma ? SHA_REG_MASK_DMA_EN : 0),
  			     SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
  }
  
  static void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length)
  {
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
486
  	omap_sham_write(dd, SHA_REG_LENGTH(dd), length);
0d373d603   Mark A. Greer   crypto: omap-sham...
487
488
489
490
491
492
493
  }
  
  static int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd)
  {
  	return omap_sham_wait(dd, SHA_REG_IRQSTATUS,
  			      SHA_REG_IRQSTATUS_INPUT_RDY);
  }
8043bb1ae   Tero Kristo   crypto: omap-sham...
494
495
  static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, size_t length,
  			      int final)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
496
497
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
498
  	int count, len32, bs32, offset = 0;
8043bb1ae   Tero Kristo   crypto: omap-sham...
499
500
501
  	const u32 *buffer;
  	int mlen;
  	struct sg_mapping_iter mi;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
502
503
504
505
  
  	dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d
  ",
  						ctx->digcnt, length, final);
0d373d603   Mark A. Greer   crypto: omap-sham...
506
507
  	dd->pdata->write_ctrl(dd, length, final, 0);
  	dd->pdata->trigger(dd, length);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
508

3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
509
510
  	/* should be non-zero before next lines to disable clocks later */
  	ctx->digcnt += length;
8043bb1ae   Tero Kristo   crypto: omap-sham...
511
  	ctx->total -= length;
3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
512

8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
513
  	if (final)
ed3ea9a82   Dmitry Kasatkin   crypto: omap-sham...
514
  		set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
515

6c63db821   Dmitry Kasatkin   crypto: omap-sham...
516
  	set_bit(FLAGS_CPU, &dd->flags);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
517
  	len32 = DIV_ROUND_UP(length, sizeof(u32));
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
518
  	bs32 = get_block_size(ctx) / sizeof(u32);
8043bb1ae   Tero Kristo   crypto: omap-sham...
519
520
521
522
  	sg_miter_start(&mi, ctx->sg, ctx->sg_len,
  		       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
  
  	mlen = 0;
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
523
524
525
  	while (len32) {
  		if (dd->pdata->poll_irq(dd))
  			return -ETIMEDOUT;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
526

8043bb1ae   Tero Kristo   crypto: omap-sham...
527
528
529
530
531
532
533
534
535
536
537
538
  		for (count = 0; count < min(len32, bs32); count++, offset++) {
  			if (!mlen) {
  				sg_miter_next(&mi);
  				mlen = mi.length;
  				if (!mlen) {
  					pr_err("sg miter failure.
  ");
  					return -EINVAL;
  				}
  				offset = 0;
  				buffer = mi.addr;
  			}
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
539
540
  			omap_sham_write(dd, SHA_REG_DIN(dd, count),
  					buffer[offset]);
8043bb1ae   Tero Kristo   crypto: omap-sham...
541
542
  			mlen -= 4;
  		}
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
543
544
  		len32 -= min(len32, bs32);
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
545

8043bb1ae   Tero Kristo   crypto: omap-sham...
546
  	sg_miter_stop(&mi);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
547
548
  	return -EINPROGRESS;
  }
dfd061d5a   Mark A. Greer   crypto: omap-sham...
549
550
551
552
553
554
555
  static void omap_sham_dma_callback(void *param)
  {
  	struct omap_sham_dev *dd = param;
  
  	set_bit(FLAGS_DMA_READY, &dd->flags);
  	tasklet_schedule(&dd->done_task);
  }
dfd061d5a   Mark A. Greer   crypto: omap-sham...
556

8043bb1ae   Tero Kristo   crypto: omap-sham...
557
558
  static int omap_sham_xmit_dma(struct omap_sham_dev *dd, size_t length,
  			      int final)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
559
560
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
dfd061d5a   Mark A. Greer   crypto: omap-sham...
561
562
  	struct dma_async_tx_descriptor *tx;
  	struct dma_slave_config cfg;
8043bb1ae   Tero Kristo   crypto: omap-sham...
563
  	int ret;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
564
565
566
567
  
  	dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d
  ",
  						ctx->digcnt, length, final);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
568

8043bb1ae   Tero Kristo   crypto: omap-sham...
569
570
571
572
573
  	if (!dma_map_sg(dd->dev, ctx->sg, ctx->sg_len, DMA_TO_DEVICE)) {
  		dev_err(dd->dev, "dma_map_sg error
  ");
  		return -EINVAL;
  	}
dfd061d5a   Mark A. Greer   crypto: omap-sham...
574
  	memset(&cfg, 0, sizeof(cfg));
0d373d603   Mark A. Greer   crypto: omap-sham...
575
  	cfg.dst_addr = dd->phys_base + SHA_REG_DIN(dd, 0);
dfd061d5a   Mark A. Greer   crypto: omap-sham...
576
  	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
8043bb1ae   Tero Kristo   crypto: omap-sham...
577
  	cfg.dst_maxburst = get_block_size(ctx) / DMA_SLAVE_BUSWIDTH_4_BYTES;
dfd061d5a   Mark A. Greer   crypto: omap-sham...
578
579
580
581
582
583
584
  
  	ret = dmaengine_slave_config(dd->dma_lch, &cfg);
  	if (ret) {
  		pr_err("omap-sham: can't configure dmaengine slave: %d
  ", ret);
  		return ret;
  	}
8043bb1ae   Tero Kristo   crypto: omap-sham...
585
586
587
  	tx = dmaengine_prep_slave_sg(dd->dma_lch, ctx->sg, ctx->sg_len,
  				     DMA_MEM_TO_DEV,
  				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
588

dfd061d5a   Mark A. Greer   crypto: omap-sham...
589
  	if (!tx) {
8043bb1ae   Tero Kristo   crypto: omap-sham...
590
591
  		dev_err(dd->dev, "prep_slave_sg failed
  ");
dfd061d5a   Mark A. Greer   crypto: omap-sham...
592
593
  		return -EINVAL;
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
594

dfd061d5a   Mark A. Greer   crypto: omap-sham...
595
596
  	tx->callback = omap_sham_dma_callback;
  	tx->callback_param = dd;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
597

0d373d603   Mark A. Greer   crypto: omap-sham...
598
  	dd->pdata->write_ctrl(dd, length, final, 1);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
599
600
  
  	ctx->digcnt += length;
8043bb1ae   Tero Kristo   crypto: omap-sham...
601
  	ctx->total -= length;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
602
603
  
  	if (final)
ed3ea9a82   Dmitry Kasatkin   crypto: omap-sham...
604
  		set_bit(FLAGS_FINAL, &dd->flags); /* catch last interrupt */
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
605

a929cbeef   Dmitry Kasatkin   crypto: omap-sham...
606
  	set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
607

dfd061d5a   Mark A. Greer   crypto: omap-sham...
608
609
  	dmaengine_submit(tx);
  	dma_async_issue_pending(dd->dma_lch);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
610

0d373d603   Mark A. Greer   crypto: omap-sham...
611
  	dd->pdata->trigger(dd, length);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
612
613
614
  
  	return -EINPROGRESS;
  }
f19de1bc6   Tero Kristo   crypto: omap-sham...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  static int omap_sham_copy_sg_lists(struct omap_sham_reqctx *ctx,
  				   struct scatterlist *sg, int bs, int new_len)
  {
  	int n = sg_nents(sg);
  	struct scatterlist *tmp;
  	int offset = ctx->offset;
  
  	if (ctx->bufcnt)
  		n++;
  
  	ctx->sg = kmalloc_array(n, sizeof(*sg), GFP_KERNEL);
  	if (!ctx->sg)
  		return -ENOMEM;
  
  	sg_init_table(ctx->sg, n);
  
  	tmp = ctx->sg;
  
  	ctx->sg_len = 0;
  
  	if (ctx->bufcnt) {
  		sg_set_buf(tmp, ctx->dd->xmit_buf, ctx->bufcnt);
  		tmp = sg_next(tmp);
  		ctx->sg_len++;
  	}
  
  	while (sg && new_len) {
  		int len = sg->length - offset;
  
  		if (offset) {
  			offset -= sg->length;
  			if (offset < 0)
  				offset = 0;
  		}
  
  		if (new_len < len)
  			len = new_len;
  
  		if (len > 0) {
  			new_len -= len;
  			sg_set_page(tmp, sg_page(sg), len, sg->offset);
  			if (new_len <= 0)
  				sg_mark_end(tmp);
  			tmp = sg_next(tmp);
  			ctx->sg_len++;
  		}
  
  		sg = sg_next(sg);
  	}
  
  	set_bit(FLAGS_SGS_ALLOCED, &ctx->dd->flags);
  
  	ctx->bufcnt = 0;
  
  	return 0;
  }
  
  static int omap_sham_copy_sgs(struct omap_sham_reqctx *ctx,
  			      struct scatterlist *sg, int bs, int new_len)
  {
  	int pages;
  	void *buf;
  	int len;
  
  	len = new_len + ctx->bufcnt;
  
  	pages = get_order(ctx->total);
  
  	buf = (void *)__get_free_pages(GFP_ATOMIC, pages);
  	if (!buf) {
  		pr_err("Couldn't allocate pages for unaligned cases.
  ");
  		return -ENOMEM;
  	}
  
  	if (ctx->bufcnt)
  		memcpy(buf, ctx->dd->xmit_buf, ctx->bufcnt);
  
  	scatterwalk_map_and_copy(buf + ctx->bufcnt, sg, ctx->offset,
  				 ctx->total - ctx->bufcnt, 0);
  	sg_init_table(ctx->sgl, 1);
  	sg_set_buf(ctx->sgl, buf, len);
  	ctx->sg = ctx->sgl;
  	set_bit(FLAGS_SGS_COPIED, &ctx->dd->flags);
  	ctx->sg_len = 1;
  	ctx->bufcnt = 0;
  	ctx->offset = 0;
  
  	return 0;
  }
  
  static int omap_sham_align_sgs(struct scatterlist *sg,
  			       int nbytes, int bs, bool final,
  			       struct omap_sham_reqctx *rctx)
  {
  	int n = 0;
  	bool aligned = true;
  	bool list_ok = true;
  	struct scatterlist *sg_tmp = sg;
  	int new_len;
  	int offset = rctx->offset;
  
  	if (!sg || !sg->length || !nbytes)
  		return 0;
  
  	new_len = nbytes;
  
  	if (offset)
  		list_ok = false;
  
  	if (final)
  		new_len = DIV_ROUND_UP(new_len, bs) * bs;
  	else
  		new_len = new_len / bs * bs;
  
  	while (nbytes > 0 && sg_tmp) {
  		n++;
  
  		if (offset < sg_tmp->length) {
  			if (!IS_ALIGNED(offset + sg_tmp->offset, 4)) {
  				aligned = false;
  				break;
  			}
  
  			if (!IS_ALIGNED(sg_tmp->length - offset, bs)) {
  				aligned = false;
  				break;
  			}
  		}
  
  		if (offset) {
  			offset -= sg_tmp->length;
  			if (offset < 0) {
  				nbytes += offset;
  				offset = 0;
  			}
  		} else {
  			nbytes -= sg_tmp->length;
  		}
  
  		sg_tmp = sg_next(sg_tmp);
  
  		if (nbytes < 0) {
  			list_ok = false;
  			break;
  		}
  	}
  
  	if (!aligned)
  		return omap_sham_copy_sgs(rctx, sg, bs, new_len);
  	else if (!list_ok)
  		return omap_sham_copy_sg_lists(rctx, sg, bs, new_len);
  
  	rctx->sg_len = n;
  	rctx->sg = sg;
  
  	return 0;
  }
  
  static int omap_sham_prepare_request(struct ahash_request *req, bool update)
  {
  	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
  	int bs;
  	int ret;
  	int nbytes;
  	bool final = rctx->flags & BIT(FLAGS_FINUP);
  	int xmit_len, hash_later;
  
  	if (!req)
  		return 0;
  
  	bs = get_block_size(rctx);
  
  	if (update)
  		nbytes = req->nbytes;
  	else
  		nbytes = 0;
  
  	rctx->total = nbytes + rctx->bufcnt;
  
  	if (!rctx->total)
  		return 0;
  
  	if (nbytes && (!IS_ALIGNED(rctx->bufcnt, bs))) {
  		int len = bs - rctx->bufcnt % bs;
  
  		if (len > nbytes)
  			len = nbytes;
  		scatterwalk_map_and_copy(rctx->buffer + rctx->bufcnt, req->src,
  					 0, len, 0);
  		rctx->bufcnt += len;
  		nbytes -= len;
  		rctx->offset = len;
  	}
  
  	if (rctx->bufcnt)
  		memcpy(rctx->dd->xmit_buf, rctx->buffer, rctx->bufcnt);
  
  	ret = omap_sham_align_sgs(req->src, nbytes, bs, final, rctx);
  	if (ret)
  		return ret;
  
  	xmit_len = rctx->total;
  
  	if (!IS_ALIGNED(xmit_len, bs)) {
  		if (final)
  			xmit_len = DIV_ROUND_UP(xmit_len, bs) * bs;
  		else
  			xmit_len = xmit_len / bs * bs;
  	}
  
  	hash_later = rctx->total - xmit_len;
  	if (hash_later < 0)
  		hash_later = 0;
  
  	if (rctx->bufcnt && nbytes) {
  		/* have data from previous operation and current */
  		sg_init_table(rctx->sgl, 2);
  		sg_set_buf(rctx->sgl, rctx->dd->xmit_buf, rctx->bufcnt);
  
  		sg_chain(rctx->sgl, 2, req->src);
  
  		rctx->sg = rctx->sgl;
  
  		rctx->sg_len++;
  	} else if (rctx->bufcnt) {
  		/* have buffered data only */
  		sg_init_table(rctx->sgl, 1);
  		sg_set_buf(rctx->sgl, rctx->dd->xmit_buf, xmit_len);
  
  		rctx->sg = rctx->sgl;
  
  		rctx->sg_len = 1;
  	}
  
  	if (hash_later) {
  		if (req->nbytes) {
  			scatterwalk_map_and_copy(rctx->buffer, req->src,
  						 req->nbytes - hash_later,
  						 hash_later, 0);
  		} else {
  			memcpy(rctx->buffer, rctx->buffer + xmit_len,
  			       hash_later);
  		}
  		rctx->bufcnt = hash_later;
  	} else {
  		rctx->bufcnt = 0;
  	}
  
  	if (!final)
  		rctx->total = xmit_len;
  
  	return 0;
  }
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
869
870
871
  static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
8043bb1ae   Tero Kristo   crypto: omap-sham...
872
  	dma_unmap_sg(dd->dev, ctx->sg, ctx->sg_len, DMA_TO_DEVICE);
dfd061d5a   Mark A. Greer   crypto: omap-sham...
873

8043bb1ae   Tero Kristo   crypto: omap-sham...
874
  	clear_bit(FLAGS_DMA_ACTIVE, &dd->flags);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
875
876
877
  
  	return 0;
  }
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
878
879
880
881
882
883
  static int omap_sham_init(struct ahash_request *req)
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	struct omap_sham_dev *dd = NULL, *tmp;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
884
  	int bs = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
  
  	spin_lock_bh(&sham.lock);
  	if (!tctx->dd) {
  		list_for_each_entry(tmp, &sham.dev_list, list) {
  			dd = tmp;
  			break;
  		}
  		tctx->dd = dd;
  	} else {
  		dd = tctx->dd;
  	}
  	spin_unlock_bh(&sham.lock);
  
  	ctx->dd = dd;
  
  	ctx->flags = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
901
902
903
  	dev_dbg(dd->dev, "init: digest size: %d
  ",
  		crypto_ahash_digestsize(tfm));
0d373d603   Mark A. Greer   crypto: omap-sham...
904
905
906
  	switch (crypto_ahash_digestsize(tfm)) {
  	case MD5_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_MD5;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
907
  		bs = SHA1_BLOCK_SIZE;
0d373d603   Mark A. Greer   crypto: omap-sham...
908
909
910
  		break;
  	case SHA1_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_SHA1;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
911
  		bs = SHA1_BLOCK_SIZE;
0d373d603   Mark A. Greer   crypto: omap-sham...
912
  		break;
d20fb18be   Mark A. Greer   crypto: omap-sham...
913
914
  	case SHA224_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_SHA224;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
915
  		bs = SHA224_BLOCK_SIZE;
d20fb18be   Mark A. Greer   crypto: omap-sham...
916
917
918
  		break;
  	case SHA256_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_SHA256;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
919
920
921
922
923
924
925
926
927
  		bs = SHA256_BLOCK_SIZE;
  		break;
  	case SHA384_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_SHA384;
  		bs = SHA384_BLOCK_SIZE;
  		break;
  	case SHA512_DIGEST_SIZE:
  		ctx->flags |= FLAGS_MODE_SHA512;
  		bs = SHA512_BLOCK_SIZE;
d20fb18be   Mark A. Greer   crypto: omap-sham...
928
  		break;
0d373d603   Mark A. Greer   crypto: omap-sham...
929
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
930
931
932
  
  	ctx->bufcnt = 0;
  	ctx->digcnt = 0;
8043bb1ae   Tero Kristo   crypto: omap-sham...
933
934
  	ctx->total = 0;
  	ctx->offset = 0;
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
935
  	ctx->buflen = BUFLEN;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
936

ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
937
  	if (tctx->flags & BIT(FLAGS_HMAC)) {
0d373d603   Mark A. Greer   crypto: omap-sham...
938
939
  		if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
  			struct omap_sham_hmac_ctx *bctx = tctx->base;
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
940
941
  			memcpy(ctx->buffer, bctx->ipad, bs);
  			ctx->bufcnt = bs;
0d373d603   Mark A. Greer   crypto: omap-sham...
942
  		}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
943

ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
944
  		ctx->flags |= BIT(FLAGS_HMAC);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
945
946
947
948
949
950
951
952
953
954
955
  	}
  
  	return 0;
  
  }
  
  static int omap_sham_update_req(struct omap_sham_dev *dd)
  {
  	struct ahash_request *req = dd->req;
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	int err;
8043bb1ae   Tero Kristo   crypto: omap-sham...
956
  	bool final = ctx->flags & BIT(FLAGS_FINUP);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
957
958
959
  
  	dev_dbg(dd->dev, "update_req: total: %u, digcnt: %d, finup: %d
  ",
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
960
  		 ctx->total, ctx->digcnt, (ctx->flags & BIT(FLAGS_FINUP)) != 0);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
961

8043bb1ae   Tero Kristo   crypto: omap-sham...
962
963
964
  	if (ctx->total < get_block_size(ctx) ||
  	    ctx->total < OMAP_SHA_DMA_THRESHOLD)
  		ctx->flags |= BIT(FLAGS_CPU);
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
965
  	if (ctx->flags & BIT(FLAGS_CPU))
8043bb1ae   Tero Kristo   crypto: omap-sham...
966
  		err = omap_sham_xmit_cpu(dd, ctx->total, final);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
967
  	else
8043bb1ae   Tero Kristo   crypto: omap-sham...
968
  		err = omap_sham_xmit_dma(dd, ctx->total, final);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
969
970
971
972
973
974
975
976
977
978
979
980
981
  
  	/* wait for dma completion before can take more data */
  	dev_dbg(dd->dev, "update: err: %d, digcnt: %d
  ", err, ctx->digcnt);
  
  	return err;
  }
  
  static int omap_sham_final_req(struct omap_sham_dev *dd)
  {
  	struct ahash_request *req = dd->req;
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	int err = 0, use_dma = 1;
8043bb1ae   Tero Kristo   crypto: omap-sham...
982
  	if ((ctx->total <= get_block_size(ctx)) || dd->polling_mode)
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
983
984
985
986
  		/*
  		 * faster to handle last block with cpu or
  		 * use cpu when dma is not present.
  		 */
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
987
988
989
  		use_dma = 0;
  
  	if (use_dma)
8043bb1ae   Tero Kristo   crypto: omap-sham...
990
  		err = omap_sham_xmit_dma(dd, ctx->total, 1);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
991
  	else
8043bb1ae   Tero Kristo   crypto: omap-sham...
992
  		err = omap_sham_xmit_cpu(dd, ctx->total, 1);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
993
994
  
  	ctx->bufcnt = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
995
996
997
998
999
  	dev_dbg(dd->dev, "final_req: err: %d
  ", err);
  
  	return err;
  }
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1000
  static int omap_sham_finish_hmac(struct ahash_request *req)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1001
1002
1003
1004
1005
  {
  	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
  	struct omap_sham_hmac_ctx *bctx = tctx->base;
  	int bs = crypto_shash_blocksize(bctx->shash);
  	int ds = crypto_shash_digestsize(bctx->shash);
7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1006
  	SHASH_DESC_ON_STACK(shash, bctx->shash);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1007

7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1008
1009
  	shash->tfm = bctx->shash;
  	shash->flags = 0; /* not CRYPTO_TFM_REQ_MAY_SLEEP */
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1010

7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1011
1012
1013
  	return crypto_shash_init(shash) ?:
  	       crypto_shash_update(shash, bctx->opad, bs) ?:
  	       crypto_shash_finup(shash, req->result, ds, req->result);
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  }
  
  static int omap_sham_finish(struct ahash_request *req)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	struct omap_sham_dev *dd = ctx->dd;
  	int err = 0;
  
  	if (ctx->digcnt) {
  		omap_sham_copy_ready_hash(req);
0d373d603   Mark A. Greer   crypto: omap-sham...
1024
1025
  		if ((ctx->flags & BIT(FLAGS_HMAC)) &&
  				!test_bit(FLAGS_AUTO_XOR, &dd->flags))
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1026
1027
1028
1029
1030
1031
1032
  			err = omap_sham_finish_hmac(req);
  	}
  
  	dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d
  ", ctx->digcnt, ctx->bufcnt);
  
  	return err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1033
1034
1035
1036
1037
  }
  
  static void omap_sham_finish_req(struct ahash_request *req, int err)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1038
  	struct omap_sham_dev *dd = ctx->dd;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1039

8043bb1ae   Tero Kristo   crypto: omap-sham...
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  	if (test_bit(FLAGS_SGS_COPIED, &dd->flags))
  		free_pages((unsigned long)sg_virt(ctx->sg),
  			   get_order(ctx->sg->length));
  
  	if (test_bit(FLAGS_SGS_ALLOCED, &dd->flags))
  		kfree(ctx->sg);
  
  	ctx->sg = NULL;
  
  	dd->flags &= ~(BIT(FLAGS_SGS_ALLOCED) | BIT(FLAGS_SGS_COPIED));
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1050
  	if (!err) {
0d373d603   Mark A. Greer   crypto: omap-sham...
1051
  		dd->pdata->copy_hash(req, 1);
ed3ea9a82   Dmitry Kasatkin   crypto: omap-sham...
1052
  		if (test_bit(FLAGS_FINAL, &dd->flags))
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1053
  			err = omap_sham_finish(req);
3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
1054
  	} else {
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1055
  		ctx->flags |= BIT(FLAGS_ERROR);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1056
  	}
0efd4d8a6   Dmitry Kasatkin   crypto: omap-sham...
1057
1058
1059
  	/* atomic operation is not needed here */
  	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
  			BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
b359f034c   Mark A. Greer   crypto: omap-sham...
1060

e93f767be   Tero Kristo   crypto: omap-sham...
1061
1062
  	pm_runtime_mark_last_busy(dd->dev);
  	pm_runtime_put_autosuspend(dd->dev);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1063
1064
1065
1066
  
  	if (req->base.complete)
  		req->base.complete(&req->base, err);
  }
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1067
1068
  static int omap_sham_handle_queue(struct omap_sham_dev *dd,
  				  struct ahash_request *req)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1069
  {
6c39d116b   Dmitry Kasatkin   crypto: omap-sham...
1070
  	struct crypto_async_request *async_req, *backlog;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1071
  	struct omap_sham_reqctx *ctx;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1072
  	unsigned long flags;
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1073
  	int err = 0, ret = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1074

4e7813a0b   Tero Kristo   crypto: omap-sham...
1075
  retry:
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1076
  	spin_lock_irqsave(&dd->lock, flags);
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1077
1078
  	if (req)
  		ret = ahash_enqueue_request(&dd->queue, req);
a929cbeef   Dmitry Kasatkin   crypto: omap-sham...
1079
  	if (test_bit(FLAGS_BUSY, &dd->flags)) {
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1080
1081
1082
  		spin_unlock_irqrestore(&dd->lock, flags);
  		return ret;
  	}
6c39d116b   Dmitry Kasatkin   crypto: omap-sham...
1083
  	backlog = crypto_get_backlog(&dd->queue);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1084
  	async_req = crypto_dequeue_request(&dd->queue);
6c39d116b   Dmitry Kasatkin   crypto: omap-sham...
1085
  	if (async_req)
a929cbeef   Dmitry Kasatkin   crypto: omap-sham...
1086
  		set_bit(FLAGS_BUSY, &dd->flags);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1087
1088
1089
  	spin_unlock_irqrestore(&dd->lock, flags);
  
  	if (!async_req)
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1090
  		return ret;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1091
1092
1093
1094
1095
  
  	if (backlog)
  		backlog->complete(backlog, -EINPROGRESS);
  
  	req = ahash_request_cast(async_req);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1096
  	dd->req = req;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1097
  	ctx = ahash_request_ctx(req);
8043bb1ae   Tero Kristo   crypto: omap-sham...
1098
  	err = omap_sham_prepare_request(req, ctx->op == OP_UPDATE);
f19de1bc6   Tero Kristo   crypto: omap-sham...
1099
1100
  	if (err)
  		goto err1;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1101
1102
1103
  	dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d
  ",
  						ctx->op, req->nbytes);
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1104
1105
1106
  	err = omap_sham_hw_init(dd);
  	if (err)
  		goto err1;
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1107
  	if (ctx->digcnt)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1108
  		/* request has changed - restore hash */
0d373d603   Mark A. Greer   crypto: omap-sham...
1109
  		dd->pdata->copy_hash(req, 0);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1110
1111
1112
  
  	if (ctx->op == OP_UPDATE) {
  		err = omap_sham_update_req(dd);
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1113
  		if (err != -EINPROGRESS && (ctx->flags & BIT(FLAGS_FINUP)))
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1114
1115
1116
1117
1118
  			/* no final() after finup() */
  			err = omap_sham_final_req(dd);
  	} else if (ctx->op == OP_FINAL) {
  		err = omap_sham_final_req(dd);
  	}
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1119
  err1:
4e7813a0b   Tero Kristo   crypto: omap-sham...
1120
1121
1122
1123
  	dev_dbg(dd->dev, "exit, err: %d
  ", err);
  
  	if (err != -EINPROGRESS) {
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1124
1125
  		/* done_task will not finish it, so do it here */
  		omap_sham_finish_req(req, err);
4e7813a0b   Tero Kristo   crypto: omap-sham...
1126
  		req = NULL;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1127

4e7813a0b   Tero Kristo   crypto: omap-sham...
1128
1129
1130
1131
1132
1133
  		/*
  		 * Execute next request immediately if there is anything
  		 * in queue.
  		 */
  		goto retry;
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1134

a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1135
  	return ret;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1136
1137
1138
1139
1140
1141
1142
  }
  
  static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
  	struct omap_sham_dev *dd = tctx->dd;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1143
1144
  
  	ctx->op = op;
a5d87237b   Dmitry Kasatkin   crypto: omap-sham...
1145
  	return omap_sham_handle_queue(dd, req);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1146
1147
1148
1149
1150
  }
  
  static int omap_sham_update(struct ahash_request *req)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
1151
  	struct omap_sham_dev *dd = ctx->dd;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1152
1153
1154
  
  	if (!req->nbytes)
  		return 0;
8043bb1ae   Tero Kristo   crypto: omap-sham...
1155
1156
1157
1158
1159
  	if (ctx->total + req->nbytes < ctx->buflen) {
  		scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, req->src,
  					 0, req->nbytes, 0);
  		ctx->bufcnt += req->nbytes;
  		ctx->total += req->nbytes;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1160
1161
  		return 0;
  	}
acef7b0f2   Lokesh Vutla   crypto: omap-sham...
1162
1163
  	if (dd->polling_mode)
  		ctx->flags |= BIT(FLAGS_CPU);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1164
1165
  	return omap_sham_enqueue(req, OP_UPDATE);
  }
7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1166
  static int omap_sham_shash_digest(struct crypto_shash *tfm, u32 flags,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1167
1168
  				  const u8 *data, unsigned int len, u8 *out)
  {
7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1169
  	SHASH_DESC_ON_STACK(shash, tfm);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1170

7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1171
1172
  	shash->tfm = tfm;
  	shash->flags = flags & CRYPTO_TFM_REQ_MAY_SLEEP;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1173

7bc53c3f9   Behan Webster   crypto: LLVMLinux...
1174
  	return crypto_shash_digest(shash, data, len, out);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1175
1176
1177
1178
1179
1180
  }
  
  static int omap_sham_final_shash(struct ahash_request *req)
  {
  	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
cb8d5c834   Tero Kristo   crypto: omap-sham...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
  	int offset = 0;
  
  	/*
  	 * If we are running HMAC on limited hardware support, skip
  	 * the ipad in the beginning of the buffer if we are going for
  	 * software fallback algorithm.
  	 */
  	if (test_bit(FLAGS_HMAC, &ctx->flags) &&
  	    !test_bit(FLAGS_AUTO_XOR, &ctx->dd->flags))
  		offset = get_block_size(ctx);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1191
1192
  
  	return omap_sham_shash_digest(tctx->fallback, req->base.flags,
cb8d5c834   Tero Kristo   crypto: omap-sham...
1193
1194
  				      ctx->buffer + offset,
  				      ctx->bufcnt - offset, req->result);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1195
1196
1197
1198
1199
  }
  
  static int omap_sham_final(struct ahash_request *req)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1200

ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1201
  	ctx->flags |= BIT(FLAGS_FINUP);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1202

ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1203
  	if (ctx->flags & BIT(FLAGS_ERROR))
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1204
  		return 0; /* uncompleted hash is not needed */
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1205

85e0687f8   Bin Liu   crypto: omap-sham...
1206
1207
1208
  	/*
  	 * OMAP HW accel works only with buffers >= 9.
  	 * HMAC is always >= 9 because ipad == block size.
2c5bd1ef1   Tero Kristo   crypto: omap-sham...
1209
1210
1211
  	 * If buffersize is less than DMA_THRESHOLD, we use fallback
  	 * SW encoding, as using DMA + HW in this case doesn't provide
  	 * any benefit.
85e0687f8   Bin Liu   crypto: omap-sham...
1212
  	 */
2c5bd1ef1   Tero Kristo   crypto: omap-sham...
1213
  	if (!ctx->digcnt && ctx->bufcnt < OMAP_SHA_DMA_THRESHOLD)
bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1214
1215
1216
  		return omap_sham_final_shash(req);
  	else if (ctx->bufcnt)
  		return omap_sham_enqueue(req, OP_FINAL);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1217

bf3627590   Dmitry Kasatkin   crypto: omap-sham...
1218
1219
  	/* copy ready hash (+ finalize hmac) */
  	return omap_sham_finish(req);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1220
1221
1222
1223
1224
1225
  }
  
  static int omap_sham_finup(struct ahash_request *req)
  {
  	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
  	int err1, err2;
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1226
  	ctx->flags |= BIT(FLAGS_FINUP);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1227
1228
  
  	err1 = omap_sham_update(req);
455e33898   Markku Kylanpaa   crypto: omap-sham...
1229
  	if (err1 == -EINPROGRESS || err1 == -EBUSY)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
  		return err1;
  	/*
  	 * final() has to be always called to cleanup resources
  	 * even if udpate() failed, except EINPROGRESS
  	 */
  	err2 = omap_sham_final(req);
  
  	return err1 ?: err2;
  }
  
  static int omap_sham_digest(struct ahash_request *req)
  {
  	return omap_sham_init(req) ?: omap_sham_finup(req);
  }
  
  static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
  		      unsigned int keylen)
  {
  	struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
  	struct omap_sham_hmac_ctx *bctx = tctx->base;
  	int bs = crypto_shash_blocksize(bctx->shash);
  	int ds = crypto_shash_digestsize(bctx->shash);
0d373d603   Mark A. Greer   crypto: omap-sham...
1252
  	struct omap_sham_dev *dd = NULL, *tmp;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1253
  	int err, i;
0d373d603   Mark A. Greer   crypto: omap-sham...
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  
  	spin_lock_bh(&sham.lock);
  	if (!tctx->dd) {
  		list_for_each_entry(tmp, &sham.dev_list, list) {
  			dd = tmp;
  			break;
  		}
  		tctx->dd = dd;
  	} else {
  		dd = tctx->dd;
  	}
  	spin_unlock_bh(&sham.lock);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  	err = crypto_shash_setkey(tctx->fallback, key, keylen);
  	if (err)
  		return err;
  
  	if (keylen > bs) {
  		err = omap_sham_shash_digest(bctx->shash,
  				crypto_shash_get_flags(bctx->shash),
  				key, keylen, bctx->ipad);
  		if (err)
  			return err;
  		keylen = ds;
  	} else {
  		memcpy(bctx->ipad, key, keylen);
  	}
  
  	memset(bctx->ipad + keylen, 0, bs - keylen);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1282

0d373d603   Mark A. Greer   crypto: omap-sham...
1283
1284
1285
1286
1287
1288
1289
  	if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
  		memcpy(bctx->opad, bctx->ipad, bs);
  
  		for (i = 0; i < bs; i++) {
  			bctx->ipad[i] ^= 0x36;
  			bctx->opad[i] ^= 0x5c;
  		}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
  	}
  
  	return err;
  }
  
  static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
  {
  	struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
  	const char *alg_name = crypto_tfm_alg_name(tfm);
  
  	/* Allocate a fallback and abort if it failed. */
  	tctx->fallback = crypto_alloc_shash(alg_name, 0,
  					    CRYPTO_ALG_NEED_FALLBACK);
  	if (IS_ERR(tctx->fallback)) {
  		pr_err("omap-sham: fallback driver '%s' "
  				"could not be loaded.
  ", alg_name);
  		return PTR_ERR(tctx->fallback);
  	}
  
  	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1311
  				 sizeof(struct omap_sham_reqctx) + BUFLEN);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1312
1313
1314
  
  	if (alg_base) {
  		struct omap_sham_hmac_ctx *bctx = tctx->base;
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1315
  		tctx->flags |= BIT(FLAGS_HMAC);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
  		bctx->shash = crypto_alloc_shash(alg_base, 0,
  						CRYPTO_ALG_NEED_FALLBACK);
  		if (IS_ERR(bctx->shash)) {
  			pr_err("omap-sham: base driver '%s' "
  					"could not be loaded.
  ", alg_base);
  			crypto_free_shash(tctx->fallback);
  			return PTR_ERR(bctx->shash);
  		}
  
  	}
  
  	return 0;
  }
  
  static int omap_sham_cra_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, NULL);
  }
  
  static int omap_sham_cra_sha1_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "sha1");
  }
d20fb18be   Mark A. Greer   crypto: omap-sham...
1340
1341
1342
1343
1344
1345
1346
1347
1348
  static int omap_sham_cra_sha224_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "sha224");
  }
  
  static int omap_sham_cra_sha256_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "sha256");
  }
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1349
1350
1351
1352
  static int omap_sham_cra_md5_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "md5");
  }
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1353
1354
1355
1356
1357
1358
1359
1360
1361
  static int omap_sham_cra_sha384_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "sha384");
  }
  
  static int omap_sham_cra_sha512_init(struct crypto_tfm *tfm)
  {
  	return omap_sham_cra_init_alg(tfm, "sha512");
  }
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1362
1363
1364
1365
1366
1367
  static void omap_sham_cra_exit(struct crypto_tfm *tfm)
  {
  	struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
  
  	crypto_free_shash(tctx->fallback);
  	tctx->fallback = NULL;
ea1fd2246   Dmitry Kasatkin   crypto: omap-sham...
1368
  	if (tctx->flags & BIT(FLAGS_HMAC)) {
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1369
1370
1371
1372
  		struct omap_sham_hmac_ctx *bctx = tctx->base;
  		crypto_free_shash(bctx->shash);
  	}
  }
99a7ffffd   Tero Kristo   crypto: omap-sham...
1373
1374
  static int omap_sham_export(struct ahash_request *req, void *out)
  {
a84d351f6   Tero Kristo   crypto: omap-sham...
1375
1376
1377
1378
1379
  	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
  
  	memcpy(out, rctx, sizeof(*rctx) + rctx->bufcnt);
  
  	return 0;
99a7ffffd   Tero Kristo   crypto: omap-sham...
1380
1381
1382
1383
  }
  
  static int omap_sham_import(struct ahash_request *req, const void *in)
  {
a84d351f6   Tero Kristo   crypto: omap-sham...
1384
1385
1386
1387
1388
1389
  	struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
  	const struct omap_sham_reqctx *ctx_in = in;
  
  	memcpy(rctx, in, sizeof(*rctx) + ctx_in->bufcnt);
  
  	return 0;
99a7ffffd   Tero Kristo   crypto: omap-sham...
1390
  }
d20fb18be   Mark A. Greer   crypto: omap-sham...
1391
  static struct ahash_alg algs_sha1_md5[] = {
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= SHA1_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "sha1",
  		.cra_driver_name	= "omap-sha1",
eb3547859   Bin Liu   crypto: omap-sham...
1402
  		.cra_priority		= 400,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1403
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
d912bb767   Nikos Mavrogiannopoulos   crypto: Add CRYPT...
1404
  						CRYPTO_ALG_KERN_DRIVER_ONLY |
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1405
1406
1407
1408
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA1_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
744e686a4   Tero Kristo   crypto: omap-sham...
1409
  		.cra_alignmask		= OMAP_ALIGN_MASK,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= MD5_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "md5",
  		.cra_driver_name	= "omap-md5",
eb3547859   Bin Liu   crypto: omap-sham...
1425
  		.cra_priority		= 400,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1426
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
d912bb767   Nikos Mavrogiannopoulos   crypto: Add CRYPT...
1427
  						CRYPTO_ALG_KERN_DRIVER_ONLY |
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1428
1429
1430
1431
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA1_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1432
  		.cra_alignmask		= OMAP_ALIGN_MASK,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= SHA1_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(sha1)",
  		.cra_driver_name	= "omap-hmac-sha1",
eb3547859   Bin Liu   crypto: omap-sham...
1449
  		.cra_priority		= 400,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1450
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
d912bb767   Nikos Mavrogiannopoulos   crypto: Add CRYPT...
1451
  						CRYPTO_ALG_KERN_DRIVER_ONLY |
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1452
1453
1454
1455
1456
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA1_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1457
  		.cra_alignmask		= OMAP_ALIGN_MASK,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_sha1_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= MD5_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(md5)",
  		.cra_driver_name	= "omap-hmac-md5",
eb3547859   Bin Liu   crypto: omap-sham...
1474
  		.cra_priority		= 400,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1475
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
d912bb767   Nikos Mavrogiannopoulos   crypto: Add CRYPT...
1476
  						CRYPTO_ALG_KERN_DRIVER_ONLY |
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1477
1478
1479
1480
1481
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA1_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
798eed5d9   Dmitry Kasatkin   crypto: omap-sham...
1482
  		.cra_alignmask		= OMAP_ALIGN_MASK,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1483
1484
1485
1486
1487
1488
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_md5_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  }
  };
d20fb18be   Mark A. Greer   crypto: omap-sham...
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
  /* OMAP4 has some algs in addition to what OMAP2 has */
  static struct ahash_alg algs_sha224_sha256[] = {
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= SHA224_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "sha224",
  		.cra_driver_name	= "omap-sha224",
eb3547859   Bin Liu   crypto: omap-sham...
1501
  		.cra_priority		= 400,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1502
1503
1504
1505
1506
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA224_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
744e686a4   Tero Kristo   crypto: omap-sham...
1507
  		.cra_alignmask		= OMAP_ALIGN_MASK,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= SHA256_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "sha256",
  		.cra_driver_name	= "omap-sha256",
eb3547859   Bin Liu   crypto: omap-sham...
1523
  		.cra_priority		= 400,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1524
1525
1526
1527
1528
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA256_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
744e686a4   Tero Kristo   crypto: omap-sham...
1529
  		.cra_alignmask		= OMAP_ALIGN_MASK,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= SHA224_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(sha224)",
  		.cra_driver_name	= "omap-hmac-sha224",
eb3547859   Bin Liu   crypto: omap-sham...
1546
  		.cra_priority		= 400,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA224_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
  		.cra_alignmask		= OMAP_ALIGN_MASK,
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_sha224_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= SHA256_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(sha256)",
  		.cra_driver_name	= "omap-hmac-sha256",
eb3547859   Bin Liu   crypto: omap-sham...
1570
  		.cra_priority		= 400,
d20fb18be   Mark A. Greer   crypto: omap-sham...
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA256_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
  		.cra_alignmask		= OMAP_ALIGN_MASK,
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_sha256_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  };
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
  static struct ahash_alg algs_sha384_sha512[] = {
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= SHA384_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "sha384",
  		.cra_driver_name	= "omap-sha384",
eb3547859   Bin Liu   crypto: omap-sham...
1595
  		.cra_priority		= 400,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1596
1597
1598
1599
1600
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA384_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
744e686a4   Tero Kristo   crypto: omap-sham...
1601
  		.cra_alignmask		= OMAP_ALIGN_MASK,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.halg.digestsize	= SHA512_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "sha512",
  		.cra_driver_name	= "omap-sha512",
eb3547859   Bin Liu   crypto: omap-sham...
1617
  		.cra_priority		= 400,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1618
1619
1620
1621
1622
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA512_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
744e686a4   Tero Kristo   crypto: omap-sham...
1623
  		.cra_alignmask		= OMAP_ALIGN_MASK,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= SHA384_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(sha384)",
  		.cra_driver_name	= "omap-hmac-sha384",
eb3547859   Bin Liu   crypto: omap-sham...
1640
  		.cra_priority		= 400,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA384_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
  		.cra_alignmask		= OMAP_ALIGN_MASK,
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_sha384_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  {
  	.init		= omap_sham_init,
  	.update		= omap_sham_update,
  	.final		= omap_sham_final,
  	.finup		= omap_sham_finup,
  	.digest		= omap_sham_digest,
  	.setkey		= omap_sham_setkey,
  	.halg.digestsize	= SHA512_DIGEST_SIZE,
  	.halg.base	= {
  		.cra_name		= "hmac(sha512)",
  		.cra_driver_name	= "omap-hmac-sha512",
eb3547859   Bin Liu   crypto: omap-sham...
1664
  		.cra_priority		= 400,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
  		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
  						CRYPTO_ALG_ASYNC |
  						CRYPTO_ALG_NEED_FALLBACK,
  		.cra_blocksize		= SHA512_BLOCK_SIZE,
  		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
  					sizeof(struct omap_sham_hmac_ctx),
  		.cra_alignmask		= OMAP_ALIGN_MASK,
  		.cra_module		= THIS_MODULE,
  		.cra_init		= omap_sham_cra_sha512_init,
  		.cra_exit		= omap_sham_cra_exit,
  	}
  },
  };
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1678
1679
1680
  static void omap_sham_done_task(unsigned long data)
  {
  	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1681
  	int err = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1682

6cb3ffe10   Dmitry Kasatkin   crypto: omap-sham...
1683
1684
1685
1686
  	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
  		omap_sham_handle_queue(dd, NULL);
  		return;
  	}
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1687
  	if (test_bit(FLAGS_CPU, &dd->flags)) {
8043bb1ae   Tero Kristo   crypto: omap-sham...
1688
1689
  		if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags))
  			goto finish;
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
  	} else if (test_bit(FLAGS_DMA_READY, &dd->flags)) {
  		if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
  			omap_sham_update_dma_stop(dd);
  			if (dd->err) {
  				err = dd->err;
  				goto finish;
  			}
  		}
  		if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags)) {
  			/* hash or semi-hash ready */
  			clear_bit(FLAGS_DMA_READY, &dd->flags);
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1701
1702
  				goto finish;
  		}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1703
  	}
6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1704
  	return;
3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
1705

6c63db821   Dmitry Kasatkin   crypto: omap-sham...
1706
1707
1708
1709
1710
  finish:
  	dev_dbg(dd->dev, "update done: err: %d
  ", err);
  	/* finish curent request */
  	omap_sham_finish_req(dd->req, err);
4e7813a0b   Tero Kristo   crypto: omap-sham...
1711
1712
1713
1714
  
  	/* If we are not busy, process next req */
  	if (!test_bit(FLAGS_BUSY, &dd->flags))
  		omap_sham_handle_queue(dd, NULL);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1715
  }
0d373d603   Mark A. Greer   crypto: omap-sham...
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
  static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
  {
  	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
  		dev_warn(dd->dev, "Interrupt when no active requests.
  ");
  	} else {
  		set_bit(FLAGS_OUTPUT_READY, &dd->flags);
  		tasklet_schedule(&dd->done_task);
  	}
  
  	return IRQ_HANDLED;
  }
  
  static irqreturn_t omap_sham_irq_omap2(int irq, void *dev_id)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1730
1731
  {
  	struct omap_sham_dev *dd = dev_id;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1732

ed3ea9a82   Dmitry Kasatkin   crypto: omap-sham...
1733
  	if (unlikely(test_bit(FLAGS_FINAL, &dd->flags)))
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1734
1735
1736
1737
1738
1739
  		/* final -> allow device to go to power-saving mode */
  		omap_sham_write_mask(dd, SHA_REG_CTRL, 0, SHA_REG_CTRL_LENGTH);
  
  	omap_sham_write_mask(dd, SHA_REG_CTRL, SHA_REG_CTRL_OUTPUT_READY,
  				 SHA_REG_CTRL_OUTPUT_READY);
  	omap_sham_read(dd, SHA_REG_CTRL);
0d373d603   Mark A. Greer   crypto: omap-sham...
1740
1741
  	return omap_sham_irq_common(dd);
  }
cd3f1d545   Dmitry Kasatkin   crypto: omap-sham...
1742

0d373d603   Mark A. Greer   crypto: omap-sham...
1743
1744
1745
  static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
  {
  	struct omap_sham_dev *dd = dev_id;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1746

0d373d603   Mark A. Greer   crypto: omap-sham...
1747
1748
1749
  	omap_sham_write_mask(dd, SHA_REG_MASK(dd), 0, SHA_REG_MASK_IT_EN);
  
  	return omap_sham_irq_common(dd);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1750
  }
d20fb18be   Mark A. Greer   crypto: omap-sham...
1751
1752
1753
1754
1755
1756
  static struct omap_sham_algs_info omap_sham_algs_info_omap2[] = {
  	{
  		.algs_list	= algs_sha1_md5,
  		.size		= ARRAY_SIZE(algs_sha1_md5),
  	},
  };
0d373d603   Mark A. Greer   crypto: omap-sham...
1757
  static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
d20fb18be   Mark A. Greer   crypto: omap-sham...
1758
1759
  	.algs_info	= omap_sham_algs_info_omap2,
  	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap2),
0d373d603   Mark A. Greer   crypto: omap-sham...
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
  	.flags		= BIT(FLAGS_BE32_SHA1),
  	.digest_size	= SHA1_DIGEST_SIZE,
  	.copy_hash	= omap_sham_copy_hash_omap2,
  	.write_ctrl	= omap_sham_write_ctrl_omap2,
  	.trigger	= omap_sham_trigger_omap2,
  	.poll_irq	= omap_sham_poll_irq_omap2,
  	.intr_hdlr	= omap_sham_irq_omap2,
  	.idigest_ofs	= 0x00,
  	.din_ofs	= 0x1c,
  	.digcnt_ofs	= 0x14,
  	.rev_ofs	= 0x5c,
  	.mask_ofs	= 0x60,
  	.sysstatus_ofs	= 0x64,
  	.major_mask	= 0xf0,
  	.major_shift	= 4,
  	.minor_mask	= 0x0f,
  	.minor_shift	= 0,
  };
03feec9cc   Mark A. Greer   crypto: omap-sham...
1778
  #ifdef CONFIG_OF
d20fb18be   Mark A. Greer   crypto: omap-sham...
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
  static struct omap_sham_algs_info omap_sham_algs_info_omap4[] = {
  	{
  		.algs_list	= algs_sha1_md5,
  		.size		= ARRAY_SIZE(algs_sha1_md5),
  	},
  	{
  		.algs_list	= algs_sha224_sha256,
  		.size		= ARRAY_SIZE(algs_sha224_sha256),
  	},
  };
0d373d603   Mark A. Greer   crypto: omap-sham...
1789
  static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
d20fb18be   Mark A. Greer   crypto: omap-sham...
1790
1791
  	.algs_info	= omap_sham_algs_info_omap4,
  	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap4),
0d373d603   Mark A. Greer   crypto: omap-sham...
1792
1793
1794
1795
1796
1797
1798
1799
  	.flags		= BIT(FLAGS_AUTO_XOR),
  	.digest_size	= SHA256_DIGEST_SIZE,
  	.copy_hash	= omap_sham_copy_hash_omap4,
  	.write_ctrl	= omap_sham_write_ctrl_omap4,
  	.trigger	= omap_sham_trigger_omap4,
  	.poll_irq	= omap_sham_poll_irq_omap4,
  	.intr_hdlr	= omap_sham_irq_omap4,
  	.idigest_ofs	= 0x020,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1800
  	.odigest_ofs	= 0x0,
0d373d603   Mark A. Greer   crypto: omap-sham...
1801
1802
1803
1804
1805
  	.din_ofs	= 0x080,
  	.digcnt_ofs	= 0x040,
  	.rev_ofs	= 0x100,
  	.mask_ofs	= 0x110,
  	.sysstatus_ofs	= 0x114,
eaef7e3f3   Lokesh Vutla   crypto: omap-sham...
1806
1807
  	.mode_ofs	= 0x44,
  	.length_ofs	= 0x48,
0d373d603   Mark A. Greer   crypto: omap-sham...
1808
1809
1810
1811
1812
  	.major_mask	= 0x0700,
  	.major_shift	= 8,
  	.minor_mask	= 0x003f,
  	.minor_shift	= 0,
  };
7d7c704d0   Lokesh Vutla   crypto: omap-sham...
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
  static struct omap_sham_algs_info omap_sham_algs_info_omap5[] = {
  	{
  		.algs_list	= algs_sha1_md5,
  		.size		= ARRAY_SIZE(algs_sha1_md5),
  	},
  	{
  		.algs_list	= algs_sha224_sha256,
  		.size		= ARRAY_SIZE(algs_sha224_sha256),
  	},
  	{
  		.algs_list	= algs_sha384_sha512,
  		.size		= ARRAY_SIZE(algs_sha384_sha512),
  	},
  };
  
  static const struct omap_sham_pdata omap_sham_pdata_omap5 = {
  	.algs_info	= omap_sham_algs_info_omap5,
  	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap5),
  	.flags		= BIT(FLAGS_AUTO_XOR),
  	.digest_size	= SHA512_DIGEST_SIZE,
  	.copy_hash	= omap_sham_copy_hash_omap4,
  	.write_ctrl	= omap_sham_write_ctrl_omap4,
  	.trigger	= omap_sham_trigger_omap4,
  	.poll_irq	= omap_sham_poll_irq_omap4,
  	.intr_hdlr	= omap_sham_irq_omap4,
  	.idigest_ofs	= 0x240,
  	.odigest_ofs	= 0x200,
  	.din_ofs	= 0x080,
  	.digcnt_ofs	= 0x280,
  	.rev_ofs	= 0x100,
  	.mask_ofs	= 0x110,
  	.sysstatus_ofs	= 0x114,
  	.mode_ofs	= 0x284,
  	.length_ofs	= 0x288,
  	.major_mask	= 0x0700,
  	.major_shift	= 8,
  	.minor_mask	= 0x003f,
  	.minor_shift	= 0,
  };
03feec9cc   Mark A. Greer   crypto: omap-sham...
1852
1853
1854
  static const struct of_device_id omap_sham_of_match[] = {
  	{
  		.compatible	= "ti,omap2-sham",
0d373d603   Mark A. Greer   crypto: omap-sham...
1855
1856
1857
  		.data		= &omap_sham_pdata_omap2,
  	},
  	{
eddca85b1   Pali Rohár   crypto: omap-sham...
1858
1859
1860
1861
  		.compatible	= "ti,omap3-sham",
  		.data		= &omap_sham_pdata_omap2,
  	},
  	{
0d373d603   Mark A. Greer   crypto: omap-sham...
1862
1863
  		.compatible	= "ti,omap4-sham",
  		.data		= &omap_sham_pdata_omap4,
03feec9cc   Mark A. Greer   crypto: omap-sham...
1864
  	},
7d7c704d0   Lokesh Vutla   crypto: omap-sham...
1865
1866
1867
1868
  	{
  		.compatible	= "ti,omap5-sham",
  		.data		= &omap_sham_pdata_omap5,
  	},
03feec9cc   Mark A. Greer   crypto: omap-sham...
1869
1870
1871
1872
1873
1874
  	{},
  };
  MODULE_DEVICE_TABLE(of, omap_sham_of_match);
  
  static int omap_sham_get_res_of(struct omap_sham_dev *dd,
  		struct device *dev, struct resource *res)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1875
  {
03feec9cc   Mark A. Greer   crypto: omap-sham...
1876
1877
1878
  	struct device_node *node = dev->of_node;
  	const struct of_device_id *match;
  	int err = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1879

03feec9cc   Mark A. Greer   crypto: omap-sham...
1880
1881
1882
1883
1884
1885
  	match = of_match_device(of_match_ptr(omap_sham_of_match), dev);
  	if (!match) {
  		dev_err(dev, "no compatible OF match
  ");
  		err = -EINVAL;
  		goto err;
3e133c8bf   Dmitry Kasatkin   crypto: omap-sham...
1886
  	}
03feec9cc   Mark A. Greer   crypto: omap-sham...
1887
1888
1889
1890
1891
1892
1893
  	err = of_address_to_resource(node, 0, res);
  	if (err < 0) {
  		dev_err(dev, "can't translate OF node address
  ");
  		err = -EINVAL;
  		goto err;
  	}
f7578496a   Thierry Reding   of/irq: Use irq_o...
1894
  	dd->irq = irq_of_parse_and_map(node, 0);
03feec9cc   Mark A. Greer   crypto: omap-sham...
1895
1896
1897
1898
1899
1900
  	if (!dd->irq) {
  		dev_err(dev, "can't translate OF irq value
  ");
  		err = -EINVAL;
  		goto err;
  	}
0d373d603   Mark A. Greer   crypto: omap-sham...
1901
  	dd->pdata = match->data;
03feec9cc   Mark A. Greer   crypto: omap-sham...
1902
1903
1904
  
  err:
  	return err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1905
  }
03feec9cc   Mark A. Greer   crypto: omap-sham...
1906
  #else
c3c3b3292   Mark A. Greer   crypto: omap-sham...
1907
1908
1909
  static const struct of_device_id omap_sham_of_match[] = {
  	{},
  };
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1910

c3c3b3292   Mark A. Greer   crypto: omap-sham...
1911
  static int omap_sham_get_res_of(struct omap_sham_dev *dd,
03feec9cc   Mark A. Greer   crypto: omap-sham...
1912
  		struct device *dev, struct resource *res)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1913
  {
03feec9cc   Mark A. Greer   crypto: omap-sham...
1914
1915
1916
  	return -EINVAL;
  }
  #endif
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1917

03feec9cc   Mark A. Greer   crypto: omap-sham...
1918
1919
1920
1921
1922
1923
  static int omap_sham_get_res_pdev(struct omap_sham_dev *dd,
  		struct platform_device *pdev, struct resource *res)
  {
  	struct device *dev = &pdev->dev;
  	struct resource *r;
  	int err = 0;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1924

03feec9cc   Mark A. Greer   crypto: omap-sham...
1925
1926
1927
1928
1929
1930
1931
  	/* Get the base address */
  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!r) {
  		dev_err(dev, "no MEM resource info
  ");
  		err = -ENODEV;
  		goto err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1932
  	}
03feec9cc   Mark A. Greer   crypto: omap-sham...
1933
  	memcpy(res, r, sizeof(*res));
584db6a1b   Samu Onkalo   crypto: omap-sham...
1934

03feec9cc   Mark A. Greer   crypto: omap-sham...
1935
1936
1937
1938
1939
1940
1941
1942
  	/* Get the IRQ */
  	dd->irq = platform_get_irq(pdev, 0);
  	if (dd->irq < 0) {
  		dev_err(dev, "no IRQ resource info
  ");
  		err = dd->irq;
  		goto err;
  	}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1943

0d373d603   Mark A. Greer   crypto: omap-sham...
1944
1945
  	/* Only OMAP2/3 can be non-DT */
  	dd->pdata = &omap_sham_pdata_omap2;
03feec9cc   Mark A. Greer   crypto: omap-sham...
1946
1947
  err:
  	return err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1948
  }
49cfe4db2   Greg Kroah-Hartman   Drivers: crypto: ...
1949
  static int omap_sham_probe(struct platform_device *pdev)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1950
1951
1952
  {
  	struct omap_sham_dev *dd;
  	struct device *dev = &pdev->dev;
03feec9cc   Mark A. Greer   crypto: omap-sham...
1953
  	struct resource res;
dfd061d5a   Mark A. Greer   crypto: omap-sham...
1954
  	dma_cap_mask_t mask;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1955
  	int err, i, j;
0d373d603   Mark A. Greer   crypto: omap-sham...
1956
  	u32 rev;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1957

7a7e4b73b   Lokesh Vutla   crypto: omap-sham...
1958
  	dd = devm_kzalloc(dev, sizeof(struct omap_sham_dev), GFP_KERNEL);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
  	if (dd == NULL) {
  		dev_err(dev, "unable to alloc data struct.
  ");
  		err = -ENOMEM;
  		goto data_err;
  	}
  	dd->dev = dev;
  	platform_set_drvdata(pdev, dd);
  
  	INIT_LIST_HEAD(&dd->list);
  	spin_lock_init(&dd->lock);
  	tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1971
  	crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
03feec9cc   Mark A. Greer   crypto: omap-sham...
1972
1973
1974
  	err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) :
  			       omap_sham_get_res_pdev(dd, pdev, &res);
  	if (err)
7a7e4b73b   Lokesh Vutla   crypto: omap-sham...
1975
  		goto data_err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1976

30862281f   Laurent Navet   drivers: crypto: ...
1977
1978
1979
  	dd->io_base = devm_ioremap_resource(dev, &res);
  	if (IS_ERR(dd->io_base)) {
  		err = PTR_ERR(dd->io_base);
7a7e4b73b   Lokesh Vutla   crypto: omap-sham...
1980
  		goto data_err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1981
  	}
03feec9cc   Mark A. Greer   crypto: omap-sham...
1982
  	dd->phys_base = res.start;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1983

0de9c3876   Lokesh Vutla   crypto: omap-sham...
1984
1985
  	err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr,
  			       IRQF_TRIGGER_NONE, dev_name(dev), dd);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1986
  	if (err) {
0de9c3876   Lokesh Vutla   crypto: omap-sham...
1987
1988
1989
  		dev_err(dev, "unable to request irq %d, err = %d
  ",
  			dd->irq, err);
7a7e4b73b   Lokesh Vutla   crypto: omap-sham...
1990
  		goto data_err;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1991
  	}
dfd061d5a   Mark A. Greer   crypto: omap-sham...
1992
1993
  	dma_cap_zero(mask);
  	dma_cap_set(DMA_SLAVE, mask);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
1994

dbe246209   Peter Ujfalusi   crypto: omap-sham...
1995
1996
1997
1998
1999
  	dd->dma_lch = dma_request_chan(dev, "rx");
  	if (IS_ERR(dd->dma_lch)) {
  		err = PTR_ERR(dd->dma_lch);
  		if (err == -EPROBE_DEFER)
  			goto data_err;
b8411ccd6   Lokesh Vutla   crypto: omap-sham...
2000
2001
2002
  		dd->polling_mode = 1;
  		dev_dbg(dev, "using polling mode instead of dma
  ");
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2003
  	}
0d373d603   Mark A. Greer   crypto: omap-sham...
2004
  	dd->flags |= dd->pdata->flags;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2005

e93f767be   Tero Kristo   crypto: omap-sham...
2006
2007
  	pm_runtime_use_autosuspend(dev);
  	pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
b359f034c   Mark A. Greer   crypto: omap-sham...
2008
  	pm_runtime_enable(dev);
b0a3d8986   Vutla, Lokesh   crypto: omap-sham...
2009
  	pm_runtime_irq_safe(dev);
604c31039   Pali Rohár   crypto: omap-sham...
2010
2011
2012
2013
2014
2015
2016
  
  	err = pm_runtime_get_sync(dev);
  	if (err < 0) {
  		dev_err(dev, "failed to get sync: %d
  ", err);
  		goto err_pm;
  	}
0d373d603   Mark A. Greer   crypto: omap-sham...
2017
2018
  	rev = omap_sham_read(dd, SHA_REG_REV(dd));
  	pm_runtime_put_sync(&pdev->dev);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2019

8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2020
2021
  	dev_info(dev, "hw accel on OMAP rev %u.%u
  ",
0d373d603   Mark A. Greer   crypto: omap-sham...
2022
2023
  		(rev & dd->pdata->major_mask) >> dd->pdata->major_shift,
  		(rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2024
2025
2026
2027
  
  	spin_lock(&sham.lock);
  	list_add_tail(&dd->list, &sham.dev_list);
  	spin_unlock(&sham.lock);
d20fb18be   Mark A. Greer   crypto: omap-sham...
2028
2029
  	for (i = 0; i < dd->pdata->algs_info_size; i++) {
  		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
99a7ffffd   Tero Kristo   crypto: omap-sham...
2030
2031
2032
2033
2034
  			struct ahash_alg *alg;
  
  			alg = &dd->pdata->algs_info[i].algs_list[j];
  			alg->export = omap_sham_export;
  			alg->import = omap_sham_import;
a84d351f6   Tero Kristo   crypto: omap-sham...
2035
2036
  			alg->halg.statesize = sizeof(struct omap_sham_reqctx) +
  					      BUFLEN;
99a7ffffd   Tero Kristo   crypto: omap-sham...
2037
  			err = crypto_register_ahash(alg);
d20fb18be   Mark A. Greer   crypto: omap-sham...
2038
2039
2040
2041
2042
  			if (err)
  				goto err_algs;
  
  			dd->pdata->algs_info[i].registered++;
  		}
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2043
2044
2045
2046
2047
  	}
  
  	return 0;
  
  err_algs:
d20fb18be   Mark A. Greer   crypto: omap-sham...
2048
2049
2050
2051
  	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
  		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
  			crypto_unregister_ahash(
  					&dd->pdata->algs_info[i].algs_list[j]);
604c31039   Pali Rohár   crypto: omap-sham...
2052
  err_pm:
b359f034c   Mark A. Greer   crypto: omap-sham...
2053
  	pm_runtime_disable(dev);
d462e3225   Dan Carpenter   crypto: omap-sham...
2054
  	if (!dd->polling_mode)
f13ab86a6   Mark A. Greer   crypto: omap-sham...
2055
  		dma_release_channel(dd->dma_lch);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2056
2057
2058
2059
2060
2061
  data_err:
  	dev_err(dev, "initialization failed.
  ");
  
  	return err;
  }
49cfe4db2   Greg Kroah-Hartman   Drivers: crypto: ...
2062
  static int omap_sham_remove(struct platform_device *pdev)
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2063
2064
  {
  	static struct omap_sham_dev *dd;
d20fb18be   Mark A. Greer   crypto: omap-sham...
2065
  	int i, j;
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2066
2067
2068
2069
2070
2071
2072
  
  	dd = platform_get_drvdata(pdev);
  	if (!dd)
  		return -ENODEV;
  	spin_lock(&sham.lock);
  	list_del(&dd->list);
  	spin_unlock(&sham.lock);
d20fb18be   Mark A. Greer   crypto: omap-sham...
2073
2074
2075
2076
  	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
  		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
  			crypto_unregister_ahash(
  					&dd->pdata->algs_info[i].algs_list[j]);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2077
  	tasklet_kill(&dd->done_task);
b359f034c   Mark A. Greer   crypto: omap-sham...
2078
  	pm_runtime_disable(&pdev->dev);
f13ab86a6   Mark A. Greer   crypto: omap-sham...
2079

dbe246209   Peter Ujfalusi   crypto: omap-sham...
2080
  	if (!dd->polling_mode)
f13ab86a6   Mark A. Greer   crypto: omap-sham...
2081
  		dma_release_channel(dd->dma_lch);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2082
2083
2084
  
  	return 0;
  }
3b3f44002   Mark A. Greer   crypto: omap-sham...
2085
2086
2087
2088
2089
2090
2091
2092
2093
  #ifdef CONFIG_PM_SLEEP
  static int omap_sham_suspend(struct device *dev)
  {
  	pm_runtime_put_sync(dev);
  	return 0;
  }
  
  static int omap_sham_resume(struct device *dev)
  {
604c31039   Pali Rohár   crypto: omap-sham...
2094
2095
2096
2097
2098
2099
  	int err = pm_runtime_get_sync(dev);
  	if (err < 0) {
  		dev_err(dev, "failed to get sync: %d
  ", err);
  		return err;
  	}
3b3f44002   Mark A. Greer   crypto: omap-sham...
2100
2101
2102
  	return 0;
  }
  #endif
ae12fe288   Jingoo Han   crypto: omap-sham...
2103
  static SIMPLE_DEV_PM_OPS(omap_sham_pm_ops, omap_sham_suspend, omap_sham_resume);
3b3f44002   Mark A. Greer   crypto: omap-sham...
2104

8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2105
2106
2107
2108
2109
  static struct platform_driver omap_sham_driver = {
  	.probe	= omap_sham_probe,
  	.remove	= omap_sham_remove,
  	.driver	= {
  		.name	= "omap-sham",
3b3f44002   Mark A. Greer   crypto: omap-sham...
2110
  		.pm	= &omap_sham_pm_ops,
03feec9cc   Mark A. Greer   crypto: omap-sham...
2111
  		.of_match_table	= omap_sham_of_match,
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2112
2113
  	},
  };
026137026   Sachin Kamat   crypto: omap-sham...
2114
  module_platform_driver(omap_sham_driver);
8628e7c89   Dmitry Kasatkin   crypto: omap - sh...
2115
2116
2117
2118
  
  MODULE_DESCRIPTION("OMAP SHA1/MD5 hw acceleration support.");
  MODULE_LICENSE("GPL v2");
  MODULE_AUTHOR("Dmitry Kasatkin");
718249d7f   Joni Lapilainen   crypto: omap-sham...
2119
  MODULE_ALIAS("platform:omap-sham");