aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/atmel-sha.c
diff options
context:
space:
mode:
authorCyrille Pitchen <cyrille.pitchen@atmel.com>2017-01-26 11:07:52 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2017-02-03 05:16:13 -0500
commiteec12f66b02c3812252103d5efcb80754b04012c (patch)
treeec84949d020e869cfff9300a335bd27a333cefef /drivers/crypto/atmel-sha.c
parent563c47df79747412bf5d0fdb8fd24089d7316c2b (diff)
crypto: atmel-sha - add atmel_sha_cpu_start()
This patch adds a simple function to perform data transfer with PIO, hence handled by the CPU. Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/atmel-sha.c')
-rw-r--r--drivers/crypto/atmel-sha.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index be0d72cf4352..58d9ca8ac0f2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -64,6 +64,8 @@
64#define SHA_FLAGS_ERROR BIT(23) 64#define SHA_FLAGS_ERROR BIT(23)
65#define SHA_FLAGS_PAD BIT(24) 65#define SHA_FLAGS_PAD BIT(24)
66#define SHA_FLAGS_RESTORE BIT(25) 66#define SHA_FLAGS_RESTORE BIT(25)
67#define SHA_FLAGS_IDATAR0 BIT(26)
68#define SHA_FLAGS_WAIT_DATARDY BIT(27)
67 69
68#define SHA_OP_UPDATE 1 70#define SHA_OP_UPDATE 1
69#define SHA_OP_FINAL 2 71#define SHA_OP_FINAL 2
@@ -141,6 +143,7 @@ struct atmel_sha_dev {
141 struct ahash_request *req; 143 struct ahash_request *req;
142 bool is_async; 144 bool is_async;
143 atmel_sha_fn_t resume; 145 atmel_sha_fn_t resume;
146 atmel_sha_fn_t cpu_transfer_complete;
144 147
145 struct atmel_sha_dma dma_lch_in; 148 struct atmel_sha_dma dma_lch_in;
146 149
@@ -1317,6 +1320,93 @@ static irqreturn_t atmel_sha_irq(int irq, void *dev_id)
1317 return IRQ_NONE; 1320 return IRQ_NONE;
1318} 1321}
1319 1322
1323
1324/* CPU transfer functions */
1325
1326static int atmel_sha_cpu_transfer(struct atmel_sha_dev *dd)
1327{
1328 struct ahash_request *req = dd->req;
1329 struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
1330 const u32 *words = (const u32 *)ctx->buffer;
1331 size_t i, num_words;
1332 u32 isr, din, din_inc;
1333
1334 din_inc = (ctx->flags & SHA_FLAGS_IDATAR0) ? 0 : 1;
1335 for (;;) {
1336 /* Write data into the Input Data Registers. */
1337 num_words = DIV_ROUND_UP(ctx->bufcnt, sizeof(u32));
1338 for (i = 0, din = 0; i < num_words; ++i, din += din_inc)
1339 atmel_sha_write(dd, SHA_REG_DIN(din), words[i]);
1340
1341 ctx->offset += ctx->bufcnt;
1342 ctx->total -= ctx->bufcnt;
1343
1344 if (!ctx->total)
1345 break;
1346
1347 /*
1348 * Prepare next block:
1349 * Fill ctx->buffer now with the next data to be written into
1350 * IDATARx: it gives time for the SHA hardware to process
1351 * the current data so the SHA_INT_DATARDY flag might be set
1352 * in SHA_ISR when polling this register at the beginning of
1353 * the next loop.
1354 */
1355 ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
1356 scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
1357 ctx->offset, ctx->bufcnt, 0);
1358
1359 /* Wait for hardware to be ready again. */
1360 isr = atmel_sha_read(dd, SHA_ISR);
1361 if (!(isr & SHA_INT_DATARDY)) {
1362 /* Not ready yet. */
1363 dd->resume = atmel_sha_cpu_transfer;
1364 atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY);
1365 return -EINPROGRESS;
1366 }
1367 }
1368
1369 if (unlikely(!(ctx->flags & SHA_FLAGS_WAIT_DATARDY)))
1370 return dd->cpu_transfer_complete(dd);
1371
1372 return atmel_sha_wait_for_data_ready(dd, dd->cpu_transfer_complete);
1373}
1374
1375static int atmel_sha_cpu_start(struct atmel_sha_dev *dd,
1376 struct scatterlist *sg,
1377 unsigned int len,
1378 bool idatar0_only,
1379 bool wait_data_ready,
1380 atmel_sha_fn_t resume)
1381{
1382 struct ahash_request *req = dd->req;
1383 struct atmel_sha_reqctx *ctx = ahash_request_ctx(req);
1384
1385 if (!len)
1386 return resume(dd);
1387
1388 ctx->flags &= ~(SHA_FLAGS_IDATAR0 | SHA_FLAGS_WAIT_DATARDY);
1389
1390 if (idatar0_only)
1391 ctx->flags |= SHA_FLAGS_IDATAR0;
1392
1393 if (wait_data_ready)
1394 ctx->flags |= SHA_FLAGS_WAIT_DATARDY;
1395
1396 ctx->sg = sg;
1397 ctx->total = len;
1398 ctx->offset = 0;
1399
1400 /* Prepare the first block to be written. */
1401 ctx->bufcnt = min_t(size_t, ctx->block_size, ctx->total);
1402 scatterwalk_map_and_copy(ctx->buffer, ctx->sg,
1403 ctx->offset, ctx->bufcnt, 0);
1404
1405 dd->cpu_transfer_complete = resume;
1406 return atmel_sha_cpu_transfer(dd);
1407}
1408
1409
1320static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd) 1410static void atmel_sha_unregister_algs(struct atmel_sha_dev *dd)
1321{ 1411{
1322 int i; 1412 int i;