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