aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2012-12-21 12:04:08 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-01-05 05:43:58 -0500
commit0d373d603202b8bfecc87b9b3602e6ffbf9e4feb (patch)
tree96c182173e28ae2369085f4a28838e6467b94466 /drivers/crypto
parent0e87e73f4abe1ada69cf780fe2550c6361a1b53b (diff)
crypto: omap-sham - Add OMAP4/AM33XX SHAM Support
Add support for the OMAP4 version of the SHAM module that is present on OMAP4 and AM33xx SoCs. The modules have several differences including register offsets, hardware XORing, and how DMA is triggered. To handle these differences, a platform_data structure is defined and contains routine pointers, register offsets, bit shifts within registers, and flags to indicate whether the hardware supports XORing and provides SHA1 results in big or little endian. OMAP2/OMAP3-specific routines are suffixed with '_omap2' and OMAP4/AM33xx routines are suffixed with '_omap4'. Note: The code being integrated is from the TI AM33xx SDK and was written by Greg Turner <gkmturner@gmail.com> and Herman Schuurman (current email unknown) while at TI. CC: Greg Turner <gkmturner@gmail.com> CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/omap-sham.c416
1 files changed, 332 insertions, 84 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 8074bd9947d1..fab0af488b83 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (c) 2010 Nokia Corporation 6 * Copyright (c) 2010 Nokia Corporation
7 * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 7 * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
8 * Copyright (c) 2011 Texas Instruments Incorporated
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published 11 * it under the terms of the GNU General Public License version 2 as published
@@ -43,16 +44,17 @@
43#include <crypto/hash.h> 44#include <crypto/hash.h>
44#include <crypto/internal/hash.h> 45#include <crypto/internal/hash.h>
45 46
46#define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
47#define SHA_REG_DIN(x) (0x1C + ((x) * 0x04))
48
49#define SHA1_MD5_BLOCK_SIZE SHA1_BLOCK_SIZE 47#define SHA1_MD5_BLOCK_SIZE SHA1_BLOCK_SIZE
50#define MD5_DIGEST_SIZE 16 48#define MD5_DIGEST_SIZE 16
51 49
52#define DST_MAXBURST 16 50#define DST_MAXBURST 16
53#define DMA_MIN (DST_MAXBURST * sizeof(u32)) 51#define DMA_MIN (DST_MAXBURST * sizeof(u32))
54 52
55#define SHA_REG_DIGCNT 0x14 53#define SHA_REG_IDIGEST(dd, x) ((dd)->pdata->idigest_ofs + ((x)*0x04))
54#define SHA_REG_DIN(dd, x) ((dd)->pdata->din_ofs + ((x) * 0x04))
55#define SHA_REG_DIGCNT(dd) ((dd)->pdata->digcnt_ofs)
56
57#define SHA_REG_ODIGEST(x) (0x00 + ((x) * 0x04))
56 58
57#define SHA_REG_CTRL 0x18 59#define SHA_REG_CTRL 0x18
58#define SHA_REG_CTRL_LENGTH (0xFFFFFFFF << 5) 60#define SHA_REG_CTRL_LENGTH (0xFFFFFFFF << 5)
@@ -62,19 +64,40 @@
62#define SHA_REG_CTRL_INPUT_READY (1 << 1) 64#define SHA_REG_CTRL_INPUT_READY (1 << 1)
63#define SHA_REG_CTRL_OUTPUT_READY (1 << 0) 65#define SHA_REG_CTRL_OUTPUT_READY (1 << 0)
64 66
65#define SHA_REG_REV 0x5C 67#define SHA_REG_REV(dd) ((dd)->pdata->rev_ofs)
66#define SHA_REG_REV_MAJOR 0xF0
67#define SHA_REG_REV_MINOR 0x0F
68 68
69#define SHA_REG_MASK 0x60 69#define SHA_REG_MASK(dd) ((dd)->pdata->mask_ofs)
70#define SHA_REG_MASK_DMA_EN (1 << 3) 70#define SHA_REG_MASK_DMA_EN (1 << 3)
71#define SHA_REG_MASK_IT_EN (1 << 2) 71#define SHA_REG_MASK_IT_EN (1 << 2)
72#define SHA_REG_MASK_SOFTRESET (1 << 1) 72#define SHA_REG_MASK_SOFTRESET (1 << 1)
73#define SHA_REG_AUTOIDLE (1 << 0) 73#define SHA_REG_AUTOIDLE (1 << 0)
74 74
75#define SHA_REG_SYSSTATUS 0x64 75#define SHA_REG_SYSSTATUS(dd) ((dd)->pdata->sysstatus_ofs)
76#define SHA_REG_SYSSTATUS_RESETDONE (1 << 0) 76#define SHA_REG_SYSSTATUS_RESETDONE (1 << 0)
77 77
78#define SHA_REG_MODE 0x44
79#define SHA_REG_MODE_HMAC_OUTER_HASH (1 << 7)
80#define SHA_REG_MODE_HMAC_KEY_PROC (1 << 5)
81#define SHA_REG_MODE_CLOSE_HASH (1 << 4)
82#define SHA_REG_MODE_ALGO_CONSTANT (1 << 3)
83#define SHA_REG_MODE_ALGO_MASK (3 << 1)
84#define SHA_REG_MODE_ALGO_MD5_128 (0 << 1)
85#define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1)
86
87#define SHA_REG_LENGTH 0x48
88
89#define SHA_REG_IRQSTATUS 0x118
90#define SHA_REG_IRQSTATUS_CTX_RDY (1 << 3)
91#define SHA_REG_IRQSTATUS_PARTHASH_RDY (1 << 2)
92#define SHA_REG_IRQSTATUS_INPUT_RDY (1 << 1)
93#define SHA_REG_IRQSTATUS_OUTPUT_RDY (1 << 0)
94
95#define SHA_REG_IRQENA 0x11C
96#define SHA_REG_IRQENA_CTX_RDY (1 << 3)
97#define SHA_REG_IRQENA_PARTHASH_RDY (1 << 2)
98#define SHA_REG_IRQENA_INPUT_RDY (1 << 1)
99#define SHA_REG_IRQENA_OUTPUT_RDY (1 << 0)
100
78#define DEFAULT_TIMEOUT_INTERVAL HZ 101#define DEFAULT_TIMEOUT_INTERVAL HZ
79 102
80/* mostly device flags */ 103/* mostly device flags */
@@ -85,20 +108,29 @@
85#define FLAGS_INIT 4 108#define FLAGS_INIT 4
86#define FLAGS_CPU 5 109#define FLAGS_CPU 5
87#define FLAGS_DMA_READY 6 110#define FLAGS_DMA_READY 6
111#define FLAGS_AUTO_XOR 7
112#define FLAGS_BE32_SHA1 8
88/* context flags */ 113/* context flags */
89#define FLAGS_FINUP 16 114#define FLAGS_FINUP 16
90#define FLAGS_SG 17 115#define FLAGS_SG 17
91#define FLAGS_SHA1 18
92#define FLAGS_HMAC 19
93#define FLAGS_ERROR 20
94 116
95#define OP_UPDATE 1 117#define FLAGS_MODE_SHIFT 18
96#define OP_FINAL 2 118#define FLAGS_MODE_MASK (SHA_REG_MODE_ALGO_MASK \
119 << (FLAGS_MODE_SHIFT - 1))
120#define FLAGS_MODE_MD5 (SHA_REG_MODE_ALGO_MD5_128 \
121 << (FLAGS_MODE_SHIFT - 1))
122#define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 \
123 << (FLAGS_MODE_SHIFT - 1))
124#define FLAGS_HMAC 20
125#define FLAGS_ERROR 21
126
127#define OP_UPDATE 1
128#define OP_FINAL 2
97 129
98#define OMAP_ALIGN_MASK (sizeof(u32)-1) 130#define OMAP_ALIGN_MASK (sizeof(u32)-1)
99#define OMAP_ALIGNED __attribute__((aligned(sizeof(u32)))) 131#define OMAP_ALIGNED __attribute__((aligned(sizeof(u32))))
100 132
101#define BUFLEN PAGE_SIZE 133#define BUFLEN PAGE_SIZE
102 134
103struct omap_sham_dev; 135struct omap_sham_dev;
104 136
@@ -107,7 +139,7 @@ struct omap_sham_reqctx {
107 unsigned long flags; 139 unsigned long flags;
108 unsigned long op; 140 unsigned long op;
109 141
110 u8 digest[SHA1_DIGEST_SIZE] OMAP_ALIGNED; 142 u8 digest[SHA256_DIGEST_SIZE] OMAP_ALIGNED;
111 size_t digcnt; 143 size_t digcnt;
112 size_t bufcnt; 144 size_t bufcnt;
113 size_t buflen; 145 size_t buflen;
@@ -124,8 +156,8 @@ struct omap_sham_reqctx {
124 156
125struct omap_sham_hmac_ctx { 157struct omap_sham_hmac_ctx {
126 struct crypto_shash *shash; 158 struct crypto_shash *shash;
127 u8 ipad[SHA1_MD5_BLOCK_SIZE]; 159 u8 ipad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
128 u8 opad[SHA1_MD5_BLOCK_SIZE]; 160 u8 opad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
129}; 161};
130 162
131struct omap_sham_ctx { 163struct omap_sham_ctx {
@@ -141,6 +173,31 @@ struct omap_sham_ctx {
141 173
142#define OMAP_SHAM_QUEUE_LENGTH 1 174#define OMAP_SHAM_QUEUE_LENGTH 1
143 175
176struct omap_sham_pdata {
177 unsigned long flags;
178 int digest_size;
179
180 void (*copy_hash)(struct ahash_request *req, int out);
181 void (*write_ctrl)(struct omap_sham_dev *dd, size_t length,
182 int final, int dma);
183 void (*trigger)(struct omap_sham_dev *dd, size_t length);
184 int (*poll_irq)(struct omap_sham_dev *dd);
185 irqreturn_t (*intr_hdlr)(int irq, void *dev_id);
186
187 u32 odigest_ofs;
188 u32 idigest_ofs;
189 u32 din_ofs;
190 u32 digcnt_ofs;
191 u32 rev_ofs;
192 u32 mask_ofs;
193 u32 sysstatus_ofs;
194
195 u32 major_mask;
196 u32 major_shift;
197 u32 minor_mask;
198 u32 minor_shift;
199};
200
144struct omap_sham_dev { 201struct omap_sham_dev {
145 struct list_head list; 202 struct list_head list;
146 unsigned long phys_base; 203 unsigned long phys_base;
@@ -156,6 +213,8 @@ struct omap_sham_dev {
156 unsigned long flags; 213 unsigned long flags;
157 struct crypto_queue queue; 214 struct crypto_queue queue;
158 struct ahash_request *req; 215 struct ahash_request *req;
216
217 const struct omap_sham_pdata *pdata;
159}; 218};
160 219
161struct omap_sham_drv { 220struct omap_sham_drv {
@@ -203,21 +262,44 @@ static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit)
203 return 0; 262 return 0;
204} 263}
205 264
206static void omap_sham_copy_hash(struct ahash_request *req, int out) 265static void omap_sham_copy_hash_omap2(struct ahash_request *req, int out)
207{ 266{
208 struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 267 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
268 struct omap_sham_dev *dd = ctx->dd;
209 u32 *hash = (u32 *)ctx->digest; 269 u32 *hash = (u32 *)ctx->digest;
210 int i; 270 int i;
211 271
212 /* MD5 is almost unused. So copy sha1 size to reduce code */ 272 for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
213 for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) {
214 if (out) 273 if (out)
215 hash[i] = omap_sham_read(ctx->dd, 274 hash[i] = omap_sham_read(dd, SHA_REG_IDIGEST(dd, i));
216 SHA_REG_DIGEST(i));
217 else 275 else
218 omap_sham_write(ctx->dd, 276 omap_sham_write(dd, SHA_REG_IDIGEST(dd, i), hash[i]);
219 SHA_REG_DIGEST(i), hash[i]); 277 }
278}
279
280static void omap_sham_copy_hash_omap4(struct ahash_request *req, int out)
281{
282 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
283 struct omap_sham_dev *dd = ctx->dd;
284 int i;
285
286 if (ctx->flags & BIT(FLAGS_HMAC)) {
287 struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
288 struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
289 struct omap_sham_hmac_ctx *bctx = tctx->base;
290 u32 *opad = (u32 *)bctx->opad;
291
292 for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
293 if (out)
294 opad[i] = omap_sham_read(dd,
295 SHA_REG_ODIGEST(i));
296 else
297 omap_sham_write(dd, SHA_REG_ODIGEST(i),
298 opad[i]);
299 }
220 } 300 }
301
302 omap_sham_copy_hash_omap2(req, out);
221} 303}
222 304
223static void omap_sham_copy_ready_hash(struct ahash_request *req) 305static void omap_sham_copy_ready_hash(struct ahash_request *req)
@@ -225,20 +307,31 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
225 struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 307 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
226 u32 *in = (u32 *)ctx->digest; 308 u32 *in = (u32 *)ctx->digest;
227 u32 *hash = (u32 *)req->result; 309 u32 *hash = (u32 *)req->result;
228 int i; 310 int i, d, big_endian = 0;
229 311
230 if (!hash) 312 if (!hash)
231 return; 313 return;
232 314
233 if (likely(ctx->flags & BIT(FLAGS_SHA1))) { 315 switch (ctx->flags & FLAGS_MODE_MASK) {
234 /* SHA1 results are in big endian */ 316 case FLAGS_MODE_MD5:
235 for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) 317 d = MD5_DIGEST_SIZE / sizeof(u32);
318 break;
319 case FLAGS_MODE_SHA1:
320 /* OMAP2 SHA1 is big endian */
321 if (test_bit(FLAGS_BE32_SHA1, &ctx->dd->flags))
322 big_endian = 1;
323 d = SHA1_DIGEST_SIZE / sizeof(u32);
324 break;
325 default:
326 d = 0;
327 }
328
329 if (big_endian)
330 for (i = 0; i < d; i++)
236 hash[i] = be32_to_cpu(in[i]); 331 hash[i] = be32_to_cpu(in[i]);
237 } else { 332 else
238 /* MD5 results are in little endian */ 333 for (i = 0; i < d; i++)
239 for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++)
240 hash[i] = le32_to_cpu(in[i]); 334 hash[i] = le32_to_cpu(in[i]);
241 }
242} 335}
243 336
244static int omap_sham_hw_init(struct omap_sham_dev *dd) 337static int omap_sham_hw_init(struct omap_sham_dev *dd)
@@ -246,13 +339,6 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
246 pm_runtime_get_sync(dd->dev); 339 pm_runtime_get_sync(dd->dev);
247 340
248 if (!test_bit(FLAGS_INIT, &dd->flags)) { 341 if (!test_bit(FLAGS_INIT, &dd->flags)) {
249 omap_sham_write_mask(dd, SHA_REG_MASK,
250 SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
251
252 if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
253 SHA_REG_SYSSTATUS_RESETDONE))
254 return -ETIMEDOUT;
255
256 set_bit(FLAGS_INIT, &dd->flags); 342 set_bit(FLAGS_INIT, &dd->flags);
257 dd->err = 0; 343 dd->err = 0;
258 } 344 }
@@ -260,23 +346,23 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
260 return 0; 346 return 0;
261} 347}
262 348
263static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length, 349static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
264 int final, int dma) 350 int final, int dma)
265{ 351{
266 struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 352 struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
267 u32 val = length << 5, mask; 353 u32 val = length << 5, mask;
268 354
269 if (likely(ctx->digcnt)) 355 if (likely(ctx->digcnt))
270 omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt); 356 omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
271 357
272 omap_sham_write_mask(dd, SHA_REG_MASK, 358 omap_sham_write_mask(dd, SHA_REG_MASK(dd),
273 SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0), 359 SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0),
274 SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN); 360 SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
275 /* 361 /*
276 * Setting ALGO_CONST only for the first iteration 362 * Setting ALGO_CONST only for the first iteration
277 * and CLOSE_HASH only for the last one. 363 * and CLOSE_HASH only for the last one.
278 */ 364 */
279 if (ctx->flags & BIT(FLAGS_SHA1)) 365 if ((ctx->flags & FLAGS_MODE_MASK) == FLAGS_MODE_SHA1)
280 val |= SHA_REG_CTRL_ALGO; 366 val |= SHA_REG_CTRL_ALGO;
281 if (!ctx->digcnt) 367 if (!ctx->digcnt)
282 val |= SHA_REG_CTRL_ALGO_CONST; 368 val |= SHA_REG_CTRL_ALGO_CONST;
@@ -289,6 +375,81 @@ static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
289 omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask); 375 omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask);
290} 376}
291 377
378static void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length)
379{
380}
381
382static int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd)
383{
384 return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY);
385}
386
387static void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset,
388 u32 *value, int count)
389{
390 for (; count--; value++, offset += 4)
391 omap_sham_write(dd, offset, *value);
392}
393
394static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
395 int final, int dma)
396{
397 struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
398 u32 val, mask;
399
400 /*
401 * Setting ALGO_CONST only for the first iteration and
402 * CLOSE_HASH only for the last one. Note that flags mode bits
403 * correspond to algorithm encoding in mode register.
404 */
405 val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT - 1);
406 if (!ctx->digcnt) {
407 struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
408 struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
409 struct omap_sham_hmac_ctx *bctx = tctx->base;
410
411 val |= SHA_REG_MODE_ALGO_CONSTANT;
412
413 if (ctx->flags & BIT(FLAGS_HMAC)) {
414 val |= SHA_REG_MODE_HMAC_KEY_PROC;
415 omap_sham_write_n(dd, SHA_REG_ODIGEST(0),
416 (u32 *)bctx->ipad,
417 SHA1_BLOCK_SIZE / sizeof(u32));
418 ctx->digcnt += SHA1_BLOCK_SIZE;
419 }
420 }
421
422 if (final) {
423 val |= SHA_REG_MODE_CLOSE_HASH;
424
425 if (ctx->flags & BIT(FLAGS_HMAC))
426 val |= SHA_REG_MODE_HMAC_OUTER_HASH;
427 }
428
429 mask = SHA_REG_MODE_ALGO_CONSTANT | SHA_REG_MODE_CLOSE_HASH |
430 SHA_REG_MODE_ALGO_MASK | SHA_REG_MODE_HMAC_OUTER_HASH |
431 SHA_REG_MODE_HMAC_KEY_PROC;
432
433 dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx\n", val, ctx->flags);
434 omap_sham_write_mask(dd, SHA_REG_MODE, val, mask);
435 omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY);
436 omap_sham_write_mask(dd, SHA_REG_MASK(dd),
437 SHA_REG_MASK_IT_EN |
438 (dma ? SHA_REG_MASK_DMA_EN : 0),
439 SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
440}
441
442static void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length)
443{
444 omap_sham_write(dd, SHA_REG_LENGTH, length);
445}
446
447static int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd)
448{
449 return omap_sham_wait(dd, SHA_REG_IRQSTATUS,
450 SHA_REG_IRQSTATUS_INPUT_RDY);
451}
452
292static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf, 453static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
293 size_t length, int final) 454 size_t length, int final)
294{ 455{
@@ -299,12 +460,13 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
299 dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n", 460 dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
300 ctx->digcnt, length, final); 461 ctx->digcnt, length, final);
301 462
302 omap_sham_write_ctrl(dd, length, final, 0); 463 dd->pdata->write_ctrl(dd, length, final, 0);
464 dd->pdata->trigger(dd, length);
303 465
304 /* should be non-zero before next lines to disable clocks later */ 466 /* should be non-zero before next lines to disable clocks later */
305 ctx->digcnt += length; 467 ctx->digcnt += length;
306 468
307 if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY)) 469 if (dd->pdata->poll_irq(dd))
308 return -ETIMEDOUT; 470 return -ETIMEDOUT;
309 471
310 if (final) 472 if (final)
@@ -315,7 +477,7 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
315 len32 = DIV_ROUND_UP(length, sizeof(u32)); 477 len32 = DIV_ROUND_UP(length, sizeof(u32));
316 478
317 for (count = 0; count < len32; count++) 479 for (count = 0; count < len32; count++)
318 omap_sham_write(dd, SHA_REG_DIN(count), buffer[count]); 480 omap_sham_write(dd, SHA_REG_DIN(dd, count), buffer[count]);
319 481
320 return -EINPROGRESS; 482 return -EINPROGRESS;
321} 483}
@@ -341,7 +503,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
341 503
342 memset(&cfg, 0, sizeof(cfg)); 504 memset(&cfg, 0, sizeof(cfg));
343 505
344 cfg.dst_addr = dd->phys_base + SHA_REG_DIN(0); 506 cfg.dst_addr = dd->phys_base + SHA_REG_DIN(dd, 0);
345 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 507 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
346 cfg.dst_maxburst = DST_MAXBURST; 508 cfg.dst_maxburst = DST_MAXBURST;
347 509
@@ -381,7 +543,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
381 tx->callback = omap_sham_dma_callback; 543 tx->callback = omap_sham_dma_callback;
382 tx->callback_param = dd; 544 tx->callback_param = dd;
383 545
384 omap_sham_write_ctrl(dd, length, final, 1); 546 dd->pdata->write_ctrl(dd, length, final, 1);
385 547
386 ctx->digcnt += length; 548 ctx->digcnt += length;
387 549
@@ -393,6 +555,8 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
393 dmaengine_submit(tx); 555 dmaengine_submit(tx);
394 dma_async_issue_pending(dd->dma_lch); 556 dma_async_issue_pending(dd->dma_lch);
395 557
558 dd->pdata->trigger(dd, length);
559
396 return -EINPROGRESS; 560 return -EINPROGRESS;
397} 561}
398 562
@@ -450,7 +614,7 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
450 ctx->flags &= ~BIT(FLAGS_SG); 614 ctx->flags &= ~BIT(FLAGS_SG);
451 615
452 ret = omap_sham_xmit_dma(dd, ctx->dma_addr, length, final, 0); 616 ret = omap_sham_xmit_dma(dd, ctx->dma_addr, length, final, 0);
453 if (ret) 617 if (ret != -EINPROGRESS)
454 dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen, 618 dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
455 DMA_TO_DEVICE); 619 DMA_TO_DEVICE);
456 620
@@ -544,7 +708,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
544 final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total; 708 final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
545 709
546 ret = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final, 1); 710 ret = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final, 1);
547 if (ret) 711 if (ret != -EINPROGRESS)
548 dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE); 712 dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
549 713
550 return ret; 714 return ret;
@@ -609,18 +773,27 @@ static int omap_sham_init(struct ahash_request *req)
609 dev_dbg(dd->dev, "init: digest size: %d\n", 773 dev_dbg(dd->dev, "init: digest size: %d\n",
610 crypto_ahash_digestsize(tfm)); 774 crypto_ahash_digestsize(tfm));
611 775
612 if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE) 776 switch (crypto_ahash_digestsize(tfm)) {
613 ctx->flags |= BIT(FLAGS_SHA1); 777 case MD5_DIGEST_SIZE:
778 ctx->flags |= FLAGS_MODE_MD5;
779 break;
780 case SHA1_DIGEST_SIZE:
781 ctx->flags |= FLAGS_MODE_SHA1;
782 break;
783 }
614 784
615 ctx->bufcnt = 0; 785 ctx->bufcnt = 0;
616 ctx->digcnt = 0; 786 ctx->digcnt = 0;
617 ctx->buflen = BUFLEN; 787 ctx->buflen = BUFLEN;
618 788
619 if (tctx->flags & BIT(FLAGS_HMAC)) { 789 if (tctx->flags & BIT(FLAGS_HMAC)) {
620 struct omap_sham_hmac_ctx *bctx = tctx->base; 790 if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
791 struct omap_sham_hmac_ctx *bctx = tctx->base;
792
793 memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
794 ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
795 }
621 796
622 memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
623 ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
624 ctx->flags |= BIT(FLAGS_HMAC); 797 ctx->flags |= BIT(FLAGS_HMAC);
625 } 798 }
626 799
@@ -697,7 +870,8 @@ static int omap_sham_finish(struct ahash_request *req)
697 870
698 if (ctx->digcnt) { 871 if (ctx->digcnt) {
699 omap_sham_copy_ready_hash(req); 872 omap_sham_copy_ready_hash(req);
700 if (ctx->flags & BIT(FLAGS_HMAC)) 873 if ((ctx->flags & BIT(FLAGS_HMAC)) &&
874 !test_bit(FLAGS_AUTO_XOR, &dd->flags))
701 err = omap_sham_finish_hmac(req); 875 err = omap_sham_finish_hmac(req);
702 } 876 }
703 877
@@ -712,7 +886,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
712 struct omap_sham_dev *dd = ctx->dd; 886 struct omap_sham_dev *dd = ctx->dd;
713 887
714 if (!err) { 888 if (!err) {
715 omap_sham_copy_hash(req, 1); 889 dd->pdata->copy_hash(req, 1);
716 if (test_bit(FLAGS_FINAL, &dd->flags)) 890 if (test_bit(FLAGS_FINAL, &dd->flags))
717 err = omap_sham_finish(req); 891 err = omap_sham_finish(req);
718 } else { 892 } else {
@@ -772,7 +946,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
772 946
773 if (ctx->digcnt) 947 if (ctx->digcnt)
774 /* request has changed - restore hash */ 948 /* request has changed - restore hash */
775 omap_sham_copy_hash(req, 0); 949 dd->pdata->copy_hash(req, 0);
776 950
777 if (ctx->op == OP_UPDATE) { 951 if (ctx->op == OP_UPDATE) {
778 err = omap_sham_update_req(dd); 952 err = omap_sham_update_req(dd);
@@ -911,7 +1085,21 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
911 struct omap_sham_hmac_ctx *bctx = tctx->base; 1085 struct omap_sham_hmac_ctx *bctx = tctx->base;
912 int bs = crypto_shash_blocksize(bctx->shash); 1086 int bs = crypto_shash_blocksize(bctx->shash);
913 int ds = crypto_shash_digestsize(bctx->shash); 1087 int ds = crypto_shash_digestsize(bctx->shash);
1088 struct omap_sham_dev *dd = NULL, *tmp;
914 int err, i; 1089 int err, i;
1090
1091 spin_lock_bh(&sham.lock);
1092 if (!tctx->dd) {
1093 list_for_each_entry(tmp, &sham.dev_list, list) {
1094 dd = tmp;
1095 break;
1096 }
1097 tctx->dd = dd;
1098 } else {
1099 dd = tctx->dd;
1100 }
1101 spin_unlock_bh(&sham.lock);
1102
915 err = crypto_shash_setkey(tctx->fallback, key, keylen); 1103 err = crypto_shash_setkey(tctx->fallback, key, keylen);
916 if (err) 1104 if (err)
917 return err; 1105 return err;
@@ -928,11 +1116,14 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
928 } 1116 }
929 1117
930 memset(bctx->ipad + keylen, 0, bs - keylen); 1118 memset(bctx->ipad + keylen, 0, bs - keylen);
931 memcpy(bctx->opad, bctx->ipad, bs);
932 1119
933 for (i = 0; i < bs; i++) { 1120 if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
934 bctx->ipad[i] ^= 0x36; 1121 memcpy(bctx->opad, bctx->ipad, bs);
935 bctx->opad[i] ^= 0x5c; 1122
1123 for (i = 0; i < bs; i++) {
1124 bctx->ipad[i] ^= 0x36;
1125 bctx->opad[i] ^= 0x5c;
1126 }
936 } 1127 }
937 1128
938 return err; 1129 return err;
@@ -1137,7 +1328,19 @@ finish:
1137 omap_sham_finish_req(dd->req, err); 1328 omap_sham_finish_req(dd->req, err);
1138} 1329}
1139 1330
1140static irqreturn_t omap_sham_irq(int irq, void *dev_id) 1331static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
1332{
1333 if (!test_bit(FLAGS_BUSY, &dd->flags)) {
1334 dev_warn(dd->dev, "Interrupt when no active requests.\n");
1335 } else {
1336 set_bit(FLAGS_OUTPUT_READY, &dd->flags);
1337 tasklet_schedule(&dd->done_task);
1338 }
1339
1340 return IRQ_HANDLED;
1341}
1342
1343static irqreturn_t omap_sham_irq_omap2(int irq, void *dev_id)
1141{ 1344{
1142 struct omap_sham_dev *dd = dev_id; 1345 struct omap_sham_dev *dd = dev_id;
1143 1346
@@ -1149,21 +1352,67 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
1149 SHA_REG_CTRL_OUTPUT_READY); 1352 SHA_REG_CTRL_OUTPUT_READY);
1150 omap_sham_read(dd, SHA_REG_CTRL); 1353 omap_sham_read(dd, SHA_REG_CTRL);
1151 1354
1152 if (!test_bit(FLAGS_BUSY, &dd->flags)) { 1355 return omap_sham_irq_common(dd);
1153 dev_warn(dd->dev, "Interrupt when no active requests.\n"); 1356}
1154 return IRQ_HANDLED;
1155 }
1156 1357
1157 set_bit(FLAGS_OUTPUT_READY, &dd->flags); 1358static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
1158 tasklet_schedule(&dd->done_task); 1359{
1360 struct omap_sham_dev *dd = dev_id;
1159 1361
1160 return IRQ_HANDLED; 1362 omap_sham_write_mask(dd, SHA_REG_MASK(dd), 0, SHA_REG_MASK_IT_EN);
1363
1364 return omap_sham_irq_common(dd);
1161} 1365}
1162 1366
1367static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
1368 .flags = BIT(FLAGS_BE32_SHA1),
1369 .digest_size = SHA1_DIGEST_SIZE,
1370 .copy_hash = omap_sham_copy_hash_omap2,
1371 .write_ctrl = omap_sham_write_ctrl_omap2,
1372 .trigger = omap_sham_trigger_omap2,
1373 .poll_irq = omap_sham_poll_irq_omap2,
1374 .intr_hdlr = omap_sham_irq_omap2,
1375 .idigest_ofs = 0x00,
1376 .din_ofs = 0x1c,
1377 .digcnt_ofs = 0x14,
1378 .rev_ofs = 0x5c,
1379 .mask_ofs = 0x60,
1380 .sysstatus_ofs = 0x64,
1381 .major_mask = 0xf0,
1382 .major_shift = 4,
1383 .minor_mask = 0x0f,
1384 .minor_shift = 0,
1385};
1386
1163#ifdef CONFIG_OF 1387#ifdef CONFIG_OF
1388static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
1389 .flags = BIT(FLAGS_AUTO_XOR),
1390 .digest_size = SHA256_DIGEST_SIZE,
1391 .copy_hash = omap_sham_copy_hash_omap4,
1392 .write_ctrl = omap_sham_write_ctrl_omap4,
1393 .trigger = omap_sham_trigger_omap4,
1394 .poll_irq = omap_sham_poll_irq_omap4,
1395 .intr_hdlr = omap_sham_irq_omap4,
1396 .idigest_ofs = 0x020,
1397 .din_ofs = 0x080,
1398 .digcnt_ofs = 0x040,
1399 .rev_ofs = 0x100,
1400 .mask_ofs = 0x110,
1401 .sysstatus_ofs = 0x114,
1402 .major_mask = 0x0700,
1403 .major_shift = 8,
1404 .minor_mask = 0x003f,
1405 .minor_shift = 0,
1406};
1407
1164static const struct of_device_id omap_sham_of_match[] = { 1408static const struct of_device_id omap_sham_of_match[] = {
1165 { 1409 {
1166 .compatible = "ti,omap2-sham", 1410 .compatible = "ti,omap2-sham",
1411 .data = &omap_sham_pdata_omap2,
1412 },
1413 {
1414 .compatible = "ti,omap4-sham",
1415 .data = &omap_sham_pdata_omap4,
1167 }, 1416 },
1168 {}, 1417 {},
1169}; 1418};
@@ -1198,6 +1447,7 @@ static int omap_sham_get_res_of(struct omap_sham_dev *dd,
1198 } 1447 }
1199 1448
1200 dd->dma = -1; /* Dummy value that's unused */ 1449 dd->dma = -1; /* Dummy value that's unused */
1450 dd->pdata = match->data;
1201 1451
1202err: 1452err:
1203 return err; 1453 return err;
@@ -1243,6 +1493,9 @@ static int omap_sham_get_res_pdev(struct omap_sham_dev *dd,
1243 } 1493 }
1244 dd->dma = r->start; 1494 dd->dma = r->start;
1245 1495
1496 /* Only OMAP2/3 can be non-DT */
1497 dd->pdata = &omap_sham_pdata_omap2;
1498
1246err: 1499err:
1247 return err; 1500 return err;
1248} 1501}
@@ -1254,6 +1507,7 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
1254 struct resource res; 1507 struct resource res;
1255 dma_cap_mask_t mask; 1508 dma_cap_mask_t mask;
1256 int err, i, j; 1509 int err, i, j;
1510 u32 rev;
1257 1511
1258 dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL); 1512 dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
1259 if (dd == NULL) { 1513 if (dd == NULL) {
@@ -1282,8 +1536,8 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
1282 } 1536 }
1283 dd->phys_base = res.start; 1537 dd->phys_base = res.start;
1284 1538
1285 err = request_irq(dd->irq, omap_sham_irq, 1539 err = request_irq(dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_LOW,
1286 IRQF_TRIGGER_LOW, dev_name(dev), dd); 1540 dev_name(dev), dd);
1287 if (err) { 1541 if (err) {
1288 dev_err(dev, "unable to request irq.\n"); 1542 dev_err(dev, "unable to request irq.\n");
1289 goto res_err; 1543 goto res_err;
@@ -1301,21 +1555,16 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
1301 goto dma_err; 1555 goto dma_err;
1302 } 1556 }
1303 1557
1304 dd->io_base = ioremap(dd->phys_base, SZ_4K); 1558 dd->flags |= dd->pdata->flags;
1305 if (!dd->io_base) {
1306 dev_err(dev, "can't ioremap\n");
1307 err = -ENOMEM;
1308 goto io_err;
1309 }
1310 1559
1311 pm_runtime_enable(dev); 1560 pm_runtime_enable(dev);
1312 pm_runtime_get_sync(dev); 1561 pm_runtime_get_sync(dev);
1562 rev = omap_sham_read(dd, SHA_REG_REV(dd));
1563 pm_runtime_put_sync(&pdev->dev);
1313 1564
1314 dev_info(dev, "hw accel on OMAP rev %u.%u\n", 1565 dev_info(dev, "hw accel on OMAP rev %u.%u\n",
1315 (omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MAJOR) >> 4, 1566 (rev & dd->pdata->major_mask) >> dd->pdata->major_shift,
1316 omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MINOR); 1567 (rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
1317
1318 pm_runtime_put_sync(&pdev->dev);
1319 1568
1320 spin_lock(&sham.lock); 1569 spin_lock(&sham.lock);
1321 list_add_tail(&dd->list, &sham.dev_list); 1570 list_add_tail(&dd->list, &sham.dev_list);
@@ -1333,7 +1582,6 @@ err_algs:
1333 for (j = 0; j < i; j++) 1582 for (j = 0; j < i; j++)
1334 crypto_unregister_ahash(&algs[j]); 1583 crypto_unregister_ahash(&algs[j]);
1335 pm_runtime_disable(dev); 1584 pm_runtime_disable(dev);
1336io_err:
1337 dma_release_channel(dd->dma_lch); 1585 dma_release_channel(dd->dma_lch);
1338dma_err: 1586dma_err:
1339 free_irq(dd->irq, dd); 1587 free_irq(dd->irq, dd);