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