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