xref: /openbmc/u-boot/cmd/otp.c (revision a8bd6d8c21ba71250afa946b7ee65653653c2948)
169d5fd8fSJohnny Huang /*
269d5fd8fSJohnny Huang  *  This program is distributed in the hope that it will be useful,
369d5fd8fSJohnny Huang  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
469d5fd8fSJohnny Huang  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
569d5fd8fSJohnny Huang  *  GNU General Public License for more details.
669d5fd8fSJohnny Huang  *
769d5fd8fSJohnny Huang  *  You should have received a copy of the GNU General Public License
869d5fd8fSJohnny Huang  *  along with this program; if not, write to the Free Software
969d5fd8fSJohnny Huang  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1069d5fd8fSJohnny Huang  */
114c1c9b35SJohnny Huang #include <stdlib.h>
1269d5fd8fSJohnny Huang #include <common.h>
1369d5fd8fSJohnny Huang #include <console.h>
1469d5fd8fSJohnny Huang #include <bootretry.h>
1569d5fd8fSJohnny Huang #include <cli.h>
1669d5fd8fSJohnny Huang #include <command.h>
1769d5fd8fSJohnny Huang #include <console.h>
184c1c9b35SJohnny Huang #include <malloc.h>
1969d5fd8fSJohnny Huang #include <inttypes.h>
2069d5fd8fSJohnny Huang #include <mapmem.h>
2169d5fd8fSJohnny Huang #include <asm/io.h>
2269d5fd8fSJohnny Huang #include <linux/compiler.h>
2369d5fd8fSJohnny Huang 
2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2569d5fd8fSJohnny Huang 
2669d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
2769d5fd8fSJohnny Huang #define RETRY				3
28a6d0d645SJohnny Huang #define OTP_REGION_STRAP		1
29a6d0d645SJohnny Huang #define OTP_REGION_CONF			2
30a6d0d645SJohnny Huang #define OTP_REGION_DATA			3
31a6d0d645SJohnny Huang #define OTP_REGION_ALL			4
3269d5fd8fSJohnny Huang 
332a856b9aSJohnny Huang #define OTP_USAGE			-1
342a856b9aSJohnny Huang #define OTP_FAILURE			-2
352a856b9aSJohnny Huang #define OTP_SUCCESS			0
362a856b9aSJohnny Huang 
37a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
38a6af4a17SJohnny Huang 
3966f2f8e5SJohnny Huang #define DISABLE_SECREG_PROG(x)		(x & 0x1)
4066f2f8e5SJohnny Huang #define ENABLE_SEC_BOOT(x)		((x >> 1) & 0x1)
4166f2f8e5SJohnny Huang #define INIT_PROG_DONE(x)		((x >> 2) & 0x1)
4266f2f8e5SJohnny Huang #define ENABLE_USERREG_ECC(x)		((x >> 3) & 0x1)
4366f2f8e5SJohnny Huang #define ENABLE_SECREG_ECC(x)		((x >> 4) & 0x1)
4466f2f8e5SJohnny Huang #define DISABLE_LOW_SEC_KEY(x)		((x >> 5) & 0x1)
4566f2f8e5SJohnny Huang #define IGNORE_SEC_BOOT_HWSTRAP(x)	((x >> 6) & 0x1)
4666f2f8e5SJohnny Huang #define SEC_BOOT_MDOES(x)		((x >> 7) & 0x1)
47e1f9e54eSJohnny Huang #define   SEC_MODE1			0x0
48e1f9e54eSJohnny Huang #define   SEC_MODE2			0x1
49e1f9e54eSJohnny Huang #define OTP_BIT_CELL_MODES(x)		((x >> 8) & 0x3)
50e1f9e54eSJohnny Huang #define   SINGLE_CELL_MODE		0x0
51e1f9e54eSJohnny Huang #define   DIFFERENTIAL_MODE		0x1
52e1f9e54eSJohnny Huang #define   DIFFERENTIAL_REDUDANT_MODE	0x2
53e1f9e54eSJohnny Huang #define CRYPTO_MODES(x)			((x >> 10) & 0x3)
54e1f9e54eSJohnny Huang #define   CRYPTO_RSA1024		0x0
55e1f9e54eSJohnny Huang #define   CRYPTO_RSA2048		0x1
56e1f9e54eSJohnny Huang #define   CRYPTO_RSA3072		0x2
57e1f9e54eSJohnny Huang #define   CRYPTO_RSA4096		0x3
58e1f9e54eSJohnny Huang #define HASH_MODES(x)			((x >> 12) & 0x3)
59e1f9e54eSJohnny Huang #define   HASH_SAH224			0x0
60e1f9e54eSJohnny Huang #define   HASH_SAH256			0x1
61e1f9e54eSJohnny Huang #define   HASH_SAH384			0x2
62e1f9e54eSJohnny Huang #define   HASH_SAH512			0x3
63e1f9e54eSJohnny Huang #define SECREG_SIZE(x)			((x >> 16) & 0x3f)
6466f2f8e5SJohnny Huang #define WRITE_PROTECT_SECREG(x)		((x >> 22) & 0x1)
6566f2f8e5SJohnny Huang #define WRITE_PROTECT_USERREG(x)	((x >> 23) & 0x1)
6666f2f8e5SJohnny Huang #define WRITE_PROTECT_CONFREG(x)	((x >> 24) & 0x1)
6766f2f8e5SJohnny Huang #define WRITE_PROTECT_STRAPREG(x)	((x >> 25) & 0x1)
6866f2f8e5SJohnny Huang #define ENABLE_COPY_TO_SRAM(x)		((x >> 26) & 0x1)
6966f2f8e5SJohnny Huang #define ENABLE_IMAGE_ENC(x)		((x >> 27) & 0x1)
7066f2f8e5SJohnny Huang #define WRITE_PROTECT_KEY_RETIRE(x)	((x >> 29) & 0x1)
7166f2f8e5SJohnny Huang #define ENABLE_SIPROM_RED(x)		((x >> 30) & 0x1)
7266f2f8e5SJohnny Huang #define ENABLE_SIPROM_MLOCK(x)		((x >> 31) & 0x1)
73e1f9e54eSJohnny Huang 
74e1f9e54eSJohnny Huang #define VENDER_ID(x) 			(x & 0xFFFF)
75e1f9e54eSJohnny Huang #define KEY_REVISION(x)			((x >> 16) & 0xFFFF)
76e1f9e54eSJohnny Huang 
77e1f9e54eSJohnny Huang #define SEC_BOOT_HEADER_OFFSET(x)	(x & 0xFFFF)
78e1f9e54eSJohnny Huang 
79e1f9e54eSJohnny Huang #define KEYS_VALID_BITS(x)		(x & 0xff)
80e1f9e54eSJohnny Huang #define KEYS_RETIRE_BITS(x)		((x >> 16) & 0xff)
814c1c9b35SJohnny Huang 
82*a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
8376d13988SJohnny Huang 
844c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
854c1c9b35SJohnny Huang #define PBWIDTH 60
864c1c9b35SJohnny Huang 
8766f2f8e5SJohnny Huang struct otpstrap_status {
8869d5fd8fSJohnny Huang 	int value;
8969d5fd8fSJohnny Huang 	int option_array[7];
9069d5fd8fSJohnny Huang 	int remain_times;
9169d5fd8fSJohnny Huang 	int writeable_option;
9269d5fd8fSJohnny Huang 	int protected;
9369d5fd8fSJohnny Huang };
9469d5fd8fSJohnny Huang 
9566f2f8e5SJohnny Huang struct otpconf_parse {
9666f2f8e5SJohnny Huang 	int dw_offset;
9766f2f8e5SJohnny Huang 	int bit;
9866f2f8e5SJohnny Huang 	int length;
9966f2f8e5SJohnny Huang 	int value;
10066f2f8e5SJohnny Huang 	int keep;
10166f2f8e5SJohnny Huang 	char status[80];
10266f2f8e5SJohnny Huang };
10366f2f8e5SJohnny Huang 
104*a8bd6d8cSJohnny Huang struct otpstrap_info {
105*a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
106*a8bd6d8cSJohnny Huang 	uint32_t length;
10776d13988SJohnny Huang 	int value;
108*a8bd6d8cSJohnny Huang 	char information[80];
109*a8bd6d8cSJohnny Huang };
110*a8bd6d8cSJohnny Huang 
111*a8bd6d8cSJohnny Huang struct otpconf_info {
112*a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
113*a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
114*a8bd6d8cSJohnny Huang 	uint32_t length;
115*a8bd6d8cSJohnny Huang 	int value;
116*a8bd6d8cSJohnny Huang 	char information[80];
117*a8bd6d8cSJohnny Huang };
118*a8bd6d8cSJohnny Huang 
119*a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...)
120*a8bd6d8cSJohnny Huang {
121*a8bd6d8cSJohnny Huang 	int val = numerator * 100 / denominator;
122*a8bd6d8cSJohnny Huang 	int lpad = numerator * PBWIDTH / denominator;
123*a8bd6d8cSJohnny Huang 	int rpad = PBWIDTH - lpad;
124*a8bd6d8cSJohnny Huang 	char buffer[256];
125*a8bd6d8cSJohnny Huang 	va_list aptr;
126*a8bd6d8cSJohnny Huang 
127*a8bd6d8cSJohnny Huang 	va_start(aptr, format);
128*a8bd6d8cSJohnny Huang 	vsprintf(buffer, format, aptr);
129*a8bd6d8cSJohnny Huang 	va_end(aptr);
130*a8bd6d8cSJohnny Huang 
131*a8bd6d8cSJohnny Huang 	printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer);
132*a8bd6d8cSJohnny Huang 	if (numerator == denominator)
133*a8bd6d8cSJohnny Huang 		printf("\n");
134*a8bd6d8cSJohnny Huang }
135*a8bd6d8cSJohnny Huang 
136*a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = {
137*a8bd6d8cSJohnny Huang 	{
138*a8bd6d8cSJohnny Huang 		0, 1, 0, "Disable secure boot"
139*a8bd6d8cSJohnny Huang 	}, {
140*a8bd6d8cSJohnny Huang 		0, 1, 1, "Enable secure boot"
141*a8bd6d8cSJohnny Huang 	}, {
142*a8bd6d8cSJohnny Huang 		1, 1, 0, "Disable boot from eMMC"
143*a8bd6d8cSJohnny Huang 	}, {
144*a8bd6d8cSJohnny Huang 		1, 1, 1, "Enable boot from eMMC"
145*a8bd6d8cSJohnny Huang 	}, {
146*a8bd6d8cSJohnny Huang 		2, 1, 0, "Disable Boot from debug SPI"
147*a8bd6d8cSJohnny Huang 	}, {
148*a8bd6d8cSJohnny Huang 		2, 1, 1, "Enable Boot from debug SPI"
149*a8bd6d8cSJohnny Huang 	}, {
150*a8bd6d8cSJohnny Huang 		3, 1, 0, "Enable ARM CM3"
151*a8bd6d8cSJohnny Huang 	}, {
152*a8bd6d8cSJohnny Huang 		3, 1, 1, "Disable ARM CM3"
153*a8bd6d8cSJohnny Huang 	}, {
154*a8bd6d8cSJohnny Huang 		4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS"
155*a8bd6d8cSJohnny Huang 	}, {
156*a8bd6d8cSJohnny Huang 		4, 1, 1, "Enable dedicated VGA BIOS ROM"
157*a8bd6d8cSJohnny Huang 	}, {
158*a8bd6d8cSJohnny Huang 		5, 1, 0, "MAC 1 : RMII/NCSI"
159*a8bd6d8cSJohnny Huang 	}, {
160*a8bd6d8cSJohnny Huang 		5, 1, 1, "MAC 1 : RGMII"
161*a8bd6d8cSJohnny Huang 	}, {
162*a8bd6d8cSJohnny Huang 		6, 1, 0, "MAC 2 : RMII/NCSI"
163*a8bd6d8cSJohnny Huang 	}, {
164*a8bd6d8cSJohnny Huang 		6, 1, 1, "MAC 2 : RGMII"
165*a8bd6d8cSJohnny Huang 	}, {
166*a8bd6d8cSJohnny Huang 		7, 3, 0, "CPU Frequency : 1GHz"
167*a8bd6d8cSJohnny Huang 	}, {
168*a8bd6d8cSJohnny Huang 		7, 3, 1, "CPU Frequency : 800MHz"
169*a8bd6d8cSJohnny Huang 	}, {
170*a8bd6d8cSJohnny Huang 		7, 3, 2, "CPU Frequency : 1.2GHz"
171*a8bd6d8cSJohnny Huang 	}, {
172*a8bd6d8cSJohnny Huang 		7, 3, 3, "CPU Frequency : 1.4GHz"
173*a8bd6d8cSJohnny Huang 	}, {
174*a8bd6d8cSJohnny Huang 		10, 2, 0, "HCLK ratio AXI:AHB = 2:1"
175*a8bd6d8cSJohnny Huang 	}, {
176*a8bd6d8cSJohnny Huang 		10, 2, 1, "HCLK ratio AXI:AHB = 2:1"
177*a8bd6d8cSJohnny Huang 	}, {
178*a8bd6d8cSJohnny Huang 		10, 2, 2, "HCLK ratio AXI:AHB = 3:1"
179*a8bd6d8cSJohnny Huang 	}, {
180*a8bd6d8cSJohnny Huang 		10, 2, 3, "HCLK ratio AXI:AHB = 4:1"
181*a8bd6d8cSJohnny Huang 	}, {
182*a8bd6d8cSJohnny Huang 		12, 2, 0, "VGA memory size : 8MB"
183*a8bd6d8cSJohnny Huang 	}, {
184*a8bd6d8cSJohnny Huang 		12, 2, 1, "VGA memory size : 16MB"
185*a8bd6d8cSJohnny Huang 	}, {
186*a8bd6d8cSJohnny Huang 		12, 2, 2, "VGA memory size : 32MB"
187*a8bd6d8cSJohnny Huang 	}, {
188*a8bd6d8cSJohnny Huang 		12, 2, 3, "VGA memory size : 64MB"
189*a8bd6d8cSJohnny Huang 	}, {
190*a8bd6d8cSJohnny Huang 		14, 3, OTP_REG_RESERVED, ""
191*a8bd6d8cSJohnny Huang 	}, {
192*a8bd6d8cSJohnny Huang 		17, 1, 0, "VGA class code : Class Code for video device"
193*a8bd6d8cSJohnny Huang 	}, {
194*a8bd6d8cSJohnny Huang 		17, 1, 1, "VGA class code : Class Code for VGA device"
195*a8bd6d8cSJohnny Huang 	}, {
196*a8bd6d8cSJohnny Huang 		18, 1, 0, "Enable debug interfaces 0"
197*a8bd6d8cSJohnny Huang 	}, {
198*a8bd6d8cSJohnny Huang 		18, 1, 1, "Disable debug interfaces 0"
199*a8bd6d8cSJohnny Huang 	}, {
200*a8bd6d8cSJohnny Huang 		19, 1, 0, "Boot from emmc mode : High eMMC speed"
201*a8bd6d8cSJohnny Huang 	}, {
202*a8bd6d8cSJohnny Huang 		19, 1, 1, "Boot from emmc mode : Normal eMMC speed"
203*a8bd6d8cSJohnny Huang 	}, {
204*a8bd6d8cSJohnny Huang 		20, 1, 0, "Enable Pcie EHCI device"
205*a8bd6d8cSJohnny Huang 	}, {
206*a8bd6d8cSJohnny Huang 		20, 1, 1, "Disable Pcie EHCI device"
207*a8bd6d8cSJohnny Huang 	}, {
208*a8bd6d8cSJohnny Huang 		21, 1, 0, "Enable VGA XDMA function"
209*a8bd6d8cSJohnny Huang 	}, {
210*a8bd6d8cSJohnny Huang 		21, 1, 1, "Disable VGA XDMA function"
211*a8bd6d8cSJohnny Huang 	}, {
212*a8bd6d8cSJohnny Huang 		22, 1, 0, "Normal BMC mode"
213*a8bd6d8cSJohnny Huang 	}, {
214*a8bd6d8cSJohnny Huang 		22, 1, 1, "Disable dedicated BMC functions for non-BMC application"
215*a8bd6d8cSJohnny Huang 	}, {
216*a8bd6d8cSJohnny Huang 		23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin"
217*a8bd6d8cSJohnny Huang 	}, {
218*a8bd6d8cSJohnny Huang 		23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin"
219*a8bd6d8cSJohnny Huang 	}, {
220*a8bd6d8cSJohnny Huang 		24, 1, 0, "DRAM types : DDR3"
221*a8bd6d8cSJohnny Huang 	}, {
222*a8bd6d8cSJohnny Huang 		24, 1, 1, "DRAM types : DDR4"
223*a8bd6d8cSJohnny Huang 	}, {
224*a8bd6d8cSJohnny Huang 		25, 5, OTP_REG_RESERVED, ""
225*a8bd6d8cSJohnny Huang 	}, {
226*a8bd6d8cSJohnny Huang 		30, 2, OTP_REG_RESERVED, ""
227*a8bd6d8cSJohnny Huang 	}, {
228*a8bd6d8cSJohnny Huang 		32, 1, 0, "MAC 3 : RMII/NCSI"
229*a8bd6d8cSJohnny Huang 	}, {
230*a8bd6d8cSJohnny Huang 		32, 1, 1, "MAC 3 : RGMII"
231*a8bd6d8cSJohnny Huang 	}, {
232*a8bd6d8cSJohnny Huang 		33, 1, 0, "MAC 4 : RMII/NCSI"
233*a8bd6d8cSJohnny Huang 	}, {
234*a8bd6d8cSJohnny Huang 		33, 1, 1, "MAC 4 : RGMII"
235*a8bd6d8cSJohnny Huang 	}, {
236*a8bd6d8cSJohnny Huang 		34, 1, 0, "SuperIO configuration address : 0x2E"
237*a8bd6d8cSJohnny Huang 	}, {
238*a8bd6d8cSJohnny Huang 		34, 1, 1, "SuperIO configuration address : 0x4E"
239*a8bd6d8cSJohnny Huang 	}, {
240*a8bd6d8cSJohnny Huang 		35, 1, 0, "Enable LPC to decode SuperIO"
241*a8bd6d8cSJohnny Huang 	}, {
242*a8bd6d8cSJohnny Huang 		35, 1, 1, "Disable LPC to decode SuperIO"
243*a8bd6d8cSJohnny Huang 	}, {
244*a8bd6d8cSJohnny Huang 		36, 1, 0, "Enable debug interfaces 1"
245*a8bd6d8cSJohnny Huang 	}, {
246*a8bd6d8cSJohnny Huang 		36, 1, 1, "Disable debug interfaces 1"
247*a8bd6d8cSJohnny Huang 	}, {
248*a8bd6d8cSJohnny Huang 		37, 1, 0, "Disable ACPI function"
249*a8bd6d8cSJohnny Huang 	}, {
250*a8bd6d8cSJohnny Huang 		37, 1, 1, "Enable ACPI function"
251*a8bd6d8cSJohnny Huang 	}, {
252*a8bd6d8cSJohnny Huang 		38, 1, 0, "Enable eSPI mode"
253*a8bd6d8cSJohnny Huang 	}, {
254*a8bd6d8cSJohnny Huang 		38, 1, 1, "Enable LPC mode"
255*a8bd6d8cSJohnny Huang 	}, {
256*a8bd6d8cSJohnny Huang 		39, 1, 0, "Enable SAFS mode"
257*a8bd6d8cSJohnny Huang 	}, {
258*a8bd6d8cSJohnny Huang 		39, 1, 1, "Enable SAFS mode"
259*a8bd6d8cSJohnny Huang 	}, {
260*a8bd6d8cSJohnny Huang 		40, 2, OTP_REG_RESERVED, ""
261*a8bd6d8cSJohnny Huang 	}, {
262*a8bd6d8cSJohnny Huang 		42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection"
263*a8bd6d8cSJohnny Huang 	}, {
264*a8bd6d8cSJohnny Huang 		42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection"
265*a8bd6d8cSJohnny Huang 	}, {
266*a8bd6d8cSJohnny Huang 		43, 1, 0, "Disable boot SPI ABR"
267*a8bd6d8cSJohnny Huang 	}, {
268*a8bd6d8cSJohnny Huang 		43, 1, 1, "Enable boot SPI ABR"
269*a8bd6d8cSJohnny Huang 	}, {
270*a8bd6d8cSJohnny Huang 		44, 1, 0, "Boot SPI ABR mode : dual SPI flash"
271*a8bd6d8cSJohnny Huang 	}, {
272*a8bd6d8cSJohnny Huang 		44, 1, 1, "Boot SPI ABR mode : single SPI flash"
273*a8bd6d8cSJohnny Huang 	}, {
274*a8bd6d8cSJohnny Huang 		45, 3, 0, "Boot SPI flash size : no define size"
275*a8bd6d8cSJohnny Huang 	}, {
276*a8bd6d8cSJohnny Huang 		45, 3, 1, "Boot SPI flash size : 2MB"
277*a8bd6d8cSJohnny Huang 	}, {
278*a8bd6d8cSJohnny Huang 		45, 3, 2, "Boot SPI flash size : 4MB"
279*a8bd6d8cSJohnny Huang 	}, {
280*a8bd6d8cSJohnny Huang 		45, 3, 3, "Boot SPI flash size : 8MB"
281*a8bd6d8cSJohnny Huang 	}, {
282*a8bd6d8cSJohnny Huang 		45, 3, 4, "Boot SPI flash size : 16MB"
283*a8bd6d8cSJohnny Huang 	}, {
284*a8bd6d8cSJohnny Huang 		45, 3, 5, "Boot SPI flash size : 32MB"
285*a8bd6d8cSJohnny Huang 	}, {
286*a8bd6d8cSJohnny Huang 		45, 3, 6, "Boot SPI flash size : 64MB"
287*a8bd6d8cSJohnny Huang 	}, {
288*a8bd6d8cSJohnny Huang 		45, 3, 7, "Boot SPI flash size : 128MB"
289*a8bd6d8cSJohnny Huang 	}, {
290*a8bd6d8cSJohnny Huang 		48, 1, 0, "Disable host SPI ABR"
291*a8bd6d8cSJohnny Huang 	}, {
292*a8bd6d8cSJohnny Huang 		48, 1, 1, "Enable host SPI ABR"
293*a8bd6d8cSJohnny Huang 	}, {
294*a8bd6d8cSJohnny Huang 		49, 1, 0, "Disable host SPI ABR mode select pin"
295*a8bd6d8cSJohnny Huang 	}, {
296*a8bd6d8cSJohnny Huang 		49, 1, 1, "Enable host SPI ABR mode select pin"
297*a8bd6d8cSJohnny Huang 	}, {
298*a8bd6d8cSJohnny Huang 		50, 1, 0, "Host SPI ABR mode : dual SPI flash"
299*a8bd6d8cSJohnny Huang 	}, {
300*a8bd6d8cSJohnny Huang 		50, 1, 1, "Host SPI ABR mode : single SPI flash"
301*a8bd6d8cSJohnny Huang 	}, {
302*a8bd6d8cSJohnny Huang 		51, 3, 0, "Host SPI flash size : no define size"
303*a8bd6d8cSJohnny Huang 	}, {
304*a8bd6d8cSJohnny Huang 		51, 3, 1, "Host SPI flash size : 2MB"
305*a8bd6d8cSJohnny Huang 	}, {
306*a8bd6d8cSJohnny Huang 		51, 3, 2, "Host SPI flash size : 4MB"
307*a8bd6d8cSJohnny Huang 	}, {
308*a8bd6d8cSJohnny Huang 		51, 3, 3, "Host SPI flash size : 8MB"
309*a8bd6d8cSJohnny Huang 	}, {
310*a8bd6d8cSJohnny Huang 		51, 3, 4, "Host SPI flash size : 16MB"
311*a8bd6d8cSJohnny Huang 	}, {
312*a8bd6d8cSJohnny Huang 		51, 3, 5, "Host SPI flash size : 32MB"
313*a8bd6d8cSJohnny Huang 	}, {
314*a8bd6d8cSJohnny Huang 		51, 3, 6, "Host SPI flash size : 64MB"
315*a8bd6d8cSJohnny Huang 	}, {
316*a8bd6d8cSJohnny Huang 		51, 3, 7, "Host SPI flash size : 128MB"
317*a8bd6d8cSJohnny Huang 	}, {
318*a8bd6d8cSJohnny Huang 		54, 1, 0, "Disable boot SPI auxiliary control pins"
319*a8bd6d8cSJohnny Huang 	}, {
320*a8bd6d8cSJohnny Huang 		54, 1, 1, "Enable boot SPI auxiliary control pins"
321*a8bd6d8cSJohnny Huang 	}, {
322*a8bd6d8cSJohnny Huang 		55, 2, 0, "Boot SPI CRTM size : disable CRTM"
323*a8bd6d8cSJohnny Huang 	}, {
324*a8bd6d8cSJohnny Huang 		55, 2, 1, "Boot SPI CRTM size : 256KB"
325*a8bd6d8cSJohnny Huang 	}, {
326*a8bd6d8cSJohnny Huang 		55, 2, 2, "Boot SPI CRTM size : 512KB"
327*a8bd6d8cSJohnny Huang 	}, {
328*a8bd6d8cSJohnny Huang 		55, 2, 3, "Boot SPI CRTM size : 1MB"
329*a8bd6d8cSJohnny Huang 	}, {
330*a8bd6d8cSJohnny Huang 		57, 2, 0, "Host SPI CRTM size : disable CRTM"
331*a8bd6d8cSJohnny Huang 	}, {
332*a8bd6d8cSJohnny Huang 		57, 2, 1, "Host SPI CRTM size : 256KB"
333*a8bd6d8cSJohnny Huang 	}, {
334*a8bd6d8cSJohnny Huang 		57, 2, 2, "Host SPI CRTM size : 512KB"
335*a8bd6d8cSJohnny Huang 	}, {
336*a8bd6d8cSJohnny Huang 		57, 2, 3, "Host SPI CRTM size : 1MB"
337*a8bd6d8cSJohnny Huang 	}, {
338*a8bd6d8cSJohnny Huang 		59, 1, 0, "Disable host SPI auxiliary control pins"
339*a8bd6d8cSJohnny Huang 	}, {
340*a8bd6d8cSJohnny Huang 		59, 1, 1, "Enable host SPI auxiliary control pins"
341*a8bd6d8cSJohnny Huang 	}, {
342*a8bd6d8cSJohnny Huang 		60, 1, 0, "Disable GPIO pass through"
343*a8bd6d8cSJohnny Huang 	}, {
344*a8bd6d8cSJohnny Huang 		60, 1, 1, "Enable GPIO pass through"
345*a8bd6d8cSJohnny Huang 	}, {
346*a8bd6d8cSJohnny Huang 		61, 1, 0, "Enable low security secure boot key"
347*a8bd6d8cSJohnny Huang 	}, {
348*a8bd6d8cSJohnny Huang 		61, 1, 1, "Disable low security secure boot key"
349*a8bd6d8cSJohnny Huang 	}, {
350*a8bd6d8cSJohnny Huang 		62, 1, 0, "Disable dedicate GPIO strap pins"
351*a8bd6d8cSJohnny Huang 	}, {
352*a8bd6d8cSJohnny Huang 		62, 1, 1, "Enable dedicate GPIO strap pins"
353*a8bd6d8cSJohnny Huang 	}
35476d13988SJohnny Huang };
35576d13988SJohnny Huang 
3562a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
35769d5fd8fSJohnny Huang {
35869d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
35969d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
36069d5fd8fSJohnny Huang 	udelay(2);
36169d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
36269d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
36369d5fd8fSJohnny Huang }
36469d5fd8fSJohnny Huang 
3652a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
36669d5fd8fSJohnny Huang {
36769d5fd8fSJohnny Huang 	int config_offset;
36869d5fd8fSJohnny Huang 
36969d5fd8fSJohnny Huang 	config_offset = 0x800;
37069d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
37169d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
37269d5fd8fSJohnny Huang 
37369d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
37469d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
37569d5fd8fSJohnny Huang 	udelay(2);
37669d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
37769d5fd8fSJohnny Huang }
37869d5fd8fSJohnny Huang 
37969d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
38069d5fd8fSJohnny Huang {
38169d5fd8fSJohnny Huang 	int i;
38269d5fd8fSJohnny Huang 	uint32_t ret[1];
38369d5fd8fSJohnny Huang 
38469d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
3852a856b9aSJohnny Huang 		return OTP_USAGE;
38669d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
38769d5fd8fSJohnny Huang 		otp_read_config(i, ret);
388a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
38969d5fd8fSJohnny Huang 	}
39069d5fd8fSJohnny Huang 	printf("\n");
3912a856b9aSJohnny Huang 	return OTP_SUCCESS;
39269d5fd8fSJohnny Huang }
39369d5fd8fSJohnny Huang 
39469d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
39569d5fd8fSJohnny Huang {
39669d5fd8fSJohnny Huang 	int i;
39769d5fd8fSJohnny Huang 	uint32_t ret[2];
39869d5fd8fSJohnny Huang 
39969d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
4002a856b9aSJohnny Huang 		return OTP_USAGE;
40169d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
40269d5fd8fSJohnny Huang 		otp_read_data(i, ret);
40369d5fd8fSJohnny Huang 		if (i % 4 == 0)
40469d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
40569d5fd8fSJohnny Huang 		else
40669d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
40769d5fd8fSJohnny Huang 
40869d5fd8fSJohnny Huang 	}
40969d5fd8fSJohnny Huang 	printf("\n");
4102a856b9aSJohnny Huang 	return OTP_SUCCESS;
41169d5fd8fSJohnny Huang }
41269d5fd8fSJohnny Huang 
41369d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
41469d5fd8fSJohnny Huang {
41569d5fd8fSJohnny Huang 	uint32_t ret;
41669d5fd8fSJohnny Huang 	uint32_t *buf;
41769d5fd8fSJohnny Huang 
41869d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
41969d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
42069d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
42169d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
42269d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
42369d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
42469d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
42569d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
42669d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
42769d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
42869d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
42969d5fd8fSJohnny Huang 	udelay(10);
43069d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
43169d5fd8fSJohnny Huang 	if (ret & 0x1)
43269d5fd8fSJohnny Huang 		return 0;
43369d5fd8fSJohnny Huang 	else
43469d5fd8fSJohnny Huang 		return -1;
43569d5fd8fSJohnny Huang }
43669d5fd8fSJohnny Huang 
43769d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
43869d5fd8fSJohnny Huang {
43969d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
44069d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
44169d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
44269d5fd8fSJohnny Huang 	udelay(100);
44369d5fd8fSJohnny Huang }
44469d5fd8fSJohnny Huang 
44569d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
44669d5fd8fSJohnny Huang {
44769d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
44869d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
44969d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
45069d5fd8fSJohnny Huang 	udelay(85);
45169d5fd8fSJohnny Huang }
45269d5fd8fSJohnny Huang 
453a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
45469d5fd8fSJohnny Huang {
45569d5fd8fSJohnny Huang 	int ret;
45669d5fd8fSJohnny Huang 
45769d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
45869d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
45969d5fd8fSJohnny Huang 	udelay(2);
46069d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
461a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
46269d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
46369d5fd8fSJohnny Huang 		return 0;
46469d5fd8fSJohnny Huang 	else
46569d5fd8fSJohnny Huang 		return -1;
46669d5fd8fSJohnny Huang }
46769d5fd8fSJohnny Huang 
468d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
4694c1c9b35SJohnny Huang {
4704c1c9b35SJohnny Huang 	uint32_t ret[2];
4714c1c9b35SJohnny Huang 
4724c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
4734c1c9b35SJohnny Huang 
4744c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
4754c1c9b35SJohnny Huang 		writel(otp_addr, 0x1e6f2010); //Read address
4764c1c9b35SJohnny Huang 	else
4774c1c9b35SJohnny Huang 		writel(otp_addr - 1, 0x1e6f2010); //Read address
4784c1c9b35SJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
4794c1c9b35SJohnny Huang 	udelay(2);
4804c1c9b35SJohnny Huang 	ret[0] = readl(0x1e6f2020);
4814c1c9b35SJohnny Huang 	ret[1] = readl(0x1e6f2024);
4824c1c9b35SJohnny Huang 	if (size == 1) {
4834c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
4844c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
485d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
4864c1c9b35SJohnny Huang 				compare[0] = 0;
4874c1c9b35SJohnny Huang 				return 0;
4884c1c9b35SJohnny Huang 			} else {
4894c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
4904c1c9b35SJohnny Huang 				return -1;
4914c1c9b35SJohnny Huang 			}
4924c1c9b35SJohnny Huang 
4934c1c9b35SJohnny Huang 		} else {
4944c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
495d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
4964c1c9b35SJohnny Huang 				compare[0] = ~0;
4974c1c9b35SJohnny Huang 				return 0;
4984c1c9b35SJohnny Huang 			} else {
499d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
5004c1c9b35SJohnny Huang 				return -1;
5014c1c9b35SJohnny Huang 			}
5024c1c9b35SJohnny Huang 		}
5034c1c9b35SJohnny Huang 	} else if (size == 2) {
5044c1c9b35SJohnny Huang 		// otp_addr should be even
505d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
5064c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
5074c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
5084c1c9b35SJohnny Huang 			compare[0] = 0;
5094c1c9b35SJohnny Huang 			compare[1] = ~0;
5104c1c9b35SJohnny Huang 			return 0;
5114c1c9b35SJohnny Huang 		} else {
5124c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
5134c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
5144c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
5154c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
5164c1c9b35SJohnny Huang 			return -1;
5174c1c9b35SJohnny Huang 		}
5184c1c9b35SJohnny Huang 	} else {
5194c1c9b35SJohnny Huang 		return -1;
5204c1c9b35SJohnny Huang 	}
5214c1c9b35SJohnny Huang }
5224c1c9b35SJohnny Huang 
5237e22f42dSJohnny Huang static void otp_soak(int soak)
524d90825e2SJohnny Huang {
525d90825e2SJohnny Huang 	if (soak) {
526d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
527d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
528d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
529d90825e2SJohnny Huang 		writel(0x041930d4, 0x1e602008); //soak program
530d90825e2SJohnny Huang 	} else {
531d90825e2SJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
532d90825e2SJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
533d90825e2SJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
534d90825e2SJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
535d90825e2SJohnny Huang 	}
536d90825e2SJohnny Huang }
537d90825e2SJohnny Huang 
538d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
539d90825e2SJohnny Huang {
540d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
541d90825e2SJohnny Huang 
542d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
543d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
544d90825e2SJohnny Huang 			continue;
545d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
546d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
547d90825e2SJohnny Huang 			if (bit_value)
548d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
549d90825e2SJohnny Huang 			else
550d90825e2SJohnny Huang 				continue;
551d90825e2SJohnny Huang 		} else {
552d90825e2SJohnny Huang 			prog_address |= 1 << 15;
553d90825e2SJohnny Huang 			if (bit_value)
554d90825e2SJohnny Huang 				continue;
555d90825e2SJohnny Huang 			else
556d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
557d90825e2SJohnny Huang 		}
558d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
559d90825e2SJohnny Huang 	}
560d90825e2SJohnny Huang }
561d90825e2SJohnny Huang 
56276d13988SJohnny Huang 
56376d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap)
56476d13988SJohnny Huang {
56576d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
56676d13988SJohnny Huang 	int i, j;
56776d13988SJohnny Huang 
56876d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
56976d13988SJohnny Huang 		otpstrap[j].value = 0;
57076d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
57176d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
57276d13988SJohnny Huang 		otpstrap[j].protected = 0;
57376d13988SJohnny Huang 	}
57476d13988SJohnny Huang 
57576d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
57676d13988SJohnny Huang 		int option = (i - 16) / 2;
57776d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
57876d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
57976d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
58076d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
58176d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
58276d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
58376d13988SJohnny Huang 			}
58476d13988SJohnny Huang 			if (bit_value == 1)
58576d13988SJohnny Huang 				otpstrap[j].remain_times --;
58676d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
58776d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
58876d13988SJohnny Huang 		}
58976d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
59076d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
59176d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
59276d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
59376d13988SJohnny Huang 			}
59476d13988SJohnny Huang 			if (bit_value == 1)
59576d13988SJohnny Huang 				otpstrap[j].remain_times --;
59676d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
59776d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
59876d13988SJohnny Huang 		}
59976d13988SJohnny Huang 	}
60076d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
60176d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
60276d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
60376d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
60476d13988SJohnny Huang 			otpstrap[j].protected = 1;
60576d13988SJohnny Huang 	}
60676d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
60776d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
60876d13988SJohnny Huang 			otpstrap[j].protected = 1;
60976d13988SJohnny Huang 	}
61076d13988SJohnny Huang }
61176d13988SJohnny Huang 
61266f2f8e5SJohnny Huang static int otp_conf_parse(uint32_t *OTPCFG, struct otpconf_parse *conf_parse)
61369d5fd8fSJohnny Huang {
6144c1c9b35SJohnny Huang 	int tmp, i;
61566f2f8e5SJohnny Huang 	int k = 0;
6164c1c9b35SJohnny Huang 	int pass = 0;
617442839bbSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[12];
61869d5fd8fSJohnny Huang 
61966f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
62066f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
62166f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
62266f2f8e5SJohnny Huang 	conf_parse[k].value = DISABLE_SECREG_PROG(OTPCFG[0]);
62366f2f8e5SJohnny Huang 	if (DISABLE_SECREG_PROG(OTPCFG_KEEP[0])) {
62466f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
62566f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
626442839bbSJohnny Huang 	} else {
62766f2f8e5SJohnny Huang 		if (DISABLE_SECREG_PROG(OTPCFG[0]))
62866f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
62966f2f8e5SJohnny Huang 			       "Disable Secure Region programming");
63069d5fd8fSJohnny Huang 		else
63166f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
63266f2f8e5SJohnny Huang 			       "Enable Secure Region programming");
633442839bbSJohnny Huang 	}
634442839bbSJohnny Huang 
63566f2f8e5SJohnny Huang 	k++;
63666f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
63766f2f8e5SJohnny Huang 	conf_parse[k].bit = 1;
63866f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
63966f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_SEC_BOOT(OTPCFG[0]);
64066f2f8e5SJohnny Huang 	if (ENABLE_SEC_BOOT(OTPCFG_KEEP[0])) {
64166f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
64266f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
643442839bbSJohnny Huang 	} else {
64466f2f8e5SJohnny Huang 		if (ENABLE_SEC_BOOT(OTPCFG[0]))
64566f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
64666f2f8e5SJohnny Huang 			       "Enable Secure Boot");
64769d5fd8fSJohnny Huang 		else
64866f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
64966f2f8e5SJohnny Huang 			       "Disable Secure Boot");
650442839bbSJohnny Huang 	}
651442839bbSJohnny Huang 
65266f2f8e5SJohnny Huang 	k++;
65366f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
65466f2f8e5SJohnny Huang 	conf_parse[k].bit = 3;
65566f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
65666f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_USERREG_ECC(OTPCFG[0]);
65766f2f8e5SJohnny Huang 	if (ENABLE_USERREG_ECC(OTPCFG_KEEP[0])) {
65866f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
65966f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
660442839bbSJohnny Huang 	} else {
66166f2f8e5SJohnny Huang 		if (ENABLE_USERREG_ECC(OTPCFG[0]))
66266f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
66366f2f8e5SJohnny Huang 			       "User region ECC enable");
66469d5fd8fSJohnny Huang 		else
66566f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
66666f2f8e5SJohnny Huang 			       "User region ECC disable");
667442839bbSJohnny Huang 	}
668442839bbSJohnny Huang 
66966f2f8e5SJohnny Huang 	k++;
67066f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
67166f2f8e5SJohnny Huang 	conf_parse[k].bit = 4;
67266f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
67366f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_SECREG_ECC(OTPCFG[0]);
67466f2f8e5SJohnny Huang 	if (ENABLE_SECREG_ECC(OTPCFG_KEEP[0])) {
67566f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
67666f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
677442839bbSJohnny Huang 	} else {
67866f2f8e5SJohnny Huang 		if (ENABLE_SECREG_ECC(OTPCFG[0]))
67966f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
68066f2f8e5SJohnny Huang 			       "Secure Region ECC enable");
68169d5fd8fSJohnny Huang 		else
68266f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
68366f2f8e5SJohnny Huang 			       "Secure Region ECC disable");
684442839bbSJohnny Huang 	}
685442839bbSJohnny Huang 
68666f2f8e5SJohnny Huang 	k++;
68766f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
68866f2f8e5SJohnny Huang 	conf_parse[k].bit = 5;
68966f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
69066f2f8e5SJohnny Huang 	conf_parse[k].value = DISABLE_LOW_SEC_KEY(OTPCFG[0]);
69166f2f8e5SJohnny Huang 	if (DISABLE_LOW_SEC_KEY(OTPCFG_KEEP[0])) {
69266f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
69366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
694442839bbSJohnny Huang 	} else {
69566f2f8e5SJohnny Huang 		if (DISABLE_LOW_SEC_KEY(OTPCFG[0]))
69666f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
69766f2f8e5SJohnny Huang 			       "Disable low security key");
69869d5fd8fSJohnny Huang 		else
69966f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
70066f2f8e5SJohnny Huang 			       "Enable low security key");
701442839bbSJohnny Huang 	}
702442839bbSJohnny Huang 
70366f2f8e5SJohnny Huang 	k++;
70466f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
70566f2f8e5SJohnny Huang 	conf_parse[k].bit = 6;
70666f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
70766f2f8e5SJohnny Huang 	conf_parse[k].value = IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0]);
70866f2f8e5SJohnny Huang 	if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG_KEEP[0])) {
70966f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
71066f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
711442839bbSJohnny Huang 	} else {
71266f2f8e5SJohnny Huang 		if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0]))
71366f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
71466f2f8e5SJohnny Huang 			       "Ignore Secure Boot hardware strap");
71569d5fd8fSJohnny Huang 		else
71666f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
71766f2f8e5SJohnny Huang 			       "Do not ignore Secure Boot hardware strap");
718442839bbSJohnny Huang 	}
719442839bbSJohnny Huang 
72066f2f8e5SJohnny Huang 	k++;
72166f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
72266f2f8e5SJohnny Huang 	conf_parse[k].bit = 7;
72366f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
72466f2f8e5SJohnny Huang 	conf_parse[k].value = SEC_BOOT_MDOES(OTPCFG[0]);
72566f2f8e5SJohnny Huang 	if (SEC_BOOT_MDOES(OTPCFG_KEEP[0])) {
72666f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
72766f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
728442839bbSJohnny Huang 	} else {
72966f2f8e5SJohnny Huang 		if (SEC_BOOT_MDOES(OTPCFG[0]))
73066f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
73166f2f8e5SJohnny Huang 			       "Secure Boot Mode: 1");
732e1f9e54eSJohnny Huang 		else
73366f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
73466f2f8e5SJohnny Huang 			       "Secure Boot Mode: 2");
735442839bbSJohnny Huang 	}
736442839bbSJohnny Huang 
73766f2f8e5SJohnny Huang 	k++;
73866f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
73966f2f8e5SJohnny Huang 	conf_parse[k].bit = 8;
74066f2f8e5SJohnny Huang 	conf_parse[k].length = 2;
74166f2f8e5SJohnny Huang 	conf_parse[k].value = OTP_BIT_CELL_MODES(OTPCFG[0]);
742442839bbSJohnny Huang 	if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0x3) {
74366f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
74466f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
74566f2f8e5SJohnny Huang 	} else if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0) {
74666f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "OTP bit cell mode : ");
74766f2f8e5SJohnny Huang 		if (conf_parse[k].value == SINGLE_CELL_MODE) {
74866f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
74966f2f8e5SJohnny Huang 			       "Single cell mode (recommended)");
75066f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == DIFFERENTIAL_MODE) {
75166f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
75266f2f8e5SJohnny Huang 			       "Differnetial mode");
75366f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == DIFFERENTIAL_REDUDANT_MODE) {
75466f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
75566f2f8e5SJohnny Huang 			       "Differential-redundant mode");
756442839bbSJohnny Huang 		} else {
75766f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
75866f2f8e5SJohnny Huang 			       "Value error");
75969d5fd8fSJohnny Huang 			return -1;
76069d5fd8fSJohnny Huang 		}
76166f2f8e5SJohnny Huang 	} else {
76266f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
76366f2f8e5SJohnny Huang 		return -1;
764442839bbSJohnny Huang 	}
76566f2f8e5SJohnny Huang 
76666f2f8e5SJohnny Huang 	k++;
76766f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
76866f2f8e5SJohnny Huang 	conf_parse[k].bit = 10;
76966f2f8e5SJohnny Huang 	conf_parse[k].length = 2;
77066f2f8e5SJohnny Huang 	conf_parse[k].value = CRYPTO_MODES(OTPCFG[0]);
771442839bbSJohnny Huang 	if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0x3) {
77266f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
77366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
77466f2f8e5SJohnny Huang 	} else if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0) {
77566f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "RSA mode : ");
77666f2f8e5SJohnny Huang 		if (conf_parse[k].value == CRYPTO_RSA1024) {
77766f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
77866f2f8e5SJohnny Huang 			       "RSA1024");
77966f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == CRYPTO_RSA2048) {
78066f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
78166f2f8e5SJohnny Huang 			       "RSA2048");
78266f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == CRYPTO_RSA3072) {
78366f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
78466f2f8e5SJohnny Huang 			       "RSA3072");
785442839bbSJohnny Huang 		} else {
78666f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
78766f2f8e5SJohnny Huang 			       "RSA4096");
78866f2f8e5SJohnny Huang 		}
78969d5fd8fSJohnny Huang 	} else {
79066f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
79166f2f8e5SJohnny Huang 		return -1;
79269d5fd8fSJohnny Huang 	}
79366f2f8e5SJohnny Huang 
79466f2f8e5SJohnny Huang 	k++;
79566f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
79666f2f8e5SJohnny Huang 	conf_parse[k].bit = 12;
79766f2f8e5SJohnny Huang 	conf_parse[k].length = 2;
79866f2f8e5SJohnny Huang 	conf_parse[k].value = HASH_MODES(OTPCFG[0]);
799442839bbSJohnny Huang 	if (HASH_MODES(OTPCFG_KEEP[0]) == 0x3) {
80066f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
80166f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
80266f2f8e5SJohnny Huang 	} else if (HASH_MODES(OTPCFG_KEEP[0]) == 0) {
80366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "SHA mode : ");
80466f2f8e5SJohnny Huang 		if (conf_parse[k].value == HASH_SAH224) {
80566f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
80666f2f8e5SJohnny Huang 			       "SHA224");
80766f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == HASH_SAH256) {
80866f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
80966f2f8e5SJohnny Huang 			       "SHA256");
81066f2f8e5SJohnny Huang 		} else if (conf_parse[k].value == HASH_SAH384) {
81166f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
81266f2f8e5SJohnny Huang 			       "SHA384");
813442839bbSJohnny Huang 		} else {
81466f2f8e5SJohnny Huang 			strcat(conf_parse[k].status,
81566f2f8e5SJohnny Huang 			       "SHA512");
81669d5fd8fSJohnny Huang 		}
81766f2f8e5SJohnny Huang 	} else {
81866f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
81966f2f8e5SJohnny Huang 		return -1;
820442839bbSJohnny Huang 	}
82169d5fd8fSJohnny Huang 
82266f2f8e5SJohnny Huang 	k++;
82366f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
82466f2f8e5SJohnny Huang 	conf_parse[k].bit = 16;
82566f2f8e5SJohnny Huang 	conf_parse[k].length = 6;
82666f2f8e5SJohnny Huang 	conf_parse[k].value = SECREG_SIZE(OTPCFG[0]);
827442839bbSJohnny Huang 	if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0x3f) {
82866f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
82966f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
83066f2f8e5SJohnny Huang 	} else if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0) {
83166f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
83266f2f8e5SJohnny Huang 			"Secure Region size (DW): 0x%x", SECREG_SIZE(OTPCFG[0]));
833442839bbSJohnny Huang 	} else {
83466f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
83566f2f8e5SJohnny Huang 		return -1;
836442839bbSJohnny Huang 	}
83769d5fd8fSJohnny Huang 
83866f2f8e5SJohnny Huang 	k++;
83966f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
84066f2f8e5SJohnny Huang 	conf_parse[k].bit = 22;
84166f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
84266f2f8e5SJohnny Huang 	conf_parse[k].value = WRITE_PROTECT_SECREG(OTPCFG[0]);
84366f2f8e5SJohnny Huang 	if (WRITE_PROTECT_SECREG(OTPCFG_KEEP[0])) {
84466f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
84566f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
846442839bbSJohnny Huang 	} else {
84766f2f8e5SJohnny Huang 		if (WRITE_PROTECT_SECREG(OTPCFG[0]))
84866f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
84966f2f8e5SJohnny Huang 			       "Secure Region : Write Protect");
85069d5fd8fSJohnny Huang 		else
85166f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
85266f2f8e5SJohnny Huang 			       "Secure Region : Writable");
853442839bbSJohnny Huang 	}
854442839bbSJohnny Huang 
85566f2f8e5SJohnny Huang 	k++;
85666f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
85766f2f8e5SJohnny Huang 	conf_parse[k].bit = 23;
85866f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
85966f2f8e5SJohnny Huang 	conf_parse[k].value = WRITE_PROTECT_USERREG(OTPCFG[0]);
86066f2f8e5SJohnny Huang 	if (WRITE_PROTECT_USERREG(OTPCFG_KEEP[0])) {
86166f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
86266f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
863442839bbSJohnny Huang 	} else {
86466f2f8e5SJohnny Huang 		if (WRITE_PROTECT_USERREG(OTPCFG[0]))
86566f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
86666f2f8e5SJohnny Huang 			       "User Region : Write Protect");
86769d5fd8fSJohnny Huang 		else
86866f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
86966f2f8e5SJohnny Huang 			       "User Region : Writable");
870442839bbSJohnny Huang 	}
871442839bbSJohnny Huang 
87266f2f8e5SJohnny Huang 	k++;
87366f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
87466f2f8e5SJohnny Huang 	conf_parse[k].bit = 24;
87566f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
87666f2f8e5SJohnny Huang 	conf_parse[k].value = WRITE_PROTECT_CONFREG(OTPCFG[0]);
87766f2f8e5SJohnny Huang 	if (WRITE_PROTECT_CONFREG(OTPCFG_KEEP[0])) {
87866f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
87966f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
880442839bbSJohnny Huang 	} else {
88166f2f8e5SJohnny Huang 		if (WRITE_PROTECT_CONFREG(OTPCFG[0]))
88266f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
88366f2f8e5SJohnny Huang 			       "Configure Region : Write Protect");
88469d5fd8fSJohnny Huang 		else
88566f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
88666f2f8e5SJohnny Huang 			       "Configure Region : Writable");
887442839bbSJohnny Huang 	}
888442839bbSJohnny Huang 
88966f2f8e5SJohnny Huang 	k++;
89066f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
89166f2f8e5SJohnny Huang 	conf_parse[k].bit = 25;
89266f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
89366f2f8e5SJohnny Huang 	conf_parse[k].value = WRITE_PROTECT_STRAPREG(OTPCFG[0]);
89466f2f8e5SJohnny Huang 	if (WRITE_PROTECT_STRAPREG(OTPCFG_KEEP[0])) {
89566f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
89666f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
897442839bbSJohnny Huang 	} else {
89866f2f8e5SJohnny Huang 		if (WRITE_PROTECT_STRAPREG(OTPCFG[0]))
89966f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
90066f2f8e5SJohnny Huang 			       "OTP strap Region : Write Protect");
90169d5fd8fSJohnny Huang 		else
90266f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
90366f2f8e5SJohnny Huang 			       "OTP strap Region : Writable");
904442839bbSJohnny Huang 	}
905442839bbSJohnny Huang 
90666f2f8e5SJohnny Huang 	k++;
90766f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
90866f2f8e5SJohnny Huang 	conf_parse[k].bit = 26;
90966f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
91066f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_COPY_TO_SRAM(OTPCFG[0]);
91166f2f8e5SJohnny Huang 	if (ENABLE_COPY_TO_SRAM(OTPCFG_KEEP[0])) {
91266f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
91366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
914442839bbSJohnny Huang 	} else {
91566f2f8e5SJohnny Huang 		if (ENABLE_COPY_TO_SRAM(OTPCFG[0]))
91666f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
91766f2f8e5SJohnny Huang 			       "Copy Boot Image to Internal SRAM");
91869d5fd8fSJohnny Huang 		else
91966f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
92066f2f8e5SJohnny Huang 			       "Disable Copy Boot Image to Internal SRAM");
921442839bbSJohnny Huang 	}
92266f2f8e5SJohnny Huang 
92366f2f8e5SJohnny Huang 	k++;
92466f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
92566f2f8e5SJohnny Huang 	conf_parse[k].bit = 27;
92666f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
92766f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_IMAGE_ENC(OTPCFG[0]);
92866f2f8e5SJohnny Huang 	if (ENABLE_IMAGE_ENC(OTPCFG_KEEP[0])) {
92966f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
93066f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
931442839bbSJohnny Huang 	} else {
93266f2f8e5SJohnny Huang 		if (ENABLE_IMAGE_ENC(OTPCFG[0]))
93366f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
93466f2f8e5SJohnny Huang 			       "Enable image encryption");
93569d5fd8fSJohnny Huang 		else
93666f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
93766f2f8e5SJohnny Huang 			       "Disable image encryption");
938442839bbSJohnny Huang 	}
939442839bbSJohnny Huang 
94066f2f8e5SJohnny Huang 	k++;
94166f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
94266f2f8e5SJohnny Huang 	conf_parse[k].bit = 29;
94366f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
94466f2f8e5SJohnny Huang 	conf_parse[k].value = WRITE_PROTECT_KEY_RETIRE(OTPCFG[0]);
94566f2f8e5SJohnny Huang 	if (WRITE_PROTECT_KEY_RETIRE(OTPCFG_KEEP[0])) {
94666f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
94766f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
948442839bbSJohnny Huang 	} else {
94966f2f8e5SJohnny Huang 		if (WRITE_PROTECT_KEY_RETIRE(OTPCFG[0]))
95066f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
95166f2f8e5SJohnny Huang 			       "OTP key retire Region : Write Protect");
95269d5fd8fSJohnny Huang 		else
95366f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
95466f2f8e5SJohnny Huang 			       "OTP key retire Region : Writable");
955442839bbSJohnny Huang 	}
956442839bbSJohnny Huang 
95766f2f8e5SJohnny Huang 	k++;
95866f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
95966f2f8e5SJohnny Huang 	conf_parse[k].bit = 30;
96066f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
96166f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_SIPROM_RED(OTPCFG[0]);
96266f2f8e5SJohnny Huang 	if (ENABLE_SIPROM_RED(OTPCFG_KEEP[0])) {
96366f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
96466f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
965442839bbSJohnny Huang 	} else {
96666f2f8e5SJohnny Huang 		if (ENABLE_SIPROM_RED(OTPCFG[0]))
96766f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
96866f2f8e5SJohnny Huang 			       "SIPROM RED_EN redundancy repair enable");
96969d5fd8fSJohnny Huang 		else
97066f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
97166f2f8e5SJohnny Huang 			       "SIPROM RED_EN redundancy repair disable");
972442839bbSJohnny Huang 	}
973442839bbSJohnny Huang 
97466f2f8e5SJohnny Huang 	k++;
97566f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 0;
97666f2f8e5SJohnny Huang 	conf_parse[k].bit = 31;
97766f2f8e5SJohnny Huang 	conf_parse[k].length = 1;
97866f2f8e5SJohnny Huang 	conf_parse[k].value = ENABLE_SIPROM_MLOCK(OTPCFG[0]);
97966f2f8e5SJohnny Huang 	if (ENABLE_SIPROM_MLOCK(OTPCFG_KEEP[0])) {
98066f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
98166f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
982442839bbSJohnny Huang 	} else {
98366f2f8e5SJohnny Huang 		if (ENABLE_SIPROM_MLOCK(OTPCFG[0]))
98466f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
98566f2f8e5SJohnny Huang 			       "SIPROM Mlock memory lock enable");
98669d5fd8fSJohnny Huang 		else
98766f2f8e5SJohnny Huang 			strcpy(conf_parse[k].status,
98866f2f8e5SJohnny Huang 			       "SIPROM Mlock memory lock disable");
989442839bbSJohnny Huang 	}
99069d5fd8fSJohnny Huang 
99166f2f8e5SJohnny Huang 	k++;
99266f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 2;
99366f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
99466f2f8e5SJohnny Huang 	conf_parse[k].length = 16;
99566f2f8e5SJohnny Huang 	conf_parse[k].value = VENDER_ID(OTPCFG[2]);
99666f2f8e5SJohnny Huang 	if (VENDER_ID(OTPCFG_KEEP[2]) == 0xffff) {
99766f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
99866f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
99966f2f8e5SJohnny Huang 	} else if (VENDER_ID(OTPCFG_KEEP[2]) == 0) {
100066f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
100166f2f8e5SJohnny Huang 			"Vender ID : 0x%x", VENDER_ID(OTPCFG[2]));
1002442839bbSJohnny Huang 	} else {
100366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
100466f2f8e5SJohnny Huang 		return -1;
1005442839bbSJohnny Huang 	}
100669d5fd8fSJohnny Huang 
100766f2f8e5SJohnny Huang 	k++;
100866f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 2;
100966f2f8e5SJohnny Huang 	conf_parse[k].bit = 16;
101066f2f8e5SJohnny Huang 	conf_parse[k].length = 16;
101166f2f8e5SJohnny Huang 	conf_parse[k].value = KEY_REVISION(OTPCFG[2]);
101266f2f8e5SJohnny Huang 	if (KEY_REVISION(OTPCFG_KEEP[2]) == 0xffff) {
101366f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
101466f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
101566f2f8e5SJohnny Huang 	} else if (KEY_REVISION(OTPCFG_KEEP[2]) == 0) {
101666f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
101766f2f8e5SJohnny Huang 			"Key Revision : 0x%x", KEY_REVISION(OTPCFG[2]));
1018442839bbSJohnny Huang 	} else {
101966f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
102066f2f8e5SJohnny Huang 		return -1;
102166f2f8e5SJohnny Huang 	}
102266f2f8e5SJohnny Huang 
102366f2f8e5SJohnny Huang 	k++;
102466f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 3;
102566f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
102666f2f8e5SJohnny Huang 	conf_parse[k].length = 16;
102766f2f8e5SJohnny Huang 	conf_parse[k].value = SEC_BOOT_HEADER_OFFSET(OTPCFG[3]);
102866f2f8e5SJohnny Huang 	if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0xffff) {
102966f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
103066f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
103166f2f8e5SJohnny Huang 	} else if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0) {
103266f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
103366f2f8e5SJohnny Huang 			"Secure boot header offset : 0x%x",
1034e1f9e54eSJohnny Huang 			SEC_BOOT_HEADER_OFFSET(OTPCFG[3]));
103566f2f8e5SJohnny Huang 	} else {
103666f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
103766f2f8e5SJohnny Huang 		return -1;
1038442839bbSJohnny Huang 	}
103969d5fd8fSJohnny Huang 
104066f2f8e5SJohnny Huang 	k++;
104166f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 4;
104266f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
104366f2f8e5SJohnny Huang 	conf_parse[k].length = 8;
104466f2f8e5SJohnny Huang 	conf_parse[k].value = KEYS_VALID_BITS(OTPCFG[4]);
104566f2f8e5SJohnny Huang 	if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0xff) {
104666f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
104766f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
104866f2f8e5SJohnny Huang 	} else if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0) {
1049e1f9e54eSJohnny Huang 		tmp = KEYS_VALID_BITS(OTPCFG[4]);
1050e1f9e54eSJohnny Huang 		if (tmp != 0) {
105169d5fd8fSJohnny Huang 			for (i = 0; i < 7; i++) {
105269d5fd8fSJohnny Huang 				if (tmp == (1 << i)) {
1053e1f9e54eSJohnny Huang 					pass = i + 1;
105469d5fd8fSJohnny Huang 				}
105569d5fd8fSJohnny Huang 			}
1056e1f9e54eSJohnny Huang 		} else {
1057e1f9e54eSJohnny Huang 			pass = 0;
1058e1f9e54eSJohnny Huang 		}
105966f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
106066f2f8e5SJohnny Huang 			"Keys valid  : %d", pass);
1061442839bbSJohnny Huang 	} else {
106266f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
106366f2f8e5SJohnny Huang 		return -1;
106466f2f8e5SJohnny Huang 	}
106566f2f8e5SJohnny Huang 
106666f2f8e5SJohnny Huang 	k++;
106766f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 4;
106866f2f8e5SJohnny Huang 	conf_parse[k].bit = 16;
106966f2f8e5SJohnny Huang 	conf_parse[k].length = 8;
107066f2f8e5SJohnny Huang 	conf_parse[k].value = KEYS_RETIRE_BITS(OTPCFG[4]);
107166f2f8e5SJohnny Huang 	if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0xff) {
107266f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
107366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
107466f2f8e5SJohnny Huang 	} else if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0) {
1075e1f9e54eSJohnny Huang 		tmp = KEYS_RETIRE_BITS(OTPCFG[4]);
1076e1f9e54eSJohnny Huang 		if (tmp != 0) {
107769d5fd8fSJohnny Huang 			for (i = 0; i < 7; i++) {
107869d5fd8fSJohnny Huang 				if (tmp == (1 << i)) {
1079e1f9e54eSJohnny Huang 					pass = i + 1;
108069d5fd8fSJohnny Huang 				}
108169d5fd8fSJohnny Huang 			}
1082e1f9e54eSJohnny Huang 		} else {
1083e1f9e54eSJohnny Huang 			pass = 0;
108469d5fd8fSJohnny Huang 		}
108566f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
108666f2f8e5SJohnny Huang 			"Keys Retire ID  : %d", pass);
108766f2f8e5SJohnny Huang 	} else {
108866f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
108966f2f8e5SJohnny Huang 		return -1;
1090442839bbSJohnny Huang 	}
109166f2f8e5SJohnny Huang 
109266f2f8e5SJohnny Huang 	k++;
109366f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 5;
109466f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
109566f2f8e5SJohnny Huang 	conf_parse[k].length = 32;
109666f2f8e5SJohnny Huang 	conf_parse[k].value = OTPCFG[5];
1097442839bbSJohnny Huang 	if (OTPCFG_KEEP[5] == 0xFFFFFFFF) {
109866f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
109966f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
110066f2f8e5SJohnny Huang 	} else if (OTPCFG_KEEP[5] == 0) {
110166f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
110266f2f8e5SJohnny Huang 			"User define data, random number low : 0x%x", OTPCFG[5]);
1103442839bbSJohnny Huang 	} else {
110466f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
110566f2f8e5SJohnny Huang 		return -1;
1106442839bbSJohnny Huang 	}
110769d5fd8fSJohnny Huang 
110866f2f8e5SJohnny Huang 	k++;
110966f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 6;
111066f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
111166f2f8e5SJohnny Huang 	conf_parse[k].length = 32;
111266f2f8e5SJohnny Huang 	conf_parse[k].value = OTPCFG[6];
1113442839bbSJohnny Huang 	if (OTPCFG_KEEP[6] == 0xFFFFFFFF) {
111466f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
111566f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
111666f2f8e5SJohnny Huang 	} else if (OTPCFG_KEEP[6] == 0) {
111766f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
111866f2f8e5SJohnny Huang 			"User define data, random number high : 0x%x", OTPCFG[6]);
1119442839bbSJohnny Huang 	} else {
112066f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
112166f2f8e5SJohnny Huang 		return -1;
1122442839bbSJohnny Huang 	}
112369d5fd8fSJohnny Huang 
112466f2f8e5SJohnny Huang 	k++;
112566f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 8;
112666f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
112766f2f8e5SJohnny Huang 	conf_parse[k].length = 32;
112866f2f8e5SJohnny Huang 	conf_parse[k].value = OTPCFG[8];
1129442839bbSJohnny Huang 	if (OTPCFG_KEEP[8] == 0xFFFFFFFF) {
113066f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
113166f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
113266f2f8e5SJohnny Huang 	} else if (OTPCFG_KEEP[8] == 0) {
113366f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
113466f2f8e5SJohnny Huang 			"Redundancy Repair : 0x%x", OTPCFG[8]);
1135442839bbSJohnny Huang 	} else {
113666f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
113766f2f8e5SJohnny Huang 		return -1;
1138442839bbSJohnny Huang 	}
113969d5fd8fSJohnny Huang 
114066f2f8e5SJohnny Huang 	k++;
114166f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 10;
114266f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
114366f2f8e5SJohnny Huang 	conf_parse[k].length = 32;
114466f2f8e5SJohnny Huang 	conf_parse[k].value = OTPCFG[10];
1145442839bbSJohnny Huang 	if (OTPCFG_KEEP[10] == 0xFFFFFFFF) {
114666f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
114766f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
114866f2f8e5SJohnny Huang 	} else if (OTPCFG_KEEP[10] == 0) {
114966f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
115066f2f8e5SJohnny Huang 			"Manifest ID low : 0x%x", OTPCFG[10]);
1151442839bbSJohnny Huang 	} else {
115266f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
115366f2f8e5SJohnny Huang 		return -1;
1154442839bbSJohnny Huang 	}
115569d5fd8fSJohnny Huang 
115666f2f8e5SJohnny Huang 	k++;
115766f2f8e5SJohnny Huang 	conf_parse[k].dw_offset = 11;
115866f2f8e5SJohnny Huang 	conf_parse[k].bit = 0;
115966f2f8e5SJohnny Huang 	conf_parse[k].length = 32;
116066f2f8e5SJohnny Huang 	conf_parse[k].value = OTPCFG[11];
1161442839bbSJohnny Huang 	if (OTPCFG_KEEP[11] == 0xFFFFFFFF) {
116266f2f8e5SJohnny Huang 		conf_parse[k].keep = 1;
116366f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Skip");
116466f2f8e5SJohnny Huang 	} else if (OTPCFG_KEEP[11] == 0) {
116566f2f8e5SJohnny Huang 		sprintf(conf_parse[k].status,
116666f2f8e5SJohnny Huang 			"Manifest ID high : 0x%x", OTPCFG[11]);
1167442839bbSJohnny Huang 	} else {
116866f2f8e5SJohnny Huang 		strcpy(conf_parse[k].status, "Keep mask error!");
116966f2f8e5SJohnny Huang 		return -1;
1170442839bbSJohnny Huang 	}
1171442839bbSJohnny Huang 
117266f2f8e5SJohnny Huang 	return k + 1;
117369d5fd8fSJohnny Huang 
117469d5fd8fSJohnny Huang }
117569d5fd8fSJohnny Huang 
117666f2f8e5SJohnny Huang static int otp_print_conf_info(uint32_t *OTPCFG)
117766f2f8e5SJohnny Huang {
117866f2f8e5SJohnny Huang 	struct otpconf_parse conf_parse[60];
117966f2f8e5SJohnny Huang 	int length;
118066f2f8e5SJohnny Huang 	int i;
118166f2f8e5SJohnny Huang 
118266f2f8e5SJohnny Huang 	length = otp_conf_parse(OTPCFG, conf_parse);
118366f2f8e5SJohnny Huang 
118466f2f8e5SJohnny Huang 	if (length <= 0)
118566f2f8e5SJohnny Huang 		return OTP_FAILURE;
118666f2f8e5SJohnny Huang 
1187737ed20bSJohnny Huang 	printf("DW  BIT     Value       Description\n");
118866f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
118966f2f8e5SJohnny Huang 	for (i = 0; i < length; i++) {
119066f2f8e5SJohnny Huang 		printf("%-4d", conf_parse[i].dw_offset);
119166f2f8e5SJohnny Huang 		if (conf_parse[i].length == 1) {
119266f2f8e5SJohnny Huang 			printf("%-8d", conf_parse[i].bit);
119366f2f8e5SJohnny Huang 		} else {
119466f2f8e5SJohnny Huang 			printf("%-2d:%-5d",
119566f2f8e5SJohnny Huang 			       conf_parse[i].bit + conf_parse[i].length - 1,
119666f2f8e5SJohnny Huang 			       conf_parse[i].bit);
119766f2f8e5SJohnny Huang 		}
119866f2f8e5SJohnny Huang 		printf("0x%-10x", conf_parse[i].value);
119966f2f8e5SJohnny Huang 		printf("%s\n", conf_parse[i].status);
120066f2f8e5SJohnny Huang 	}
120166f2f8e5SJohnny Huang 	return OTP_SUCCESS;
120266f2f8e5SJohnny Huang }
120366f2f8e5SJohnny Huang 
120466f2f8e5SJohnny Huang static void otp_info_config(void)
120566f2f8e5SJohnny Huang {
120666f2f8e5SJohnny Huang 	uint32_t OTPCFG[24];
120766f2f8e5SJohnny Huang 	int i;
120866f2f8e5SJohnny Huang 
120966f2f8e5SJohnny Huang 	for (i = 0; i < 12; i++)
121066f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
121166f2f8e5SJohnny Huang 
121266f2f8e5SJohnny Huang 	for (i = 12; i < 24; i++)
121366f2f8e5SJohnny Huang 		OTPCFG[i] = 0;
121466f2f8e5SJohnny Huang 
121566f2f8e5SJohnny Huang 	otp_print_conf_info(OTPCFG);
121666f2f8e5SJohnny Huang }
121766f2f8e5SJohnny Huang 
1218*a8bd6d8cSJohnny Huang static int otp_print_strap_info(uint32_t *OTPSTRAP, int view)
121976d13988SJohnny Huang {
1220*a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
1221*a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
122276d13988SJohnny Huang 	int i;
1223*a8bd6d8cSJohnny Huang 	int fail = 0;
1224*a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
1225*a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
1226*a8bd6d8cSJohnny Huang 	uint32_t mask;
1227*a8bd6d8cSJohnny Huang 	uint32_t otp_value;
1228*a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
1229*a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
123076d13988SJohnny Huang 
1231*a8bd6d8cSJohnny Huang 	if (view) {
1232*a8bd6d8cSJohnny Huang 		printf("BIT(hex) Value       Protect     Description\n");
1233*a8bd6d8cSJohnny Huang 		printf("__________________________________________________________________________________________\n");
1234*a8bd6d8cSJohnny Huang 	} else {
1235*a8bd6d8cSJohnny Huang 		printf("BIT(hex) Value       Description\n");
1236*a8bd6d8cSJohnny Huang 		printf("______________________________________________________________________________\n");
1237*a8bd6d8cSJohnny Huang 	}
1238*a8bd6d8cSJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
1239*a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].bit_offset > 32) {
1240*a8bd6d8cSJohnny Huang 			dw_offset = 1;
1241*a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset - 32;
1242*a8bd6d8cSJohnny Huang 		} else {
1243*a8bd6d8cSJohnny Huang 			dw_offset = 0;
1244*a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset;
1245*a8bd6d8cSJohnny Huang 		}
124676d13988SJohnny Huang 
1247*a8bd6d8cSJohnny Huang 		mask = BIT(a0_strap_info[i].length) - 1;
1248*a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
1249*a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
1250*a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
1251*a8bd6d8cSJohnny Huang 
1252*a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
1253*a8bd6d8cSJohnny Huang 			continue;
1254*a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
1255*a8bd6d8cSJohnny Huang 			fail = 1;
1256*a8bd6d8cSJohnny Huang 		}
1257*a8bd6d8cSJohnny Huang 
1258*a8bd6d8cSJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
1259*a8bd6d8cSJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
1260*a8bd6d8cSJohnny Huang 			continue;
1261*a8bd6d8cSJohnny Huang 
1262*a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].length == 1) {
1263*a8bd6d8cSJohnny Huang 			printf("%-9X", a0_strap_info[i].bit_offset);
1264*a8bd6d8cSJohnny Huang 		} else {
1265*a8bd6d8cSJohnny Huang 			printf("%-2X:%-6X",
1266*a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1,
1267*a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset);
1268*a8bd6d8cSJohnny Huang 		}
1269*a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
1270*a8bd6d8cSJohnny Huang 		if (view)
1271*a8bd6d8cSJohnny Huang 			printf("0x%-10x", otp_protect);
1272*a8bd6d8cSJohnny Huang 
1273*a8bd6d8cSJohnny Huang 		if (fail) {
1274*a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
1275*a8bd6d8cSJohnny Huang 		} else {
1276*a8bd6d8cSJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
1277*a8bd6d8cSJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
1278*a8bd6d8cSJohnny Huang 			else
1279*a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1280*a8bd6d8cSJohnny Huang 		}
1281*a8bd6d8cSJohnny Huang 	}
1282*a8bd6d8cSJohnny Huang 
1283*a8bd6d8cSJohnny Huang 	if (fail)
128476d13988SJohnny Huang 		return OTP_FAILURE;
128576d13988SJohnny Huang 
128676d13988SJohnny Huang 	return OTP_SUCCESS;
128776d13988SJohnny Huang }
128876d13988SJohnny Huang 
1289*a8bd6d8cSJohnny Huang static void otp_info_strap(int view)
129076d13988SJohnny Huang {
129176d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
129276d13988SJohnny Huang 	uint32_t OTPSTRAP[6];
129376d13988SJohnny Huang 	int i;
129476d13988SJohnny Huang 
129576d13988SJohnny Huang 
129676d13988SJohnny Huang 	otp_strp_status(strap_status);
129776d13988SJohnny Huang 
129876d13988SJohnny Huang 	for (i = 0; i < 6; i++)
129976d13988SJohnny Huang 		OTPSTRAP[i] = 0;
130076d13988SJohnny Huang 	for (i = 0; i < 32; i++) {
130176d13988SJohnny Huang 		OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i;
130276d13988SJohnny Huang 		OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i;
130376d13988SJohnny Huang 	}
130476d13988SJohnny Huang 	for (i = 0; i < 32; i++) {
130576d13988SJohnny Huang 		OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i;
130676d13988SJohnny Huang 		OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i;
130776d13988SJohnny Huang 	}
130876d13988SJohnny Huang 
1309*a8bd6d8cSJohnny Huang 	otp_print_strap_info(OTPSTRAP, view);
131076d13988SJohnny Huang }
131176d13988SJohnny Huang 
131269d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
131369d5fd8fSJohnny Huang {
131469d5fd8fSJohnny Huang 	int i;
131569d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
131669d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
131769d5fd8fSJohnny Huang 		if (i % 16 == 0) {
131869d5fd8fSJohnny Huang 			printf("%04X: ", i);
131969d5fd8fSJohnny Huang 		}
132069d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
132169d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
132269d5fd8fSJohnny Huang 			printf("\n");
132369d5fd8fSJohnny Huang 		}
132469d5fd8fSJohnny Huang 	}
132569d5fd8fSJohnny Huang }
132669d5fd8fSJohnny Huang 
13277f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
132869d5fd8fSJohnny Huang {
132969d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
133069d5fd8fSJohnny Huang 	char *byte_buf;
133169d5fd8fSJohnny Huang 	int i = 0, len = 0;
133269d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
133369d5fd8fSJohnny Huang 	while (1) {
133469d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
133569d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
133669d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
133769d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
133869d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
133969d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
13407f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
134169d5fd8fSJohnny Huang 		printf("Key Type: ");
134269d5fd8fSJohnny Huang 		switch (key_type) {
134369d5fd8fSJohnny Huang 		case 0:
134469d5fd8fSJohnny Huang 			printf("AES-256 as OEM platform key for image encryption/decryption\n");
134569d5fd8fSJohnny Huang 			break;
134669d5fd8fSJohnny Huang 		case 1:
134769d5fd8fSJohnny Huang 			printf("AES-256 as secret vault key\n");
134869d5fd8fSJohnny Huang 			break;
134969d5fd8fSJohnny Huang 		case 4:
135069d5fd8fSJohnny Huang 			printf("HMAC as encrypted OEM HMAC keys in Mode 1\n");
135169d5fd8fSJohnny Huang 			break;
135269d5fd8fSJohnny Huang 		case 8:
135369d5fd8fSJohnny Huang 			printf("RSA-public as OEM DSS public keys in Mode 2\n");
135469d5fd8fSJohnny Huang 			break;
135569d5fd8fSJohnny Huang 		case 9:
135669d5fd8fSJohnny Huang 			printf("RSA-public as SOC public key\n");
135769d5fd8fSJohnny Huang 			break;
135869d5fd8fSJohnny Huang 		case 10:
135969d5fd8fSJohnny Huang 			printf("RSA-public as AES key decryption key\n");
136069d5fd8fSJohnny Huang 			break;
136169d5fd8fSJohnny Huang 		case 13:
136269d5fd8fSJohnny Huang 			printf("RSA-private as SOC private key\n");
136369d5fd8fSJohnny Huang 			break;
136469d5fd8fSJohnny Huang 		case 14:
136569d5fd8fSJohnny Huang 			printf("RSA-private as AES key decryption key\n");
136669d5fd8fSJohnny Huang 			break;
136769d5fd8fSJohnny Huang 		default:
136869d5fd8fSJohnny Huang 			printf("key_type error: %x\n", key_type);
136969d5fd8fSJohnny Huang 			return -1;
137069d5fd8fSJohnny Huang 		}
137169d5fd8fSJohnny Huang 		if (key_type == 4) {
137269d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
137369d5fd8fSJohnny Huang 			switch (key_length) {
137469d5fd8fSJohnny Huang 			case 0:
137569d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
137669d5fd8fSJohnny Huang 				break;
137769d5fd8fSJohnny Huang 			case 1:
137869d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
137969d5fd8fSJohnny Huang 				break;
138069d5fd8fSJohnny Huang 			case 2:
138169d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
138269d5fd8fSJohnny Huang 				break;
138369d5fd8fSJohnny Huang 			case 3:
138469d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
138569d5fd8fSJohnny Huang 				break;
138669d5fd8fSJohnny Huang 			}
1387cd1610b4SJohnny Huang 		} else if (key_type != 0 && key_type != 1) {
138869d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
138969d5fd8fSJohnny Huang 			switch (key_length) {
139069d5fd8fSJohnny Huang 			case 0:
139169d5fd8fSJohnny Huang 				printf("RSA1024\n");
139269d5fd8fSJohnny Huang 				len = 0x100;
139369d5fd8fSJohnny Huang 				break;
139469d5fd8fSJohnny Huang 			case 1:
139569d5fd8fSJohnny Huang 				printf("RSA2048\n");
139669d5fd8fSJohnny Huang 				len = 0x200;
139769d5fd8fSJohnny Huang 				break;
139869d5fd8fSJohnny Huang 			case 2:
139969d5fd8fSJohnny Huang 				printf("RSA3072\n");
140069d5fd8fSJohnny Huang 				len = 0x300;
140169d5fd8fSJohnny Huang 				break;
140269d5fd8fSJohnny Huang 			case 3:
140369d5fd8fSJohnny Huang 				printf("RSA4096\n");
140469d5fd8fSJohnny Huang 				len = 0x400;
140569d5fd8fSJohnny Huang 				break;
140669d5fd8fSJohnny Huang 			}
140769d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
140869d5fd8fSJohnny Huang 		}
140969d5fd8fSJohnny Huang 		if (key_type == 4 || key_type == 8)
141069d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
141169d5fd8fSJohnny Huang 		printf("Key Value:\n");
141269d5fd8fSJohnny Huang 		if (key_type == 4) {
141369d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
141469d5fd8fSJohnny Huang 		} else if (key_type == 0 || key_type == 1) {
141569d5fd8fSJohnny Huang 			printf("AES Key:\n");
141669d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
141769d5fd8fSJohnny Huang 			printf("AES IV:\n");
141869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + 0x20], 0x10);
141969d5fd8fSJohnny Huang 
142069d5fd8fSJohnny Huang 		} else {
142169d5fd8fSJohnny Huang 			printf("RSA mod:\n");
142269d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
142369d5fd8fSJohnny Huang 			printf("RSA exp:\n");
142469d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
142569d5fd8fSJohnny Huang 		}
142669d5fd8fSJohnny Huang 		if (last)
142769d5fd8fSJohnny Huang 			break;
142869d5fd8fSJohnny Huang 		i++;
142969d5fd8fSJohnny Huang 	}
143069d5fd8fSJohnny Huang 	return 0;
143169d5fd8fSJohnny Huang }
143269d5fd8fSJohnny Huang 
1433a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
143469d5fd8fSJohnny Huang {
1435a6d0d645SJohnny Huang 	int i, k;
1436d90825e2SJohnny Huang 	int pass = 0;
1437d90825e2SJohnny Huang 	int soak = 0;
1438a6d0d645SJohnny Huang 	uint32_t prog_address;
1439a6d0d645SJohnny Huang 	uint32_t data[12];
1440a6d0d645SJohnny Huang 	uint32_t compare[2];
1441d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[12];
1442d90825e2SJohnny Huang 	uint32_t data_masked;
1443d90825e2SJohnny Huang 	uint32_t buf_masked;
144469d5fd8fSJohnny Huang 
1445a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1446a6d0d645SJohnny Huang 
1447a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1448a6d0d645SJohnny Huang 	for (i = 0; i < 12 ; i ++) {
1449a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "");
145069d5fd8fSJohnny Huang 		prog_address = 0x800;
1451a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1452a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1453a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1454a6d0d645SJohnny Huang 	}
1455a6d0d645SJohnny Huang 
1456a6d0d645SJohnny Huang 	printf("Check writable...\n");
1457a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1458d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1459d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1460d90825e2SJohnny Huang 		if (data_masked == buf_masked)
146169d5fd8fSJohnny Huang 			continue;
1462d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1463a6d0d645SJohnny Huang 			continue;
1464a6d0d645SJohnny Huang 		} else {
1465a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1466a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1467a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1468a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
14692a856b9aSJohnny Huang 			return OTP_FAILURE;
1470a6d0d645SJohnny Huang 		}
1471a6d0d645SJohnny Huang 	}
1472a6d0d645SJohnny Huang 
1473a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1474a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1475d90825e2SJohnny Huang 	otp_soak(0);
1476a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1477d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1478d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1479a6d0d645SJohnny Huang 		prog_address = 0x800;
1480a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1481a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1482d90825e2SJohnny Huang 		if (data_masked == buf_masked) {
1483a6d0d645SJohnny Huang 			printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]);
1484a6d0d645SJohnny Huang 			continue;
1485a6d0d645SJohnny Huang 		}
1486d90825e2SJohnny Huang 		if (soak) {
1487d90825e2SJohnny Huang 			soak = 0;
1488d90825e2SJohnny Huang 			otp_soak(0);
1489d90825e2SJohnny Huang 		}
1490a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "[%03X]=%08X    ", prog_address, buf[i]);
1491a6d0d645SJohnny Huang 
1492d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1493a6d0d645SJohnny Huang 
149469d5fd8fSJohnny Huang 		pass = 0;
149569d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1496d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1497d90825e2SJohnny Huang 				if (soak == 0) {
1498d90825e2SJohnny Huang 					soak = 1;
1499d90825e2SJohnny Huang 					otp_soak(1);
1500d90825e2SJohnny Huang 				}
1501a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1502a6d0d645SJohnny Huang 			} else {
150369d5fd8fSJohnny Huang 				pass = 1;
150469d5fd8fSJohnny Huang 				break;
150569d5fd8fSJohnny Huang 			}
150669d5fd8fSJohnny Huang 		}
1507a6d0d645SJohnny Huang 	}
1508a6d0d645SJohnny Huang 
150969d5fd8fSJohnny Huang 	if (!pass)
15102a856b9aSJohnny Huang 		return OTP_FAILURE;
1511a6d0d645SJohnny Huang 
15122a856b9aSJohnny Huang 	return OTP_SUCCESS;
1513d90825e2SJohnny Huang 
151469d5fd8fSJohnny Huang }
151569d5fd8fSJohnny Huang 
151669d5fd8fSJohnny Huang 
151776d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
151869d5fd8fSJohnny Huang {
151969d5fd8fSJohnny Huang 	int i;
152069d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
152169d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
152269d5fd8fSJohnny Huang 	int bit, pbit, kbit;
152369d5fd8fSJohnny Huang 	int fail = 0;
1524a6af4a17SJohnny Huang 	int skip = -1;
152566f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
152669d5fd8fSJohnny Huang 
152769d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
152869d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
152969d5fd8fSJohnny Huang 		if (i < 32) {
153069d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
153169d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
153269d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
153369d5fd8fSJohnny Huang 		} else {
153469d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
153569d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
153669d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
153769d5fd8fSJohnny Huang 		}
153869d5fd8fSJohnny Huang 
153969d5fd8fSJohnny Huang 		if (kbit == 1) {
154069d5fd8fSJohnny Huang 			continue;
154169d5fd8fSJohnny Huang 		} else {
1542a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
154369d5fd8fSJohnny Huang 		}
154469d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
154569d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1546a6af4a17SJohnny Huang 			if (skip == -1)
1547a6af4a17SJohnny Huang 				skip = 1;
154869d5fd8fSJohnny Huang 			continue;
1549a6af4a17SJohnny Huang 		} else {
1550a6af4a17SJohnny Huang 			skip = 0;
155169d5fd8fSJohnny Huang 		}
155269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
155369d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
155469d5fd8fSJohnny Huang 			fail = 1;
155569d5fd8fSJohnny Huang 			continue;
155669d5fd8fSJohnny Huang 		}
155769d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1558a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
155969d5fd8fSJohnny Huang 			fail = 1;
156069d5fd8fSJohnny Huang 			continue;
156169d5fd8fSJohnny Huang 		}
156269d5fd8fSJohnny Huang 		if (pbit == 1) {
156369d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
156469d5fd8fSJohnny Huang 		}
1565a6af4a17SJohnny Huang 		printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1);
156669d5fd8fSJohnny Huang 	}
156769d5fd8fSJohnny Huang 	if (fail == 1)
1568a6af4a17SJohnny Huang 		return OTP_FAILURE;
1569a6af4a17SJohnny Huang 	else if (skip == 1)
1570a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
15717e22f42dSJohnny Huang 
15727e22f42dSJohnny Huang 	return 0;
157369d5fd8fSJohnny Huang }
157469d5fd8fSJohnny Huang 
15752a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
157669d5fd8fSJohnny Huang {
157769d5fd8fSJohnny Huang 	int i, j;
157866f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
157969d5fd8fSJohnny Huang 
15802a856b9aSJohnny Huang 	if (start < 0 || start > 64)
15812a856b9aSJohnny Huang 		return OTP_USAGE;
15822a856b9aSJohnny Huang 
15832a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
15842a856b9aSJohnny Huang 		return OTP_USAGE;
15852a856b9aSJohnny Huang 
158669d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
158769d5fd8fSJohnny Huang 
1588*a8bd6d8cSJohnny Huang 	printf("BIT(hex)  Value  Avaliable        Status\n");
1589*a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1590737ed20bSJohnny Huang 
1591cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
1592*a8bd6d8cSJohnny Huang 		printf("%-10X", i);
1593737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1594737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1595737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1596737ed20bSJohnny Huang 		printf("   ");
159769d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1598737ed20bSJohnny Huang 			printf("protected and not writable");
159969d5fd8fSJohnny Huang 		} else {
1600737ed20bSJohnny Huang 			printf("not protected ");
160169d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1602737ed20bSJohnny Huang 				printf("and no remaining times to write.");
160369d5fd8fSJohnny Huang 			} else {
1604737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
160569d5fd8fSJohnny Huang 			}
160669d5fd8fSJohnny Huang 		}
1607737ed20bSJohnny Huang 		printf("\n");
160869d5fd8fSJohnny Huang 	}
16092a856b9aSJohnny Huang 
16102a856b9aSJohnny Huang 	return OTP_SUCCESS;
161169d5fd8fSJohnny Huang }
161269d5fd8fSJohnny Huang 
161369d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
161469d5fd8fSJohnny Huang {
161569d5fd8fSJohnny Huang 	int i, j;
161669d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
161769d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
161869d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
161969d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
162069d5fd8fSJohnny Huang 	int fail = 0;
16217e22f42dSJohnny Huang 	int pass = 0;
16227e22f42dSJohnny Huang 	int soak = 0;
162366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
162469d5fd8fSJohnny Huang 
16257f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
162669d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
162769d5fd8fSJohnny Huang 
16287f795e57SJohnny Huang 	printf("Check writable...\n");
16297f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
16307f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
16317f795e57SJohnny Huang 		return OTP_FAILURE;
16327f795e57SJohnny Huang 	}
16337e22f42dSJohnny Huang 
16347f795e57SJohnny Huang 	otp_soak(0);
163569d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
16364c1c9b35SJohnny Huang 		printProgress(i + 1, 64, "");
163769d5fd8fSJohnny Huang 		prog_address = 0x800;
163869d5fd8fSJohnny Huang 		if (i < 32) {
163969d5fd8fSJohnny Huang 			offset = i;
164069d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
164169d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
164269d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
164369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
164469d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
164569d5fd8fSJohnny Huang 
164669d5fd8fSJohnny Huang 		} else {
164769d5fd8fSJohnny Huang 			offset = (i - 32);
164869d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
164969d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
165069d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
165169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
165269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
165369d5fd8fSJohnny Huang 		}
165469d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
165569d5fd8fSJohnny Huang 
165669d5fd8fSJohnny Huang 		if (kbit == 1) {
165769d5fd8fSJohnny Huang 			continue;
165869d5fd8fSJohnny Huang 		}
165969d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
166069d5fd8fSJohnny Huang 			continue;
166169d5fd8fSJohnny Huang 		}
166269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
166369d5fd8fSJohnny Huang 			fail = 1;
166469d5fd8fSJohnny Huang 			continue;
166569d5fd8fSJohnny Huang 		}
166669d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
166769d5fd8fSJohnny Huang 			fail = 1;
166869d5fd8fSJohnny Huang 			continue;
166969d5fd8fSJohnny Huang 		}
16707e22f42dSJohnny Huang 
16717e22f42dSJohnny Huang 		if (soak) {
167269d5fd8fSJohnny Huang 			soak = 0;
16737e22f42dSJohnny Huang 			otp_soak(0);
16747e22f42dSJohnny Huang 		}
16757e22f42dSJohnny Huang 
16767e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
16777e22f42dSJohnny Huang 
16787e22f42dSJohnny Huang 		pass = 0;
16797e22f42dSJohnny Huang 
168069d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1681a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
168269d5fd8fSJohnny Huang 				pass = 1;
168369d5fd8fSJohnny Huang 				break;
168469d5fd8fSJohnny Huang 			}
16857e22f42dSJohnny Huang 			if (soak == 0) {
168669d5fd8fSJohnny Huang 				soak = 1;
16877e22f42dSJohnny Huang 				otp_soak(1);
16884b65a65dSJohnny Huang 			}
168969d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
169069d5fd8fSJohnny Huang 		}
169169d5fd8fSJohnny Huang 		if (!pass)
16922a856b9aSJohnny Huang 			return OTP_FAILURE;
169369d5fd8fSJohnny Huang 
169469d5fd8fSJohnny Huang 		if (pbit == 0)
169569d5fd8fSJohnny Huang 			continue;
169669d5fd8fSJohnny Huang 		prog_address = 0x800;
169769d5fd8fSJohnny Huang 		if (i < 32)
169869d5fd8fSJohnny Huang 			prog_address |= 0x60c;
169969d5fd8fSJohnny Huang 		else
170069d5fd8fSJohnny Huang 			prog_address |= 0x60e;
170169d5fd8fSJohnny Huang 
17027e22f42dSJohnny Huang 
17037e22f42dSJohnny Huang 		if (soak) {
17047e22f42dSJohnny Huang 			soak = 0;
17057e22f42dSJohnny Huang 			otp_soak(0);
17067e22f42dSJohnny Huang 		}
17077e22f42dSJohnny Huang 
17087e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
17097e22f42dSJohnny Huang 
17107e22f42dSJohnny Huang 		pass = 0;
17117e22f42dSJohnny Huang 
171269d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
17137e22f42dSJohnny Huang 
1714a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
171569d5fd8fSJohnny Huang 				pass = 1;
171669d5fd8fSJohnny Huang 				break;
171769d5fd8fSJohnny Huang 			}
17187e22f42dSJohnny Huang 			if (soak == 0) {
171969d5fd8fSJohnny Huang 				soak = 1;
17207e22f42dSJohnny Huang 				otp_soak(1);
172169d5fd8fSJohnny Huang 			}
172269d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
172369d5fd8fSJohnny Huang 		}
172469d5fd8fSJohnny Huang 		if (!pass)
17252a856b9aSJohnny Huang 			return OTP_FAILURE;
172669d5fd8fSJohnny Huang 
172769d5fd8fSJohnny Huang 	}
172869d5fd8fSJohnny Huang 	if (fail == 1)
17292a856b9aSJohnny Huang 		return OTP_FAILURE;
173069d5fd8fSJohnny Huang 	else
17312a856b9aSJohnny Huang 		return OTP_SUCCESS;
173269d5fd8fSJohnny Huang 
173369d5fd8fSJohnny Huang }
173469d5fd8fSJohnny Huang 
1735cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak)
1736cd1610b4SJohnny Huang {
1737cd1610b4SJohnny Huang 	int prog_bit;
1738cd1610b4SJohnny Huang 
17397e22f42dSJohnny Huang 	otp_soak(soak);
17407e22f42dSJohnny Huang 
1741cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1742cd1610b4SJohnny Huang 		if (value)
1743cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1744cd1610b4SJohnny Huang 		else
1745cd1610b4SJohnny Huang 			return;
1746cd1610b4SJohnny Huang 	} else {
1747cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1748cd1610b4SJohnny Huang 		if (!value)
1749cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1750cd1610b4SJohnny Huang 		else
1751cd1610b4SJohnny Huang 			return;
1752cd1610b4SJohnny Huang 	}
1753cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1754cd1610b4SJohnny Huang }
1755cd1610b4SJohnny Huang 
1756d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
17574c1c9b35SJohnny Huang {
17584c1c9b35SJohnny Huang 	int i, k;
17594c1c9b35SJohnny Huang 	int pass;
1760d90825e2SJohnny Huang 	int soak = 0;
17614c1c9b35SJohnny Huang 	uint32_t prog_address;
1762d90825e2SJohnny Huang 	uint32_t data[2048];
17634c1c9b35SJohnny Huang 	uint32_t compare[2];
1764d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
17654c1c9b35SJohnny Huang 
1766d90825e2SJohnny Huang 	uint32_t data0_masked;
1767d90825e2SJohnny Huang 	uint32_t data1_masked;
1768d90825e2SJohnny Huang 	uint32_t buf0_masked;
1769d90825e2SJohnny Huang 	uint32_t buf1_masked;
17704c1c9b35SJohnny Huang 
17714c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
17724c1c9b35SJohnny Huang 
1773d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1774d90825e2SJohnny Huang 	for (i = 0; i < 2048 ; i += 2) {
1775d90825e2SJohnny Huang 		printProgress(i + 2, 2048, "");
1776d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
17774c1c9b35SJohnny Huang 	}
1778d90825e2SJohnny Huang 
17794c1c9b35SJohnny Huang 
17804c1c9b35SJohnny Huang 	printf("Check writable...\n");
1781d90825e2SJohnny Huang 	for (i = 0; i < 2048; i++) {
1782d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1783d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1784d90825e2SJohnny Huang 		if (data0_masked == buf0_masked)
17854c1c9b35SJohnny Huang 			continue;
1786d90825e2SJohnny Huang 		if (i % 2 == 0) {
1787d90825e2SJohnny Huang 			if ((data0_masked | buf0_masked) == buf0_masked) {
17884c1c9b35SJohnny Huang 				continue;
17894c1c9b35SJohnny Huang 			} else {
17904c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1791d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
17924c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1793d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
17942a856b9aSJohnny Huang 				return OTP_FAILURE;
179569d5fd8fSJohnny Huang 			}
1796d90825e2SJohnny Huang 		} else {
1797d90825e2SJohnny Huang 			if ((data0_masked & buf0_masked) == buf0_masked) {
1798d90825e2SJohnny Huang 				continue;
1799d90825e2SJohnny Huang 			} else {
1800d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1801d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1802d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1803d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
18042a856b9aSJohnny Huang 				return OTP_FAILURE;
1805d90825e2SJohnny Huang 			}
1806d90825e2SJohnny Huang 		}
1807d90825e2SJohnny Huang 	}
180869d5fd8fSJohnny Huang 
1809d90825e2SJohnny Huang 	printf("Start Programing...\n");
1810d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1811d90825e2SJohnny Huang 
1812d90825e2SJohnny Huang 	for (i = 0; i < 2048; i += 2) {
1813d90825e2SJohnny Huang 		prog_address = i;
1814d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1815d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1816d90825e2SJohnny Huang 		data1_masked = data[i + 1]  & ~buf_keep[i + 1];
1817d90825e2SJohnny Huang 		buf1_masked  = buf[i + 1] & ~buf_keep[i + 1];
1818d90825e2SJohnny Huang 		if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) {
1819d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1820d90825e2SJohnny Huang 			continue;
1821d90825e2SJohnny Huang 		}
1822d90825e2SJohnny Huang 		if (soak) {
1823d90825e2SJohnny Huang 			soak = 0;
1824d90825e2SJohnny Huang 			otp_soak(0);
1825d90825e2SJohnny Huang 		}
1826d90825e2SJohnny Huang 		if (data1_masked == buf1_masked) {
1827d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1828d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1829d90825e2SJohnny Huang 		} else if (data0_masked == buf0_masked) {
1830d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1831d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1832d90825e2SJohnny Huang 		} else {
1833d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1834d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1835d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1836d90825e2SJohnny Huang 		}
1837d90825e2SJohnny Huang 
1838d90825e2SJohnny Huang 		pass = 0;
1839d90825e2SJohnny Huang 		for (k = 0; k < RETRY; k++) {
1840d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) {
1841d90825e2SJohnny Huang 				if (soak == 0) {
1842d90825e2SJohnny Huang 					soak = 1;
1843d90825e2SJohnny Huang 					otp_soak(1);
1844d90825e2SJohnny Huang 				}
1845d90825e2SJohnny Huang 				if (compare[0] != 0) {
1846d90825e2SJohnny Huang 					otp_prog_dw(compare[0], buf_keep[i], prog_address);
1847d90825e2SJohnny Huang 				}
1848d90825e2SJohnny Huang 				if (compare[1] != ~0) {
1849d90825e2SJohnny Huang 					otp_prog_dw(compare[1], buf_keep[i], prog_address + 1);
1850d90825e2SJohnny Huang 				}
1851d90825e2SJohnny Huang 			} else {
1852d90825e2SJohnny Huang 				pass = 1;
1853d90825e2SJohnny Huang 				break;
1854d90825e2SJohnny Huang 			}
1855d90825e2SJohnny Huang 		}
1856d90825e2SJohnny Huang 
1857d90825e2SJohnny Huang 		if (!pass)
18582a856b9aSJohnny Huang 			return OTP_FAILURE;
1859d90825e2SJohnny Huang 	}
18602a856b9aSJohnny Huang 	return OTP_SUCCESS;
1861d90825e2SJohnny Huang 
1862d90825e2SJohnny Huang }
1863d90825e2SJohnny Huang 
1864d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
186569d5fd8fSJohnny Huang {
186669d5fd8fSJohnny Huang 	int ret;
1867d90825e2SJohnny Huang 	int mode;
186869d5fd8fSJohnny Huang 	uint32_t *buf;
1869d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1870d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1871d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
187269d5fd8fSJohnny Huang 
1873d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
187469d5fd8fSJohnny Huang 	if (!buf) {
187569d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
18762a856b9aSJohnny Huang 		return OTP_FAILURE;
187769d5fd8fSJohnny Huang 	}
1878d90825e2SJohnny Huang 
1879d90825e2SJohnny Huang 	if (((buf[0] >> 29) & 0x7) == 0x7) {
1880d90825e2SJohnny Huang 		mode = OTP_REGION_ALL;
1881d90825e2SJohnny Huang 		conf_region = &buf[1];
1882d90825e2SJohnny Huang 		strap_region = &buf[25];
1883d90825e2SJohnny Huang 		data_region = &buf[31];
1884d90825e2SJohnny Huang 	} else {
1885d90825e2SJohnny Huang 		if (buf[0] & BIT(29)) {
1886d90825e2SJohnny Huang 			mode = OTP_REGION_DATA;
1887d90825e2SJohnny Huang 			data_region = &buf[31];
1888d90825e2SJohnny Huang 		}
1889d90825e2SJohnny Huang 		if (buf[0] & BIT(30)) {
1890d90825e2SJohnny Huang 			mode = OTP_REGION_CONF;
1891d90825e2SJohnny Huang 			strap_region = &buf[25];
1892d90825e2SJohnny Huang 		}
1893d90825e2SJohnny Huang 		if (buf[0] & BIT(31)) {
1894d90825e2SJohnny Huang 			mode = OTP_REGION_STRAP;
1895d90825e2SJohnny Huang 			conf_region = &buf[1];
1896d90825e2SJohnny Huang 		}
1897d90825e2SJohnny Huang 	}
189869d5fd8fSJohnny Huang 	if (!nconfirm) {
1899a6d0d645SJohnny Huang 		if (mode == OTP_REGION_CONF) {
19007f795e57SJohnny Huang 			printf("\nOTP configuration region :\n");
190166f2f8e5SJohnny Huang 			if (otp_print_conf_info(conf_region) < 0) {
190269d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
19032a856b9aSJohnny Huang 				return OTP_FAILURE;
190469d5fd8fSJohnny Huang 			}
1905a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_DATA) {
19067f795e57SJohnny Huang 			printf("\nOTP data region :\n");
19077f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
190869d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
19092a856b9aSJohnny Huang 				return OTP_FAILURE;
191069d5fd8fSJohnny Huang 			}
1911a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_STRAP) {
19127f795e57SJohnny Huang 			printf("\nOTP strap region :\n");
1913*a8bd6d8cSJohnny Huang 			if (otp_print_strap_info(strap_region, 1) < 0) {
191469d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
19152a856b9aSJohnny Huang 				return OTP_FAILURE;
191669d5fd8fSJohnny Huang 			}
1917a6d0d645SJohnny Huang 		} else if (mode == OTP_REGION_ALL) {
19187f795e57SJohnny Huang 			printf("\nOTP configuration region :\n");
191966f2f8e5SJohnny Huang 			if (otp_print_conf_info(conf_region) < 0) {
192069d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
19212a856b9aSJohnny Huang 				return OTP_FAILURE;
192269d5fd8fSJohnny Huang 			}
19237f795e57SJohnny Huang 			printf("\nOTP strap region :\n");
1924*a8bd6d8cSJohnny Huang 			if (otp_print_strap_info(strap_region, 1) < 0) {
192569d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
19262a856b9aSJohnny Huang 				return OTP_FAILURE;
192769d5fd8fSJohnny Huang 			}
19287f795e57SJohnny Huang 			printf("\nOTP data region :\n");
19297f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
193069d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
19312a856b9aSJohnny Huang 				return OTP_FAILURE;
193269d5fd8fSJohnny Huang 			}
193369d5fd8fSJohnny Huang 		}
193469d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
193569d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
193669d5fd8fSJohnny Huang 			printf(" Aborting\n");
19372a856b9aSJohnny Huang 			return OTP_FAILURE;
193869d5fd8fSJohnny Huang 		}
193969d5fd8fSJohnny Huang 	}
1940a6d0d645SJohnny Huang 	if (mode == OTP_REGION_CONF) {
1941d90825e2SJohnny Huang 		return otp_prog_conf(conf_region);
1942a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_STRAP) {
1943d90825e2SJohnny Huang 		return otp_prog_strap(strap_region);
1944a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_DATA) {
1945d90825e2SJohnny Huang 		return otp_prog_data(data_region);
1946a6d0d645SJohnny Huang 	} else if (mode == OTP_REGION_ALL) {
194769d5fd8fSJohnny Huang 		printf("programing data region ... ");
1948d90825e2SJohnny Huang 		ret = otp_prog_data(data_region);
19492a856b9aSJohnny Huang 		if (ret != 0) {
195069d5fd8fSJohnny Huang 			printf("Error\n");
195169d5fd8fSJohnny Huang 			return ret;
195269d5fd8fSJohnny Huang 		} else {
195369d5fd8fSJohnny Huang 			printf("Done\n");
195469d5fd8fSJohnny Huang 		}
195569d5fd8fSJohnny Huang 		printf("programing strap region ... ");
1956d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
19572a856b9aSJohnny Huang 		if (ret != 0) {
195869d5fd8fSJohnny Huang 			printf("Error\n");
195969d5fd8fSJohnny Huang 			return ret;
196069d5fd8fSJohnny Huang 		} else {
196169d5fd8fSJohnny Huang 			printf("Done\n");
196269d5fd8fSJohnny Huang 		}
196369d5fd8fSJohnny Huang 		printf("programing configuration region ... ");
1964d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
19652a856b9aSJohnny Huang 		if (ret != 0) {
196669d5fd8fSJohnny Huang 			printf("Error\n");
196769d5fd8fSJohnny Huang 			return ret;
196869d5fd8fSJohnny Huang 		}
196969d5fd8fSJohnny Huang 		printf("Done\n");
19702a856b9aSJohnny Huang 		return OTP_SUCCESS;
197169d5fd8fSJohnny Huang 	}
1972cd1610b4SJohnny Huang 
19732a856b9aSJohnny Huang 	return OTP_USAGE;
19742a856b9aSJohnny Huang }
19752a856b9aSJohnny Huang 
19762a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1977cd1610b4SJohnny Huang {
1978a6af4a17SJohnny Huang 	uint32_t read[2];
1979cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1980d90825e2SJohnny Huang 	uint32_t prog_address = 0;
198166f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1982cd1610b4SJohnny Huang 	int otp_bit;
1983cd1610b4SJohnny Huang 	int i;
1984cd1610b4SJohnny Huang 	int pass;
1985a6af4a17SJohnny Huang 	int ret;
1986cd1610b4SJohnny Huang 
1987cd1610b4SJohnny Huang 	switch (mode) {
1988a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1989a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1990cd1610b4SJohnny Huang 		prog_address = 0x800;
1991cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1992cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1993a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1994cd1610b4SJohnny Huang 		if (otp_bit == value) {
1995a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1996cd1610b4SJohnny Huang 			printf("No need to program\n");
19972a856b9aSJohnny Huang 			return OTP_SUCCESS;
1998cd1610b4SJohnny Huang 		}
1999cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
2000a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
2001cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
20022a856b9aSJohnny Huang 			return OTP_FAILURE;
2003cd1610b4SJohnny Huang 		}
2004a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
2005cd1610b4SJohnny Huang 		break;
2006a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2007cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
2008cd1610b4SJohnny Huang 
2009cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
2010a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
2011a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
2012cd1610b4SJohnny Huang 		} else {
2013a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
2014a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
2015cd1610b4SJohnny Huang 		}
2016cd1610b4SJohnny Huang 		if (otp_bit == value) {
2017a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
2018cd1610b4SJohnny Huang 			printf("No need to program\n");
20192a856b9aSJohnny Huang 			return OTP_SUCCESS;
2020cd1610b4SJohnny Huang 		}
2021cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
2022a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
2023cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
20242a856b9aSJohnny Huang 			return OTP_FAILURE;
2025cd1610b4SJohnny Huang 		}
2026a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
2027cd1610b4SJohnny Huang 		break;
2028a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
2029cd1610b4SJohnny Huang 		otp_strp_status(otpstrap);
2030cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
2031cd1610b4SJohnny Huang 		if (bit_offset < 32) {
2032cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
2033cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
2034cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
2035cd1610b4SJohnny Huang 			strap_buf[5] = 0;
20362a856b9aSJohnny Huang 			// if (protect)
20372a856b9aSJohnny Huang 			// 	strap_buf[4] = BIT(bit_offset);
20382a856b9aSJohnny Huang 			// else
20392a856b9aSJohnny Huang 			// 	strap_buf[4] = 0;
2040cd1610b4SJohnny Huang 		} else {
2041cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
2042cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
2043cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
2044cd1610b4SJohnny Huang 			strap_buf[4] = 0;
20452a856b9aSJohnny Huang 			// if (protect)
20462a856b9aSJohnny Huang 			// 	strap_buf[5] = BIT(bit_offset - 32);
20472a856b9aSJohnny Huang 			// else
20482a856b9aSJohnny Huang 			// 	strap_buf[5] = 0;
2049cd1610b4SJohnny Huang 		}
205076d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
2051a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
20522a856b9aSJohnny Huang 			return OTP_FAILURE;
2053a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
2054a6af4a17SJohnny Huang 			return OTP_SUCCESS;
2055a6af4a17SJohnny Huang 
2056cd1610b4SJohnny Huang 		break;
2057cd1610b4SJohnny Huang 	}
2058cd1610b4SJohnny Huang 
2059cd1610b4SJohnny Huang 	if (!nconfirm) {
2060cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2061cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
2062cd1610b4SJohnny Huang 			printf(" Aborting\n");
20632a856b9aSJohnny Huang 			return OTP_FAILURE;
2064cd1610b4SJohnny Huang 		}
2065cd1610b4SJohnny Huang 	}
2066cd1610b4SJohnny Huang 
2067cd1610b4SJohnny Huang 	switch (mode) {
2068a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
2069cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
2070a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2071a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2072cd1610b4SJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset, 0);
2073cd1610b4SJohnny Huang 		pass = -1;
2074cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
2075a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
2076cd1610b4SJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset, 1);
2077cd1610b4SJohnny Huang 			} else {
2078cd1610b4SJohnny Huang 				pass = 0;
2079cd1610b4SJohnny Huang 				break;
2080cd1610b4SJohnny Huang 			}
2081cd1610b4SJohnny Huang 		}
20822a856b9aSJohnny Huang 		if (pass == 0)
20832a856b9aSJohnny Huang 			return OTP_SUCCESS;
2084cd1610b4SJohnny Huang 	}
2085cd1610b4SJohnny Huang 
20862a856b9aSJohnny Huang 	return OTP_USAGE;
2087cd1610b4SJohnny Huang }
2088cd1610b4SJohnny Huang 
20892a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
209069d5fd8fSJohnny Huang {
20912a856b9aSJohnny Huang 	uint32_t offset, count;
20922a856b9aSJohnny Huang 	int ret;
209369d5fd8fSJohnny Huang 
20942a856b9aSJohnny Huang 	if (argc == 4) {
20952a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
20962a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
20972a856b9aSJohnny Huang 	} else if (argc == 3) {
20982a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
20992a856b9aSJohnny Huang 		count = 1;
21002a856b9aSJohnny Huang 	} else {
210169d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
210269d5fd8fSJohnny Huang 	}
210369d5fd8fSJohnny Huang 
210469d5fd8fSJohnny Huang 
21052a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
210669d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
21072a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
21082a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
21092a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
21102a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
21112a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
21122a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
21132a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
21142a856b9aSJohnny Huang 	} else {
21152a856b9aSJohnny Huang 		return CMD_RET_USAGE;
211669d5fd8fSJohnny Huang 	}
211769d5fd8fSJohnny Huang 
21182a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
21192a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
21202a856b9aSJohnny Huang 	else
21212a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21222a856b9aSJohnny Huang 
21232a856b9aSJohnny Huang }
21242a856b9aSJohnny Huang 
21252a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21262a856b9aSJohnny Huang {
21272a856b9aSJohnny Huang 	phys_addr_t addr;
21282a856b9aSJohnny Huang 	uint32_t byte_size;
21292a856b9aSJohnny Huang 	int ret;
21302a856b9aSJohnny Huang 
21312a856b9aSJohnny Huang 	if (argc == 4) {
21322a856b9aSJohnny Huang 		if (strcmp(argv[1], "f"))
21332a856b9aSJohnny Huang 			return CMD_RET_USAGE;
21342a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
21352a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
213669d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
21372a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
21382a856b9aSJohnny Huang 	} else if (argc == 3) {
21392a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
21402a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
21412a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
21422a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
21432a856b9aSJohnny Huang 	} else {
21442a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21452a856b9aSJohnny Huang 	}
21462a856b9aSJohnny Huang 
21472a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
21482a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
21492a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
21502a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
21512a856b9aSJohnny Huang 	else
21522a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21532a856b9aSJohnny Huang }
21542a856b9aSJohnny Huang 
21552a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21562a856b9aSJohnny Huang {
21572a856b9aSJohnny Huang 	int mode = 0;
21582a856b9aSJohnny Huang 	int nconfirm = 0;
21592a856b9aSJohnny Huang 	int otp_addr = 0;
21602a856b9aSJohnny Huang 	int bit_offset;
21612a856b9aSJohnny Huang 	int value;
21622a856b9aSJohnny Huang 	int ret;
21632a856b9aSJohnny Huang 
21642a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
21652a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21662a856b9aSJohnny Huang 
21672a856b9aSJohnny Huang 	/* Drop the pb cmd */
21682a856b9aSJohnny Huang 	argc--;
21692a856b9aSJohnny Huang 	argv++;
21702a856b9aSJohnny Huang 
21712a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2172a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
21732a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2174a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
21752a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
2176a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
2177cd1610b4SJohnny Huang 	else
21782a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21792a856b9aSJohnny Huang 
21802a856b9aSJohnny Huang 	/* Drop the region cmd */
21812a856b9aSJohnny Huang 	argc--;
21822a856b9aSJohnny Huang 	argv++;
21832a856b9aSJohnny Huang 
21842a856b9aSJohnny Huang 	if (!strcmp(argv[0], "f")) {
2185cd1610b4SJohnny Huang 		nconfirm = 1;
21862a856b9aSJohnny Huang 		/* Drop the force option */
21872a856b9aSJohnny Huang 		argc--;
21882a856b9aSJohnny Huang 		argv++;
21892a856b9aSJohnny Huang 	}
2190cd1610b4SJohnny Huang 
2191a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
21922a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
21932a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
2194cd1610b4SJohnny Huang 		if (bit_offset >= 64)
21952a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2196cd1610b4SJohnny Huang 	} else {
21972a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
21982a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
21992a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
2200cd1610b4SJohnny Huang 		if (bit_offset >= 32)
22012a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2202cd1610b4SJohnny Huang 	}
2203cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
22042a856b9aSJohnny Huang 		return CMD_RET_USAGE;
2205cd1610b4SJohnny Huang 
2206cd1610b4SJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
22072a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
22082a856b9aSJohnny Huang 
22092a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
22102a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
22112a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
22122a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
22132a856b9aSJohnny Huang 	else
22142a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22152a856b9aSJohnny Huang }
22162a856b9aSJohnny Huang 
22172a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
22182a856b9aSJohnny Huang {
22192a856b9aSJohnny Huang 	phys_addr_t addr;
22202a856b9aSJohnny Huang 	int otp_addr = 0;
22212a856b9aSJohnny Huang 
22222a856b9aSJohnny Huang 	if (argc != 3)
22232a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22242a856b9aSJohnny Huang 
222569d5fd8fSJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
22262a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
22272a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
22282a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
222969d5fd8fSJohnny Huang 		printf("Compare pass\n");
22302a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
223169d5fd8fSJohnny Huang 	} else {
223269d5fd8fSJohnny Huang 		printf("Compare fail\n");
22332a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
223469d5fd8fSJohnny Huang 	}
223569d5fd8fSJohnny Huang }
223669d5fd8fSJohnny Huang 
223766f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
223866f2f8e5SJohnny Huang {
2239*a8bd6d8cSJohnny Huang 	int mode = 0;
2240*a8bd6d8cSJohnny Huang 	int view = 0;
2241*a8bd6d8cSJohnny Huang 
2242*a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
224366f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
224466f2f8e5SJohnny Huang 
2245*a8bd6d8cSJohnny Huang 	/* Drop the info cmd */
2246*a8bd6d8cSJohnny Huang 	argc--;
2247*a8bd6d8cSJohnny Huang 	argv++;
224866f2f8e5SJohnny Huang 
2249*a8bd6d8cSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2250*a8bd6d8cSJohnny Huang 		mode = OTP_REGION_CONF;
2251*a8bd6d8cSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2252*a8bd6d8cSJohnny Huang 		mode = OTP_REGION_STRAP;
2253*a8bd6d8cSJohnny Huang 	else
2254*a8bd6d8cSJohnny Huang 		return CMD_RET_USAGE;
2255*a8bd6d8cSJohnny Huang 
2256*a8bd6d8cSJohnny Huang 	/* Drop the region cmd */
2257*a8bd6d8cSJohnny Huang 	argc--;
2258*a8bd6d8cSJohnny Huang 	argv++;
2259*a8bd6d8cSJohnny Huang 
2260*a8bd6d8cSJohnny Huang 	if (!strcmp(argv[0], "v")) {
2261*a8bd6d8cSJohnny Huang 		view = 1;
2262*a8bd6d8cSJohnny Huang 		/* Drop the view option */
2263*a8bd6d8cSJohnny Huang 		argc--;
2264*a8bd6d8cSJohnny Huang 		argv++;
2265*a8bd6d8cSJohnny Huang 	}
2266*a8bd6d8cSJohnny Huang 
2267*a8bd6d8cSJohnny Huang 	if (mode == OTP_REGION_CONF) {
226866f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
226966f2f8e5SJohnny Huang 		otp_info_config();
2270*a8bd6d8cSJohnny Huang 	} else if (mode == OTP_REGION_STRAP) {
227166f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
2272*a8bd6d8cSJohnny Huang 		otp_info_strap(view);
227366f2f8e5SJohnny Huang 	} else {
227466f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
227566f2f8e5SJohnny Huang 	}
227666f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
227766f2f8e5SJohnny Huang }
227866f2f8e5SJohnny Huang 
2279737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2280737ed20bSJohnny Huang {
2281737ed20bSJohnny Huang 	int input;
2282737ed20bSJohnny Huang 	int bit_offset;
2283737ed20bSJohnny Huang 	int prog_address;
2284737ed20bSJohnny Huang 	int pass;
2285737ed20bSJohnny Huang 	int i;
2286737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2287737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2288737ed20bSJohnny Huang 
2289737ed20bSJohnny Huang 	if (!strcmp(argv[0], "f")) {
2290737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2291737ed20bSJohnny Huang 	} else {
2292737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2293737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2294737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2295737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2296737ed20bSJohnny Huang 			printf(" Aborting\n");
2297737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2298737ed20bSJohnny Huang 		}
2299737ed20bSJohnny Huang 	}
2300737ed20bSJohnny Huang 
2301737ed20bSJohnny Huang 	prog_address = 0x800;
2302737ed20bSJohnny Huang 	if (input < 32) {
2303737ed20bSJohnny Huang 		bit_offset = input;
2304737ed20bSJohnny Huang 		prog_address |= 0x60c;
2305737ed20bSJohnny Huang 	} else if (input < 64) {
2306737ed20bSJohnny Huang 		bit_offset = input - 32;
2307737ed20bSJohnny Huang 		prog_address |= 0x60e;
2308737ed20bSJohnny Huang 	} else {
2309737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2310737ed20bSJohnny Huang 	}
2311737ed20bSJohnny Huang 
2312737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2313737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2314737ed20bSJohnny Huang 	}
2315737ed20bSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset, 0);
2316737ed20bSJohnny Huang 	pass = -1;
2317737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2318737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2319737ed20bSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset, 1);
2320737ed20bSJohnny Huang 		} else {
2321737ed20bSJohnny Huang 			pass = 0;
2322737ed20bSJohnny Huang 			break;
2323737ed20bSJohnny Huang 		}
2324737ed20bSJohnny Huang 	}
2325737ed20bSJohnny Huang 	if (pass == 0) {
2326737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2327737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2328737ed20bSJohnny Huang 	}
2329737ed20bSJohnny Huang 
2330737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2331737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2332737ed20bSJohnny Huang 
2333737ed20bSJohnny Huang }
23342a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
23352a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2336*a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
23372a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
23382a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2339737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
23402a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
23412a856b9aSJohnny Huang };
23422a856b9aSJohnny Huang 
23432a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
23442a856b9aSJohnny Huang {
23452a856b9aSJohnny Huang 	cmd_tbl_t *cp;
23462a856b9aSJohnny Huang 
23472a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
23482a856b9aSJohnny Huang 
2349737ed20bSJohnny Huang 	/* Drop the otp command */
23502a856b9aSJohnny Huang 	argc--;
23512a856b9aSJohnny Huang 	argv++;
23522a856b9aSJohnny Huang 
23532a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
23542a856b9aSJohnny Huang 		return CMD_RET_USAGE;
23552a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
23562a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
23572a856b9aSJohnny Huang 
23582a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
235969d5fd8fSJohnny Huang }
236069d5fd8fSJohnny Huang 
236169d5fd8fSJohnny Huang U_BOOT_CMD(
236269d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
236369d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
23642a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
23652a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
2366*a8bd6d8cSJohnny Huang 	"otp info conf|strap [v]\n"
2367d90825e2SJohnny Huang 	"otp prog [f] <addr> <byte_size>\n"
2368cd1610b4SJohnny Huang 	"otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n"
2369737ed20bSJohnny Huang 	"otp pb strap [f] <bit_offset> <value>\n"
2370737ed20bSJohnny Huang 	"otp protect [f] <bit_offset>\n"
23712a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
237269d5fd8fSJohnny Huang );
2373