1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * sun8i-ce.h - hardware cryptographic offloader for
4  * Allwinner H3/A64/H5/H2+/H6 SoC
5  *
6  * Copyright (C) 2016-2019 Corentin LABBE <clabbe.montjoie@gmail.com>
7  */
8 #include <crypto/aes.h>
9 #include <crypto/des.h>
10 #include <crypto/engine.h>
11 #include <crypto/skcipher.h>
12 #include <linux/atomic.h>
13 #include <linux/debugfs.h>
14 #include <linux/crypto.h>
15 
16 /* CE Registers */
17 #define CE_TDQ	0x00
18 #define CE_CTR	0x04
19 #define CE_ICR	0x08
20 #define CE_ISR	0x0C
21 #define CE_TLR	0x10
22 #define CE_TSR	0x14
23 #define CE_ESR	0x18
24 #define CE_CSSGR	0x1C
25 #define CE_CDSGR	0x20
26 #define CE_CSAR	0x24
27 #define CE_CDAR	0x28
28 #define CE_TPR	0x2C
29 
30 /* Used in struct ce_task */
31 /* ce_task common */
32 #define CE_ENCRYPTION		0
33 #define CE_DECRYPTION		BIT(8)
34 
35 #define CE_COMM_INT		BIT(31)
36 
37 /* ce_task symmetric */
38 #define CE_AES_128BITS 0
39 #define CE_AES_192BITS 1
40 #define CE_AES_256BITS 2
41 
42 #define CE_OP_ECB	0
43 #define CE_OP_CBC	(1 << 8)
44 
45 #define CE_ALG_AES		0
46 #define CE_ALG_DES		1
47 #define CE_ALG_3DES		2
48 
49 /* Used in ce_variant */
50 #define CE_ID_NOTSUPP		0xFF
51 
52 #define CE_ID_CIPHER_AES	0
53 #define CE_ID_CIPHER_DES	1
54 #define CE_ID_CIPHER_DES3	2
55 #define CE_ID_CIPHER_MAX	3
56 
57 #define CE_ID_OP_ECB	0
58 #define CE_ID_OP_CBC	1
59 #define CE_ID_OP_MAX	2
60 
61 /* Used in CE registers */
62 #define CE_ERR_ALGO_NOTSUP	BIT(0)
63 #define CE_ERR_DATALEN		BIT(1)
64 #define CE_ERR_KEYSRAM		BIT(2)
65 #define CE_ERR_ADDR_INVALID	BIT(5)
66 #define CE_ERR_KEYLADDER	BIT(6)
67 
68 #define CE_DIE_ID_SHIFT	16
69 #define CE_DIE_ID_MASK	0x07
70 
71 #define MAX_SG 8
72 
73 #define CE_MAX_CLOCKS 3
74 
75 #define MAXFLOW 4
76 
77 /*
78  * struct ce_clock - Describe clocks used by sun8i-ce
79  * @name:	Name of clock needed by this variant
80  * @freq:	Frequency to set for each clock
81  * @max_freq:	Maximum frequency for each clock (generally given by datasheet)
82  */
83 struct ce_clock {
84 	const char *name;
85 	unsigned long freq;
86 	unsigned long max_freq;
87 };
88 
89 /*
90  * struct ce_variant - Describe CE capability for each variant hardware
91  * @alg_cipher:	list of supported ciphers. for each CE_ID_ this will give the
92  *              coresponding CE_ALG_XXX value
93  * @op_mode:	list of supported block modes
94  * @has_t_dlen_in_bytes:	Does the request size for cipher is in
95  *				bytes or words
96  * @ce_clks:	list of clocks needed by this variant
97  */
98 struct ce_variant {
99 	char alg_cipher[CE_ID_CIPHER_MAX];
100 	u32 op_mode[CE_ID_OP_MAX];
101 	bool has_t_dlen_in_bytes;
102 	struct ce_clock ce_clks[CE_MAX_CLOCKS];
103 };
104 
105 struct sginfo {
106 	__le32 addr;
107 	__le32 len;
108 } __packed;
109 
110 /*
111  * struct ce_task - CE Task descriptor
112  * The structure of this descriptor could be found in the datasheet
113  */
114 struct ce_task {
115 	__le32 t_id;
116 	__le32 t_common_ctl;
117 	__le32 t_sym_ctl;
118 	__le32 t_asym_ctl;
119 	__le32 t_key;
120 	__le32 t_iv;
121 	__le32 t_ctr;
122 	__le32 t_dlen;
123 	struct sginfo t_src[MAX_SG];
124 	struct sginfo t_dst[MAX_SG];
125 	__le32 next;
126 	__le32 reserved[3];
127 } __packed __aligned(8);
128 
129 /*
130  * struct sun8i_ce_flow - Information used by each flow
131  * @engine:	ptr to the crypto_engine for this flow
132  * @bounce_iv:	buffer which contain the IV
133  * @ivlen:	size of bounce_iv
134  * @complete:	completion for the current task on this flow
135  * @status:	set to 1 by interrupt if task is done
136  * @t_phy:	Physical address of task
137  * @tl:		pointer to the current ce_task for this flow
138  * @stat_req:	number of request done by this flow
139  */
140 struct sun8i_ce_flow {
141 	struct crypto_engine *engine;
142 	void *bounce_iv;
143 	unsigned int ivlen;
144 	struct completion complete;
145 	int status;
146 	dma_addr_t t_phy;
147 	int timeout;
148 	struct ce_task *tl;
149 #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
150 	unsigned long stat_req;
151 #endif
152 };
153 
154 /*
155  * struct sun8i_ce_dev - main container for all this driver information
156  * @base:	base address of CE
157  * @ceclks:	clocks used by CE
158  * @reset:	pointer to reset controller
159  * @dev:	the platform device
160  * @mlock:	Control access to device registers
161  * @chanlist:	array of all flow
162  * @flow:	flow to use in next request
163  * @variant:	pointer to variant specific data
164  * @dbgfs_dir:	Debugfs dentry for statistic directory
165  * @dbgfs_stats: Debugfs dentry for statistic counters
166  */
167 struct sun8i_ce_dev {
168 	void __iomem *base;
169 	struct clk *ceclks[CE_MAX_CLOCKS];
170 	struct reset_control *reset;
171 	struct device *dev;
172 	struct mutex mlock;
173 	struct sun8i_ce_flow *chanlist;
174 	atomic_t flow;
175 	const struct ce_variant *variant;
176 #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
177 	struct dentry *dbgfs_dir;
178 	struct dentry *dbgfs_stats;
179 #endif
180 };
181 
182 /*
183  * struct sun8i_cipher_req_ctx - context for a skcipher request
184  * @op_dir:		direction (encrypt vs decrypt) for this request
185  * @flow:		the flow to use for this request
186  * @fallback_req:	request struct for invoking the fallback skcipher TFM
187  */
188 struct sun8i_cipher_req_ctx {
189 	u32 op_dir;
190 	int flow;
191 	struct skcipher_request fallback_req;   // keep at the end
192 };
193 
194 /*
195  * struct sun8i_cipher_tfm_ctx - context for a skcipher TFM
196  * @enginectx:		crypto_engine used by this TFM
197  * @key:		pointer to key data
198  * @keylen:		len of the key
199  * @ce:			pointer to the private data of driver handling this TFM
200  * @fallback_tfm:	pointer to the fallback TFM
201  */
202 struct sun8i_cipher_tfm_ctx {
203 	struct crypto_engine_ctx enginectx;
204 	u32 *key;
205 	u32 keylen;
206 	struct sun8i_ce_dev *ce;
207 	struct crypto_skcipher *fallback_tfm;
208 };
209 
210 /*
211  * struct sun8i_ce_alg_template - crypto_alg template
212  * @type:		the CRYPTO_ALG_TYPE for this template
213  * @ce_algo_id:		the CE_ID for this template
214  * @ce_blockmode:	the type of block operation CE_ID
215  * @ce:			pointer to the sun8i_ce_dev structure associated with
216  *			this template
217  * @alg:		one of sub struct must be used
218  * @stat_req:		number of request done on this template
219  * @stat_fb:		number of request which has fallbacked
220  */
221 struct sun8i_ce_alg_template {
222 	u32 type;
223 	u32 ce_algo_id;
224 	u32 ce_blockmode;
225 	struct sun8i_ce_dev *ce;
226 	union {
227 		struct skcipher_alg skcipher;
228 	} alg;
229 #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
230 	unsigned long stat_req;
231 	unsigned long stat_fb;
232 #endif
233 };
234 
235 int sun8i_ce_enqueue(struct crypto_async_request *areq, u32 type);
236 
237 int sun8i_ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
238 			unsigned int keylen);
239 int sun8i_ce_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
240 			 unsigned int keylen);
241 int sun8i_ce_cipher_init(struct crypto_tfm *tfm);
242 void sun8i_ce_cipher_exit(struct crypto_tfm *tfm);
243 int sun8i_ce_skdecrypt(struct skcipher_request *areq);
244 int sun8i_ce_skencrypt(struct skcipher_request *areq);
245 
246 int sun8i_ce_get_engine_number(struct sun8i_ce_dev *ce);
247 
248 int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name);
249