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