diff options
-rw-r--r-- | drivers/crypto/omap-sham.c | 416 |
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 | ||
103 | struct omap_sham_dev; | 135 | struct 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 | ||
125 | struct omap_sham_hmac_ctx { | 157 | struct 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 | ||
131 | struct omap_sham_ctx { | 163 | struct 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 | ||
176 | struct 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 | |||
144 | struct omap_sham_dev { | 201 | struct 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 | ||
161 | struct omap_sham_drv { | 220 | struct 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 | ||
206 | static void omap_sham_copy_hash(struct ahash_request *req, int out) | 265 | static 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 | |||
280 | static 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 | ||
223 | static void omap_sham_copy_ready_hash(struct ahash_request *req) | 305 | static 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 | ||
244 | static int omap_sham_hw_init(struct omap_sham_dev *dd) | 337 | static 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 | ||
263 | static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length, | 349 | static 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 | ||
378 | static void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length) | ||
379 | { | ||
380 | } | ||
381 | |||
382 | static 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 | |||
387 | static 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 | |||
394 | static 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 | |||
442 | static 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 | |||
447 | static 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 | |||
292 | static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf, | 453 | static 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 | ||
1140 | static irqreturn_t omap_sham_irq(int irq, void *dev_id) | 1331 | static 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 | |||
1343 | static 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); | 1358 | static 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 | ||
1367 | static 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 |
1388 | static 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 | |||
1164 | static const struct of_device_id omap_sham_of_match[] = { | 1408 | static 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 | ||
1202 | err: | 1452 | err: |
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 | |||
1246 | err: | 1499 | err: |
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); |
1336 | io_err: | ||
1337 | dma_release_channel(dd->dma_lch); | 1585 | dma_release_channel(dd->dma_lch); |
1338 | dma_err: | 1586 | dma_err: |
1339 | free_irq(dd->irq, dd); | 1587 | free_irq(dd->irq, dd); |