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