xref: /arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <arch_helpers.h>
8*91f16700Schasinglulu #include <assert.h>
9*91f16700Schasinglulu #include <crypto/sha_dma.h>
10*91f16700Schasinglulu #include <lib/mmio.h>
11*91f16700Schasinglulu #include <platform_def.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include "aml_private.h"
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #define ASD_MODE_SHA224 0x7
16*91f16700Schasinglulu #define ASD_MODE_SHA256 0x6
17*91f16700Schasinglulu 
18*91f16700Schasinglulu /* SHA DMA descriptor */
19*91f16700Schasinglulu struct asd_desc {
20*91f16700Schasinglulu 	uint32_t cfg;
21*91f16700Schasinglulu 	uint32_t src;
22*91f16700Schasinglulu 	uint32_t dst;
23*91f16700Schasinglulu };
24*91f16700Schasinglulu #define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk))
25*91f16700Schasinglulu #define ASD_DESC_SET(x, v, msk, off)					\
26*91f16700Schasinglulu 	((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off)))
27*91f16700Schasinglulu 
28*91f16700Schasinglulu #define ASD_DESC_LEN_OFF 0
29*91f16700Schasinglulu #define ASD_DESC_LEN_MASK 0x1ffff
30*91f16700Schasinglulu #define ASD_DESC_LEN(d)							\
31*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
32*91f16700Schasinglulu #define ASD_DESC_LEN_SET(d, v)						\
33*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
34*91f16700Schasinglulu 
35*91f16700Schasinglulu #define ASD_DESC_IRQ_OFF 17
36*91f16700Schasinglulu #define ASD_DESC_IRQ_MASK 0x1
37*91f16700Schasinglulu #define ASD_DESC_IRQ(d)							\
38*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
39*91f16700Schasinglulu #define ASD_DESC_IRQ_SET(d, v)						\
40*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
41*91f16700Schasinglulu 
42*91f16700Schasinglulu #define ASD_DESC_EOD_OFF 18
43*91f16700Schasinglulu #define ASD_DESC_EOD_MASK 0x1
44*91f16700Schasinglulu #define ASD_DESC_EOD(d)							\
45*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
46*91f16700Schasinglulu #define ASD_DESC_EOD_SET(d, v)						\
47*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
48*91f16700Schasinglulu 
49*91f16700Schasinglulu #define ASD_DESC_LOOP_OFF 19
50*91f16700Schasinglulu #define ASD_DESC_LOOP_MASK 0x1
51*91f16700Schasinglulu #define ASD_DESC_LOOP(d)						\
52*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
53*91f16700Schasinglulu #define ASD_DESC_LOOP_SET(d, v)						\
54*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
55*91f16700Schasinglulu 
56*91f16700Schasinglulu #define ASD_DESC_MODE_OFF 20
57*91f16700Schasinglulu #define ASD_DESC_MODE_MASK 0xf
58*91f16700Schasinglulu #define ASD_DESC_MODE(d)						\
59*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
60*91f16700Schasinglulu #define ASD_DESC_MODE_SET(d, v)						\
61*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
62*91f16700Schasinglulu 
63*91f16700Schasinglulu #define ASD_DESC_BEGIN_OFF 24
64*91f16700Schasinglulu #define ASD_DESC_BEGIN_MASK 0x1
65*91f16700Schasinglulu #define ASD_DESC_BEGIN(d)						\
66*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
67*91f16700Schasinglulu #define ASD_DESC_BEGIN_SET(d, v)					\
68*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
69*91f16700Schasinglulu 
70*91f16700Schasinglulu #define ASD_DESC_END_OFF 25
71*91f16700Schasinglulu #define ASD_DESC_END_MASK 0x1
72*91f16700Schasinglulu #define ASD_DESC_END(d)							\
73*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
74*91f16700Schasinglulu #define ASD_DESC_END_SET(d, v)						\
75*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
76*91f16700Schasinglulu 
77*91f16700Schasinglulu #define ASD_DESC_OP_OFF 26
78*91f16700Schasinglulu #define ASD_DESC_OP_MASK 0x2
79*91f16700Schasinglulu #define ASD_DESC_OP(d)							\
80*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
81*91f16700Schasinglulu #define ASD_DESC_OP_SET(d, v)						\
82*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
83*91f16700Schasinglulu 
84*91f16700Schasinglulu #define ASD_DESC_ENCONLY_OFF 28
85*91f16700Schasinglulu #define ASD_DESC_ENCONLY_MASK 0x1
86*91f16700Schasinglulu #define ASD_DESC_ENCONLY(d)						\
87*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
88*91f16700Schasinglulu #define ASD_DESC_ENCONLY_SET(d, v)					\
89*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
90*91f16700Schasinglulu 
91*91f16700Schasinglulu #define ASD_DESC_BLOCK_OFF 29
92*91f16700Schasinglulu #define ASD_DESC_BLOCK_MASK 0x1
93*91f16700Schasinglulu #define ASD_DESC_BLOCK(d)						\
94*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
95*91f16700Schasinglulu #define ASD_DESC_BLOCK_SET(d, v)					\
96*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
97*91f16700Schasinglulu 
98*91f16700Schasinglulu #define ASD_DESC_ERR_OFF 30
99*91f16700Schasinglulu #define ASD_DESC_ERR_MASK 0x1
100*91f16700Schasinglulu #define ASD_DESC_ERR(d)						\
101*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
102*91f16700Schasinglulu #define ASD_DESC_ERR_SET(d, v)					\
103*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
104*91f16700Schasinglulu 
105*91f16700Schasinglulu #define ASD_DESC_OWNER_OFF 31u
106*91f16700Schasinglulu #define ASD_DESC_OWNER_MASK 0x1u
107*91f16700Schasinglulu #define ASD_DESC_OWNER(d)					\
108*91f16700Schasinglulu 	(ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
109*91f16700Schasinglulu #define ASD_DESC_OWNER_SET(d, v)				\
110*91f16700Schasinglulu 	(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
111*91f16700Schasinglulu 
112*91f16700Schasinglulu static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len,
113*91f16700Schasinglulu 		int finalize)
114*91f16700Schasinglulu {
115*91f16700Schasinglulu 	/* Make it cache line size aligned ? */
116*91f16700Schasinglulu 	struct asd_desc desc = {
117*91f16700Schasinglulu 		.src = (uint32_t)(uintptr_t)data,
118*91f16700Schasinglulu 		.dst = (uint32_t)(uintptr_t)ctx->digest,
119*91f16700Schasinglulu 	};
120*91f16700Schasinglulu 
121*91f16700Schasinglulu 	/* Check data address is 32bit compatible */
122*91f16700Schasinglulu 	assert((uintptr_t)data == (uintptr_t)desc.src);
123*91f16700Schasinglulu 	assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst);
124*91f16700Schasinglulu 	assert((uintptr_t)&desc == (uintptr_t)&desc);
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	ASD_DESC_LEN_SET(&desc, len);
127*91f16700Schasinglulu 	ASD_DESC_OWNER_SET(&desc, 1u);
128*91f16700Schasinglulu 	ASD_DESC_ENCONLY_SET(&desc, 1);
129*91f16700Schasinglulu 	ASD_DESC_EOD_SET(&desc, 1);
130*91f16700Schasinglulu 	if (ctx->started == 0) {
131*91f16700Schasinglulu 		ASD_DESC_BEGIN_SET(&desc, 1);
132*91f16700Schasinglulu 		ctx->started = 1;
133*91f16700Schasinglulu 	}
134*91f16700Schasinglulu 	if (finalize) {
135*91f16700Schasinglulu 		ASD_DESC_END_SET(&desc, 1);
136*91f16700Schasinglulu 		ctx->started = 0;
137*91f16700Schasinglulu 	}
138*91f16700Schasinglulu 	if (ctx->mode == ASM_SHA224)
139*91f16700Schasinglulu 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224);
140*91f16700Schasinglulu 	else
141*91f16700Schasinglulu 		ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256);
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)&desc, sizeof(desc));
144*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)data, len);
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	mmio_write_32(AML_SHA_DMA_STATUS, 0xf);
147*91f16700Schasinglulu 	mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2);
148*91f16700Schasinglulu 	while (mmio_read_32(AML_SHA_DMA_STATUS) == 0)
149*91f16700Schasinglulu 		continue;
150*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ);
151*91f16700Schasinglulu }
152*91f16700Schasinglulu 
153*91f16700Schasinglulu void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len)
154*91f16700Schasinglulu {
155*91f16700Schasinglulu 	size_t nr;
156*91f16700Schasinglulu 
157*91f16700Schasinglulu 	if (ctx->blocksz) {
158*91f16700Schasinglulu 		nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz);
159*91f16700Schasinglulu 		memcpy(ctx->block + ctx->blocksz, data, nr);
160*91f16700Schasinglulu 		ctx->blocksz += nr;
161*91f16700Schasinglulu 		len -= nr;
162*91f16700Schasinglulu 		data += nr;
163*91f16700Schasinglulu 	}
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 	if (ctx->blocksz == SHA256_BLOCKSZ) {
166*91f16700Schasinglulu 		asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0);
167*91f16700Schasinglulu 		ctx->blocksz = 0;
168*91f16700Schasinglulu 	}
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0);
171*91f16700Schasinglulu 	data += len & ~(SHA256_BLOCKSZ - 1);
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	if (len & (SHA256_BLOCKSZ - 1)) {
174*91f16700Schasinglulu 		nr = len & (SHA256_BLOCKSZ - 1);
175*91f16700Schasinglulu 		memcpy(ctx->block + ctx->blocksz, data, nr);
176*91f16700Schasinglulu 		ctx->blocksz += nr;
177*91f16700Schasinglulu 	}
178*91f16700Schasinglulu }
179*91f16700Schasinglulu 
180*91f16700Schasinglulu void asd_sha_finalize(struct asd_ctx *ctx)
181*91f16700Schasinglulu {
182*91f16700Schasinglulu 	asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1);
183*91f16700Schasinglulu }
184