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