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