summaryrefslogtreecommitdiff
path: root/drivers/crypto/gemini/sl3516-ce.h
blob: 4c0ec6c920d1d3f63df62b21648583107338cc37 (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
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * sl3516-ce.h - hardware cryptographic offloader for cortina/gemini SoC
 *
 * Copyright (C) 2021 Corentin LABBE <clabbe@baylibre.com>
 *
 * General notes on this driver:
 * Called either Crypto Acceleration Engine Module, Security Acceleration Engine
 * or IPSEC module in the datasheet, it will be called Crypto Engine for short
 * in this driver.
 * The CE was designed to handle IPSEC and wifi(TKIP WEP) protocol.
 * It can handle AES, DES, 3DES, MD5, WEP, TKIP, SHA1, HMAC(MD5), HMAC(SHA1),
 * Michael cipher/digest suites.
 * It acts the same as a network hw, with both RX and TX chained descriptors.
 */
#include <crypto/aes.h>
#include <crypto/engine.h>
#include <crypto/scatterwalk.h>
#include <crypto/skcipher.h>
#include <linux/crypto.h>
#include <linux/debugfs.h>
#include <linux/hw_random.h>

#define TQ0_TYPE_DATA 0
#define TQ0_TYPE_CTRL BIT(0)
#define TQ1_CIPHER BIT(1)
#define TQ2_AUTH BIT(2)
#define TQ3_IV BIT(3)
#define TQ4_KEY0 BIT(4)
#define TQ5_KEY4 BIT(5)
#define TQ6_KEY6 BIT(6)
#define TQ7_AKEY0 BIT(7)
#define TQ8_AKEY2 BIT(8)
#define TQ9_AKEY2 BIT(9)

#define ECB_AES       0x2

#define DESC_LAST 0x01
#define DESC_FIRST 0x02

#define IPSEC_ID		0x0000
#define IPSEC_STATUS_REG	0x00a8
#define IPSEC_RAND_NUM_REG	0x00ac
#define IPSEC_DMA_DEVICE_ID	0xff00
#define IPSEC_DMA_STATUS	0xff04
#define IPSEC_TXDMA_CTRL	0xff08
#define IPSEC_TXDMA_FIRST_DESC	0xff0c
#define IPSEC_TXDMA_CURR_DESC	0xff10
#define IPSEC_RXDMA_CTRL	0xff14
#define IPSEC_RXDMA_FIRST_DESC	0xff18
#define IPSEC_RXDMA_CURR_DESC	0xff1c
#define IPSEC_TXDMA_BUF_ADDR	0xff28
#define IPSEC_RXDMA_BUF_ADDR	0xff38
#define IPSEC_RXDMA_BUF_SIZE	0xff30

#define CE_ENCRYPTION		0x01
#define CE_DECRYPTION		0x03

#define MAXDESC 6

#define DMA_STATUS_RS_EOFI	BIT(22)
#define DMA_STATUS_RS_PERR	BIT(24)
#define DMA_STATUS_RS_DERR	BIT(25)
#define DMA_STATUS_TS_EOFI	BIT(27)
#define DMA_STATUS_TS_PERR	BIT(29)
#define DMA_STATUS_TS_DERR	BIT(30)

#define TXDMA_CTRL_START BIT(31)
#define TXDMA_CTRL_CONTINUE BIT(30)
#define TXDMA_CTRL_CHAIN_MODE BIT(29)
/* the burst value is not documented in the datasheet */
#define TXDMA_CTRL_BURST_UNK BIT(22)
#define TXDMA_CTRL_INT_FAIL BIT(17)
#define TXDMA_CTRL_INT_PERR BIT(16)

#define RXDMA_CTRL_START BIT(31)
#define RXDMA_CTRL_CONTINUE BIT(30)
#define RXDMA_CTRL_CHAIN_MODE BIT(29)
/* the burst value is not documented in the datasheet */
#define RXDMA_CTRL_BURST_UNK BIT(22)
#define RXDMA_CTRL_INT_FINISH BIT(18)
#define RXDMA_CTRL_INT_FAIL BIT(17)
#define RXDMA_CTRL_INT_PERR BIT(16)
#define RXDMA_CTRL_INT_EOD BIT(15)
#define RXDMA_CTRL_INT_EOF BIT(14)

#define CE_CPU 0
#define CE_DMA 1

/*
 * struct sl3516_ce_descriptor - descriptor for CE operations
 * @frame_ctrl:		Information for the current descriptor
 * @flag_status:	For send packet, describe flag of operations.
 * @buf_adr:		pointer to a send/recv buffer for data packet
 * @next_desc:		control linking to other descriptors
 */
struct descriptor {
	union {
		u32 raw;
		/*
		 * struct desc_frame_ctrl - Information for the current descriptor
		 * @buffer_size:	the size of buffer at buf_adr
		 * @desc_count:		Upon completion of a DMA operation, DMA
		 *			write the number of descriptors used
		 *			for the current frame
		 * @checksum:		unknown
		 * @authcomp:		unknown
		 * @perr:		Protocol error during processing this descriptor
		 * @derr:		Data error during processing this descriptor
		 * @own:		0 if owned by CPU, 1 for DMA
		 */
		struct desc_frame_ctrl {
			u32 buffer_size	:16;
			u32 desc_count	:6;
			u32 checksum	:6;
			u32 authcomp	:1;
			u32 perr	:1;
			u32 derr	:1;
			u32 own		:1;
		} bits;
	} frame_ctrl;

	union {
		u32 raw;
		/*
		 * struct desc_flag_status - flag for this descriptor
		 * @tqflag:	list of flag describing the type of operation
		 *		to be performed.
		 */
		struct desc_tx_flag_status {
			u32 tqflag	:10;
			u32 unused	:22;
		} tx_flag;
	} flag_status;

	u32 buf_adr;

	union {
		u32 next_descriptor;
		/*
		 * struct desc_next - describe chaining of descriptors
		 * @sof_eof:	does the descriptor is first (0x11),
		 *		the last (0x01), middle of a chan (0x00)
		 *		or the only one (0x11)
		 * @dec:	AHB bus address increase (0), decrease (1)
		 * @eofie:	End of frame interrupt enable
		 * @ndar:	Next descriptor address
		 */
		struct desc_next {
			u32 sof_eof	:2;
			u32 dec		:1;
			u32 eofie	:1;
			u32 ndar	:28;
		} bits;
	} next_desc;
};

/*
 * struct control - The value of this register is used to set the
 *			operation mode of the IPSec Module.
 * @process_id:		Used to identify the process. The number will be copied
 *			to the descriptor status of the received packet.
 * @auth_check_len:	Number of 32-bit words to be checked or appended by the
 *			authentication module
 * @auth_algorithm:
 * @auth_mode:		0:append 1:Check Authentication Result
 * @fcs_stream_copy:	0:enable 1:disable authentication stream copy
 * @mix_key_sel:	0:use rCipherKey0-3  1:use Key Mixer
 * @aesnk:		AES Key Size
 * @cipher_algorithm:	choice of CBC/ECE and AES/DES/3DES
 * @op_mode:		Operation Mode for the IPSec Module
 */
struct pkt_control_header {
	u32 process_id		:8;
	u32 auth_check_len	:3;
	u32 un1			:1;
	u32 auth_algorithm	:3;
	u32 auth_mode		:1;
	u32 fcs_stream_copy	:1;
	u32 un2			:2;
	u32 mix_key_sel		:1;
	u32 aesnk		:4;
	u32 cipher_algorithm	:3;
	u32 un3			:1;
	u32 op_mode		:4;
};

struct pkt_control_cipher {
	u32 algorithm_len	:16;
	u32 header_len		:16;
};

/*
 * struct pkt_control_ecb - control packet for ECB
 */
struct pkt_control_ecb {
	struct pkt_control_header control;
	struct pkt_control_cipher cipher;
	unsigned char key[AES_MAX_KEY_SIZE];
};

/*
 * struct sl3516_ce_dev - main container for all this driver information
 * @base:	base address
 * @clks:	clocks used
 * @reset:	pointer to reset controller
 * @dev:	the platform device
 * @engine:	ptr to the crypto/crypto_engine
 * @complete:	completion for the current task on this flow
 * @status:	set to 1 by interrupt if task is done
 * @dtx:	base DMA address for TX descriptors
 * @tx		base address of TX descriptors
 * @drx:	base DMA address for RX descriptors
 * @rx		base address of RX descriptors
 * @ctx		current used TX descriptor
 * @crx		current used RX descriptor
 * @trng	hw_random structure for RNG
 * @hwrng_stat_req	number of HWRNG requests
 * @hwrng_stat_bytes	total number of bytes generated by RNG
 * @stat_irq	number of IRQ handled by CE
 * @stat_irq_tx	number of TX IRQ handled by CE
 * @stat_irq_rx	number of RX IRQ handled by CE
 * @stat_req	number of requests handled by CE
 * @fallbak_sg_count_tx		number of fallback due to destination SG count
 * @fallbak_sg_count_rx		number of fallback due to source SG count
 * @fallbak_not_same_len	number of fallback due to difference in SG length
 * @dbgfs_dir:	Debugfs dentry for statistic directory
 * @dbgfs_stats: Debugfs dentry for statistic counters
 */
struct sl3516_ce_dev {
	void __iomem *base;
	struct clk *clks;
	struct reset_control *reset;
	struct device *dev;
	struct crypto_engine *engine;
	struct completion complete;
	int status;
	dma_addr_t dtx;
	struct descriptor *tx;
	dma_addr_t drx;
	struct descriptor *rx;
	int ctx;
	int crx;
	struct hwrng trng;
	unsigned long hwrng_stat_req;
	unsigned long hwrng_stat_bytes;
	unsigned long stat_irq;
	unsigned long stat_irq_tx;
	unsigned long stat_irq_rx;
	unsigned long stat_req;
	unsigned long fallback_sg_count_tx;
	unsigned long fallback_sg_count_rx;
	unsigned long fallback_not_same_len;
	unsigned long fallback_mod16;
	unsigned long fallback_align16;
#ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG
	struct dentry *dbgfs_dir;
	struct dentry *dbgfs_stats;
#endif
	void *pctrl;
	dma_addr_t dctrl;
};

struct sginfo {
	u32 addr;
	u32 len;
};

/*
 * struct sl3516_ce_cipher_req_ctx - context for a skcipher request
 * @t_src:		list of mapped SGs with their size
 * @t_dst:		list of mapped SGs with their size
 * @op_dir:		direction (encrypt vs decrypt) for this request
 * @pctrllen:		the length of the ctrl packet
 * @tqflag:		the TQflag to set in data packet
 * @h			pointer to the pkt_control_cipher header
 * @nr_sgs:		number of source SG
 * @nr_sgd:		number of destination SG
 * @fallback_req:	request struct for invoking the fallback skcipher TFM
 */
struct sl3516_ce_cipher_req_ctx {
	struct sginfo t_src[MAXDESC];
	struct sginfo t_dst[MAXDESC];
	u32 op_dir;
	unsigned int pctrllen;
	u32 tqflag;
	struct pkt_control_cipher *h;
	int nr_sgs;
	int nr_sgd;
	struct skcipher_request fallback_req;   // keep at the end
};

/*
 * struct sl3516_ce_cipher_tfm_ctx - context for a skcipher TFM
 * @enginectx:		crypto_engine used by this TFM
 * @key:		pointer to key data
 * @keylen:		len of the key
 * @ce:			pointer to the private data of driver handling this TFM
 * @fallback_tfm:	pointer to the fallback TFM
 *
 * enginectx must be the first element
 */
struct sl3516_ce_cipher_tfm_ctx {
	struct crypto_engine_ctx enginectx;
	u32 *key;
	u32 keylen;
	struct sl3516_ce_dev *ce;
	struct crypto_skcipher *fallback_tfm;
};

/*
 * struct sl3516_ce_alg_template - crypto_alg template
 * @type:		the CRYPTO_ALG_TYPE for this template
 * @mode:		value to be used in control packet for this algorithm
 * @ce:			pointer to the sl3516_ce_dev structure associated with
 *			this template
 * @alg:		one of sub struct must be used
 * @stat_req:		number of request done on this template
 * @stat_fb:		number of request which has fallbacked
 * @stat_bytes:		total data size done by this template
 */
struct sl3516_ce_alg_template {
	u32 type;
	u32 mode;
	struct sl3516_ce_dev *ce;
	union {
		struct skcipher_alg skcipher;
	} alg;
	unsigned long stat_req;
	unsigned long stat_fb;
	unsigned long stat_bytes;
};

int sl3516_ce_enqueue(struct crypto_async_request *areq, u32 type);

int sl3516_ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
			 unsigned int keylen);
int sl3516_ce_cipher_init(struct crypto_tfm *tfm);
void sl3516_ce_cipher_exit(struct crypto_tfm *tfm);
int sl3516_ce_skdecrypt(struct skcipher_request *areq);
int sl3516_ce_skencrypt(struct skcipher_request *areq);

int sl3516_ce_run_task(struct sl3516_ce_dev *ce,
		       struct sl3516_ce_cipher_req_ctx *rctx, const char *name);

int sl3516_ce_rng_register(struct sl3516_ce_dev *ce);
void sl3516_ce_rng_unregister(struct sl3516_ce_dev *ce);