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