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 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 */ 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 */ 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 */ 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 */ 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 */ 159*a0edacb8SPankaj Gupta static inline void configure_rtic(void) 160*a0edacb8SPankaj Gupta { 161*a0edacb8SPankaj Gupta } 162*a0edacb8SPankaj Gupta 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 */ 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 */ 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 */ 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 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