1*54fd6939SJiyong Park /* 2*54fd6939SJiyong Park * Copyright 2021 NXP 3*54fd6939SJiyong Park * 4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause 5*54fd6939SJiyong Park * 6*54fd6939SJiyong Park */ 7*54fd6939SJiyong Park 8*54fd6939SJiyong Park #include <stdint.h> 9*54fd6939SJiyong Park #include <stdio.h> 10*54fd6939SJiyong Park #include <stdlib.h> 11*54fd6939SJiyong Park #include <string.h> 12*54fd6939SJiyong Park 13*54fd6939SJiyong Park #include <caam.h> 14*54fd6939SJiyong Park #include <common/debug.h> 15*54fd6939SJiyong Park #include <drivers/delay_timer.h> 16*54fd6939SJiyong Park #include <sfp.h> 17*54fd6939SJiyong Park #include <sfp_error_codes.h> 18*54fd6939SJiyong Park 19*54fd6939SJiyong Park static uintptr_t g_nxp_sfp_addr; 20*54fd6939SJiyong Park static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)] 21*54fd6939SJiyong Park __aligned(CACHE_WRITEBACK_GRANULE); 22*54fd6939SJiyong Park sfp_init(uintptr_t nxp_sfp_addr)23*54fd6939SJiyong Parkvoid sfp_init(uintptr_t nxp_sfp_addr) 24*54fd6939SJiyong Park { 25*54fd6939SJiyong Park g_nxp_sfp_addr = nxp_sfp_addr; 26*54fd6939SJiyong Park } 27*54fd6939SJiyong Park get_sfp_addr(void)28*54fd6939SJiyong Parkuintptr_t get_sfp_addr(void) 29*54fd6939SJiyong Park { 30*54fd6939SJiyong Park return g_nxp_sfp_addr; 31*54fd6939SJiyong Park } 32*54fd6939SJiyong Park get_sfp_srk_hash(void)33*54fd6939SJiyong Parkuint32_t *get_sfp_srk_hash(void) 34*54fd6939SJiyong Park { 35*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = 36*54fd6939SJiyong Park (void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET); 37*54fd6939SJiyong Park int i = 0; 38*54fd6939SJiyong Park 39*54fd6939SJiyong Park /* Add comparison of hash with SFP hash here */ 40*54fd6939SJiyong Park for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++) 41*54fd6939SJiyong Park srk_hash[i] = 42*54fd6939SJiyong Park mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); 43*54fd6939SJiyong Park 44*54fd6939SJiyong Park return srk_hash; 45*54fd6939SJiyong Park } 46*54fd6939SJiyong Park set_sfp_wr_disable(void)47*54fd6939SJiyong Parkvoid set_sfp_wr_disable(void) 48*54fd6939SJiyong Park { 49*54fd6939SJiyong Park /* 50*54fd6939SJiyong Park * Mark SFP Write Disable and Write Disable Lock 51*54fd6939SJiyong Park * Bit to prevent write to SFP fuses like 52*54fd6939SJiyong Park * OUID's, Key Revocation fuse etc 53*54fd6939SJiyong Park */ 54*54fd6939SJiyong Park void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET); 55*54fd6939SJiyong Park uint32_t sfpcr_val; 56*54fd6939SJiyong Park 57*54fd6939SJiyong Park sfpcr_val = sfp_read32(sfpcr); 58*54fd6939SJiyong Park sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL); 59*54fd6939SJiyong Park sfp_write32(sfpcr, sfpcr_val); 60*54fd6939SJiyong Park } 61*54fd6939SJiyong Park sfp_program_fuses(void)62*54fd6939SJiyong Parkint sfp_program_fuses(void) 63*54fd6939SJiyong Park { 64*54fd6939SJiyong Park uint32_t ingr; 65*54fd6939SJiyong Park uint32_t sfp_cmd_status = 0U; 66*54fd6939SJiyong Park int ret = 0; 67*54fd6939SJiyong Park 68*54fd6939SJiyong Park /* Program SFP fuses from mirror registers */ 69*54fd6939SJiyong Park sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET), 70*54fd6939SJiyong Park SFP_INGR_PROGFB_CMD); 71*54fd6939SJiyong Park 72*54fd6939SJiyong Park /* Wait until fuse programming is successful */ 73*54fd6939SJiyong Park do { 74*54fd6939SJiyong Park ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET); 75*54fd6939SJiyong Park } while (ingr & SFP_INGR_PROGFB_CMD); 76*54fd6939SJiyong Park 77*54fd6939SJiyong Park /* Check for SFP fuse programming error */ 78*54fd6939SJiyong Park sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET) 79*54fd6939SJiyong Park & SFP_INGR_ERROR_MASK; 80*54fd6939SJiyong Park 81*54fd6939SJiyong Park if (sfp_cmd_status != 0U) { 82*54fd6939SJiyong Park return ERROR_PROGFB_CMD; 83*54fd6939SJiyong Park } 84*54fd6939SJiyong Park 85*54fd6939SJiyong Park return ret; 86*54fd6939SJiyong Park } 87*54fd6939SJiyong Park sfp_read_oem_uid(uint8_t oem_uid)88*54fd6939SJiyong Parkuint32_t sfp_read_oem_uid(uint8_t oem_uid) 89*54fd6939SJiyong Park { 90*54fd6939SJiyong Park uint32_t val = 0U; 91*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr 92*54fd6939SJiyong Park + SFP_FUSE_REGS_OFFSET); 93*54fd6939SJiyong Park 94*54fd6939SJiyong Park if (oem_uid > MAX_OEM_UID) { 95*54fd6939SJiyong Park ERROR("Invalid OEM UID received.\n"); 96*54fd6939SJiyong Park return ERROR_OEMUID_WRITE; 97*54fd6939SJiyong Park } 98*54fd6939SJiyong Park 99*54fd6939SJiyong Park val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]); 100*54fd6939SJiyong Park 101*54fd6939SJiyong Park return val; 102*54fd6939SJiyong Park } 103*54fd6939SJiyong Park 104*54fd6939SJiyong Park /* 105*54fd6939SJiyong Park * return val: 0 - No update required. 106*54fd6939SJiyong Park * 1 - successful update done. 107*54fd6939SJiyong Park * ERROR_OEMUID_WRITE - Invalid OEM UID 108*54fd6939SJiyong Park */ sfp_write_oem_uid(uint8_t oem_uid,uint32_t sfp_val)109*54fd6939SJiyong Parkuint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val) 110*54fd6939SJiyong Park { 111*54fd6939SJiyong Park uint32_t val = 0U; 112*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr 113*54fd6939SJiyong Park + SFP_FUSE_REGS_OFFSET); 114*54fd6939SJiyong Park 115*54fd6939SJiyong Park val = sfp_read_oem_uid(oem_uid); 116*54fd6939SJiyong Park 117*54fd6939SJiyong Park if (val == ERROR_OEMUID_WRITE) { 118*54fd6939SJiyong Park return ERROR_OEMUID_WRITE; 119*54fd6939SJiyong Park } 120*54fd6939SJiyong Park 121*54fd6939SJiyong Park /* Counter already set. No need to do anything */ 122*54fd6939SJiyong Park if ((val & sfp_val) != 0U) { 123*54fd6939SJiyong Park return 0U; 124*54fd6939SJiyong Park } 125*54fd6939SJiyong Park 126*54fd6939SJiyong Park val |= sfp_val; 127*54fd6939SJiyong Park 128*54fd6939SJiyong Park INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val); 129*54fd6939SJiyong Park 130*54fd6939SJiyong Park sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val); 131*54fd6939SJiyong Park 132*54fd6939SJiyong Park return 1U; 133*54fd6939SJiyong Park } 134*54fd6939SJiyong Park sfp_check_its(void)135*54fd6939SJiyong Parkint sfp_check_its(void) 136*54fd6939SJiyong Park { 137*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr 138*54fd6939SJiyong Park + SFP_FUSE_REGS_OFFSET); 139*54fd6939SJiyong Park 140*54fd6939SJiyong Park if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) { 141*54fd6939SJiyong Park return 1; 142*54fd6939SJiyong Park } else { 143*54fd6939SJiyong Park return 0; 144*54fd6939SJiyong Park } 145*54fd6939SJiyong Park } 146*54fd6939SJiyong Park sfp_check_oem_wp(void)147*54fd6939SJiyong Parkint sfp_check_oem_wp(void) 148*54fd6939SJiyong Park { 149*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr 150*54fd6939SJiyong Park + SFP_FUSE_REGS_OFFSET); 151*54fd6939SJiyong Park 152*54fd6939SJiyong Park if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) { 153*54fd6939SJiyong Park return 1; 154*54fd6939SJiyong Park } else { 155*54fd6939SJiyong Park return 0; 156*54fd6939SJiyong Park } 157*54fd6939SJiyong Park } 158*54fd6939SJiyong Park 159*54fd6939SJiyong Park /* This function returns ospr's key_revoc values.*/ get_key_revoc(void)160*54fd6939SJiyong Parkuint32_t get_key_revoc(void) 161*54fd6939SJiyong Park { 162*54fd6939SJiyong Park struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr 163*54fd6939SJiyong Park + SFP_FUSE_REGS_OFFSET); 164*54fd6939SJiyong Park 165*54fd6939SJiyong Park return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >> 166*54fd6939SJiyong Park OSPR_KEY_REVOC_SHIFT; 167*54fd6939SJiyong Park } 168