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