xref: /arm-trusted-firmware/drivers/st/crypto/stm32_saes.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu #include <assert.h>
7*91f16700Schasinglulu #include <endian.h>
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu #include <stdint.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu #include <drivers/clk.h>
12*91f16700Schasinglulu #include <drivers/delay_timer.h>
13*91f16700Schasinglulu #include <drivers/st/stm32_saes.h>
14*91f16700Schasinglulu #include <drivers/st/stm32mp_reset.h>
15*91f16700Schasinglulu #include <lib/mmio.h>
16*91f16700Schasinglulu #include <lib/utils_def.h>
17*91f16700Schasinglulu #include <libfdt.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu #include <platform_def.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #define UINT8_BIT			8U
22*91f16700Schasinglulu #define AES_BLOCK_SIZE_BIT		128U
23*91f16700Schasinglulu #define AES_BLOCK_SIZE			(AES_BLOCK_SIZE_BIT / UINT8_BIT)
24*91f16700Schasinglulu 
25*91f16700Schasinglulu #define AES_KEYSIZE_128			16U
26*91f16700Schasinglulu #define AES_KEYSIZE_256			32U
27*91f16700Schasinglulu #define AES_IVSIZE			16U
28*91f16700Schasinglulu 
29*91f16700Schasinglulu /* SAES control register */
30*91f16700Schasinglulu #define _SAES_CR			0x0U
31*91f16700Schasinglulu /* SAES status register */
32*91f16700Schasinglulu #define _SAES_SR			0x04U
33*91f16700Schasinglulu /* SAES data input register */
34*91f16700Schasinglulu #define _SAES_DINR			0x08U
35*91f16700Schasinglulu /* SAES data output register */
36*91f16700Schasinglulu #define _SAES_DOUTR			0x0CU
37*91f16700Schasinglulu /* SAES key registers [0-3] */
38*91f16700Schasinglulu #define _SAES_KEYR0			0x10U
39*91f16700Schasinglulu #define _SAES_KEYR1			0x14U
40*91f16700Schasinglulu #define _SAES_KEYR2			0x18U
41*91f16700Schasinglulu #define _SAES_KEYR3			0x1CU
42*91f16700Schasinglulu /* SAES initialization vector registers [0-3] */
43*91f16700Schasinglulu #define _SAES_IVR0			0x20U
44*91f16700Schasinglulu #define _SAES_IVR1			0x24U
45*91f16700Schasinglulu #define _SAES_IVR2			0x28U
46*91f16700Schasinglulu #define _SAES_IVR3			0x2CU
47*91f16700Schasinglulu /* SAES key registers [4-7] */
48*91f16700Schasinglulu #define _SAES_KEYR4			0x30U
49*91f16700Schasinglulu #define _SAES_KEYR5			0x34U
50*91f16700Schasinglulu #define _SAES_KEYR6			0x38U
51*91f16700Schasinglulu #define _SAES_KEYR7			0x3CU
52*91f16700Schasinglulu /* SAES suspend registers [0-7] */
53*91f16700Schasinglulu #define _SAES_SUSPR0			0x40U
54*91f16700Schasinglulu #define _SAES_SUSPR1			0x44U
55*91f16700Schasinglulu #define _SAES_SUSPR2			0x48U
56*91f16700Schasinglulu #define _SAES_SUSPR3			0x4CU
57*91f16700Schasinglulu #define _SAES_SUSPR4			0x50U
58*91f16700Schasinglulu #define _SAES_SUSPR5			0x54U
59*91f16700Schasinglulu #define _SAES_SUSPR6			0x58U
60*91f16700Schasinglulu #define _SAES_SUSPR7			0x5CU
61*91f16700Schasinglulu /* SAES Interrupt Enable Register */
62*91f16700Schasinglulu #define _SAES_IER			0x300U
63*91f16700Schasinglulu /* SAES Interrupt Status Register */
64*91f16700Schasinglulu #define _SAES_ISR			0x304U
65*91f16700Schasinglulu /* SAES Interrupt Clear Register */
66*91f16700Schasinglulu #define _SAES_ICR			0x308U
67*91f16700Schasinglulu 
68*91f16700Schasinglulu /* SAES control register fields */
69*91f16700Schasinglulu #define _SAES_CR_RESET_VALUE		0x0U
70*91f16700Schasinglulu #define _SAES_CR_IPRST			BIT(31)
71*91f16700Schasinglulu #define _SAES_CR_KEYSEL_MASK		GENMASK(30, 28)
72*91f16700Schasinglulu #define _SAES_CR_KEYSEL_SHIFT		28U
73*91f16700Schasinglulu #define _SAES_CR_KEYSEL_SOFT		0x0U
74*91f16700Schasinglulu #define _SAES_CR_KEYSEL_DHUK		0x1U
75*91f16700Schasinglulu #define _SAES_CR_KEYSEL_BHK		0x2U
76*91f16700Schasinglulu #define _SAES_CR_KEYSEL_BHU_XOR_BH_K	0x4U
77*91f16700Schasinglulu #define _SAES_CR_KEYSEL_TEST		0x7U
78*91f16700Schasinglulu #define _SAES_CR_KSHAREID_MASK		GENMASK(27, 26)
79*91f16700Schasinglulu #define _SAES_CR_KSHAREID_SHIFT		26U
80*91f16700Schasinglulu #define _SAES_CR_KSHAREID_CRYP		0x0U
81*91f16700Schasinglulu #define _SAES_CR_KEYMOD_MASK		GENMASK(25, 24)
82*91f16700Schasinglulu #define _SAES_CR_KEYMOD_SHIFT		24U
83*91f16700Schasinglulu #define _SAES_CR_KEYMOD_NORMAL		0x0U
84*91f16700Schasinglulu #define _SAES_CR_KEYMOD_WRAPPED		0x1U
85*91f16700Schasinglulu #define _SAES_CR_KEYMOD_SHARED		0x2U
86*91f16700Schasinglulu #define _SAES_CR_NPBLB_MASK		GENMASK(23, 20)
87*91f16700Schasinglulu #define _SAES_CR_NPBLB_SHIFT		20U
88*91f16700Schasinglulu #define _SAES_CR_KEYPROT		BIT(19)
89*91f16700Schasinglulu #define _SAES_CR_KEYSIZE		BIT(18)
90*91f16700Schasinglulu #define _SAES_CR_GCMPH_MASK		GENMASK(14, 13)
91*91f16700Schasinglulu #define _SAES_CR_GCMPH_SHIFT		13U
92*91f16700Schasinglulu #define _SAES_CR_GCMPH_INIT		0U
93*91f16700Schasinglulu #define _SAES_CR_GCMPH_HEADER		1U
94*91f16700Schasinglulu #define _SAES_CR_GCMPH_PAYLOAD		2U
95*91f16700Schasinglulu #define _SAES_CR_GCMPH_FINAL		3U
96*91f16700Schasinglulu #define _SAES_CR_DMAOUTEN		BIT(12)
97*91f16700Schasinglulu #define _SAES_CR_DMAINEN		BIT(11)
98*91f16700Schasinglulu #define _SAES_CR_CHMOD_MASK		(BIT(16) | GENMASK(6, 5))
99*91f16700Schasinglulu #define _SAES_CR_CHMOD_SHIFT		5U
100*91f16700Schasinglulu #define _SAES_CR_CHMOD_ECB		0x0U
101*91f16700Schasinglulu #define _SAES_CR_CHMOD_CBC		0x1U
102*91f16700Schasinglulu #define _SAES_CR_CHMOD_CTR		0x2U
103*91f16700Schasinglulu #define _SAES_CR_CHMOD_GCM		0x3U
104*91f16700Schasinglulu #define _SAES_CR_CHMOD_GMAC		0x3U
105*91f16700Schasinglulu #define _SAES_CR_CHMOD_CCM		0x800U
106*91f16700Schasinglulu #define _SAES_CR_MODE_MASK		GENMASK(4, 3)
107*91f16700Schasinglulu #define _SAES_CR_MODE_SHIFT		3U
108*91f16700Schasinglulu #define _SAES_CR_MODE_ENC		0U
109*91f16700Schasinglulu #define _SAES_CR_MODE_KEYPREP		1U
110*91f16700Schasinglulu #define _SAES_CR_MODE_DEC		2U
111*91f16700Schasinglulu #define _SAES_CR_DATATYPE_MASK		GENMASK(2, 1)
112*91f16700Schasinglulu #define _SAES_CR_DATATYPE_SHIFT		1U
113*91f16700Schasinglulu #define _SAES_CR_DATATYPE_NONE		0U
114*91f16700Schasinglulu #define _SAES_CR_DATATYPE_HALF_WORD	1U
115*91f16700Schasinglulu #define _SAES_CR_DATATYPE_BYTE		2U
116*91f16700Schasinglulu #define _SAES_CR_DATATYPE_BIT		3U
117*91f16700Schasinglulu #define _SAES_CR_EN			BIT(0)
118*91f16700Schasinglulu 
119*91f16700Schasinglulu /* SAES status register fields */
120*91f16700Schasinglulu #define _SAES_SR_KEYVALID		BIT(7)
121*91f16700Schasinglulu #define _SAES_SR_BUSY			BIT(3)
122*91f16700Schasinglulu #define _SAES_SR_WRERR			BIT(2)
123*91f16700Schasinglulu #define _SAES_SR_RDERR			BIT(1)
124*91f16700Schasinglulu #define _SAES_SR_CCF			BIT(0)
125*91f16700Schasinglulu 
126*91f16700Schasinglulu /* SAES interrupt registers fields */
127*91f16700Schasinglulu #define _SAES_I_RNG_ERR			BIT(3)
128*91f16700Schasinglulu #define _SAES_I_KEY_ERR			BIT(2)
129*91f16700Schasinglulu #define _SAES_I_RW_ERR			BIT(1)
130*91f16700Schasinglulu #define _SAES_I_CC			BIT(0)
131*91f16700Schasinglulu 
132*91f16700Schasinglulu #define SAES_TIMEOUT_US			100000U
133*91f16700Schasinglulu #define TIMEOUT_US_1MS			1000U
134*91f16700Schasinglulu #define SAES_RESET_DELAY		20U
135*91f16700Schasinglulu 
136*91f16700Schasinglulu #define IS_CHAINING_MODE(mod, cr) \
137*91f16700Schasinglulu 	(((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT))
138*91f16700Schasinglulu 
139*91f16700Schasinglulu #define SET_CHAINING_MODE(mod, cr) \
140*91f16700Schasinglulu 	mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)
141*91f16700Schasinglulu 
142*91f16700Schasinglulu static struct stm32_saes_platdata saes_pdata;
143*91f16700Schasinglulu 
144*91f16700Schasinglulu static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata)
145*91f16700Schasinglulu {
146*91f16700Schasinglulu 	int node;
147*91f16700Schasinglulu 	struct dt_node_info info;
148*91f16700Schasinglulu 	void *fdt;
149*91f16700Schasinglulu 
150*91f16700Schasinglulu 	if (fdt_get_address(&fdt) == 0) {
151*91f16700Schasinglulu 		return -FDT_ERR_NOTFOUND;
152*91f16700Schasinglulu 	}
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	node = dt_get_node(&info, -1, DT_SAES_COMPAT);
155*91f16700Schasinglulu 	if (node < 0) {
156*91f16700Schasinglulu 		ERROR("No SAES entry in DT\n");
157*91f16700Schasinglulu 		return -FDT_ERR_NOTFOUND;
158*91f16700Schasinglulu 	}
159*91f16700Schasinglulu 
160*91f16700Schasinglulu 	if (info.status == DT_DISABLED) {
161*91f16700Schasinglulu 		return -FDT_ERR_NOTFOUND;
162*91f16700Schasinglulu 	}
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 	if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) {
165*91f16700Schasinglulu 		return -FDT_ERR_BADVALUE;
166*91f16700Schasinglulu 	}
167*91f16700Schasinglulu 
168*91f16700Schasinglulu 	pdata->base = (uintptr_t)info.base;
169*91f16700Schasinglulu 	pdata->clock_id = (unsigned long)info.clock;
170*91f16700Schasinglulu 	pdata->reset_id = (unsigned int)info.reset;
171*91f16700Schasinglulu 
172*91f16700Schasinglulu 	return 0;
173*91f16700Schasinglulu }
174*91f16700Schasinglulu 
175*91f16700Schasinglulu static bool does_chaining_mode_need_iv(uint32_t cr)
176*91f16700Schasinglulu {
177*91f16700Schasinglulu 	return !(IS_CHAINING_MODE(ECB, cr));
178*91f16700Schasinglulu }
179*91f16700Schasinglulu 
180*91f16700Schasinglulu static bool is_encrypt(uint32_t cr)
181*91f16700Schasinglulu {
182*91f16700Schasinglulu 	return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
183*91f16700Schasinglulu }
184*91f16700Schasinglulu 
185*91f16700Schasinglulu static bool is_decrypt(uint32_t cr)
186*91f16700Schasinglulu {
187*91f16700Schasinglulu 	return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
188*91f16700Schasinglulu }
189*91f16700Schasinglulu 
190*91f16700Schasinglulu static int wait_computation_completed(uintptr_t base)
191*91f16700Schasinglulu {
192*91f16700Schasinglulu 	uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US);
193*91f16700Schasinglulu 
194*91f16700Schasinglulu 	while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) {
195*91f16700Schasinglulu 		if (timeout_elapsed(timeout)) {
196*91f16700Schasinglulu 			WARN("%s: timeout\n", __func__);
197*91f16700Schasinglulu 			return -ETIMEDOUT;
198*91f16700Schasinglulu 		}
199*91f16700Schasinglulu 	}
200*91f16700Schasinglulu 
201*91f16700Schasinglulu 	return 0;
202*91f16700Schasinglulu }
203*91f16700Schasinglulu 
204*91f16700Schasinglulu static void clear_computation_completed(uintptr_t base)
205*91f16700Schasinglulu {
206*91f16700Schasinglulu 	mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC);
207*91f16700Schasinglulu }
208*91f16700Schasinglulu 
209*91f16700Schasinglulu static int saes_start(struct stm32_saes_context *ctx)
210*91f16700Schasinglulu {
211*91f16700Schasinglulu 	uint64_t timeout;
212*91f16700Schasinglulu 
213*91f16700Schasinglulu 	/* Reset IP */
214*91f16700Schasinglulu 	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
215*91f16700Schasinglulu 	udelay(SAES_RESET_DELAY);
216*91f16700Schasinglulu 	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
217*91f16700Schasinglulu 
218*91f16700Schasinglulu 	timeout = timeout_init_us(SAES_TIMEOUT_US);
219*91f16700Schasinglulu 	while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) {
220*91f16700Schasinglulu 		if (timeout_elapsed(timeout)) {
221*91f16700Schasinglulu 			WARN("%s: timeout\n", __func__);
222*91f16700Schasinglulu 			return -ETIMEDOUT;
223*91f16700Schasinglulu 		}
224*91f16700Schasinglulu 	}
225*91f16700Schasinglulu 
226*91f16700Schasinglulu 	return 0;
227*91f16700Schasinglulu }
228*91f16700Schasinglulu 
229*91f16700Schasinglulu static void saes_end(struct stm32_saes_context *ctx, int prev_error)
230*91f16700Schasinglulu {
231*91f16700Schasinglulu 	if (prev_error != 0) {
232*91f16700Schasinglulu 		/* Reset IP */
233*91f16700Schasinglulu 		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
234*91f16700Schasinglulu 		udelay(SAES_RESET_DELAY);
235*91f16700Schasinglulu 		mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
236*91f16700Schasinglulu 	}
237*91f16700Schasinglulu 
238*91f16700Schasinglulu 	/* Disable the SAES peripheral */
239*91f16700Schasinglulu 	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
240*91f16700Schasinglulu }
241*91f16700Schasinglulu 
242*91f16700Schasinglulu static void saes_write_iv(struct stm32_saes_context *ctx)
243*91f16700Schasinglulu {
244*91f16700Schasinglulu 	/* If chaining mode need to restore IV */
245*91f16700Schasinglulu 	if (does_chaining_mode_need_iv(ctx->cr)) {
246*91f16700Schasinglulu 		uint8_t i;
247*91f16700Schasinglulu 
248*91f16700Schasinglulu 		/* Restore the _SAES_IVRx */
249*91f16700Schasinglulu 		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
250*91f16700Schasinglulu 			mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]);
251*91f16700Schasinglulu 		}
252*91f16700Schasinglulu 	}
253*91f16700Schasinglulu 
254*91f16700Schasinglulu }
255*91f16700Schasinglulu 
256*91f16700Schasinglulu static void saes_write_key(struct stm32_saes_context *ctx)
257*91f16700Schasinglulu {
258*91f16700Schasinglulu 	/* Restore the _SAES_KEYRx if SOFTWARE key */
259*91f16700Schasinglulu 	if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) {
260*91f16700Schasinglulu 		uint8_t i;
261*91f16700Schasinglulu 
262*91f16700Schasinglulu 		for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
263*91f16700Schasinglulu 			mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]);
264*91f16700Schasinglulu 		}
265*91f16700Schasinglulu 
266*91f16700Schasinglulu 		if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) {
267*91f16700Schasinglulu 			for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) {
268*91f16700Schasinglulu 				mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t),
269*91f16700Schasinglulu 					      ctx->key[i + 4U]);
270*91f16700Schasinglulu 			}
271*91f16700Schasinglulu 		}
272*91f16700Schasinglulu 	}
273*91f16700Schasinglulu }
274*91f16700Schasinglulu 
275*91f16700Schasinglulu static int saes_prepare_key(struct stm32_saes_context *ctx)
276*91f16700Schasinglulu {
277*91f16700Schasinglulu 	/* Disable the SAES peripheral */
278*91f16700Schasinglulu 	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 	/* Set key size */
281*91f16700Schasinglulu 	if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) {
282*91f16700Schasinglulu 		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
283*91f16700Schasinglulu 	} else {
284*91f16700Schasinglulu 		mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
285*91f16700Schasinglulu 	}
286*91f16700Schasinglulu 
287*91f16700Schasinglulu 	saes_write_key(ctx);
288*91f16700Schasinglulu 
289*91f16700Schasinglulu 	/* For ECB/CBC decryption, key preparation mode must be selected to populate the key */
290*91f16700Schasinglulu 	if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) &&
291*91f16700Schasinglulu 	    is_decrypt(ctx->cr)) {
292*91f16700Schasinglulu 		int ret;
293*91f16700Schasinglulu 
294*91f16700Schasinglulu 		/* Select Mode 2 */
295*91f16700Schasinglulu 		mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
296*91f16700Schasinglulu 				   _SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT);
297*91f16700Schasinglulu 
298*91f16700Schasinglulu 		/* Enable SAES */
299*91f16700Schasinglulu 		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
300*91f16700Schasinglulu 
301*91f16700Schasinglulu 		/* Wait Computation completed */
302*91f16700Schasinglulu 		ret = wait_computation_completed(ctx->base);
303*91f16700Schasinglulu 		if (ret != 0) {
304*91f16700Schasinglulu 			return ret;
305*91f16700Schasinglulu 		}
306*91f16700Schasinglulu 
307*91f16700Schasinglulu 		clear_computation_completed(ctx->base);
308*91f16700Schasinglulu 
309*91f16700Schasinglulu 		/* Set Mode 3 */
310*91f16700Schasinglulu 		mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
311*91f16700Schasinglulu 				   _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
312*91f16700Schasinglulu 	}
313*91f16700Schasinglulu 
314*91f16700Schasinglulu 	return 0;
315*91f16700Schasinglulu }
316*91f16700Schasinglulu 
317*91f16700Schasinglulu static int save_context(struct stm32_saes_context *ctx)
318*91f16700Schasinglulu {
319*91f16700Schasinglulu 	if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) {
320*91f16700Schasinglulu 		/* Device should not be in a processing phase */
321*91f16700Schasinglulu 		return -EINVAL;
322*91f16700Schasinglulu 	}
323*91f16700Schasinglulu 
324*91f16700Schasinglulu 	/* Save CR */
325*91f16700Schasinglulu 	ctx->cr = mmio_read_32(ctx->base + _SAES_CR);
326*91f16700Schasinglulu 
327*91f16700Schasinglulu 	/* If chaining mode need to save current IV */
328*91f16700Schasinglulu 	if (does_chaining_mode_need_iv(ctx->cr)) {
329*91f16700Schasinglulu 		uint8_t i;
330*91f16700Schasinglulu 
331*91f16700Schasinglulu 		/* Save IV */
332*91f16700Schasinglulu 		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
333*91f16700Schasinglulu 			ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t));
334*91f16700Schasinglulu 		}
335*91f16700Schasinglulu 	}
336*91f16700Schasinglulu 
337*91f16700Schasinglulu 	/* Disable the SAES peripheral */
338*91f16700Schasinglulu 	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
339*91f16700Schasinglulu 
340*91f16700Schasinglulu 	return 0;
341*91f16700Schasinglulu }
342*91f16700Schasinglulu 
343*91f16700Schasinglulu /* To resume the processing of a message */
344*91f16700Schasinglulu static int restore_context(struct stm32_saes_context *ctx)
345*91f16700Schasinglulu {
346*91f16700Schasinglulu 	int ret;
347*91f16700Schasinglulu 
348*91f16700Schasinglulu 	/* IP should be disabled */
349*91f16700Schasinglulu 	if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) {
350*91f16700Schasinglulu 		VERBOSE("%s: Device is still enabled\n", __func__);
351*91f16700Schasinglulu 		return -EINVAL;
352*91f16700Schasinglulu 	}
353*91f16700Schasinglulu 
354*91f16700Schasinglulu 	/* Reset internal state */
355*91f16700Schasinglulu 	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
356*91f16700Schasinglulu 
357*91f16700Schasinglulu 	/* Restore the _SAES_CR */
358*91f16700Schasinglulu 	mmio_write_32(ctx->base + _SAES_CR, ctx->cr);
359*91f16700Schasinglulu 
360*91f16700Schasinglulu 	/* Preparation decrypt key */
361*91f16700Schasinglulu 	ret = saes_prepare_key(ctx);
362*91f16700Schasinglulu 	if (ret != 0) {
363*91f16700Schasinglulu 		return ret;
364*91f16700Schasinglulu 	}
365*91f16700Schasinglulu 
366*91f16700Schasinglulu 	saes_write_iv(ctx);
367*91f16700Schasinglulu 
368*91f16700Schasinglulu 	/* Enable the SAES peripheral */
369*91f16700Schasinglulu 	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
370*91f16700Schasinglulu 
371*91f16700Schasinglulu 	return 0;
372*91f16700Schasinglulu }
373*91f16700Schasinglulu 
374*91f16700Schasinglulu /**
375*91f16700Schasinglulu  * @brief Initialize SAES driver.
376*91f16700Schasinglulu  * @param None.
377*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
378*91f16700Schasinglulu  */
379*91f16700Schasinglulu int stm32_saes_driver_init(void)
380*91f16700Schasinglulu {
381*91f16700Schasinglulu 	int err;
382*91f16700Schasinglulu 
383*91f16700Schasinglulu 	err = stm32_saes_parse_fdt(&saes_pdata);
384*91f16700Schasinglulu 	if (err != 0) {
385*91f16700Schasinglulu 		return err;
386*91f16700Schasinglulu 	}
387*91f16700Schasinglulu 
388*91f16700Schasinglulu 	clk_enable(saes_pdata.clock_id);
389*91f16700Schasinglulu 	if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
390*91f16700Schasinglulu 		panic();
391*91f16700Schasinglulu 	}
392*91f16700Schasinglulu 
393*91f16700Schasinglulu 	udelay(SAES_RESET_DELAY);
394*91f16700Schasinglulu 	if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
395*91f16700Schasinglulu 		panic();
396*91f16700Schasinglulu 	}
397*91f16700Schasinglulu 
398*91f16700Schasinglulu 	return 0;
399*91f16700Schasinglulu }
400*91f16700Schasinglulu 
401*91f16700Schasinglulu /**
402*91f16700Schasinglulu  * @brief Start a AES computation.
403*91f16700Schasinglulu  * @param ctx: SAES process context
404*91f16700Schasinglulu  * @param is_dec: true if decryption, false if encryption
405*91f16700Schasinglulu  * @param ch_mode: define the chaining mode
406*91f16700Schasinglulu  * @param key_select: define where the key comes from.
407*91f16700Schasinglulu  * @param key: pointer to key (if key_select is KEY_SOFT, else unused)
408*91f16700Schasinglulu  * @param key_size: key size
409*91f16700Schasinglulu  * @param iv: pointer to initialization vectore (unsed if ch_mode is ECB)
410*91f16700Schasinglulu  * @param iv_size: iv size
411*91f16700Schasinglulu  * @note this function doesn't access to hardware but store in ctx the values
412*91f16700Schasinglulu  *
413*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
414*91f16700Schasinglulu  */
415*91f16700Schasinglulu int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
416*91f16700Schasinglulu 		    enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
417*91f16700Schasinglulu 		    const void *key, size_t key_size, const void *iv, size_t iv_size)
418*91f16700Schasinglulu {
419*91f16700Schasinglulu 	unsigned int i;
420*91f16700Schasinglulu 	const uint32_t *iv_u32;
421*91f16700Schasinglulu 	const uint32_t *key_u32;
422*91f16700Schasinglulu 
423*91f16700Schasinglulu 	ctx->assoc_len = 0U;
424*91f16700Schasinglulu 	ctx->load_len = 0U;
425*91f16700Schasinglulu 
426*91f16700Schasinglulu 	ctx->base = saes_pdata.base;
427*91f16700Schasinglulu 	ctx->cr = _SAES_CR_RESET_VALUE;
428*91f16700Schasinglulu 
429*91f16700Schasinglulu 	/* We want buffer to be u32 aligned */
430*91f16700Schasinglulu 	assert((uintptr_t)key % __alignof__(uint32_t) == 0);
431*91f16700Schasinglulu 	assert((uintptr_t)iv % __alignof__(uint32_t) == 0);
432*91f16700Schasinglulu 
433*91f16700Schasinglulu 	iv_u32 = iv;
434*91f16700Schasinglulu 	key_u32 = key;
435*91f16700Schasinglulu 
436*91f16700Schasinglulu 	if (is_dec) {
437*91f16700Schasinglulu 		/* Save Mode 3 = decrypt */
438*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
439*91f16700Schasinglulu 				   _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
440*91f16700Schasinglulu 	} else {
441*91f16700Schasinglulu 		/* Save Mode 1 = crypt */
442*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
443*91f16700Schasinglulu 				   _SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
444*91f16700Schasinglulu 	}
445*91f16700Schasinglulu 
446*91f16700Schasinglulu 	/* Save chaining mode */
447*91f16700Schasinglulu 	switch (ch_mode) {
448*91f16700Schasinglulu 	case STM32_SAES_MODE_ECB:
449*91f16700Schasinglulu 		SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr));
450*91f16700Schasinglulu 		break;
451*91f16700Schasinglulu 	case STM32_SAES_MODE_CBC:
452*91f16700Schasinglulu 		SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr));
453*91f16700Schasinglulu 		break;
454*91f16700Schasinglulu 	case STM32_SAES_MODE_CTR:
455*91f16700Schasinglulu 		SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr));
456*91f16700Schasinglulu 		break;
457*91f16700Schasinglulu 	case STM32_SAES_MODE_GCM:
458*91f16700Schasinglulu 		SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr));
459*91f16700Schasinglulu 		break;
460*91f16700Schasinglulu 	case STM32_SAES_MODE_CCM:
461*91f16700Schasinglulu 		SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr));
462*91f16700Schasinglulu 		break;
463*91f16700Schasinglulu 	default:
464*91f16700Schasinglulu 		return -EINVAL;
465*91f16700Schasinglulu 	}
466*91f16700Schasinglulu 
467*91f16700Schasinglulu 	/* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data.
468*91f16700Schasinglulu 	 * so we won't need to
469*91f16700Schasinglulu 	 * htobe32(data) before write to DINR
470*91f16700Schasinglulu 	 * nor
471*91f16700Schasinglulu 	 * be32toh after reading from DOUTR
472*91f16700Schasinglulu 	 *
473*91f16700Schasinglulu 	 * But note that wrap key only accept _SAES_CR_DATATYPE_NONE
474*91f16700Schasinglulu 	 */
475*91f16700Schasinglulu 	mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK,
476*91f16700Schasinglulu 			   _SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT);
477*91f16700Schasinglulu 
478*91f16700Schasinglulu 	/* Configure keysize */
479*91f16700Schasinglulu 	switch (key_size) {
480*91f16700Schasinglulu 	case AES_KEYSIZE_128:
481*91f16700Schasinglulu 		mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
482*91f16700Schasinglulu 		break;
483*91f16700Schasinglulu 	case AES_KEYSIZE_256:
484*91f16700Schasinglulu 		mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
485*91f16700Schasinglulu 		break;
486*91f16700Schasinglulu 	default:
487*91f16700Schasinglulu 		return -EINVAL;
488*91f16700Schasinglulu 	}
489*91f16700Schasinglulu 
490*91f16700Schasinglulu 	/* Configure key */
491*91f16700Schasinglulu 	switch (key_select) {
492*91f16700Schasinglulu 	case STM32_SAES_KEY_SOFT:
493*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
494*91f16700Schasinglulu 				   _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
495*91f16700Schasinglulu 		/* Save key */
496*91f16700Schasinglulu 		switch (key_size) {
497*91f16700Schasinglulu 		case AES_KEYSIZE_128:
498*91f16700Schasinglulu 			/* First 16 bytes == 4 u32 */
499*91f16700Schasinglulu 			for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
500*91f16700Schasinglulu 				mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i]));
501*91f16700Schasinglulu 				/* /!\ we save the key in HW byte order
502*91f16700Schasinglulu 				 * and word order : key[i] is for _SAES_KEYRi
503*91f16700Schasinglulu 				 */
504*91f16700Schasinglulu 			}
505*91f16700Schasinglulu 			break;
506*91f16700Schasinglulu 		case AES_KEYSIZE_256:
507*91f16700Schasinglulu 			for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) {
508*91f16700Schasinglulu 				mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i]));
509*91f16700Schasinglulu 				/* /!\ we save the key in HW byte order
510*91f16700Schasinglulu 				 * and word order : key[i] is for _SAES_KEYRi
511*91f16700Schasinglulu 				 */
512*91f16700Schasinglulu 			}
513*91f16700Schasinglulu 			break;
514*91f16700Schasinglulu 		default:
515*91f16700Schasinglulu 			return -EINVAL;
516*91f16700Schasinglulu 		}
517*91f16700Schasinglulu 
518*91f16700Schasinglulu 		break;
519*91f16700Schasinglulu 	case STM32_SAES_KEY_DHU:
520*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
521*91f16700Schasinglulu 				   _SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT);
522*91f16700Schasinglulu 		break;
523*91f16700Schasinglulu 	case STM32_SAES_KEY_BH:
524*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
525*91f16700Schasinglulu 				   _SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT);
526*91f16700Schasinglulu 		break;
527*91f16700Schasinglulu 	case STM32_SAES_KEY_BHU_XOR_BH:
528*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
529*91f16700Schasinglulu 				   _SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT);
530*91f16700Schasinglulu 		break;
531*91f16700Schasinglulu 	case STM32_SAES_KEY_WRAPPED:
532*91f16700Schasinglulu 		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
533*91f16700Schasinglulu 				   _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
534*91f16700Schasinglulu 		break;
535*91f16700Schasinglulu 
536*91f16700Schasinglulu 	default:
537*91f16700Schasinglulu 		return -EINVAL;
538*91f16700Schasinglulu 	}
539*91f16700Schasinglulu 
540*91f16700Schasinglulu 	/* Save IV */
541*91f16700Schasinglulu 	if (ch_mode != STM32_SAES_MODE_ECB) {
542*91f16700Schasinglulu 		if ((iv == NULL) || (iv_size != AES_IVSIZE)) {
543*91f16700Schasinglulu 			return -EINVAL;
544*91f16700Schasinglulu 		}
545*91f16700Schasinglulu 
546*91f16700Schasinglulu 		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
547*91f16700Schasinglulu 			mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i]));
548*91f16700Schasinglulu 			/* /!\ We save the iv in HW byte order */
549*91f16700Schasinglulu 		}
550*91f16700Schasinglulu 	}
551*91f16700Schasinglulu 
552*91f16700Schasinglulu 	return saes_start(ctx);
553*91f16700Schasinglulu }
554*91f16700Schasinglulu 
555*91f16700Schasinglulu /**
556*91f16700Schasinglulu  * @brief Update (or start) a AES authentificate process of associated data (CCM or GCM).
557*91f16700Schasinglulu  * @param ctx: SAES process context
558*91f16700Schasinglulu  * @param last_block: true if last assoc data block
559*91f16700Schasinglulu  * @param data: pointer to associated data
560*91f16700Schasinglulu  * @param data_size: data size
561*91f16700Schasinglulu  *
562*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
563*91f16700Schasinglulu  */
564*91f16700Schasinglulu int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
565*91f16700Schasinglulu 			       uint8_t *data, size_t data_size)
566*91f16700Schasinglulu {
567*91f16700Schasinglulu 	int ret;
568*91f16700Schasinglulu 	uint32_t *data_u32;
569*91f16700Schasinglulu 	unsigned int i = 0U;
570*91f16700Schasinglulu 
571*91f16700Schasinglulu 	/* We want buffers to be u32 aligned */
572*91f16700Schasinglulu 	assert((uintptr_t)data % __alignof__(uint32_t) == 0);
573*91f16700Schasinglulu 	data_u32 = (uint32_t *)data;
574*91f16700Schasinglulu 
575*91f16700Schasinglulu 	/* Init phase */
576*91f16700Schasinglulu 	ret = restore_context(ctx);
577*91f16700Schasinglulu 	if (ret != 0) {
578*91f16700Schasinglulu 		goto out;
579*91f16700Schasinglulu 	}
580*91f16700Schasinglulu 
581*91f16700Schasinglulu 	ret = wait_computation_completed(ctx->base);
582*91f16700Schasinglulu 	if (ret != 0) {
583*91f16700Schasinglulu 		return ret;
584*91f16700Schasinglulu 	}
585*91f16700Schasinglulu 
586*91f16700Schasinglulu 	clear_computation_completed(ctx->base);
587*91f16700Schasinglulu 
588*91f16700Schasinglulu 	if ((data == NULL) || (data_size == 0U)) {
589*91f16700Schasinglulu 		/* No associated data */
590*91f16700Schasinglulu 		/* ret already = 0 */
591*91f16700Schasinglulu 		goto out;
592*91f16700Schasinglulu 	}
593*91f16700Schasinglulu 
594*91f16700Schasinglulu 	/* There is an header/associated data phase */
595*91f16700Schasinglulu 	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
596*91f16700Schasinglulu 			   _SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT);
597*91f16700Schasinglulu 
598*91f16700Schasinglulu 	/* Enable the SAES peripheral */
599*91f16700Schasinglulu 	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
600*91f16700Schasinglulu 
601*91f16700Schasinglulu 	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
602*91f16700Schasinglulu 		unsigned int w; /* Word index */
603*91f16700Schasinglulu 
604*91f16700Schasinglulu 		w = i / sizeof(uint32_t);
605*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
606*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]);
607*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]);
608*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]);
609*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]);
610*91f16700Schasinglulu 
611*91f16700Schasinglulu 		ret = wait_computation_completed(ctx->base);
612*91f16700Schasinglulu 		if (ret != 0) {
613*91f16700Schasinglulu 			goto out;
614*91f16700Schasinglulu 		}
615*91f16700Schasinglulu 
616*91f16700Schasinglulu 		clear_computation_completed(ctx->base);
617*91f16700Schasinglulu 
618*91f16700Schasinglulu 		/* Process next block */
619*91f16700Schasinglulu 		i += AES_BLOCK_SIZE;
620*91f16700Schasinglulu 		ctx->assoc_len += AES_BLOCK_SIZE_BIT;
621*91f16700Schasinglulu 	}
622*91f16700Schasinglulu 
623*91f16700Schasinglulu 	/* Manage last block if not a block size multiple */
624*91f16700Schasinglulu 	if ((last_block) && (i < data_size)) {
625*91f16700Schasinglulu 		/* We don't manage unaligned last block yet */
626*91f16700Schasinglulu 		ret = -ENODEV;
627*91f16700Schasinglulu 		goto out;
628*91f16700Schasinglulu 	}
629*91f16700Schasinglulu 
630*91f16700Schasinglulu out:
631*91f16700Schasinglulu 	if (ret != 0) {
632*91f16700Schasinglulu 		saes_end(ctx, ret);
633*91f16700Schasinglulu 	}
634*91f16700Schasinglulu 
635*91f16700Schasinglulu 	return ret;
636*91f16700Schasinglulu }
637*91f16700Schasinglulu 
638*91f16700Schasinglulu /**
639*91f16700Schasinglulu  * @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM).
640*91f16700Schasinglulu  * @param ctx: SAES process context
641*91f16700Schasinglulu  * @param last_block: true if last payload data block
642*91f16700Schasinglulu  * @param data_in: pointer to payload
643*91f16700Schasinglulu  * @param data_out: pointer where to save de/encrypted payload
644*91f16700Schasinglulu  * @param data_size: payload size
645*91f16700Schasinglulu  *
646*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
647*91f16700Schasinglulu  */
648*91f16700Schasinglulu int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
649*91f16700Schasinglulu 			   uint8_t *data_in, uint8_t *data_out, size_t data_size)
650*91f16700Schasinglulu {
651*91f16700Schasinglulu 	int ret = 0;
652*91f16700Schasinglulu 	uint32_t *data_in_u32;
653*91f16700Schasinglulu 	uint32_t *data_out_u32;
654*91f16700Schasinglulu 	unsigned int i = 0U;
655*91f16700Schasinglulu 	uint32_t prev_cr;
656*91f16700Schasinglulu 
657*91f16700Schasinglulu 	/* We want buffers to be u32 aligned */
658*91f16700Schasinglulu 	assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
659*91f16700Schasinglulu 	assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
660*91f16700Schasinglulu 	data_in_u32 = (uint32_t *)data_in;
661*91f16700Schasinglulu 	data_out_u32 = (uint32_t *)data_out;
662*91f16700Schasinglulu 
663*91f16700Schasinglulu 	prev_cr = mmio_read_32(ctx->base + _SAES_CR);
664*91f16700Schasinglulu 
665*91f16700Schasinglulu 	if ((data_in == NULL) || (data_size == 0U)) {
666*91f16700Schasinglulu 		/* there is no data */
667*91f16700Schasinglulu 		goto out;
668*91f16700Schasinglulu 	}
669*91f16700Schasinglulu 
670*91f16700Schasinglulu 	/* There is a load phase */
671*91f16700Schasinglulu 	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
672*91f16700Schasinglulu 			   _SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT);
673*91f16700Schasinglulu 
674*91f16700Schasinglulu 	if ((prev_cr & _SAES_CR_GCMPH_MASK) ==
675*91f16700Schasinglulu 	    (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
676*91f16700Schasinglulu 		/* Still in initialization phase, no header
677*91f16700Schasinglulu 		 * We need to enable the SAES peripheral
678*91f16700Schasinglulu 		 */
679*91f16700Schasinglulu 		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
680*91f16700Schasinglulu 	}
681*91f16700Schasinglulu 
682*91f16700Schasinglulu 	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
683*91f16700Schasinglulu 		unsigned int w; /* Word index */
684*91f16700Schasinglulu 
685*91f16700Schasinglulu 		w = i / sizeof(uint32_t);
686*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
687*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
688*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
689*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
690*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
691*91f16700Schasinglulu 
692*91f16700Schasinglulu 		ret = wait_computation_completed(ctx->base);
693*91f16700Schasinglulu 		if (ret != 0) {
694*91f16700Schasinglulu 			goto out;
695*91f16700Schasinglulu 		}
696*91f16700Schasinglulu 
697*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
698*91f16700Schasinglulu 		data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
699*91f16700Schasinglulu 		data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
700*91f16700Schasinglulu 		data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
701*91f16700Schasinglulu 		data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
702*91f16700Schasinglulu 
703*91f16700Schasinglulu 		clear_computation_completed(ctx->base);
704*91f16700Schasinglulu 
705*91f16700Schasinglulu 		/* Process next block */
706*91f16700Schasinglulu 		i += AES_BLOCK_SIZE;
707*91f16700Schasinglulu 		ctx->load_len += AES_BLOCK_SIZE_BIT;
708*91f16700Schasinglulu 	}
709*91f16700Schasinglulu 	/* Manage last block if not a block size multiple */
710*91f16700Schasinglulu 	if ((last_block) && (i < data_size)) {
711*91f16700Schasinglulu 		uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
712*91f16700Schasinglulu 		uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
713*91f16700Schasinglulu 
714*91f16700Schasinglulu 		memcpy(block_in, data_in + i, data_size - i);
715*91f16700Schasinglulu 
716*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
717*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]);
718*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]);
719*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]);
720*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]);
721*91f16700Schasinglulu 
722*91f16700Schasinglulu 		ret = wait_computation_completed(ctx->base);
723*91f16700Schasinglulu 		if (ret != 0) {
724*91f16700Schasinglulu 			VERBOSE("%s %d\n", __func__, __LINE__);
725*91f16700Schasinglulu 			goto out;
726*91f16700Schasinglulu 		}
727*91f16700Schasinglulu 
728*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
729*91f16700Schasinglulu 		block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
730*91f16700Schasinglulu 		block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
731*91f16700Schasinglulu 		block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
732*91f16700Schasinglulu 		block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
733*91f16700Schasinglulu 
734*91f16700Schasinglulu 		clear_computation_completed(ctx->base);
735*91f16700Schasinglulu 
736*91f16700Schasinglulu 		memcpy(data_out + i, block_out, data_size - i);
737*91f16700Schasinglulu 
738*91f16700Schasinglulu 		ctx->load_len += (data_size - i) * UINT8_BIT;
739*91f16700Schasinglulu 	}
740*91f16700Schasinglulu 
741*91f16700Schasinglulu out:
742*91f16700Schasinglulu 	if (ret != 0) {
743*91f16700Schasinglulu 		saes_end(ctx, ret);
744*91f16700Schasinglulu 	}
745*91f16700Schasinglulu 
746*91f16700Schasinglulu 	return ret;
747*91f16700Schasinglulu }
748*91f16700Schasinglulu 
749*91f16700Schasinglulu /**
750*91f16700Schasinglulu  * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM).
751*91f16700Schasinglulu  * @param ctx: SAES process context
752*91f16700Schasinglulu  * @param tag: pointer where to save the tag
753*91f16700Schasinglulu  * @param data_size: tag size
754*91f16700Schasinglulu  *
755*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
756*91f16700Schasinglulu  */
757*91f16700Schasinglulu int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag,
758*91f16700Schasinglulu 		     size_t tag_size)
759*91f16700Schasinglulu {
760*91f16700Schasinglulu 	int ret;
761*91f16700Schasinglulu 	uint32_t tag_u32[4];
762*91f16700Schasinglulu 	uint32_t prev_cr;
763*91f16700Schasinglulu 
764*91f16700Schasinglulu 	prev_cr = mmio_read_32(ctx->base + _SAES_CR);
765*91f16700Schasinglulu 
766*91f16700Schasinglulu 	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
767*91f16700Schasinglulu 			   _SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT);
768*91f16700Schasinglulu 
769*91f16700Schasinglulu 	if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
770*91f16700Schasinglulu 		/* Still in initialization phase, no header
771*91f16700Schasinglulu 		 * We need to enable the SAES peripheral
772*91f16700Schasinglulu 		 */
773*91f16700Schasinglulu 		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
774*91f16700Schasinglulu 	}
775*91f16700Schasinglulu 
776*91f16700Schasinglulu 	/* No need to htobe() as we configure the HW to swap bytes */
777*91f16700Schasinglulu 	mmio_write_32(ctx->base + _SAES_DINR, 0);
778*91f16700Schasinglulu 	mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len);
779*91f16700Schasinglulu 	mmio_write_32(ctx->base + _SAES_DINR, 0);
780*91f16700Schasinglulu 	mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len);
781*91f16700Schasinglulu 
782*91f16700Schasinglulu 	ret = wait_computation_completed(ctx->base);
783*91f16700Schasinglulu 	if (ret != 0) {
784*91f16700Schasinglulu 		goto out;
785*91f16700Schasinglulu 	}
786*91f16700Schasinglulu 
787*91f16700Schasinglulu 	/* No need to htobe() as we configure the HW to swap bytes */
788*91f16700Schasinglulu 	tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR);
789*91f16700Schasinglulu 	tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR);
790*91f16700Schasinglulu 	tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR);
791*91f16700Schasinglulu 	tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR);
792*91f16700Schasinglulu 
793*91f16700Schasinglulu 	clear_computation_completed(ctx->base);
794*91f16700Schasinglulu 
795*91f16700Schasinglulu 	memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size));
796*91f16700Schasinglulu 
797*91f16700Schasinglulu out:
798*91f16700Schasinglulu 	saes_end(ctx, ret);
799*91f16700Schasinglulu 
800*91f16700Schasinglulu 	return ret;
801*91f16700Schasinglulu }
802*91f16700Schasinglulu 
803*91f16700Schasinglulu /**
804*91f16700Schasinglulu  * @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR).
805*91f16700Schasinglulu  * @param ctx: SAES process context
806*91f16700Schasinglulu  * @param last_block: true if last payload data block
807*91f16700Schasinglulu  * @param data_in: pointer to payload
808*91f16700Schasinglulu  * @param data_out: pointer where to save de/encrypted payload
809*91f16700Schasinglulu  * @param data_size: payload size
810*91f16700Schasinglulu  *
811*91f16700Schasinglulu  * @retval 0 if OK; negative value else.
812*91f16700Schasinglulu  */
813*91f16700Schasinglulu int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
814*91f16700Schasinglulu 		      uint8_t *data_in, uint8_t *data_out, size_t data_size)
815*91f16700Schasinglulu {
816*91f16700Schasinglulu 	int ret;
817*91f16700Schasinglulu 	uint32_t *data_in_u32;
818*91f16700Schasinglulu 	uint32_t *data_out_u32;
819*91f16700Schasinglulu 	unsigned int i = 0U;
820*91f16700Schasinglulu 
821*91f16700Schasinglulu 	/* We want buffers to be u32 aligned */
822*91f16700Schasinglulu 	assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
823*91f16700Schasinglulu 	assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
824*91f16700Schasinglulu 	data_in_u32 = (uint32_t *)data_in;
825*91f16700Schasinglulu 	data_out_u32 = (uint32_t *)data_out;
826*91f16700Schasinglulu 
827*91f16700Schasinglulu 	if ((!last_block) &&
828*91f16700Schasinglulu 	    (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
829*91f16700Schasinglulu 		ERROR("%s: non last block must be multiple of 128 bits\n",
830*91f16700Schasinglulu 		      __func__);
831*91f16700Schasinglulu 		ret = -EINVAL;
832*91f16700Schasinglulu 		goto out;
833*91f16700Schasinglulu 	}
834*91f16700Schasinglulu 
835*91f16700Schasinglulu 	/* In CBC encryption we need to manage specifically last 2 128bits
836*91f16700Schasinglulu 	 * blocks if total size in not a block size aligned
837*91f16700Schasinglulu 	 * work TODO. Currently return ENODEV.
838*91f16700Schasinglulu 	 * Morevoer as we need to know last 2 block, if unaligned and
839*91f16700Schasinglulu 	 * call with less than two block, return -EINVAL.
840*91f16700Schasinglulu 	 */
841*91f16700Schasinglulu 	if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) &&
842*91f16700Schasinglulu 	    (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
843*91f16700Schasinglulu 		if (data_size < AES_BLOCK_SIZE * 2U) {
844*91f16700Schasinglulu 			ERROR("if CBC, last part size should be at least 2 * AES_BLOCK_SIZE\n");
845*91f16700Schasinglulu 			ret = -EINVAL;
846*91f16700Schasinglulu 			goto out;
847*91f16700Schasinglulu 		}
848*91f16700Schasinglulu 		/* Moreover the CBC specific padding for encrypt is not yet implemented */
849*91f16700Schasinglulu 		ret = -ENODEV;
850*91f16700Schasinglulu 		goto out;
851*91f16700Schasinglulu 	}
852*91f16700Schasinglulu 
853*91f16700Schasinglulu 	ret = restore_context(ctx);
854*91f16700Schasinglulu 	if (ret != 0) {
855*91f16700Schasinglulu 		goto out;
856*91f16700Schasinglulu 	}
857*91f16700Schasinglulu 
858*91f16700Schasinglulu 	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
859*91f16700Schasinglulu 		unsigned int w; /* Word index */
860*91f16700Schasinglulu 
861*91f16700Schasinglulu 		w = i / sizeof(uint32_t);
862*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
863*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
864*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
865*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
866*91f16700Schasinglulu 		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
867*91f16700Schasinglulu 
868*91f16700Schasinglulu 		ret = wait_computation_completed(ctx->base);
869*91f16700Schasinglulu 		if (ret != 0) {
870*91f16700Schasinglulu 			goto out;
871*91f16700Schasinglulu 		}
872*91f16700Schasinglulu 
873*91f16700Schasinglulu 		/* No need to htobe() as we configure the HW to swap bytes */
874*91f16700Schasinglulu 		data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
875*91f16700Schasinglulu 		data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
876*91f16700Schasinglulu 		data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
877*91f16700Schasinglulu 		data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
878*91f16700Schasinglulu 
879*91f16700Schasinglulu 		clear_computation_completed(ctx->base);
880*91f16700Schasinglulu 
881*91f16700Schasinglulu 		/* Process next block */
882*91f16700Schasinglulu 		i += AES_BLOCK_SIZE;
883*91f16700Schasinglulu 	}
884*91f16700Schasinglulu 	/* Manage last block if not a block size multiple */
885*91f16700Schasinglulu 
886*91f16700Schasinglulu 	if ((last_block) && (i < data_size)) {
887*91f16700Schasinglulu 		/* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */
888*91f16700Schasinglulu 		ret = -ENODEV;
889*91f16700Schasinglulu 		goto out;
890*91f16700Schasinglulu 	}
891*91f16700Schasinglulu 
892*91f16700Schasinglulu 	if (!last_block) {
893*91f16700Schasinglulu 		ret = save_context(ctx);
894*91f16700Schasinglulu 	}
895*91f16700Schasinglulu 
896*91f16700Schasinglulu out:
897*91f16700Schasinglulu 	/* If last block or error, end of SAES process */
898*91f16700Schasinglulu 	if (last_block || (ret != 0)) {
899*91f16700Schasinglulu 		saes_end(ctx, ret);
900*91f16700Schasinglulu 	}
901*91f16700Schasinglulu 
902*91f16700Schasinglulu 	return ret;
903*91f16700Schasinglulu }
904