xref: /rk3399_ARM-atf/drivers/amlogic/crypto/sha_dma.c (revision 2aaed8608004f7d29be5da49289bb16c1b0df20f)
101b2a7fcSCarlo Caione /*
201b2a7fcSCarlo Caione  * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
301b2a7fcSCarlo Caione  *
401b2a7fcSCarlo Caione  * SPDX-License-Identifier: BSD-3-Clause
501b2a7fcSCarlo Caione  */
601b2a7fcSCarlo Caione 
701b2a7fcSCarlo Caione #include <arch_helpers.h>
801b2a7fcSCarlo Caione #include <assert.h>
901b2a7fcSCarlo Caione #include <crypto/sha_dma.h>
1001b2a7fcSCarlo Caione #include <lib/mmio.h>
11*885e2683SClaus Pedersen #include <platform_def.h>
1201b2a7fcSCarlo Caione 
1326d94393SCarlo Caione #include "aml_private.h"
1401b2a7fcSCarlo Caione 
1501b2a7fcSCarlo Caione #define ASD_MODE_SHA224 0x7
1601b2a7fcSCarlo Caione #define ASD_MODE_SHA256 0x6
1701b2a7fcSCarlo Caione 
1801b2a7fcSCarlo Caione /* SHA DMA descriptor */
1901b2a7fcSCarlo Caione struct asd_desc {
2001b2a7fcSCarlo Caione 	uint32_t cfg;
2101b2a7fcSCarlo Caione 	uint32_t src;
2201b2a7fcSCarlo Caione 	uint32_t dst;
2301b2a7fcSCarlo Caione };
2401b2a7fcSCarlo Caione #define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk))
2501b2a7fcSCarlo Caione #define ASD_DESC_SET(x, v, msk, off)					\
2601b2a7fcSCarlo Caione 	((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off)))
2701b2a7fcSCarlo Caione 
2801b2a7fcSCarlo Caione #define ASD_DESC_LEN_OFF 0
2901b2a7fcSCarlo Caione #define ASD_DESC_LEN_MASK 0x1ffff
3001b2a7fcSCarlo Caione #define ASD_DESC_LEN(d)							\
3101b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
3201b2a7fcSCarlo Caione #define ASD_DESC_LEN_SET(d, v)						\
3301b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
3401b2a7fcSCarlo Caione 
3501b2a7fcSCarlo Caione #define ASD_DESC_IRQ_OFF 17
3601b2a7fcSCarlo Caione #define ASD_DESC_IRQ_MASK 0x1
3701b2a7fcSCarlo Caione #define ASD_DESC_IRQ(d)							\
3801b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
3901b2a7fcSCarlo Caione #define ASD_DESC_IRQ_SET(d, v)						\
4001b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
4101b2a7fcSCarlo Caione 
4201b2a7fcSCarlo Caione #define ASD_DESC_EOD_OFF 18
4301b2a7fcSCarlo Caione #define ASD_DESC_EOD_MASK 0x1
4401b2a7fcSCarlo Caione #define ASD_DESC_EOD(d)							\
4501b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
4601b2a7fcSCarlo Caione #define ASD_DESC_EOD_SET(d, v)						\
4701b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
4801b2a7fcSCarlo Caione 
4901b2a7fcSCarlo Caione #define ASD_DESC_LOOP_OFF 19
5001b2a7fcSCarlo Caione #define ASD_DESC_LOOP_MASK 0x1
5101b2a7fcSCarlo Caione #define ASD_DESC_LOOP(d)						\
5201b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
5301b2a7fcSCarlo Caione #define ASD_DESC_LOOP_SET(d, v)						\
5401b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
5501b2a7fcSCarlo Caione 
5601b2a7fcSCarlo Caione #define ASD_DESC_MODE_OFF 20
5701b2a7fcSCarlo Caione #define ASD_DESC_MODE_MASK 0xf
5801b2a7fcSCarlo Caione #define ASD_DESC_MODE(d)						\
5901b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
6001b2a7fcSCarlo Caione #define ASD_DESC_MODE_SET(d, v)						\
6101b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
6201b2a7fcSCarlo Caione 
6301b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_OFF 24
6401b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_MASK 0x1
6501b2a7fcSCarlo Caione #define ASD_DESC_BEGIN(d)						\
6601b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
6701b2a7fcSCarlo Caione #define ASD_DESC_BEGIN_SET(d, v)					\
6801b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
6901b2a7fcSCarlo Caione 
7001b2a7fcSCarlo Caione #define ASD_DESC_END_OFF 25
7101b2a7fcSCarlo Caione #define ASD_DESC_END_MASK 0x1
7201b2a7fcSCarlo Caione #define ASD_DESC_END(d)							\
7301b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
7401b2a7fcSCarlo Caione #define ASD_DESC_END_SET(d, v)						\
7501b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
7601b2a7fcSCarlo Caione 
7701b2a7fcSCarlo Caione #define ASD_DESC_OP_OFF 26
7801b2a7fcSCarlo Caione #define ASD_DESC_OP_MASK 0x2
7901b2a7fcSCarlo Caione #define ASD_DESC_OP(d)							\
8001b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
8101b2a7fcSCarlo Caione #define ASD_DESC_OP_SET(d, v)						\
8201b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
8301b2a7fcSCarlo Caione 
8401b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_OFF 28
8501b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_MASK 0x1
8601b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY(d)						\
8701b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
8801b2a7fcSCarlo Caione #define ASD_DESC_ENCONLY_SET(d, v)					\
8901b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
9001b2a7fcSCarlo Caione 
9101b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_OFF 29
9201b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_MASK 0x1
9301b2a7fcSCarlo Caione #define ASD_DESC_BLOCK(d)						\
9401b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
9501b2a7fcSCarlo Caione #define ASD_DESC_BLOCK_SET(d, v)					\
9601b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
9701b2a7fcSCarlo Caione 
9801b2a7fcSCarlo Caione #define ASD_DESC_ERR_OFF 30
9901b2a7fcSCarlo Caione #define ASD_DESC_ERR_MASK 0x1
10001b2a7fcSCarlo Caione #define ASD_DESC_ERR(d)						\
10101b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
10201b2a7fcSCarlo Caione #define ASD_DESC_ERR_SET(d, v)					\
10301b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
10401b2a7fcSCarlo Caione 
10501b2a7fcSCarlo Caione #define ASD_DESC_OWNER_OFF 31u
10601b2a7fcSCarlo Caione #define ASD_DESC_OWNER_MASK 0x1u
10701b2a7fcSCarlo Caione #define ASD_DESC_OWNER(d)					\
10801b2a7fcSCarlo Caione 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
10901b2a7fcSCarlo Caione #define ASD_DESC_OWNER_SET(d, v)				\
11001b2a7fcSCarlo Caione 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
11101b2a7fcSCarlo Caione 
asd_compute_sha(struct asd_ctx * ctx,void * data,size_t len,int finalize)11201b2a7fcSCarlo Caione static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len,
11301b2a7fcSCarlo Caione 		int finalize)
11401b2a7fcSCarlo Caione {
11501b2a7fcSCarlo Caione 	/* Make it cache line size aligned ? */
11601b2a7fcSCarlo Caione 	struct asd_desc desc = {
11701b2a7fcSCarlo Caione 		.src = (uint32_t)(uintptr_t)data,
11801b2a7fcSCarlo Caione 		.dst = (uint32_t)(uintptr_t)ctx->digest,
11901b2a7fcSCarlo Caione 	};
12001b2a7fcSCarlo Caione 
12101b2a7fcSCarlo Caione 	/* Check data address is 32bit compatible */
12201b2a7fcSCarlo Caione 	assert((uintptr_t)data == (uintptr_t)desc.src);
12301b2a7fcSCarlo Caione 	assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst);
12401b2a7fcSCarlo Caione 	assert((uintptr_t)&desc == (uintptr_t)&desc);
12501b2a7fcSCarlo Caione 
12601b2a7fcSCarlo Caione 	ASD_DESC_LEN_SET(&desc, len);
12701b2a7fcSCarlo Caione 	ASD_DESC_OWNER_SET(&desc, 1u);
12801b2a7fcSCarlo Caione 	ASD_DESC_ENCONLY_SET(&desc, 1);
12901b2a7fcSCarlo Caione 	ASD_DESC_EOD_SET(&desc, 1);
13001b2a7fcSCarlo Caione 	if (ctx->started == 0) {
13101b2a7fcSCarlo Caione 		ASD_DESC_BEGIN_SET(&desc, 1);
13201b2a7fcSCarlo Caione 		ctx->started = 1;
13301b2a7fcSCarlo Caione 	}
13401b2a7fcSCarlo Caione 	if (finalize) {
13501b2a7fcSCarlo Caione 		ASD_DESC_END_SET(&desc, 1);
13601b2a7fcSCarlo Caione 		ctx->started = 0;
13701b2a7fcSCarlo Caione 	}
13801b2a7fcSCarlo Caione 	if (ctx->mode == ASM_SHA224)
13901b2a7fcSCarlo Caione 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224);
14001b2a7fcSCarlo Caione 	else
14101b2a7fcSCarlo Caione 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256);
14201b2a7fcSCarlo Caione 
14301b2a7fcSCarlo Caione 	flush_dcache_range((uintptr_t)&desc, sizeof(desc));
14401b2a7fcSCarlo Caione 	flush_dcache_range((uintptr_t)data, len);
14501b2a7fcSCarlo Caione 
14601b2a7fcSCarlo Caione 	mmio_write_32(AML_SHA_DMA_STATUS, 0xf);
14701b2a7fcSCarlo Caione 	mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2);
14801b2a7fcSCarlo Caione 	while (mmio_read_32(AML_SHA_DMA_STATUS) == 0)
14901b2a7fcSCarlo Caione 		continue;
15001b2a7fcSCarlo Caione 	flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ);
15101b2a7fcSCarlo Caione }
15201b2a7fcSCarlo Caione 
asd_sha_update(struct asd_ctx * ctx,void * data,size_t len)15301b2a7fcSCarlo Caione void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len)
15401b2a7fcSCarlo Caione {
15501b2a7fcSCarlo Caione 	size_t nr;
15601b2a7fcSCarlo Caione 
15701b2a7fcSCarlo Caione 	if (ctx->blocksz) {
15801b2a7fcSCarlo Caione 		nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz);
15901b2a7fcSCarlo Caione 		memcpy(ctx->block + ctx->blocksz, data, nr);
16001b2a7fcSCarlo Caione 		ctx->blocksz += nr;
16101b2a7fcSCarlo Caione 		len -= nr;
16201b2a7fcSCarlo Caione 		data += nr;
16301b2a7fcSCarlo Caione 	}
16401b2a7fcSCarlo Caione 
16501b2a7fcSCarlo Caione 	if (ctx->blocksz == SHA256_BLOCKSZ) {
16601b2a7fcSCarlo Caione 		asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0);
16701b2a7fcSCarlo Caione 		ctx->blocksz = 0;
16801b2a7fcSCarlo Caione 	}
16901b2a7fcSCarlo Caione 
17001b2a7fcSCarlo Caione 	asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0);
17101b2a7fcSCarlo Caione 	data += len & ~(SHA256_BLOCKSZ - 1);
17201b2a7fcSCarlo Caione 
17301b2a7fcSCarlo Caione 	if (len & (SHA256_BLOCKSZ - 1)) {
17401b2a7fcSCarlo Caione 		nr = len & (SHA256_BLOCKSZ - 1);
17501b2a7fcSCarlo Caione 		memcpy(ctx->block + ctx->blocksz, data, nr);
17601b2a7fcSCarlo Caione 		ctx->blocksz += nr;
17701b2a7fcSCarlo Caione 	}
17801b2a7fcSCarlo Caione }
17901b2a7fcSCarlo Caione 
asd_sha_finalize(struct asd_ctx * ctx)18001b2a7fcSCarlo Caione void asd_sha_finalize(struct asd_ctx *ctx)
18101b2a7fcSCarlo Caione {
18201b2a7fcSCarlo Caione 	asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1);
18301b2a7fcSCarlo Caione }
184