xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/nxp/sfp/sfp.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
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 Park void 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 Park uintptr_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 Park uint32_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 Park void 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 Park int 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 Park uint32_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 Park uint32_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 Park int 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 Park int 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 Park uint32_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