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