summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/aspeed/aspeed-hace.h
blob: 68f70e01fccbb81aed56b2f35287cb490abe9b6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ASPEED_HACE_H__
#define __ASPEED_HACE_H__

#include <crypto/aes.h>
#include <crypto/engine.h>
#include <crypto/hash.h>
#include <crypto/sha2.h>
#include <linux/bits.h>
#include <linux/compiler_attributes.h>
#include <linux/interrupt.h>
#include <linux/types.h>

/*****************************
 *                           *
 * HACE register definitions *
 *                           *
 * ***************************/
#define ASPEED_HACE_SRC			0x00	/* Crypto Data Source Base Address Register */
#define ASPEED_HACE_DEST		0x04	/* Crypto Data Destination Base Address Register */
#define ASPEED_HACE_CONTEXT		0x08	/* Crypto Context Buffer Base Address Register */
#define ASPEED_HACE_DATA_LEN		0x0C	/* Crypto Data Length Register */
#define ASPEED_HACE_CMD			0x10	/* Crypto Engine Command Register */

/* G5 */
#define ASPEED_HACE_TAG			0x18	/* HACE Tag Register */
/* G6 */
#define ASPEED_HACE_GCM_ADD_LEN		0x14	/* Crypto AES-GCM Additional Data Length Register */
#define ASPEED_HACE_GCM_TAG_BASE_ADDR	0x18	/* Crypto AES-GCM Tag Write Buff Base Address Reg */

#define ASPEED_HACE_STS			0x1C	/* HACE Status Register */

#define ASPEED_HACE_HASH_SRC		0x20	/* Hash Data Source Base Address Register */
#define ASPEED_HACE_HASH_DIGEST_BUFF	0x24	/* Hash Digest Write Buffer Base Address Register */
#define ASPEED_HACE_HASH_KEY_BUFF	0x28	/* Hash HMAC Key Buffer Base Address Register */
#define ASPEED_HACE_HASH_DATA_LEN	0x2C	/* Hash Data Length Register */
#define ASPEED_HACE_HASH_CMD		0x30	/* Hash Engine Command Register */

/* crypto cmd */
#define  HACE_CMD_SINGLE_DES		0
#define  HACE_CMD_TRIPLE_DES		BIT(17)
#define  HACE_CMD_AES_SELECT		0
#define  HACE_CMD_DES_SELECT		BIT(16)
#define  HACE_CMD_ISR_EN		BIT(12)
#define  HACE_CMD_CONTEXT_SAVE_ENABLE	(0)
#define  HACE_CMD_CONTEXT_SAVE_DISABLE	BIT(9)
#define  HACE_CMD_AES			(0)
#define  HACE_CMD_DES			(0)
#define  HACE_CMD_RC4			BIT(8)
#define  HACE_CMD_DECRYPT		(0)
#define  HACE_CMD_ENCRYPT		BIT(7)

#define  HACE_CMD_ECB			(0x0 << 4)
#define  HACE_CMD_CBC			(0x1 << 4)
#define  HACE_CMD_CFB			(0x2 << 4)
#define  HACE_CMD_OFB			(0x3 << 4)
#define  HACE_CMD_CTR			(0x4 << 4)
#define  HACE_CMD_OP_MODE_MASK		(0x7 << 4)

#define  HACE_CMD_AES128		(0x0 << 2)
#define  HACE_CMD_AES192		(0x1 << 2)
#define  HACE_CMD_AES256		(0x2 << 2)
#define  HACE_CMD_OP_CASCADE		(0x3)
#define  HACE_CMD_OP_INDEPENDENT	(0x1)

/* G5 */
#define  HACE_CMD_RI_WO_DATA_ENABLE	(0)
#define  HACE_CMD_RI_WO_DATA_DISABLE	BIT(11)
#define  HACE_CMD_CONTEXT_LOAD_ENABLE	(0)
#define  HACE_CMD_CONTEXT_LOAD_DISABLE	BIT(10)
/* G6 */
#define  HACE_CMD_AES_KEY_FROM_OTP	BIT(24)
#define  HACE_CMD_GHASH_TAG_XOR_EN	BIT(23)
#define  HACE_CMD_GHASH_PAD_LEN_INV	BIT(22)
#define  HACE_CMD_GCM_TAG_ADDR_SEL	BIT(21)
#define  HACE_CMD_MBUS_REQ_SYNC_EN	BIT(20)
#define  HACE_CMD_DES_SG_CTRL		BIT(19)
#define  HACE_CMD_SRC_SG_CTRL		BIT(18)
#define  HACE_CMD_CTR_IV_AES_96		(0x1 << 14)
#define  HACE_CMD_CTR_IV_DES_32		(0x1 << 14)
#define  HACE_CMD_CTR_IV_AES_64		(0x2 << 14)
#define  HACE_CMD_CTR_IV_AES_32		(0x3 << 14)
#define  HACE_CMD_AES_KEY_HW_EXP	BIT(13)
#define  HACE_CMD_GCM			(0x5 << 4)

/* interrupt status reg */
#define  HACE_CRYPTO_ISR		BIT(12)
#define  HACE_HASH_ISR			BIT(9)
#define  HACE_HASH_BUSY			BIT(0)

/* hash cmd reg */
#define  HASH_CMD_MBUS_REQ_SYNC_EN	BIT(20)
#define  HASH_CMD_HASH_SRC_SG_CTRL	BIT(18)
#define  HASH_CMD_SHA512_224		(0x3 << 10)
#define  HASH_CMD_SHA512_256		(0x2 << 10)
#define  HASH_CMD_SHA384		(0x1 << 10)
#define  HASH_CMD_SHA512		(0)
#define  HASH_CMD_INT_ENABLE		BIT(9)
#define  HASH_CMD_HMAC			(0x1 << 7)
#define  HASH_CMD_ACC_MODE		(0x2 << 7)
#define  HASH_CMD_HMAC_KEY		(0x3 << 7)
#define  HASH_CMD_SHA1			(0x2 << 4)
#define  HASH_CMD_SHA224		(0x4 << 4)
#define  HASH_CMD_SHA256		(0x5 << 4)
#define  HASH_CMD_SHA512_SER		(0x6 << 4)
#define  HASH_CMD_SHA_SWAP		(0x2 << 2)

#define HASH_SG_LAST_LIST		BIT(31)

#define CRYPTO_FLAGS_BUSY		BIT(1)

#define SHA_OP_UPDATE			1
#define SHA_OP_FINAL			2

#define SHA_FLAGS_SHA1			BIT(0)
#define SHA_FLAGS_SHA224		BIT(1)
#define SHA_FLAGS_SHA256		BIT(2)
#define SHA_FLAGS_SHA384		BIT(3)
#define SHA_FLAGS_SHA512		BIT(4)
#define SHA_FLAGS_SHA512_224		BIT(5)
#define SHA_FLAGS_SHA512_256		BIT(6)
#define SHA_FLAGS_HMAC			BIT(8)
#define SHA_FLAGS_FINUP			BIT(9)
#define SHA_FLAGS_MASK			(0xff)

#define ASPEED_CRYPTO_SRC_DMA_BUF_LEN	0xa000
#define ASPEED_CRYPTO_DST_DMA_BUF_LEN	0xa000
#define ASPEED_CRYPTO_GCM_TAG_OFFSET	0x9ff0
#define ASPEED_HASH_SRC_DMA_BUF_LEN	0xa000
#define ASPEED_HASH_QUEUE_LENGTH	50

#define HACE_CMD_IV_REQUIRE		(HACE_CMD_CBC | HACE_CMD_CFB | \
					 HACE_CMD_OFB | HACE_CMD_CTR)

struct aspeed_hace_dev;
struct scatterlist;

typedef int (*aspeed_hace_fn_t)(struct aspeed_hace_dev *);

struct aspeed_sg_list {
	__le32 len;
	__le32 phy_addr;
};

struct aspeed_engine_hash {
	struct tasklet_struct		done_task;
	unsigned long			flags;
	struct ahash_request		*req;

	/* input buffer */
	void				*ahash_src_addr;
	dma_addr_t			ahash_src_dma_addr;

	dma_addr_t			src_dma;
	dma_addr_t			digest_dma;

	size_t				src_length;

	/* callback func */
	aspeed_hace_fn_t		resume;
	aspeed_hace_fn_t		dma_prepare;
};

struct aspeed_sha_hmac_ctx {
	struct crypto_shash *shash;
	u8 ipad[SHA512_BLOCK_SIZE];
	u8 opad[SHA512_BLOCK_SIZE];
};

struct aspeed_sham_ctx {
	struct aspeed_hace_dev		*hace_dev;
	unsigned long			flags;	/* hmac flag */

	struct aspeed_sha_hmac_ctx	base[];
};

struct aspeed_sham_reqctx {
	unsigned long		flags;		/* final update flag should no use*/
	unsigned long		op;		/* final or update */
	u32			cmd;		/* trigger cmd */

	/* walk state */
	struct scatterlist	*src_sg;
	int			src_nents;
	unsigned int		offset;		/* offset in current sg */
	unsigned int		total;		/* per update length */

	size_t			digsize;
	size_t			block_size;
	size_t			ivsize;
	const __be32		*sha_iv;

	/* remain data buffer */
	u8			buffer[SHA512_BLOCK_SIZE * 2];
	dma_addr_t		buffer_dma_addr;
	size_t			bufcnt;		/* buffer counter */

	/* output buffer */
	u8			digest[SHA512_DIGEST_SIZE] __aligned(64);
	dma_addr_t		digest_dma_addr;
	u64			digcnt[2];
};

struct aspeed_engine_crypto {
	struct tasklet_struct		done_task;
	unsigned long			flags;
	struct skcipher_request		*req;

	/* context buffer */
	void				*cipher_ctx;
	dma_addr_t			cipher_ctx_dma;

	/* input buffer, could be single/scatter-gather lists */
	void				*cipher_addr;
	dma_addr_t			cipher_dma_addr;

	/* output buffer, only used in scatter-gather lists */
	void				*dst_sg_addr;
	dma_addr_t			dst_sg_dma_addr;

	/* callback func */
	aspeed_hace_fn_t		resume;
};

struct aspeed_cipher_ctx {
	struct aspeed_hace_dev		*hace_dev;
	int				key_len;
	u8				key[AES_MAX_KEYLENGTH];

	/* callback func */
	aspeed_hace_fn_t		start;

	struct crypto_skcipher          *fallback_tfm;
};

struct aspeed_cipher_reqctx {
	int enc_cmd;
	int src_nents;
	int dst_nents;

	struct skcipher_request         fallback_req;   /* keep at the end */
};

struct aspeed_hace_dev {
	void __iomem			*regs;
	struct device			*dev;
	int				irq;
	struct clk			*clk;
	unsigned long			version;

	struct crypto_engine		*crypt_engine_hash;
	struct crypto_engine		*crypt_engine_crypto;

	struct aspeed_engine_hash	hash_engine;
	struct aspeed_engine_crypto	crypto_engine;
};

struct aspeed_hace_alg {
	struct aspeed_hace_dev		*hace_dev;

	const char			*alg_base;

	union {
		struct skcipher_engine_alg skcipher;
		struct ahash_engine_alg ahash;
	} alg;
};

enum aspeed_version {
	AST2500_VERSION = 5,
	AST2600_VERSION
};

#define ast_hace_write(hace, val, offset)	\
	writel((val), (hace)->regs + (offset))
#define ast_hace_read(hace, offset)		\
	readl((hace)->regs + (offset))

void aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_unregister_hace_hash_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_register_hace_crypto_algs(struct aspeed_hace_dev *hace_dev);
void aspeed_unregister_hace_crypto_algs(struct aspeed_hace_dev *hace_dev);

#endif