xref: /openbmc/u-boot/drivers/crypto/aspeed_hace.c (revision e961bfaf)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (C) Copyright ASPEED Technology Inc.
4  * Copyright 2021 IBM Corp.
5  */
6 #include <common.h>
7 #include <clk.h>
8 
9 #include <log.h>
10 #include <asm/io.h>
11 #include <malloc.h>
12 #include <hash.h>
13 
14 #include <dm/device.h>
15 #include <dm/fdtaddr.h>
16 
17 #include <linux/bitops.h>
18 #include <linux/delay.h>
19 #include <linux/kernel.h>
20 #include <linux/iopoll.h>
21 
22 #define ASPEED_HACE_STS			0x1C
23 #define  HACE_RSA_ISR			BIT(13)
24 #define  HACE_CRYPTO_ISR		BIT(12)
25 #define  HACE_HASH_ISR			BIT(9)
26 #define  HACE_RSA_BUSY			BIT(2)
27 #define  HACE_CRYPTO_BUSY		BIT(1)
28 #define  HACE_HASH_BUSY			BIT(0)
29 #define ASPEED_HACE_HASH_SRC		0x20
30 #define ASPEED_HACE_HASH_DIGEST_BUFF	0x24
31 #define ASPEED_HACE_HASH_KEY_BUFF	0x28
32 #define ASPEED_HACE_HASH_DATA_LEN	0x2C
33 #define  HACE_SG_LAST			BIT(31)
34 #define ASPEED_HACE_HASH_CMD		0x30
35 #define  HACE_SHA_BE_EN			BIT(3)
36 #define  HACE_MD5_LE_EN			BIT(2)
37 #define  HACE_ALGO_MD5			0
38 #define  HACE_ALGO_SHA1			BIT(5)
39 #define  HACE_ALGO_SHA224		BIT(6)
40 #define  HACE_ALGO_SHA256		(BIT(4) | BIT(6))
41 #define  HACE_ALGO_SHA512		(BIT(5) | BIT(6))
42 #define  HACE_ALGO_SHA384		(BIT(5) | BIT(6) | BIT(10))
43 #define  HACE_SG_EN			BIT(18)
44 
45 #define ASPEED_MAX_SG			32
46 
47 struct aspeed_sg {
48 	u32 len;
49 	u32 addr;
50 };
51 
52 struct aspeed_hash_ctx {
53 	u32 method;
54 	u32 digest_size;
55 	u32 len;
56 	u32 count;
57 	struct aspeed_sg list[ASPEED_MAX_SG]; /* Must be 8 byte aligned */
58 };
59 
60 struct aspeed_hace {
61 	struct clk clk;
62 };
63 
64 static phys_addr_t base;
65 
66 static int aspeed_hace_wait_completion(u32 reg, u32 flag, int timeout_us)
67 {
68 	u32 val;
69 
70 	return readl_poll_timeout(reg, val, (val & flag) == flag, timeout_us);
71 }
72 
73 static int digest_object(const void *src, unsigned int length, void *digest,
74 			 u32 method)
75 {
76 	if (!((u32)src & BIT(31))) {
77 		debug("HACE src out of bounds: can only copy from SDRAM\n");
78 		return -EINVAL;
79 	}
80 
81 	if ((u32)digest & 0x7) {
82 		debug("HACE dest alignment incorrect: %p\n", digest);
83 		return -EINVAL;
84 	}
85 
86 	if (readl(base + ASPEED_HACE_STS) & HACE_HASH_BUSY) {
87 		debug("HACE error: engine busy\n");
88 		return -EBUSY;
89 	}
90 
91 	/* Clear pending completion status */
92 	writel(HACE_HASH_ISR, base + ASPEED_HACE_STS);
93 
94 	writel((u32)src, base + ASPEED_HACE_HASH_SRC);
95 	writel((u32)digest, base + ASPEED_HACE_HASH_DIGEST_BUFF);
96 	writel(length, base + ASPEED_HACE_HASH_DATA_LEN);
97 	writel(HACE_SHA_BE_EN | method, base + ASPEED_HACE_HASH_CMD);
98 
99 	/* SHA512 hashing appears to have a througput of about 12MB/s */
100 	return aspeed_hace_wait_completion(base + ASPEED_HACE_STS,
101 			HACE_HASH_ISR,
102 			1000 + (length >> 3));
103 }
104 
105 void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
106 	     unsigned char *pout, unsigned int chunk_size)
107 {
108 	int rc;
109 
110 	rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA1);
111 	if (rc)
112 		debug("HACE failure: %d\n", rc);
113 }
114 
115 void hw_sha256(const unsigned char *pbuf, unsigned int buf_len,
116 	       unsigned char *pout, unsigned int chunk_size)
117 {
118 	int rc;
119 
120 	rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA256);
121 	if (rc)
122 		debug("HACE failure: %d\n", rc);
123 }
124 
125 void hw_sha512(const unsigned char *pbuf, unsigned int buf_len,
126 	       unsigned char *pout, unsigned int chunk_size)
127 {
128 	int rc;
129 
130 	rc = digest_object(pbuf, buf_len, pout, HACE_ALGO_SHA512);
131 	if (rc)
132 		debug("HACE failure: %d\n", rc);
133 }
134 
135 #if IS_ENABLED(CONFIG_SHA_PROG_HW_ACCEL)
136 int hw_sha_init(struct hash_algo *algo, void **ctxp)
137 {
138 	struct aspeed_hash_ctx *ctx;
139 	u32 method;
140 
141 	if (!strcmp(algo->name, "sha1"))
142 		method = HACE_ALGO_SHA1;
143 	else if (!strcmp(algo->name, "sha256"))
144 		method = HACE_ALGO_SHA256;
145 	else if (!strcmp(algo->name, "sha512"))
146 		method = HACE_ALGO_SHA512;
147 	else
148 		return -ENOTSUPP;
149 
150 	ctx = memalign(8, sizeof(*ctx));
151 	memset(ctx, '\0', sizeof(*ctx));
152 
153 	if (!ctx) {
154 		debug("HACE error: Cannot allocate memory for context\n");
155 		return -ENOMEM;
156 	}
157 
158 	if (((uintptr_t)ctx->list & 0x3) != 0) {
159 		printf("HACE error: Invalid alignment for input data\n");
160 		return -EINVAL;
161 	}
162 
163 	ctx->method = method | HACE_SG_EN;
164 	ctx->digest_size = algo->digest_size;
165 	*ctxp = ctx;
166 
167 	return 0;
168 }
169 
170 int hw_sha_update(struct hash_algo *algo, void *hash_ctx, const void *buf,
171 		  unsigned int size, int is_last)
172 {
173 	struct aspeed_hash_ctx *ctx = hash_ctx;
174 	struct aspeed_sg *sg = &ctx->list[ctx->count];
175 
176 	if (ctx->count >= ARRAY_SIZE(ctx->list)) {
177 		debug("HACE error: Reached maximum number of hash segments\n");
178 		free(ctx);
179 		return -EINVAL;
180 	}
181 
182 	sg->addr = (u32)buf;
183 	sg->len = size;
184 	if (is_last)
185 		sg->len |= HACE_SG_LAST;
186 
187 	ctx->count++;
188 	ctx->len += size;
189 
190 	return 0;
191 }
192 
193 int hw_sha_finish(struct hash_algo *algo, void *hash_ctx, void *dest_buf, int size)
194 {
195 	struct aspeed_hash_ctx *ctx = hash_ctx;
196 	int rc;
197 
198 	if (size < ctx->digest_size) {
199 		debug("HACE error: insufficient size on destination buffer\n");
200 		free(ctx);
201 		return -EINVAL;
202 	}
203 
204 	rc = digest_object(ctx->list, ctx->len, dest_buf, ctx->method);
205 	if (rc)
206 		debug("HACE Scatter-Gather failure\n");
207 
208 	free(ctx);
209 
210 	return rc;
211 }
212 #endif
213 
214 static int aspeed_hace_probe(struct udevice *dev)
215 {
216 	struct aspeed_hace *hace = dev_get_priv(dev);
217 	int ret;
218 
219 	ret = clk_get_by_index(dev, 0, &hace->clk);
220 	if (ret < 0) {
221 		debug("Can't get clock for %s: %d\n", dev->name, ret);
222 		return ret;
223 	}
224 
225 	ret = clk_enable(&hace->clk);
226 	if (ret) {
227 		debug("Failed to enable fsi clock (%d)\n", ret);
228 		return ret;
229 	}
230 
231 	/* As the crypto code does not pass us any driver state */
232 	base = devfdt_get_addr(dev);
233 
234 	return ret;
235 }
236 
237 static int aspeed_hace_remove(struct udevice *dev)
238 {
239 	struct aspeed_hace *hace = dev_get_priv(dev);
240 
241 	clk_disable(&hace->clk);
242 
243 	return 0;
244 }
245 
246 static const struct udevice_id aspeed_hace_ids[] = {
247 	{ .compatible = "aspeed,ast2600-hace" },
248 	{ }
249 };
250 
251 U_BOOT_DRIVER(aspeed_hace) = {
252 	.name		= "aspeed_hace",
253 	.id		= UCLASS_MISC,
254 	.of_match	= aspeed_hace_ids,
255 	.probe		= aspeed_hace_probe,
256 	.remove		= aspeed_hace_remove,
257 	.priv_auto_alloc_size = sizeof(struct aspeed_hace),
258 	.flags  = DM_FLAG_PRE_RELOC,
259 };
260