• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016-2020, Broadcom
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <string.h>
8 
9 #include <common/debug.h>
10 #include <lib/mmio.h>
11 #include <sotp.h>
12 
13 #include <platform_def.h>
14 #include <platform_sotp.h>
15 
16 #ifdef USE_SOFT_SOTP
17 extern uint64_t soft_sotp[];
18 #endif
19 
20 #define SOTP_PROG_CONTROL (SOTP_REGS_OTP_BASE + 0x0000)
21 #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN 15
22 #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC 9
23 #define SOTP_PROG_CONTROL__OTP_ECC_WREN 8
24 
25 #define SOTP_WRDATA_0 (SOTP_REGS_OTP_BASE + 0x0004)
26 #define SOTP_WRDATA_1 (SOTP_REGS_OTP_BASE + 0x0008)
27 
28 #define SOTP_ADDR (SOTP_REGS_OTP_BASE + 0x000c)
29 #define SOTP_ADDR__OTP_ROW_ADDR_R 6
30 #define SOTP_ADDR_MASK 0x3FF
31 
32 #define SOTP_CTRL_0 (SOTP_REGS_OTP_BASE + 0x0010)
33 #define SOTP_CTRL_0__START 0
34 #define SOTP_CTRL_0__OTP_CMD 1
35 
36 #define SOTP_STATUS_0 (SOTP_REGS_OTP_BASE + 0x0018)
37 #define SOTP_STATUS__FDONE 3
38 
39 #define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c)
40 #define SOTP_STATUS_1__CMD_DONE 1
41 #define SOTP_STATUS_1__ECC_DET 17
42 
43 #define SOTP_RDDATA_0 (SOTP_REGS_OTP_BASE + 0x0020)
44 #define SOTP_RDDATA_1 (SOTP_REGS_OTP_BASE + 0x0024)
45 
46 #define SOTP_READ 0
47 
48 #define SOTP_PROG_WORD 10
49 #define SOTP_STATUS__PROGOK 2
50 #define SOTP_PROG_ENABLE 2
51 
52 #define SOTP_ROW_DATA_MASK 0xffffffff
53 #define SOTP_ECC_ERR_BITS_MASK 0x1ff00000000
54 
55 #define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4
56 #define SOTP_CHIP_CTRL_SW_MANU_PROG 5
57 #define SOTP_CHIP_CTRL_SW_CID_PROG 6
58 #define SOTP_CHIP_CTRL_SW_AB_DEVICE 8
59 #define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9
60 #define CHIP_STATE_UNPROGRAMMED 0x1
61 #define CHIP_STATE_UNASSIGNED 0x2
62 
sotp_mem_read(uint32_t offset,uint32_t sotp_add_ecc)63 uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc)
64 {
65 #ifdef USE_SOFT_SOTP
66 	(void)sotp_add_ecc;
67 
68 	return soft_sotp[offset];
69 #else
70 	uint64_t read_data = 0;
71 	uint64_t read_data1 = 0;
72 	uint64_t read_data2 = 0;
73 
74 	/* Check for FDONE status */
75 	while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
76 	       BIT(SOTP_STATUS__FDONE))
77 		;
78 
79 	/* Enable OTP access by CPU */
80 	mmio_setbits_32(SOTP_PROG_CONTROL,
81 			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
82 
83 	if (sotp_add_ecc == 1) {
84 		mmio_clrbits_32(SOTP_PROG_CONTROL,
85 				BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
86 	}
87 
88 	if (sotp_add_ecc == 0) {
89 		mmio_setbits_32(SOTP_PROG_CONTROL,
90 				BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC));
91 	}
92 
93 	mmio_write_32(SOTP_ADDR,
94 		      ((offset & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
95 	mmio_write_32(SOTP_CTRL_0, (SOTP_READ << SOTP_CTRL_0__OTP_CMD));
96 
97 	/* Start bit to tell SOTP to send command to the OTP controller */
98 	mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
99 
100 	/* Wait for SOTP command done to be set */
101 	while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
102 	      BIT(SOTP_STATUS_1__CMD_DONE))
103 		;
104 
105 	/* Clr Start bit after command done */
106 	mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
107 
108 	if ((offset > SOTP_DEVICE_SECURE_CFG3_ROW) &&
109 	    (mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__ECC_DET))) {
110 		ERROR("SOTP ECC ERROR Detected row offset %d\n", offset);
111 		read_data = SOTP_ECC_ERR_DETECT;
112 	} else {
113 		read_data1 = (uint64_t)mmio_read_32(SOTP_RDDATA_0);
114 		read_data1 = read_data1 & 0xFFFFFFFF;
115 		read_data2 = (uint64_t)mmio_read_32(SOTP_RDDATA_1);
116 		read_data2 = (read_data2 & 0x1ff) << 32;
117 		read_data = read_data1 | read_data2;
118 	}
119 
120 	/* Command done is cleared */
121 	mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
122 
123 	/* disable OTP access by CPU */
124 	mmio_clrbits_32(SOTP_PROG_CONTROL,
125 			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
126 
127 	return read_data;
128 #endif
129 }
130 
sotp_mem_write(uint32_t addr,uint32_t sotp_add_ecc,uint64_t wdata)131 void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata)
132 {
133 #ifdef USE_SOFT_SOTP
134 	(void)sotp_add_ecc;
135 
136 	soft_sotp[addr] = wdata;
137 #else
138 	uint32_t loop;
139 	uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D };
140 
141 	uint32_t chip_state_default =
142 		(CHIP_STATE_UNASSIGNED|CHIP_STATE_UNPROGRAMMED);
143 	uint32_t chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES);
144 	uint32_t chip_ctrl_default = 0;
145 
146 	/*
147 	 * The override settings is required to allow the customer to program
148 	 * the application specific keys into SOTP, before the conversion to
149 	 * one of the AB modes.
150 	 * At the end of write operation, the chip ctrl settings will restored
151 	 * to the state prior to write call
152 	 */
153 	if (chip_state & chip_state_default) {
154 		uint32_t chip_ctrl;
155 
156 		chip_ctrl_default = mmio_read_32(SOTP_CHIP_CTRL);
157 		INFO("SOTP: enable special prog mode\n");
158 
159 		chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) |
160 			    BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) |
161 			    BIT(SOTP_CHIP_CTRL_SW_CID_PROG) |
162 			    BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE);
163 		mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl);
164 	}
165 
166 	/*  Check for FDONE status */
167 	while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) !=
168 	       BIT(SOTP_STATUS__FDONE))
169 		;
170 
171 	/*  Enable OTP acces by CPU */
172 	mmio_setbits_32(SOTP_PROG_CONTROL,
173 			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
174 
175 	if (addr > SOTP_DEVICE_SECURE_CFG3_ROW) {
176 		if (sotp_add_ecc == 0) {
177 			mmio_clrbits_32(SOTP_PROG_CONTROL,
178 					BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
179 		}
180 		if (sotp_add_ecc == 1) {
181 			mmio_setbits_32(SOTP_PROG_CONTROL,
182 					BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
183 		}
184 	} else {
185 		mmio_clrbits_32(SOTP_PROG_CONTROL,
186 				BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN));
187 	}
188 
189 	mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_ENABLE << 1));
190 
191 	/*
192 	 * In order to avoid unintentional writes / programming of the OTP
193 	 * array, the OTP Controller must be put into programming mode before
194 	 * it will accept program commands. This is done by writing 0xF, 0x4,
195 	 * 0x8, 0xD with program commands prior to starting the actual
196 	 * programming sequence
197 	 */
198 	for (loop = 0; loop < 4; loop++) {
199 		mmio_write_32(SOTP_WRDATA_0, prog_array[loop]);
200 
201 		/*
202 		 * Start bit to tell SOTP to send command to the OTP controller
203 		 */
204 		mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
205 
206 		/*  Wait for SOTP command done to <-- be set */
207 		while ((mmio_read_32(SOTP_STATUS_1) &
208 			BIT(SOTP_STATUS_1__CMD_DONE)) !=
209 		       BIT(SOTP_STATUS_1__CMD_DONE))
210 			;
211 
212 		/* Command done is cleared w1c */
213 		mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
214 
215 		/* Clr Start bit after command done */
216 		mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
217 	}
218 
219 	/*  Check for PROGOK */
220 	while ((mmio_read_32(SOTP_STATUS_0) & 0x4) != BIT(SOTP_STATUS__PROGOK))
221 		;
222 
223 	/* Set  10 bit row address */
224 	mmio_write_32(SOTP_ADDR,
225 		      ((addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R));
226 
227 	/* Set SOTP Row data */
228 	mmio_write_32(SOTP_WRDATA_0, (wdata & SOTP_ROW_DATA_MASK));
229 
230 	/* Set SOTP ECC and error bits */
231 	mmio_write_32(SOTP_WRDATA_1, ((wdata & SOTP_ECC_ERR_BITS_MASK) >> 32));
232 
233 	/* Set prog_word command */
234 	mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_WORD << 1));
235 
236 	/*  Start bit to tell SOTP to send command to the OTP controller */
237 	mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
238 
239 	/*  Wait for SOTP command done to be set */
240 	while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) !=
241 	       BIT(SOTP_STATUS_1__CMD_DONE))
242 		;
243 
244 	/* Command done is cleared w1c */
245 	mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE));
246 
247 	/* disable OTP acces by CPU */
248 	mmio_clrbits_32(SOTP_PROG_CONTROL,
249 			BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN));
250 
251 	/* Clr Start bit after command done */
252 	mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START));
253 
254 	if (chip_state & chip_state_default)
255 		mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl_default);
256 
257 #endif
258 }
259 
sotp_read_key(uint8_t * key,size_t keysize,int start_row,int end_row)260 int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row)
261 {
262 	int row;
263 	uint32_t status = 0;
264 	uint32_t status2 = 0xFFFFFFFF;
265 	uint64_t row_data;
266 	uint32_t data;
267 	uint32_t *temp_key = (uint32_t *)key;
268 
269 	row = start_row;
270 	while ((keysize > 0) && (row <= end_row)) {
271 		row_data = sotp_mem_read(row, SOTP_ROW_ECC);
272 		if (!(row_data & (SOTP_ECC_ERR_DETECT | SOTP_FAIL_BITS))) {
273 			memcpy(temp_key++, &row_data, sizeof(uint32_t));
274 			keysize -= sizeof(uint32_t);
275 			data = (uint32_t)(row_data & SOTP_ROW_DATA_MASK);
276 			status |= data;
277 			status2 &= data;
278 		}
279 		row++;
280 	}
281 
282 	if ((status2 == 0xFFFFFFFF) || (status == 0) || (row > end_row))
283 		return -1;
284 
285 	return 0;
286 }
287 
sotp_key_erased(void)288 int sotp_key_erased(void)
289 {
290 	uint64_t row_data;
291 	int status = 0;
292 
293 	row_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0);
294 	if (row_data & SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK)
295 		status = 1;
296 
297 	else if (mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES) &
298 			SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK)
299 		status = 1;
300 
301 	return status;
302 }
303 
304 /*
305  * This function optimise the SOTP redundancy
306  * by considering the 00- zero and 01,10,11 - one
307  */
sotp_redundancy_reduction(uint32_t sotp_row_data)308 uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data)
309 {
310 	uint32_t opt_data;
311 	uint32_t opt_loop;
312 	uint32_t temp_data;
313 
314 	opt_data = 0;
315 
316 	for (opt_loop = 0; opt_loop < 16; opt_loop = opt_loop + 1) {
317 		temp_data = ((sotp_row_data >> (opt_loop * 2)) & 0x3);
318 
319 		if (temp_data != 0x0)
320 			opt_data = (opt_data | (1 << opt_loop));
321 	}
322 	return opt_data;
323 }
324