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