xref: /arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright 2021 NXP
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  *
6*91f16700Schasinglulu  */
7*91f16700Schasinglulu 
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu #include <stdbool.h>
10*91f16700Schasinglulu #include <stdint.h>
11*91f16700Schasinglulu #include <stdio.h>
12*91f16700Schasinglulu #include <stdlib.h>
13*91f16700Schasinglulu #include <string.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include <arch_helpers.h>
16*91f16700Schasinglulu #include "caam.h"
17*91f16700Schasinglulu #include <common/debug.h>
18*91f16700Schasinglulu #include "jobdesc.h"
19*91f16700Schasinglulu #include "sec_hw_specific.h"
20*91f16700Schasinglulu 
21*91f16700Schasinglulu static uintptr_t g_nxp_caam_addr;
22*91f16700Schasinglulu static void *job_ring;
23*91f16700Schasinglulu 
24*91f16700Schasinglulu uintptr_t get_caam_addr(void)
25*91f16700Schasinglulu {
26*91f16700Schasinglulu 	if (g_nxp_caam_addr == 0) {
27*91f16700Schasinglulu 		ERROR("Sec Init is not done.\n");
28*91f16700Schasinglulu 		panic();
29*91f16700Schasinglulu 	}
30*91f16700Schasinglulu 	return g_nxp_caam_addr;
31*91f16700Schasinglulu }
32*91f16700Schasinglulu 
33*91f16700Schasinglulu /* This function sets the TZ bit for the Job ring number passed as @num */
34*91f16700Schasinglulu static void config_tz(int num)
35*91f16700Schasinglulu {
36*91f16700Schasinglulu 	uint32_t jricid;
37*91f16700Schasinglulu 
38*91f16700Schasinglulu 	/* Setting TZ bit of job ring */
39*91f16700Schasinglulu 	switch (num) {
40*91f16700Schasinglulu 	case 0:
41*91f16700Schasinglulu 		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET);
42*91f16700Schasinglulu 		sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET,
43*91f16700Schasinglulu 			  jricid | JRICID_MS_TZ);
44*91f16700Schasinglulu 		break;
45*91f16700Schasinglulu 	case 1:
46*91f16700Schasinglulu 		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET);
47*91f16700Schasinglulu 		sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET,
48*91f16700Schasinglulu 			  jricid | JRICID_MS_TZ);
49*91f16700Schasinglulu 		break;
50*91f16700Schasinglulu 	case 2:
51*91f16700Schasinglulu 		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET);
52*91f16700Schasinglulu 		sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET,
53*91f16700Schasinglulu 			  jricid | JRICID_MS_TZ);
54*91f16700Schasinglulu 		break;
55*91f16700Schasinglulu 	case 3:
56*91f16700Schasinglulu 		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET);
57*91f16700Schasinglulu 		sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET,
58*91f16700Schasinglulu 			  jricid | JRICID_MS_TZ);
59*91f16700Schasinglulu 		break;
60*91f16700Schasinglulu 	default:
61*91f16700Schasinglulu 		break;
62*91f16700Schasinglulu 	}
63*91f16700Schasinglulu }
64*91f16700Schasinglulu 
65*91f16700Schasinglulu /* This function checks if Virtualization is enabled for JR and
66*91f16700Schasinglulu  * accordingly sets the bot for starting JR<num> in JRSTARTR register
67*91f16700Schasinglulu  */
68*91f16700Schasinglulu static inline void start_jr(int num)
69*91f16700Schasinglulu {
70*91f16700Schasinglulu 	uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET));
71*91f16700Schasinglulu 	uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET));
72*91f16700Schasinglulu 	uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET));
73*91f16700Schasinglulu 	bool start = false;
74*91f16700Schasinglulu 
75*91f16700Schasinglulu 	if ((ctpr & CTPR_VIRT_EN_INC) != 0U) {
76*91f16700Schasinglulu 		if (((ctpr & CTPR_VIRT_EN_POR) != 0U) ||
77*91f16700Schasinglulu 		    ((scfgr & SCFGR_VIRT_EN) != 0U)) {
78*91f16700Schasinglulu 			start = true;
79*91f16700Schasinglulu 		}
80*91f16700Schasinglulu 	} else {
81*91f16700Schasinglulu 		if ((ctpr & CTPR_VIRT_EN_POR) != 0U) {
82*91f16700Schasinglulu 			start = true;
83*91f16700Schasinglulu 		}
84*91f16700Schasinglulu 	}
85*91f16700Schasinglulu 
86*91f16700Schasinglulu 	if (start == true) {
87*91f16700Schasinglulu 		switch (num) {
88*91f16700Schasinglulu 		case 0:
89*91f16700Schasinglulu 			tmp |= JRSTARTR_STARTJR0;
90*91f16700Schasinglulu 			break;
91*91f16700Schasinglulu 		case 1:
92*91f16700Schasinglulu 			tmp |= JRSTARTR_STARTJR1;
93*91f16700Schasinglulu 			break;
94*91f16700Schasinglulu 		case 2:
95*91f16700Schasinglulu 			tmp |= JRSTARTR_STARTJR2;
96*91f16700Schasinglulu 			break;
97*91f16700Schasinglulu 		case 3:
98*91f16700Schasinglulu 			tmp |= JRSTARTR_STARTJR3;
99*91f16700Schasinglulu 			break;
100*91f16700Schasinglulu 		default:
101*91f16700Schasinglulu 			break;
102*91f16700Schasinglulu 		}
103*91f16700Schasinglulu 	}
104*91f16700Schasinglulu 	sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp);
105*91f16700Schasinglulu }
106*91f16700Schasinglulu 
107*91f16700Schasinglulu /* This functions configures the Job Ring
108*91f16700Schasinglulu  * JR3 is reserved for use by Secure world
109*91f16700Schasinglulu  */
110*91f16700Schasinglulu static int configure_jr(int num)
111*91f16700Schasinglulu {
112*91f16700Schasinglulu 	int ret;
113*91f16700Schasinglulu 	void *reg_base_addr;
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	switch (num) {
116*91f16700Schasinglulu 	case 0:
117*91f16700Schasinglulu 		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET);
118*91f16700Schasinglulu 		break;
119*91f16700Schasinglulu 	case 1:
120*91f16700Schasinglulu 		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET);
121*91f16700Schasinglulu 		break;
122*91f16700Schasinglulu 	case 2:
123*91f16700Schasinglulu 		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET);
124*91f16700Schasinglulu 		break;
125*91f16700Schasinglulu 	case 3:
126*91f16700Schasinglulu 		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET);
127*91f16700Schasinglulu 		break;
128*91f16700Schasinglulu 	default:
129*91f16700Schasinglulu 		break;
130*91f16700Schasinglulu 	}
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	/* Initialize the JR library */
133*91f16700Schasinglulu 	ret = sec_jr_lib_init();
134*91f16700Schasinglulu 	if (ret != 0) {
135*91f16700Schasinglulu 		ERROR("Error in sec_jr_lib_init");
136*91f16700Schasinglulu 		return -1;
137*91f16700Schasinglulu 	}
138*91f16700Schasinglulu 
139*91f16700Schasinglulu 	start_jr(num);
140*91f16700Schasinglulu 
141*91f16700Schasinglulu 	/* Do HW configuration of the JR */
142*91f16700Schasinglulu 	job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0,
143*91f16700Schasinglulu 				 reg_base_addr, 0);
144*91f16700Schasinglulu 
145*91f16700Schasinglulu 	if (job_ring == NULL) {
146*91f16700Schasinglulu 		ERROR("Error in init_job_ring");
147*91f16700Schasinglulu 		return -1;
148*91f16700Schasinglulu 	}
149*91f16700Schasinglulu 
150*91f16700Schasinglulu 	return ret;
151*91f16700Schasinglulu }
152*91f16700Schasinglulu 
153*91f16700Schasinglulu /* TBD - Configures and locks the ICID values for various JR */
154*91f16700Schasinglulu static inline void configure_icid(void)
155*91f16700Schasinglulu {
156*91f16700Schasinglulu }
157*91f16700Schasinglulu 
158*91f16700Schasinglulu /* TBD configures the TZ settings of RTIC */
159*91f16700Schasinglulu static inline void configure_rtic(void)
160*91f16700Schasinglulu {
161*91f16700Schasinglulu }
162*91f16700Schasinglulu 
163*91f16700Schasinglulu int sec_init(uintptr_t nxp_caam_addr)
164*91f16700Schasinglulu {
165*91f16700Schasinglulu 	g_nxp_caam_addr = nxp_caam_addr;
166*91f16700Schasinglulu 	return config_sec_block();
167*91f16700Schasinglulu }
168*91f16700Schasinglulu 
169*91f16700Schasinglulu /* This function configure SEC block:
170*91f16700Schasinglulu  * - It does basic parameter setting
171*91f16700Schasinglulu  * - Configures the default Job ring assigned to TZ /secure world
172*91f16700Schasinglulu  * - Instantiates the RNG
173*91f16700Schasinglulu  */
174*91f16700Schasinglulu int config_sec_block(void)
175*91f16700Schasinglulu {
176*91f16700Schasinglulu 	int ret = 0;
177*91f16700Schasinglulu 	uint32_t mcfgr;
178*91f16700Schasinglulu 
179*91f16700Schasinglulu 	if (g_nxp_caam_addr == 0) {
180*91f16700Schasinglulu 		ERROR("Sec Init is not done.\n");
181*91f16700Schasinglulu 		return -1;
182*91f16700Schasinglulu 	} else if (job_ring != NULL) {
183*91f16700Schasinglulu 		NOTICE("Sec is already initialized and configured.\n");
184*91f16700Schasinglulu 		return ret;
185*91f16700Schasinglulu 	}
186*91f16700Schasinglulu 
187*91f16700Schasinglulu 	mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET);
188*91f16700Schasinglulu 
189*91f16700Schasinglulu 	/* Modify CAAM Read/Write attributes
190*91f16700Schasinglulu 	 * AXI Write - Cacheable, WB and WA
191*91f16700Schasinglulu 	 * AXI Read - Cacheable, RA
192*91f16700Schasinglulu 	 */
193*91f16700Schasinglulu #if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A)
194*91f16700Schasinglulu 	mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT);
195*91f16700Schasinglulu 	mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT);
196*91f16700Schasinglulu #else
197*91f16700Schasinglulu 	mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
198*91f16700Schasinglulu #endif
199*91f16700Schasinglulu 
200*91f16700Schasinglulu 	/* Set PS bit to 1 */
201*91f16700Schasinglulu #ifdef CONFIG_PHYS_64BIT
202*91f16700Schasinglulu 	mcfgr |= (1 << MCFGR_PS_SHIFT);
203*91f16700Schasinglulu #endif
204*91f16700Schasinglulu 	sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr);
205*91f16700Schasinglulu 
206*91f16700Schasinglulu 	/* Asssign ICID to all Job rings and lock them for usage */
207*91f16700Schasinglulu 	configure_icid();
208*91f16700Schasinglulu 
209*91f16700Schasinglulu 	/* Configure the RTIC */
210*91f16700Schasinglulu 	configure_rtic();
211*91f16700Schasinglulu 
212*91f16700Schasinglulu 	/* Configure the default JR for usage */
213*91f16700Schasinglulu 	ret = configure_jr(DEFAULT_JR);
214*91f16700Schasinglulu 	if (ret != 0) {
215*91f16700Schasinglulu 		ERROR("\nFSL_JR: configuration failure\n");
216*91f16700Schasinglulu 		return -1;
217*91f16700Schasinglulu 	}
218*91f16700Schasinglulu 	/* Do TZ configuration of default JR for sec firmware */
219*91f16700Schasinglulu 	config_tz(DEFAULT_JR);
220*91f16700Schasinglulu 
221*91f16700Schasinglulu #ifdef CONFIG_RNG_INIT
222*91f16700Schasinglulu 	/* Instantiate the RNG */
223*91f16700Schasinglulu 	ret = hw_rng_instantiate();
224*91f16700Schasinglulu 	if (ret != 0) {
225*91f16700Schasinglulu 		ERROR("\nRNG Instantiation failure\n");
226*91f16700Schasinglulu 		return -1;
227*91f16700Schasinglulu 	}
228*91f16700Schasinglulu #endif
229*91f16700Schasinglulu 
230*91f16700Schasinglulu 	return ret;
231*91f16700Schasinglulu }
232*91f16700Schasinglulu 
233*91f16700Schasinglulu /* This function is used for sumbitting job to the Job Ring
234*91f16700Schasinglulu  * [param] [in] - jobdesc to be submitted
235*91f16700Schasinglulu  * Return - -1 in case of error and 0 in case of SUCCESS
236*91f16700Schasinglulu  */
237*91f16700Schasinglulu int run_descriptor_jr(struct job_descriptor *jobdesc)
238*91f16700Schasinglulu {
239*91f16700Schasinglulu 	int i = 0, ret = 0;
240*91f16700Schasinglulu 	uint32_t *desc_addr = jobdesc->desc;
241*91f16700Schasinglulu 	uint32_t desc_len = desc_length(jobdesc->desc);
242*91f16700Schasinglulu 	uint32_t desc_word;
243*91f16700Schasinglulu 
244*91f16700Schasinglulu 	for (i = 0; i < desc_len; i++) {
245*91f16700Schasinglulu 		desc_word = desc_addr[i];
246*91f16700Schasinglulu 		VERBOSE("%x\n", desc_word);
247*91f16700Schasinglulu 		sec_out32((uint32_t *)&desc_addr[i], desc_word);
248*91f16700Schasinglulu 	}
249*91f16700Schasinglulu 	dsb();
250*91f16700Schasinglulu 
251*91f16700Schasinglulu #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
252*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)desc_addr, desc_len * 4);
253*91f16700Schasinglulu 	dmbsy();
254*91f16700Schasinglulu 	dsbsy();
255*91f16700Schasinglulu 	isb();
256*91f16700Schasinglulu #endif
257*91f16700Schasinglulu 
258*91f16700Schasinglulu 	ret = enq_jr_desc(job_ring, jobdesc);
259*91f16700Schasinglulu 	if (ret == 0) {
260*91f16700Schasinglulu 		VERBOSE("JR enqueue done...\n");
261*91f16700Schasinglulu 	} else {
262*91f16700Schasinglulu 		ERROR("Error in Enqueue\n");
263*91f16700Schasinglulu 		return ret;
264*91f16700Schasinglulu 	}
265*91f16700Schasinglulu 
266*91f16700Schasinglulu 	VERBOSE("Dequeue in progress");
267*91f16700Schasinglulu 
268*91f16700Schasinglulu 	ret = dequeue_jr(job_ring, -1);
269*91f16700Schasinglulu 	if (ret >= 0) {
270*91f16700Schasinglulu 		VERBOSE("Dequeue of %x desc success\n", ret);
271*91f16700Schasinglulu 		ret = 0;
272*91f16700Schasinglulu 	} else {
273*91f16700Schasinglulu 		ERROR("deq_ret %x\n", ret);
274*91f16700Schasinglulu 		ret = -1;
275*91f16700Schasinglulu 	}
276*91f16700Schasinglulu 
277*91f16700Schasinglulu 	return ret;
278*91f16700Schasinglulu }
279*91f16700Schasinglulu 
280*91f16700Schasinglulu /* this function returns a random number using HW RNG Algo
281*91f16700Schasinglulu  * In case of failure, random number returned is 0
282*91f16700Schasinglulu  * prngWidth = 0 - 32 bit random number
283*91f16700Schasinglulu  * prngWidth > 0 means 64 bit random number
284*91f16700Schasinglulu  */
285*91f16700Schasinglulu unsigned long long get_random(int rngWidth)
286*91f16700Schasinglulu {
287*91f16700Schasinglulu 	unsigned long long result = 0;
288*91f16700Schasinglulu 	uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE);
289*91f16700Schasinglulu 	uint8_t rand_byte_swp[8];
290*91f16700Schasinglulu 	int bytes = 0;
291*91f16700Schasinglulu 	int i = 0;
292*91f16700Schasinglulu 	int ret = 0;
293*91f16700Schasinglulu 
294*91f16700Schasinglulu #ifdef CAAM_TEST
295*91f16700Schasinglulu 	rand_byte[0] = U(0x12);
296*91f16700Schasinglulu 	rand_byte[1] = U(0x34);
297*91f16700Schasinglulu 	rand_byte[2] = U(0x56);
298*91f16700Schasinglulu 	rand_byte[3] = U(0x78);
299*91f16700Schasinglulu 	rand_byte[4] = U(0x9a);
300*91f16700Schasinglulu 	rand_byte[5] = U(0xbc);
301*91f16700Schasinglulu 	rand_byte[6] = U(0xde);
302*91f16700Schasinglulu 	rand_byte[7] = U(0xf1);
303*91f16700Schasinglulu #endif
304*91f16700Schasinglulu 
305*91f16700Schasinglulu 	if (rngWidth == 0U) {
306*91f16700Schasinglulu 		bytes = 4;
307*91f16700Schasinglulu 	} else {
308*91f16700Schasinglulu 		bytes = 8;
309*91f16700Schasinglulu 	}
310*91f16700Schasinglulu 
311*91f16700Schasinglulu 	memset(rand_byte, 0, 64);
312*91f16700Schasinglulu 
313*91f16700Schasinglulu 	ret = get_rand_bytes_hw(rand_byte, bytes);
314*91f16700Schasinglulu 
315*91f16700Schasinglulu 	for (i = 0; i < bytes; i++) {
316*91f16700Schasinglulu 		if (ret != 0) {
317*91f16700Schasinglulu 			/* Return 0 in case of failure */
318*91f16700Schasinglulu 			rand_byte_swp[i] = 0;
319*91f16700Schasinglulu 		} else {
320*91f16700Schasinglulu 			rand_byte_swp[i] = rand_byte[bytes - i - 1];
321*91f16700Schasinglulu 			result = (result << 8) | rand_byte_swp[i];
322*91f16700Schasinglulu 		}
323*91f16700Schasinglulu 	}
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	INFO("result %llx\n", result);
326*91f16700Schasinglulu 
327*91f16700Schasinglulu 	return result;
328*91f16700Schasinglulu 
329*91f16700Schasinglulu } /* _get_RNG() */
330*91f16700Schasinglulu 
331*91f16700Schasinglulu unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size)
332*91f16700Schasinglulu {
333*91f16700Schasinglulu 	int ret = 0;
334*91f16700Schasinglulu 	uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr);
335*91f16700Schasinglulu 
336*91f16700Schasinglulu 	ret = get_hw_unq_key_blob_hw(hw_key, size);
337*91f16700Schasinglulu 
338*91f16700Schasinglulu 	return ret;
339*91f16700Schasinglulu }
340