xref: /openbmc/u-boot/drivers/crypto/aspeed_hace.c (revision ebf0f73fe78559686a51b91b2e4ad40676d666d8)
1e31caa5aSChia-Wei Wang // SPDX-License-Identifier: GPL-2.0-or-later
2e31caa5aSChia-Wei Wang /*
3e31caa5aSChia-Wei Wang  * (C) Copyright ASPEED Technology Inc.
4e31caa5aSChia-Wei Wang  * Copyright 2021 IBM Corp.
5e31caa5aSChia-Wei Wang  */
6e31caa5aSChia-Wei Wang #include <common.h>
7e31caa5aSChia-Wei Wang #include <clk.h>
8e31caa5aSChia-Wei Wang 
9e31caa5aSChia-Wei Wang #include <log.h>
10e31caa5aSChia-Wei Wang #include <asm/io.h>
11e31caa5aSChia-Wei Wang #include <malloc.h>
12e31caa5aSChia-Wei Wang #include <hash.h>
13e31caa5aSChia-Wei Wang 
14e31caa5aSChia-Wei Wang #include <dm/device.h>
15e31caa5aSChia-Wei Wang #include <dm/fdtaddr.h>
16e31caa5aSChia-Wei Wang 
17e31caa5aSChia-Wei Wang #include <linux/bitops.h>
18e31caa5aSChia-Wei Wang #include <linux/delay.h>
19e31caa5aSChia-Wei Wang #include <linux/kernel.h>
20e31caa5aSChia-Wei Wang #include <linux/iopoll.h>
21e31caa5aSChia-Wei Wang 
22e31caa5aSChia-Wei Wang #define ASPEED_HACE_STS			0x1C
23e31caa5aSChia-Wei Wang #define  HACE_RSA_ISR			BIT(13)
24e31caa5aSChia-Wei Wang #define  HACE_CRYPTO_ISR		BIT(12)
25e31caa5aSChia-Wei Wang #define  HACE_HASH_ISR			BIT(9)
26e31caa5aSChia-Wei Wang #define  HACE_RSA_BUSY			BIT(2)
27e31caa5aSChia-Wei Wang #define  HACE_CRYPTO_BUSY		BIT(1)
28e31caa5aSChia-Wei Wang #define  HACE_HASH_BUSY			BIT(0)
29e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_SRC		0x20
30e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_DIGEST_BUFF	0x24
31e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_KEY_BUFF	0x28
32e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_DATA_LEN	0x2C
33e31caa5aSChia-Wei Wang #define  HACE_SG_LAST			BIT(31)
34e31caa5aSChia-Wei Wang #define ASPEED_HACE_HASH_CMD		0x30
35e31caa5aSChia-Wei Wang #define  HACE_SHA_BE_EN			BIT(3)
36e31caa5aSChia-Wei Wang #define  HACE_MD5_LE_EN			BIT(2)
37e31caa5aSChia-Wei Wang #define  HACE_ALGO_MD5			0
38e31caa5aSChia-Wei Wang #define  HACE_ALGO_SHA1			BIT(5)
39e31caa5aSChia-Wei Wang #define  HACE_ALGO_SHA224		BIT(6)
40e31caa5aSChia-Wei Wang #define  HACE_ALGO_SHA256		(BIT(4) | BIT(6))
41e31caa5aSChia-Wei Wang #define  HACE_ALGO_SHA512		(BIT(5) | BIT(6))
42e31caa5aSChia-Wei Wang #define  HACE_ALGO_SHA384		(BIT(5) | BIT(6) | BIT(10))
43*ebf0f73fSJohnny Huang #define  HASH_CMD_ACC_MODE		(0x2 << 7)
44e31caa5aSChia-Wei Wang #define  HACE_SG_EN			BIT(18)
45e31caa5aSChia-Wei Wang 
46*ebf0f73fSJohnny Huang #define ASPEED_SHA1_DIGEST_SIZE		20
47*ebf0f73fSJohnny Huang #define ASPEED_SHA256_DIGEST_SIZE	32
48*ebf0f73fSJohnny Huang #define ASPEED_SHA384_DIGEST_SIZE	64
49*ebf0f73fSJohnny Huang #define ASPEED_SHA512_DIGEST_SIZE	64
50*ebf0f73fSJohnny Huang 
51*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA1		1
52*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA256		2
53*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA384		3
54*ebf0f73fSJohnny Huang #define ASPEED_SHA_TYPE_SHA512		4
55e31caa5aSChia-Wei Wang 
56e31caa5aSChia-Wei Wang struct aspeed_sg {
57e31caa5aSChia-Wei Wang 	u32 len;
58e31caa5aSChia-Wei Wang 	u32 addr;
59e31caa5aSChia-Wei Wang };
60e31caa5aSChia-Wei Wang 
61e31caa5aSChia-Wei Wang struct aspeed_hash_ctx {
62*ebf0f73fSJohnny Huang 	struct aspeed_sg sg[2]; /* Must be 8 byte aligned */
63*ebf0f73fSJohnny Huang 	u8 digest[64]; /* Must be 8 byte aligned */
64e31caa5aSChia-Wei Wang 	u32 method;
65e31caa5aSChia-Wei Wang 	u32 digest_size;
66*ebf0f73fSJohnny Huang 	u32 block_size;
67*ebf0f73fSJohnny Huang 	u64 digcnt[2]; /* total length */
68*ebf0f73fSJohnny Huang 	u32 bufcnt;
69*ebf0f73fSJohnny Huang 	u8 buffer[256];
70e31caa5aSChia-Wei Wang };
71e31caa5aSChia-Wei Wang 
72e31caa5aSChia-Wei Wang struct aspeed_hace {
73e31caa5aSChia-Wei Wang 	struct clk clk;
74e31caa5aSChia-Wei Wang };
75e31caa5aSChia-Wei Wang 
76*ebf0f73fSJohnny Huang static const u32 sha1_iv[8] = {
77*ebf0f73fSJohnny Huang 	0x01234567UL, 0x89abcdefUL, 0xfedcba98UL, 0x76543210UL,
78*ebf0f73fSJohnny Huang 	0xf0e1d2c3UL, 0, 0, 0
79*ebf0f73fSJohnny Huang };
80*ebf0f73fSJohnny Huang 
81*ebf0f73fSJohnny Huang static const u32 sha256_iv[8] = {
82*ebf0f73fSJohnny Huang 	0x67e6096aUL, 0x85ae67bbUL, 0x72f36e3cUL, 0x3af54fa5UL,
83*ebf0f73fSJohnny Huang 	0x7f520e51UL, 0x8c68059bUL, 0xabd9831fUL, 0x19cde05bUL
84*ebf0f73fSJohnny Huang };
85*ebf0f73fSJohnny Huang 
86*ebf0f73fSJohnny Huang static const u32 sha384_iv[16] = {
87*ebf0f73fSJohnny Huang 	0x5d9dbbcbUL, 0xd89e05c1UL, 0x2a299a62UL, 0x07d57c36UL,
88*ebf0f73fSJohnny Huang 	0x5a015991UL, 0x17dd7030UL, 0xd8ec2f15UL, 0x39590ef7UL,
89*ebf0f73fSJohnny Huang 	0x67263367UL, 0x310bc0ffUL, 0x874ab48eUL, 0x11155868UL,
90*ebf0f73fSJohnny Huang 	0x0d2e0cdbUL, 0xa78ff964UL, 0x1d48b547UL, 0xa44ffabeUL
91*ebf0f73fSJohnny Huang };
92*ebf0f73fSJohnny Huang 
93*ebf0f73fSJohnny Huang static const u32 sha512_iv[16] = {
94*ebf0f73fSJohnny Huang 	0x67e6096aUL, 0x08c9bcf3UL, 0x85ae67bbUL, 0x3ba7ca84UL,
95*ebf0f73fSJohnny Huang 	0x72f36e3cUL, 0x2bf894feUL, 0x3af54fa5UL, 0xf1361d5fUL,
96*ebf0f73fSJohnny Huang 	0x7f520e51UL, 0xd182e6adUL, 0x8c68059bUL, 0x1f6c3e2bUL,
97*ebf0f73fSJohnny Huang 	0xabd9831fUL, 0x6bbd41fbUL, 0x19cde05bUL, 0x79217e13UL
98*ebf0f73fSJohnny Huang };
99*ebf0f73fSJohnny Huang 
100e31caa5aSChia-Wei Wang static phys_addr_t base;
101e31caa5aSChia-Wei Wang 
102e31caa5aSChia-Wei Wang static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us)
103e31caa5aSChia-Wei Wang {
104e31caa5aSChia-Wei Wang 	u32 val;
105e31caa5aSChia-Wei Wang 
106e31caa5aSChia-Wei Wang 	return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us);
107e31caa5aSChia-Wei Wang }
108e31caa5aSChia-Wei Wang 
109*ebf0f73fSJohnny Huang static void aspeed_ahash_fill_padding(struct aspeed_hash_ctx *ctx, unsigned int remainder)
110e31caa5aSChia-Wei Wang {
111*ebf0f73fSJohnny Huang 	unsigned int index, padlen;
112*ebf0f73fSJohnny Huang 	u64 bits[2];
1130fdcca14SJoel Stanley 
114*ebf0f73fSJohnny Huang 	if (ctx->block_size == 64) {
115*ebf0f73fSJohnny Huang 		bits[0] = cpu_to_be64(ctx->digcnt[0] << 3);
116*ebf0f73fSJohnny Huang 		index = (ctx->bufcnt + remainder) & 0x3f;
117*ebf0f73fSJohnny Huang 		padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
118*ebf0f73fSJohnny Huang 		*(ctx->buffer + ctx->bufcnt) = 0x80;
119*ebf0f73fSJohnny Huang 		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
120*ebf0f73fSJohnny Huang 		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 8);
121*ebf0f73fSJohnny Huang 		ctx->bufcnt += padlen + 8;
122*ebf0f73fSJohnny Huang 	} else {
123*ebf0f73fSJohnny Huang 		bits[1] = cpu_to_be64(ctx->digcnt[0] << 3);
124*ebf0f73fSJohnny Huang 		bits[0] = cpu_to_be64(ctx->digcnt[1] << 3 | ctx->digcnt[0] >> 61);
125*ebf0f73fSJohnny Huang 		index = (ctx->bufcnt + remainder) & 0x7f;
126*ebf0f73fSJohnny Huang 		padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
127*ebf0f73fSJohnny Huang 		*(ctx->buffer + ctx->bufcnt) = 0x80;
128*ebf0f73fSJohnny Huang 		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
129*ebf0f73fSJohnny Huang 		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
130*ebf0f73fSJohnny Huang 		ctx->bufcnt += padlen + 16;
131*ebf0f73fSJohnny Huang 	}
132e31caa5aSChia-Wei Wang }
133e31caa5aSChia-Wei Wang 
134*ebf0f73fSJohnny Huang static int hash_trigger(struct aspeed_hash_ctx *ctx, int hash_len)
135*ebf0f73fSJohnny Huang {
136e31caa5aSChia-Wei Wang 	if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) {
137e31caa5aSChia-Wei Wang 		debug("HACE error: engine busy\n");
138e31caa5aSChia-Wei Wang 		return -EBUSY;
139e31caa5aSChia-Wei Wang 	}
140e31caa5aSChia-Wei Wang 	/* Clear pending completion status */
141e31caa5aSChia-Wei Wang 	writel(HACE_HASH_ISR, base + ASPEED_HACE_STS);
142e31caa5aSChia-Wei Wang 
143*ebf0f73fSJohnny Huang 	writel((u32)ctx->sg, base + ASPEED_HACE_HASH_SRC);
144*ebf0f73fSJohnny Huang 	writel((u32)ctx->digest, base + ASPEED_HACE_HASH_DIGEST_BUFF);
145*ebf0f73fSJohnny Huang 	writel((u32)ctx->digest, base + ASPEED_HACE_HASH_KEY_BUFF);
146*ebf0f73fSJohnny Huang 	writel(hash_len, base + ASPEED_HACE_HASH_DATA_LEN);
147*ebf0f73fSJohnny Huang 	writel(ctx->method, base + ASPEED_HACE_HASH_CMD);
148e31caa5aSChia-Wei Wang 
149e31caa5aSChia-Wei Wang 	/* SHA512 hashing appears to have a througput of about 12MB/s */
150*ebf0f73fSJohnny Huang 	return aspeed_hace_wait_completion(base + ASPEED_HACE_STS,
151e31caa5aSChia-Wei Wang 					   HACE_HASH_ISR,
152*ebf0f73fSJohnny Huang 					   1000 + (hash_len >> 3));
153e31caa5aSChia-Wei Wang }
154e31caa5aSChia-Wei Wang 
155e31caa5aSChia-Wei Wang #if IS_ENABLED(CONFIG_SHA_PROG_HW_ACCEL)
156e31caa5aSChia-Wei Wang int hw_sha_init(struct hash_algo *algo, void **ctxp)
157e31caa5aSChia-Wei Wang {
158e31caa5aSChia-Wei Wang 	struct aspeed_hash_ctx *ctx;
159e31caa5aSChia-Wei Wang 	u32 method;
160*ebf0f73fSJohnny Huang 	u32 block_size;
161e31caa5aSChia-Wei Wang 
162*ebf0f73fSJohnny Huang 	ctx = memalign(8, sizeof(struct aspeed_hash_ctx));
163*ebf0f73fSJohnny Huang 	memset(ctx, '\0', sizeof(struct aspeed_hash_ctx));
164*ebf0f73fSJohnny Huang 
165*ebf0f73fSJohnny Huang 	method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
166*ebf0f73fSJohnny Huang 	if (!strcmp(algo->name, "sha1")) {
167*ebf0f73fSJohnny Huang 		method |= HACE_ALGO_SHA1;
168*ebf0f73fSJohnny Huang 		block_size = 64;
169*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha1_iv, 32);
170*ebf0f73fSJohnny Huang 	} else if (!strcmp(algo->name, "sha256")) {
171*ebf0f73fSJohnny Huang 		method |= HACE_ALGO_SHA256;
172*ebf0f73fSJohnny Huang 		block_size = 64;
173*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha256_iv, 32);
174*ebf0f73fSJohnny Huang 	} else if (!strcmp(algo->name, "sha384")) {
175*ebf0f73fSJohnny Huang 		method |= HACE_ALGO_SHA384;
176*ebf0f73fSJohnny Huang 		block_size = 128;
177*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha384_iv, 64);
178*ebf0f73fSJohnny Huang 	} else if (!strcmp(algo->name, "sha512")) {
179*ebf0f73fSJohnny Huang 		method |= HACE_ALGO_SHA512;
180*ebf0f73fSJohnny Huang 		block_size = 128;
181*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha512_iv, 64);
182*ebf0f73fSJohnny Huang 	} else {
183e31caa5aSChia-Wei Wang 		return -ENOTSUPP;
184*ebf0f73fSJohnny Huang 	}
185e31caa5aSChia-Wei Wang 
186e31caa5aSChia-Wei Wang 	if (!ctx) {
187e31caa5aSChia-Wei Wang 		debug("HACE error: Cannot allocate memory for context\n");
188e31caa5aSChia-Wei Wang 		return -ENOMEM;
189e31caa5aSChia-Wei Wang 	}
190e31caa5aSChia-Wei Wang 
191*ebf0f73fSJohnny Huang 	ctx->method = method;
192*ebf0f73fSJohnny Huang 	ctx->block_size = block_size;
193e31caa5aSChia-Wei Wang 	ctx->digest_size = algo->digest_size;
194*ebf0f73fSJohnny Huang 	ctx->bufcnt = 0;
195*ebf0f73fSJohnny Huang 	ctx->digcnt[0] = 0;
196*ebf0f73fSJohnny Huang 	ctx->digcnt[1] = 0;
197e31caa5aSChia-Wei Wang 	*ctxp = ctx;
198e31caa5aSChia-Wei Wang 
199e31caa5aSChia-Wei Wang 	return 0;
200e31caa5aSChia-Wei Wang }
201e31caa5aSChia-Wei Wang 
202e31caa5aSChia-Wei Wang int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf,
203e31caa5aSChia-Wei Wang 		  unsigned int size, int is_last)
204e31caa5aSChia-Wei Wang {
205e31caa5aSChia-Wei Wang 	struct aspeed_hash_ctx *ctx = hash_ctx;
206*ebf0f73fSJohnny Huang 	struct aspeed_sg *sg = ctx->sg;
207*ebf0f73fSJohnny Huang 	int rc;
208*ebf0f73fSJohnny Huang 	int remainder;
209*ebf0f73fSJohnny Huang 	int total_len;
210*ebf0f73fSJohnny Huang 	int i;
211e31caa5aSChia-Wei Wang 
212*ebf0f73fSJohnny Huang 	ctx->digcnt[0] += size;
213*ebf0f73fSJohnny Huang 	if (ctx->digcnt[0] < size)
214*ebf0f73fSJohnny Huang 		ctx->digcnt[1]++;
215*ebf0f73fSJohnny Huang 
216*ebf0f73fSJohnny Huang 	if (ctx->bufcnt + size < ctx->block_size) {
217*ebf0f73fSJohnny Huang 		memcpy(ctx->buffer + ctx->bufcnt, buf, size);
218*ebf0f73fSJohnny Huang 		ctx->bufcnt += size;
219*ebf0f73fSJohnny Huang 		return 0;
220*ebf0f73fSJohnny Huang 	}
221*ebf0f73fSJohnny Huang 	remainder = (size + ctx->bufcnt) % ctx->block_size;
222*ebf0f73fSJohnny Huang 	total_len = size + ctx->bufcnt - remainder;
223*ebf0f73fSJohnny Huang 	i = 0;
224*ebf0f73fSJohnny Huang 	if (ctx->bufcnt != 0) {
225*ebf0f73fSJohnny Huang 		sg[0].addr = (u32)ctx->buffer;
226*ebf0f73fSJohnny Huang 		sg[0].len = ctx->bufcnt;
227*ebf0f73fSJohnny Huang 		if (total_len == ctx->bufcnt)
228*ebf0f73fSJohnny Huang 			sg[0].len |= HACE_SG_LAST;
229*ebf0f73fSJohnny Huang 		i++;
230e31caa5aSChia-Wei Wang 	}
231e31caa5aSChia-Wei Wang 
232*ebf0f73fSJohnny Huang 	if (total_len != ctx->bufcnt) {
233*ebf0f73fSJohnny Huang 		sg[i].addr = (u32)buf;
234*ebf0f73fSJohnny Huang 		sg[i].len = (total_len - ctx->bufcnt) | HACE_SG_LAST;
235*ebf0f73fSJohnny Huang 	}
236e31caa5aSChia-Wei Wang 
237*ebf0f73fSJohnny Huang 	rc = hash_trigger(ctx, total_len);
238*ebf0f73fSJohnny Huang 	if (remainder != 0) {
239*ebf0f73fSJohnny Huang 		memcpy(ctx->buffer, buf + (total_len - ctx->bufcnt), remainder);
240*ebf0f73fSJohnny Huang 		ctx->bufcnt = remainder;
241*ebf0f73fSJohnny Huang 	}
242e31caa5aSChia-Wei Wang 
243*ebf0f73fSJohnny Huang 	return rc;
244e31caa5aSChia-Wei Wang }
245e31caa5aSChia-Wei Wang 
246e31caa5aSChia-Wei Wang int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size)
247e31caa5aSChia-Wei Wang {
248e31caa5aSChia-Wei Wang 	struct aspeed_hash_ctx *ctx = hash_ctx;
249*ebf0f73fSJohnny Huang 	struct aspeed_sg *sg = ctx->sg;
250e31caa5aSChia-Wei Wang 	int rc;
251e31caa5aSChia-Wei Wang 
252e31caa5aSChia-Wei Wang 	if (size < ctx->digest_size) {
253e31caa5aSChia-Wei Wang 		debug("HACE error: insufficient size on destination buffer\n");
254e31caa5aSChia-Wei Wang 		free(ctx);
255e31caa5aSChia-Wei Wang 		return -EINVAL;
256e31caa5aSChia-Wei Wang 	}
257*ebf0f73fSJohnny Huang 	aspeed_ahash_fill_padding(ctx, 0);
258e31caa5aSChia-Wei Wang 
259*ebf0f73fSJohnny Huang 	sg[0].addr = (u32)ctx->buffer;
260*ebf0f73fSJohnny Huang 	sg[0].len = ctx->bufcnt | HACE_SG_LAST;
261*ebf0f73fSJohnny Huang 
262*ebf0f73fSJohnny Huang 	rc = hash_trigger(ctx, ctx->bufcnt);
263*ebf0f73fSJohnny Huang 	memcpy(dest_buf, ctx->digest, ctx->digest_size);
264e31caa5aSChia-Wei Wang 
265e31caa5aSChia-Wei Wang 	free(ctx);
266e31caa5aSChia-Wei Wang 
267e31caa5aSChia-Wei Wang 	return rc;
268e31caa5aSChia-Wei Wang }
269e31caa5aSChia-Wei Wang #endif
270e31caa5aSChia-Wei Wang 
271*ebf0f73fSJohnny Huang static int sha_digest(const void *src, unsigned int length, void *digest,
272*ebf0f73fSJohnny Huang 		      u32 sha_type)
273*ebf0f73fSJohnny Huang {
274*ebf0f73fSJohnny Huang 	struct aspeed_hash_ctx *ctx;
275*ebf0f73fSJohnny Huang 	int ret;
276*ebf0f73fSJohnny Huang 
277*ebf0f73fSJohnny Huang 	if (!((u32)src & BIT(31))) {
278*ebf0f73fSJohnny Huang 		debug("HACE src out of bounds: can only copy from SDRAM\n");
279*ebf0f73fSJohnny Huang 		return -EINVAL;
280*ebf0f73fSJohnny Huang 	}
281*ebf0f73fSJohnny Huang 
282*ebf0f73fSJohnny Huang 	if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) {
283*ebf0f73fSJohnny Huang 		debug("HACE error: engine busy\n");
284*ebf0f73fSJohnny Huang 		return -EBUSY;
285*ebf0f73fSJohnny Huang 	}
286*ebf0f73fSJohnny Huang 
287*ebf0f73fSJohnny Huang 	ctx = memalign(8, sizeof(struct aspeed_hash_ctx));
288*ebf0f73fSJohnny Huang 	memset(ctx, '\0', sizeof(struct aspeed_hash_ctx));
289*ebf0f73fSJohnny Huang 
290*ebf0f73fSJohnny Huang 	if (!ctx) {
291*ebf0f73fSJohnny Huang 		debug("HACE error: Cannot allocate memory for context\n");
292*ebf0f73fSJohnny Huang 		return -ENOMEM;
293*ebf0f73fSJohnny Huang 	}
294*ebf0f73fSJohnny Huang 	ctx->method = HASH_CMD_ACC_MODE | HACE_SHA_BE_EN | HACE_SG_EN;
295*ebf0f73fSJohnny Huang 
296*ebf0f73fSJohnny Huang 	switch (sha_type) {
297*ebf0f73fSJohnny Huang 	case ASPEED_SHA_TYPE_SHA1:
298*ebf0f73fSJohnny Huang 		ctx->block_size = 64;
299*ebf0f73fSJohnny Huang 		ctx->digest_size = 20;
300*ebf0f73fSJohnny Huang 		ctx->method |= HACE_ALGO_SHA1;
301*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha1_iv, 32);
302*ebf0f73fSJohnny Huang 		break;
303*ebf0f73fSJohnny Huang 	case ASPEED_SHA_TYPE_SHA256:
304*ebf0f73fSJohnny Huang 		ctx->block_size = 64;
305*ebf0f73fSJohnny Huang 		ctx->digest_size = 32;
306*ebf0f73fSJohnny Huang 		ctx->method |= HACE_ALGO_SHA256;
307*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha256_iv, 32);
308*ebf0f73fSJohnny Huang 		break;
309*ebf0f73fSJohnny Huang 	case ASPEED_SHA_TYPE_SHA384:
310*ebf0f73fSJohnny Huang 		ctx->block_size = 128;
311*ebf0f73fSJohnny Huang 		ctx->digest_size = 64;
312*ebf0f73fSJohnny Huang 		ctx->method |= HACE_ALGO_SHA384;
313*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha384_iv, 64);
314*ebf0f73fSJohnny Huang 		break;
315*ebf0f73fSJohnny Huang 	case ASPEED_SHA_TYPE_SHA512:
316*ebf0f73fSJohnny Huang 		ctx->block_size = 128;
317*ebf0f73fSJohnny Huang 		ctx->digest_size = 64;
318*ebf0f73fSJohnny Huang 		ctx->method |= HACE_ALGO_SHA512;
319*ebf0f73fSJohnny Huang 		memcpy(ctx->digest, sha512_iv, 64);
320*ebf0f73fSJohnny Huang 		break;
321*ebf0f73fSJohnny Huang 	default:
322*ebf0f73fSJohnny Huang 		return -ENOTSUPP;
323*ebf0f73fSJohnny Huang 	}
324*ebf0f73fSJohnny Huang 
325*ebf0f73fSJohnny Huang 	ctx->digcnt[0] = length;
326*ebf0f73fSJohnny Huang 	ctx->digcnt[1] = 0;
327*ebf0f73fSJohnny Huang 
328*ebf0f73fSJohnny Huang 	aspeed_ahash_fill_padding(ctx, length);
329*ebf0f73fSJohnny Huang 
330*ebf0f73fSJohnny Huang 	if (length != 0) {
331*ebf0f73fSJohnny Huang 		ctx->sg[0].addr = (u32)src;
332*ebf0f73fSJohnny Huang 		ctx->sg[0].len = length;
333*ebf0f73fSJohnny Huang 		ctx->sg[1].addr = (u32)ctx->buffer;
334*ebf0f73fSJohnny Huang 		ctx->sg[1].len = ctx->bufcnt | HACE_SG_LAST;
335*ebf0f73fSJohnny Huang 	} else {
336*ebf0f73fSJohnny Huang 		ctx->sg[0].addr = (u32)ctx->buffer;
337*ebf0f73fSJohnny Huang 		ctx->sg[0].len = ctx->bufcnt | HACE_SG_LAST;
338*ebf0f73fSJohnny Huang 	}
339*ebf0f73fSJohnny Huang 
340*ebf0f73fSJohnny Huang 	ret = hash_trigger(ctx, length + ctx->bufcnt);
341*ebf0f73fSJohnny Huang 	memcpy(digest, ctx->digest, ctx->digest_size);
342*ebf0f73fSJohnny Huang 	free(ctx);
343*ebf0f73fSJohnny Huang 
344*ebf0f73fSJohnny Huang 	return ret;
345*ebf0f73fSJohnny Huang }
346*ebf0f73fSJohnny Huang 
347*ebf0f73fSJohnny Huang void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
348*ebf0f73fSJohnny Huang 	     unsigned char *pout, unsigned int chunk_size)
349*ebf0f73fSJohnny Huang {
350*ebf0f73fSJohnny Huang 	int rc;
351*ebf0f73fSJohnny Huang 
352*ebf0f73fSJohnny Huang 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA1);
353*ebf0f73fSJohnny Huang 	if (rc)
354*ebf0f73fSJohnny Huang 		debug("HACE failure: %d\n", rc);
355*ebf0f73fSJohnny Huang }
356*ebf0f73fSJohnny Huang 
357*ebf0f73fSJohnny Huang void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
358*ebf0f73fSJohnny Huang 	       unsigned char *pout, unsigned int chunk_size)
359*ebf0f73fSJohnny Huang {
360*ebf0f73fSJohnny Huang 	int rc;
361*ebf0f73fSJohnny Huang 
362*ebf0f73fSJohnny Huang 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA256);
363*ebf0f73fSJohnny Huang 	if (rc)
364*ebf0f73fSJohnny Huang 		debug("HACE failure: %d\n", rc);
365*ebf0f73fSJohnny Huang }
366*ebf0f73fSJohnny Huang 
367*ebf0f73fSJohnny Huang void hw_sha384(const unsigned char *pbuf, unsigned int buf_len,
368*ebf0f73fSJohnny Huang 	       unsigned char *pout, unsigned int chunk_size)
369*ebf0f73fSJohnny Huang {
370*ebf0f73fSJohnny Huang 	int rc;
371*ebf0f73fSJohnny Huang 
372*ebf0f73fSJohnny Huang 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA384);
373*ebf0f73fSJohnny Huang 	if (rc)
374*ebf0f73fSJohnny Huang 		debug("HACE failure: %d\n", rc);
375*ebf0f73fSJohnny Huang }
376*ebf0f73fSJohnny Huang 
377*ebf0f73fSJohnny Huang void hw_sha512(const unsigned char *pbuf, unsigned int buf_len,
378*ebf0f73fSJohnny Huang 	       unsigned char *pout, unsigned int chunk_size)
379*ebf0f73fSJohnny Huang {
380*ebf0f73fSJohnny Huang 	int rc;
381*ebf0f73fSJohnny Huang 
382*ebf0f73fSJohnny Huang 	rc = sha_digest(pbuf, buf_len, pout, ASPEED_SHA_TYPE_SHA512);
383*ebf0f73fSJohnny Huang 	if (rc)
384*ebf0f73fSJohnny Huang 		debug("HACE failure: %d\n", rc);
385*ebf0f73fSJohnny Huang }
386*ebf0f73fSJohnny Huang 
387e31caa5aSChia-Wei Wang static int aspeed_hace_probe(struct udevice *dev)
388e31caa5aSChia-Wei Wang {
389e31caa5aSChia-Wei Wang 	struct aspeed_hace *hace = dev_get_priv(dev);
390e31caa5aSChia-Wei Wang 	int ret;
391e31caa5aSChia-Wei Wang 
392e31caa5aSChia-Wei Wang 	ret = clk_get_by_index(dev, 0, &hace->clk);
393e31caa5aSChia-Wei Wang 	if (ret < 0) {
394e31caa5aSChia-Wei Wang 		debug("Can't get clock for %s: %d\n", dev->name, ret);
395e31caa5aSChia-Wei Wang 		return ret;
396e31caa5aSChia-Wei Wang 	}
397e31caa5aSChia-Wei Wang 
398e31caa5aSChia-Wei Wang 	ret = clk_enable(&hace->clk);
399e31caa5aSChia-Wei Wang 	if (ret) {
400e31caa5aSChia-Wei Wang 		debug("Failed to enable fsi clock (%d)\n", ret);
401e31caa5aSChia-Wei Wang 		return ret;
402e31caa5aSChia-Wei Wang 	}
403e31caa5aSChia-Wei Wang 
404e31caa5aSChia-Wei Wang 	/* As the crypto code does not pass us any driver state */
405e31caa5aSChia-Wei Wang 	base = devfdt_get_addr(dev);
406e31caa5aSChia-Wei Wang 
407e31caa5aSChia-Wei Wang 	return ret;
408e31caa5aSChia-Wei Wang }
409e31caa5aSChia-Wei Wang 
410e31caa5aSChia-Wei Wang static int aspeed_hace_remove(struct udevice *dev)
411e31caa5aSChia-Wei Wang {
412e31caa5aSChia-Wei Wang 	struct aspeed_hace *hace = dev_get_priv(dev);
413e31caa5aSChia-Wei Wang 
414e31caa5aSChia-Wei Wang 	clk_disable(&hace->clk);
415e31caa5aSChia-Wei Wang 
416e31caa5aSChia-Wei Wang 	return 0;
417e31caa5aSChia-Wei Wang }
418e31caa5aSChia-Wei Wang 
419e31caa5aSChia-Wei Wang static const struct udevice_id aspeed_hace_ids[] = {
420e31caa5aSChia-Wei Wang 	{ .compatible = "aspeed,ast2600-hace" },
421e31caa5aSChia-Wei Wang 	{ }
422e31caa5aSChia-Wei Wang };
423e31caa5aSChia-Wei Wang 
424e31caa5aSChia-Wei Wang U_BOOT_DRIVER(aspeed_hace) = {
425e31caa5aSChia-Wei Wang 	.name		= "aspeed_hace",
426e31caa5aSChia-Wei Wang 	.id		= UCLASS_MISC,
427e31caa5aSChia-Wei Wang 	.of_match	= aspeed_hace_ids,
428e31caa5aSChia-Wei Wang 	.probe		= aspeed_hace_probe,
429e31caa5aSChia-Wei Wang 	.remove		= aspeed_hace_remove,
430e31caa5aSChia-Wei Wang 	.priv_auto_alloc_size = sizeof(struct aspeed_hace),
431e31caa5aSChia-Wei Wang 	.flags  = DM_FLAG_PRE_RELOC,
432e31caa5aSChia-Wei Wang };
433