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