xref: /openbmc/u-boot/cmd/otp.c (revision e14b073c)
1a219f6deSJohnny Huang // SPDX-License-Identifier: GPL-2.0+
269d5fd8fSJohnny Huang /*
3a219f6deSJohnny Huang  * Copyright 2021 Aspeed Technology Inc.
469d5fd8fSJohnny Huang  */
54c1c9b35SJohnny Huang #include <stdlib.h>
669d5fd8fSJohnny Huang #include <common.h>
769d5fd8fSJohnny Huang #include <console.h>
869d5fd8fSJohnny Huang #include <bootretry.h>
969d5fd8fSJohnny Huang #include <cli.h>
1069d5fd8fSJohnny Huang #include <command.h>
1169d5fd8fSJohnny Huang #include <console.h>
124c1c9b35SJohnny Huang #include <malloc.h>
1369d5fd8fSJohnny Huang #include <inttypes.h>
1469d5fd8fSJohnny Huang #include <mapmem.h>
1569d5fd8fSJohnny Huang #include <asm/io.h>
1669d5fd8fSJohnny Huang #include <linux/compiler.h>
17696656c6SJohnny Huang #include <u-boot/sha256.h>
180cee9a95SJohnny Huang #include "otp_info.h"
1969d5fd8fSJohnny Huang 
2069d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2169d5fd8fSJohnny Huang 
2264b66712SJohnny Huang #define OTP_VER				"1.0.3"
23f67375f7SJohnny Huang 
2469d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
25dacbba92SJohnny Huang #define RETRY				20
267332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
277332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
287332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
2969d5fd8fSJohnny Huang 
302a856b9aSJohnny Huang #define OTP_USAGE			-1
312a856b9aSJohnny Huang #define OTP_FAILURE			-2
322a856b9aSJohnny Huang #define OTP_SUCCESS			0
332a856b9aSJohnny Huang 
34a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
35a6af4a17SJohnny Huang 
36181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PUB		1
37181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PRIV		2
38181f72d8SJohnny Huang #define OTP_KEY_TYPE_AES		3
39181f72d8SJohnny Huang #define OTP_KEY_TYPE_VAULT		4
40181f72d8SJohnny Huang #define OTP_KEY_TYPE_HMAC		5
419a4fe690SJohnny Huang 
424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
434c1c9b35SJohnny Huang #define PBWIDTH 60
444c1c9b35SJohnny Huang 
453d3688adSJohnny Huang #define OTP_BASE		0x1e6f2000
463d3688adSJohnny Huang #define OTP_PROTECT_KEY		OTP_BASE
473d3688adSJohnny Huang #define OTP_COMMAND		OTP_BASE + 0x4
483d3688adSJohnny Huang #define OTP_TIMING		OTP_BASE + 0x8
493d3688adSJohnny Huang #define OTP_ADDR		OTP_BASE + 0x10
503d3688adSJohnny Huang #define OTP_STATUS		OTP_BASE + 0x14
513d3688adSJohnny Huang #define OTP_COMPARE_1		OTP_BASE + 0x20
523d3688adSJohnny Huang #define OTP_COMPARE_2		OTP_BASE + 0x24
533d3688adSJohnny Huang #define OTP_COMPARE_3		OTP_BASE + 0x28
543d3688adSJohnny Huang #define OTP_COMPARE_4		OTP_BASE + 0x2c
553d3688adSJohnny Huang 
56696656c6SJohnny Huang #define OTP_MAGIC		"SOCOTP"
57696656c6SJohnny Huang #define CHECKSUM_LEN		32
58a219f6deSJohnny Huang #define OTP_INC_DATA		BIT(31)
59a219f6deSJohnny Huang #define OTP_INC_CONFIG		BIT(30)
60a219f6deSJohnny Huang #define OTP_INC_STRAP		BIT(29)
61a219f6deSJohnny Huang #define OTP_ECC_EN		BIT(28)
62696656c6SJohnny Huang #define OTP_REGION_SIZE(info)	((info >> 16) & 0xffff)
63696656c6SJohnny Huang #define OTP_REGION_OFFSET(info)	(info & 0xffff)
64696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info)	(info & 0xffff)
65696656c6SJohnny Huang 
66696656c6SJohnny Huang #define OTP_AST2600A0		0
67696656c6SJohnny Huang #define OTP_AST2600A1		1
680dae9d52SJohnny Huang #define OTP_AST2600A2		2
6964b66712SJohnny Huang #define OTP_AST2600A3		3
70696656c6SJohnny Huang 
71696656c6SJohnny Huang struct otp_header {
72696656c6SJohnny Huang 	u8	otp_magic[8];
73696656c6SJohnny Huang 	u8	otp_version[8];
74696656c6SJohnny Huang 	u32	image_info;
75696656c6SJohnny Huang 	u32	data_info;
76696656c6SJohnny Huang 	u32	config_info;
77696656c6SJohnny Huang 	u32	strap_info;
78696656c6SJohnny Huang 	u32	checksum_offset;
79a219f6deSJohnny Huang } __packed;
80696656c6SJohnny Huang 
8166f2f8e5SJohnny Huang struct otpstrap_status {
8269d5fd8fSJohnny Huang 	int value;
8369d5fd8fSJohnny Huang 	int option_array[7];
8469d5fd8fSJohnny Huang 	int remain_times;
8569d5fd8fSJohnny Huang 	int writeable_option;
865010032bSJohnny Huang 	int reg_protected;
8769d5fd8fSJohnny Huang 	int protected;
8869d5fd8fSJohnny Huang };
8969d5fd8fSJohnny Huang 
9066f2f8e5SJohnny Huang struct otpconf_parse {
9166f2f8e5SJohnny Huang 	int dw_offset;
9266f2f8e5SJohnny Huang 	int bit;
9366f2f8e5SJohnny Huang 	int length;
9466f2f8e5SJohnny Huang 	int value;
95696656c6SJohnny Huang 	int ignore;
9666f2f8e5SJohnny Huang 	char status[80];
9766f2f8e5SJohnny Huang };
9866f2f8e5SJohnny Huang 
999a4fe690SJohnny Huang struct otpkey_type {
1009a4fe690SJohnny Huang 	int value;
1019a4fe690SJohnny Huang 	int key_type;
1029a4fe690SJohnny Huang 	int need_id;
1039a4fe690SJohnny Huang 	char information[110];
1049a4fe690SJohnny Huang };
1059a4fe690SJohnny Huang 
1069a4fe690SJohnny Huang struct otp_info_cb {
1079a4fe690SJohnny Huang 	int version;
10879e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1099a4fe690SJohnny Huang 	int strap_info_len;
11079e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1119a4fe690SJohnny Huang 	int conf_info_len;
11279e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1139a4fe690SJohnny Huang 	int key_info_len;
1145010032bSJohnny Huang 
1159a4fe690SJohnny Huang };
1169a4fe690SJohnny Huang 
117696656c6SJohnny Huang struct otp_image_layout {
1185010032bSJohnny Huang 	int data_length;
1195010032bSJohnny Huang 	int conf_length;
1205010032bSJohnny Huang 	int strap_length;
121a219f6deSJohnny Huang 	u8 *data;
122a219f6deSJohnny Huang 	u8 *data_ignore;
123a219f6deSJohnny Huang 	u8 *conf;
124a219f6deSJohnny Huang 	u8 *conf_ignore;
125a219f6deSJohnny Huang 	u8 *strap;
126a219f6deSJohnny Huang 	u8 *strap_reg_pro;
127a219f6deSJohnny Huang 	u8 *strap_pro;
128a219f6deSJohnny Huang 	u8 *strap_ignore;
129696656c6SJohnny Huang };
130696656c6SJohnny Huang 
1319a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1329a4fe690SJohnny Huang 
13379e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
1349a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
1359a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1369a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
137181f72d8SJohnny Huang 	{8, OTP_KEY_TYPE_RSA_PUB,   1, "RSA-public as OEM DSS public keys in Mode 2"},
138181f72d8SJohnny Huang 	{9, OTP_KEY_TYPE_RSA_PUB,   0, "RSA-public as SOC public key"},
139181f72d8SJohnny Huang 	{10, OTP_KEY_TYPE_RSA_PUB,  0, "RSA-public as AES key decryption key"},
140181f72d8SJohnny Huang 	{13, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as SOC private key"},
141181f72d8SJohnny Huang 	{14, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as AES key decryption key"},
1429a4fe690SJohnny Huang };
1439a4fe690SJohnny Huang 
14479e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
1459a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1469a4fe690SJohnny Huang 	{2, OTP_KEY_TYPE_AES,   1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"},
147181f72d8SJohnny Huang 	{8, OTP_KEY_TYPE_RSA_PUB,   1, "RSA-public as OEM DSS public keys in Mode 2"},
148181f72d8SJohnny Huang 	{10, OTP_KEY_TYPE_RSA_PUB,  0, "RSA-public as AES key decryption key"},
149181f72d8SJohnny Huang 	{14, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as AES key decryption key"},
1509a4fe690SJohnny Huang };
1519a4fe690SJohnny Huang 
1525fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = {
1535fdde29fSJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1545fdde29fSJohnny Huang 	{2, OTP_KEY_TYPE_AES,   1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"},
155181f72d8SJohnny Huang 	{8, OTP_KEY_TYPE_RSA_PUB,   1, "RSA-public as OEM DSS public keys in Mode 2"},
156181f72d8SJohnny Huang 	{10, OTP_KEY_TYPE_RSA_PUB,  0, "RSA-public as AES key decryption key"},
157181f72d8SJohnny Huang 	{14, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as AES key decryption key"},
158181f72d8SJohnny Huang };
159181f72d8SJohnny Huang 
160181f72d8SJohnny Huang static const struct otpkey_type a3_key_type[] = {
161181f72d8SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
162181f72d8SJohnny Huang 	{2, OTP_KEY_TYPE_AES,   1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"},
163181f72d8SJohnny Huang 	{8, OTP_KEY_TYPE_RSA_PUB,   1, "RSA-public as OEM DSS public keys in Mode 2"},
164181f72d8SJohnny Huang 	{9, OTP_KEY_TYPE_RSA_PUB,   1, "RSA-public as OEM DSS public keys in Mode 2(big endian)"},
165181f72d8SJohnny Huang 	{10, OTP_KEY_TYPE_RSA_PUB,  0, "RSA-public as AES key decryption key"},
166181f72d8SJohnny Huang 	{11, OTP_KEY_TYPE_RSA_PUB,  0, "RSA-public as AES key decryption key(big endian)"},
167181f72d8SJohnny Huang 	{12, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as AES key decryption key"},
168181f72d8SJohnny Huang 	{13, OTP_KEY_TYPE_RSA_PRIV,  0, "RSA-private as AES key decryption key(big endian)"},
1695fdde29fSJohnny Huang };
1705fdde29fSJohnny Huang 
171a219f6deSJohnny Huang static u32  chip_version(void)
1729a4fe690SJohnny Huang {
173badd21c2SJohnny Huang 	u64 rev_id;
1749a4fe690SJohnny Huang 
175badd21c2SJohnny Huang 	rev_id = readl(ASPEED_REVISION_ID0);
176badd21c2SJohnny Huang 	rev_id = ((u64)readl(ASPEED_REVISION_ID1) << 32) | rev_id;
1779a4fe690SJohnny Huang 
178badd21c2SJohnny Huang 	if (rev_id == 0x0500030305000303) {
179badd21c2SJohnny Huang 		/* AST2600-A0 */
1800dae9d52SJohnny Huang 		return OTP_AST2600A0;
181badd21c2SJohnny Huang 	} else if (rev_id == 0x0501030305010303) {
182badd21c2SJohnny Huang 		/* AST2600-A1 */
1830dae9d52SJohnny Huang 		return OTP_AST2600A1;
184badd21c2SJohnny Huang 	} else if (rev_id == 0x0501020305010203) {
185badd21c2SJohnny Huang 		/* AST2620-A1 */
186badd21c2SJohnny Huang 		return OTP_AST2600A1;
187badd21c2SJohnny Huang 	} else if (rev_id == 0x0502030305010303) {
188badd21c2SJohnny Huang 		/* AST2600-A2 */
1890dae9d52SJohnny Huang 		return OTP_AST2600A2;
190badd21c2SJohnny Huang 	} else if (rev_id == 0x0502020305010203) {
191badd21c2SJohnny Huang 		/* AST2620-A2 */
192badd21c2SJohnny Huang 		return OTP_AST2600A2;
193badd21c2SJohnny Huang 	} else if (rev_id == 0x0502010305010103) {
194badd21c2SJohnny Huang 		/* AST2605-A2 */
1950dae9d52SJohnny Huang 		return OTP_AST2600A2;
19664b66712SJohnny Huang 	} else if (rev_id == 0x0503030305030303) {
19764b66712SJohnny Huang 		/* AST2600-A3 */
19864b66712SJohnny Huang 		return OTP_AST2600A3;
19964b66712SJohnny Huang 	} else if (rev_id == 0x0503020305030203) {
20064b66712SJohnny Huang 		/* AST2620-A3 */
20164b66712SJohnny Huang 		return OTP_AST2600A3;
2020dae9d52SJohnny Huang 	}
2030dae9d52SJohnny Huang 
2045fdde29fSJohnny Huang 	return -1;
2059a4fe690SJohnny Huang }
2069a4fe690SJohnny Huang 
2073d3688adSJohnny Huang static void wait_complete(void)
2083d3688adSJohnny Huang {
2093d3688adSJohnny Huang 	int reg;
2103d3688adSJohnny Huang 
2113d3688adSJohnny Huang 	do {
2123d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
2133d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
2143d3688adSJohnny Huang }
2153d3688adSJohnny Huang 
216a219f6deSJohnny Huang static void otp_write(u32 otp_addr, u32 data)
217dacbba92SJohnny Huang {
218dacbba92SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
219dacbba92SJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
220dacbba92SJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
221dacbba92SJohnny Huang 	wait_complete();
222dacbba92SJohnny Huang }
223dacbba92SJohnny Huang 
224dacbba92SJohnny Huang static void otp_soak(int soak)
225dacbba92SJohnny Huang {
22664b66712SJohnny Huang 	if (info_cb.version == OTP_AST2600A2 || info_cb.version == OTP_AST2600A3) {
227dacbba92SJohnny Huang 		switch (soak) {
228dacbba92SJohnny Huang 		case 0: //default
229dacbba92SJohnny Huang 			otp_write(0x3000, 0x0210); // Write MRA
230dacbba92SJohnny Huang 			otp_write(0x5000, 0x2000); // Write MRB
231dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
232dacbba92SJohnny Huang 			break;
233dacbba92SJohnny Huang 		case 1: //normal program
234dacbba92SJohnny Huang 			otp_write(0x3000, 0x1200); // Write MRA
235feea3fdfSJohnny Huang 			otp_write(0x5000, 0x107F); // Write MRB
236dacbba92SJohnny Huang 			otp_write(0x1000, 0x1024); // Write MR
237feea3fdfSJohnny Huang 			writel(0x04191388, OTP_TIMING); // 200us
238dacbba92SJohnny Huang 			break;
239dacbba92SJohnny Huang 		case 2: //soak program
240dacbba92SJohnny Huang 			otp_write(0x3000, 0x1220); // Write MRA
241feea3fdfSJohnny Huang 			otp_write(0x5000, 0x2074); // Write MRB
242dacbba92SJohnny Huang 			otp_write(0x1000, 0x08a4); // Write MR
243feea3fdfSJohnny Huang 			writel(0x04193a98, OTP_TIMING); // 600us
244dacbba92SJohnny Huang 			break;
245dacbba92SJohnny Huang 		}
246dacbba92SJohnny Huang 	} else {
247dacbba92SJohnny Huang 		switch (soak) {
248dacbba92SJohnny Huang 		case 0: //default
249dacbba92SJohnny Huang 			otp_write(0x3000, 0x0); // Write MRA
250dacbba92SJohnny Huang 			otp_write(0x5000, 0x0); // Write MRB
251dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
252dacbba92SJohnny Huang 			break;
253dacbba92SJohnny Huang 		case 1: //normal program
254dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
255dacbba92SJohnny Huang 			otp_write(0x5000, 0x302f); // Write MRB
256dacbba92SJohnny Huang 			otp_write(0x1000, 0x4020); // Write MR
257feea3fdfSJohnny Huang 			writel(0x04190760, OTP_TIMING); // 75us
258dacbba92SJohnny Huang 			break;
259dacbba92SJohnny Huang 		case 2: //soak program
260dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
261dacbba92SJohnny Huang 			otp_write(0x5000, 0x1027); // Write MRB
262dacbba92SJohnny Huang 			otp_write(0x1000, 0x4820); // Write MR
263feea3fdfSJohnny Huang 			writel(0x041930d4, OTP_TIMING); // 500us
264dacbba92SJohnny Huang 			break;
265dacbba92SJohnny Huang 		}
266dacbba92SJohnny Huang 	}
267dacbba92SJohnny Huang 
268dacbba92SJohnny Huang 	wait_complete();
269dacbba92SJohnny Huang }
270dacbba92SJohnny Huang 
271a219f6deSJohnny Huang static void otp_read_data(u32 offset, u32 *data)
27269d5fd8fSJohnny Huang {
2733d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
2743d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2753d3688adSJohnny Huang 	wait_complete();
2763d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
2773d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
27869d5fd8fSJohnny Huang }
27969d5fd8fSJohnny Huang 
280a219f6deSJohnny Huang static void otp_read_config(u32 offset, u32 *data)
28169d5fd8fSJohnny Huang {
28269d5fd8fSJohnny Huang 	int config_offset;
28369d5fd8fSJohnny Huang 
28469d5fd8fSJohnny Huang 	config_offset = 0x800;
28569d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
28669d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
28769d5fd8fSJohnny Huang 
2883d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
2893d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2903d3688adSJohnny Huang 	wait_complete();
2913d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
29269d5fd8fSJohnny Huang }
29369d5fd8fSJohnny Huang 
294a219f6deSJohnny Huang static int otp_print_config(u32 offset, int dw_count)
29569d5fd8fSJohnny Huang {
29669d5fd8fSJohnny Huang 	int i;
297a219f6deSJohnny Huang 	u32 ret[1];
29869d5fd8fSJohnny Huang 
29969d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
3002a856b9aSJohnny Huang 		return OTP_USAGE;
301dacbba92SJohnny Huang 	otp_soak(0);
30269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i++) {
30369d5fd8fSJohnny Huang 		otp_read_config(i, ret);
304a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
30569d5fd8fSJohnny Huang 	}
30669d5fd8fSJohnny Huang 	printf("\n");
3072a856b9aSJohnny Huang 	return OTP_SUCCESS;
30869d5fd8fSJohnny Huang }
30969d5fd8fSJohnny Huang 
310a219f6deSJohnny Huang static int otp_print_data(u32 offset, int dw_count)
31169d5fd8fSJohnny Huang {
31269d5fd8fSJohnny Huang 	int i;
313a219f6deSJohnny Huang 	u32 ret[2];
31469d5fd8fSJohnny Huang 
31569d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
3162a856b9aSJohnny Huang 		return OTP_USAGE;
317dacbba92SJohnny Huang 	otp_soak(0);
31869d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
31969d5fd8fSJohnny Huang 		otp_read_data(i, ret);
32069d5fd8fSJohnny Huang 		if (i % 4 == 0)
32169d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
32269d5fd8fSJohnny Huang 		else
32369d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
32469d5fd8fSJohnny Huang 	}
32569d5fd8fSJohnny Huang 	printf("\n");
3262a856b9aSJohnny Huang 	return OTP_SUCCESS;
32769d5fd8fSJohnny Huang }
32869d5fd8fSJohnny Huang 
329a219f6deSJohnny Huang static int otp_compare(u32 otp_addr, u32 addr)
33069d5fd8fSJohnny Huang {
331a219f6deSJohnny Huang 	u32 ret;
332a219f6deSJohnny Huang 	u32 *buf;
33369d5fd8fSJohnny Huang 
33469d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
33569d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
33669d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
33769d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
33869d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
3393d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
3403d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
3413d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
3423d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
3433d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
3443d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
3453d3688adSJohnny Huang 	wait_complete();
3463d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
34769d5fd8fSJohnny Huang 	if (ret & 0x1)
34869d5fd8fSJohnny Huang 		return 0;
34969d5fd8fSJohnny Huang 	else
35069d5fd8fSJohnny Huang 		return -1;
35169d5fd8fSJohnny Huang }
35269d5fd8fSJohnny Huang 
353a219f6deSJohnny Huang static int verify_bit(u32 otp_addr, int bit_offset, int value)
35469d5fd8fSJohnny Huang {
355a219f6deSJohnny Huang 	u32 ret[2];
35669d5fd8fSJohnny Huang 
35730a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
3583d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
35930a8c590SJohnny Huang 	else
3603d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
36130a8c590SJohnny Huang 
3623d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3633d3688adSJohnny Huang 	wait_complete();
3643d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3653d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
36683655e91SJohnny Huang 
36730a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
36830a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
36969d5fd8fSJohnny Huang 			return 0;
37069d5fd8fSJohnny Huang 		else
37169d5fd8fSJohnny Huang 			return -1;
37230a8c590SJohnny Huang 	} else {
37330a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
37430a8c590SJohnny Huang 			return 0;
37530a8c590SJohnny Huang 		else
37630a8c590SJohnny Huang 			return -1;
37730a8c590SJohnny Huang 	}
37869d5fd8fSJohnny Huang }
37969d5fd8fSJohnny Huang 
380a219f6deSJohnny Huang static u32 verify_dw(u32 otp_addr, u32 *value, u32 *ignore, u32 *compare, int size)
3814c1c9b35SJohnny Huang {
382a219f6deSJohnny Huang 	u32 ret[2];
3834c1c9b35SJohnny Huang 
3844c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
3854c1c9b35SJohnny Huang 
3864c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
3873d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
3884c1c9b35SJohnny Huang 	else
3893d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
3903d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3913d3688adSJohnny Huang 	wait_complete();
3923d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3933d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
3944c1c9b35SJohnny Huang 	if (size == 1) {
3954c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
3964c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
397696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
3984c1c9b35SJohnny Huang 				compare[0] = 0;
3994c1c9b35SJohnny Huang 				return 0;
400a219f6deSJohnny Huang 			}
4014c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
4024c1c9b35SJohnny Huang 			return -1;
4034c1c9b35SJohnny Huang 
4044c1c9b35SJohnny Huang 		} else {
4054c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
406696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
4074c1c9b35SJohnny Huang 				compare[0] = ~0;
4084c1c9b35SJohnny Huang 				return 0;
409a219f6deSJohnny Huang 			}
410d90825e2SJohnny Huang 			compare[0] = ~(value[0] ^ ret[1]);
4114c1c9b35SJohnny Huang 			return -1;
4124c1c9b35SJohnny Huang 		}
4134c1c9b35SJohnny Huang 	} else if (size == 2) {
4144c1c9b35SJohnny Huang 		// otp_addr should be even
415696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
4164c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4174c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4184c1c9b35SJohnny Huang 			compare[0] = 0;
4194c1c9b35SJohnny Huang 			compare[1] = ~0;
4204c1c9b35SJohnny Huang 			return 0;
421a219f6deSJohnny Huang 		}
4224c1c9b35SJohnny Huang 		// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4234c1c9b35SJohnny Huang 		// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4244c1c9b35SJohnny Huang 		compare[0] = value[0] ^ ret[0];
4254c1c9b35SJohnny Huang 		compare[1] = ~(value[1] ^ ret[1]);
4264c1c9b35SJohnny Huang 		return -1;
4274c1c9b35SJohnny Huang 	} else {
4284c1c9b35SJohnny Huang 		return -1;
4294c1c9b35SJohnny Huang 	}
4304c1c9b35SJohnny Huang }
4314c1c9b35SJohnny Huang 
432a219f6deSJohnny Huang static void otp_prog(u32 otp_addr, u32 prog_bit)
43383655e91SJohnny Huang {
43490965bb3SJohnny Huang 	otp_write(0x0, prog_bit);
43583655e91SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
43683655e91SJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
43783655e91SJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
43883655e91SJohnny Huang 	wait_complete();
43983655e91SJohnny Huang }
44083655e91SJohnny Huang 
441a219f6deSJohnny Huang static void _otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset)
44283655e91SJohnny Huang {
44383655e91SJohnny Huang 	int prog_bit;
44483655e91SJohnny Huang 
44583655e91SJohnny Huang 	if (prog_address % 2 == 0) {
44683655e91SJohnny Huang 		if (value)
44783655e91SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
44883655e91SJohnny Huang 		else
44983655e91SJohnny Huang 			return;
45083655e91SJohnny Huang 	} else {
45164b66712SJohnny Huang 		if (info_cb.version != OTP_AST2600A3)
45283655e91SJohnny Huang 			prog_address |= 1 << 15;
45383655e91SJohnny Huang 		if (!value)
45483655e91SJohnny Huang 			prog_bit = 0x1 << bit_offset;
45583655e91SJohnny Huang 		else
45683655e91SJohnny Huang 			return;
45783655e91SJohnny Huang 	}
45883655e91SJohnny Huang 	otp_prog(prog_address, prog_bit);
45983655e91SJohnny Huang }
46083655e91SJohnny Huang 
461a219f6deSJohnny Huang static int otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset)
46283655e91SJohnny Huang {
46383655e91SJohnny Huang 	int pass;
46483655e91SJohnny Huang 	int i;
46583655e91SJohnny Huang 
46683655e91SJohnny Huang 	otp_soak(1);
46783655e91SJohnny Huang 	_otp_prog_bit(value, prog_address, bit_offset);
46883655e91SJohnny Huang 	pass = 0;
46983655e91SJohnny Huang 
47083655e91SJohnny Huang 	for (i = 0; i < RETRY; i++) {
47183655e91SJohnny Huang 		if (verify_bit(prog_address, bit_offset, value) != 0) {
47283655e91SJohnny Huang 			otp_soak(2);
47383655e91SJohnny Huang 			_otp_prog_bit(value, prog_address, bit_offset);
47483655e91SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
47583655e91SJohnny Huang 				otp_soak(1);
47683655e91SJohnny Huang 			} else {
47783655e91SJohnny Huang 				pass = 1;
47883655e91SJohnny Huang 				break;
47983655e91SJohnny Huang 			}
48083655e91SJohnny Huang 		} else {
48183655e91SJohnny Huang 			pass = 1;
48283655e91SJohnny Huang 			break;
48383655e91SJohnny Huang 		}
48483655e91SJohnny Huang 	}
48583655e91SJohnny Huang 
48683655e91SJohnny Huang 	return pass;
48783655e91SJohnny Huang }
48883655e91SJohnny Huang 
489a219f6deSJohnny Huang static void otp_prog_dw(u32 value, u32 ignore, u32 prog_address)
490d90825e2SJohnny Huang {
491d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
492d90825e2SJohnny Huang 
493d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
494696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
495d90825e2SJohnny Huang 			continue;
496d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
497d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
498d90825e2SJohnny Huang 			if (bit_value)
499d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
500d90825e2SJohnny Huang 			else
501d90825e2SJohnny Huang 				continue;
502d90825e2SJohnny Huang 		} else {
50364b66712SJohnny Huang 			if (info_cb.version != OTP_AST2600A3)
504d90825e2SJohnny Huang 				prog_address |= 1 << 15;
505d90825e2SJohnny Huang 			if (bit_value)
506d90825e2SJohnny Huang 				continue;
507d90825e2SJohnny Huang 			else
508d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
509d90825e2SJohnny Huang 		}
510d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
511d90825e2SJohnny Huang 	}
512d90825e2SJohnny Huang }
513d90825e2SJohnny Huang 
514a219f6deSJohnny Huang static int otp_prog_verify_2dw(u32 *data, u32 *buf, u32 *ignore_mask, u32 prog_address)
51554552c69SJohnny Huang {
51654552c69SJohnny Huang 	int pass;
51754552c69SJohnny Huang 	int i;
518a219f6deSJohnny Huang 	u32 data0_masked;
519a219f6deSJohnny Huang 	u32 data1_masked;
520a219f6deSJohnny Huang 	u32 buf0_masked;
521a219f6deSJohnny Huang 	u32 buf1_masked;
522a219f6deSJohnny Huang 	u32 compare[2];
52354552c69SJohnny Huang 
52454552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
52554552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
52654552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
52754552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
528a219f6deSJohnny Huang 	if (data0_masked == buf0_masked && data1_masked == buf1_masked)
52954552c69SJohnny Huang 		return 0;
53054552c69SJohnny Huang 
53154552c69SJohnny Huang 	otp_soak(1);
53254552c69SJohnny Huang 	if (data0_masked != buf0_masked)
53354552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
53454552c69SJohnny Huang 	if (data1_masked != buf1_masked)
53554552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
53654552c69SJohnny Huang 
53754552c69SJohnny Huang 	pass = 0;
53854552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
53954552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
54054552c69SJohnny Huang 			otp_soak(2);
541a219f6deSJohnny Huang 			if (compare[0] != 0)
54254552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
543a219f6deSJohnny Huang 			if (compare[1] != ~0)
5445537bc72SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1);
54554552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
54654552c69SJohnny Huang 				otp_soak(1);
54754552c69SJohnny Huang 			} else {
54854552c69SJohnny Huang 				pass = 1;
54954552c69SJohnny Huang 				break;
55054552c69SJohnny Huang 			}
55154552c69SJohnny Huang 		} else {
55254552c69SJohnny Huang 			pass = 1;
55354552c69SJohnny Huang 			break;
55454552c69SJohnny Huang 		}
55554552c69SJohnny Huang 	}
55654552c69SJohnny Huang 
55754552c69SJohnny Huang 	if (!pass) {
55854552c69SJohnny Huang 		otp_soak(0);
55954552c69SJohnny Huang 		return OTP_FAILURE;
56054552c69SJohnny Huang 	}
56154552c69SJohnny Huang 	return OTP_SUCCESS;
56254552c69SJohnny Huang }
56354552c69SJohnny Huang 
564541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
56576d13988SJohnny Huang {
566a219f6deSJohnny Huang 	u32 OTPSTRAP_RAW[2];
5675010032bSJohnny Huang 	int strap_end;
56876d13988SJohnny Huang 	int i, j;
56976d13988SJohnny Huang 
5705010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
57176d13988SJohnny Huang 		for (j = 0; j < 64; j++) {
57276d13988SJohnny Huang 			otpstrap[j].value = 0;
57376d13988SJohnny Huang 			otpstrap[j].remain_times = 7;
57476d13988SJohnny Huang 			otpstrap[j].writeable_option = -1;
57576d13988SJohnny Huang 			otpstrap[j].protected = 0;
57676d13988SJohnny Huang 		}
5775010032bSJohnny Huang 		strap_end = 30;
5785010032bSJohnny Huang 	} else {
5795010032bSJohnny Huang 		for (j = 0; j < 64; j++) {
5805010032bSJohnny Huang 			otpstrap[j].value = 0;
5815010032bSJohnny Huang 			otpstrap[j].remain_times = 6;
5825010032bSJohnny Huang 			otpstrap[j].writeable_option = -1;
5835010032bSJohnny Huang 			otpstrap[j].reg_protected = 0;
5845010032bSJohnny Huang 			otpstrap[j].protected = 0;
5855010032bSJohnny Huang 		}
5865010032bSJohnny Huang 		strap_end = 28;
5875010032bSJohnny Huang 	}
58876d13988SJohnny Huang 
589dacbba92SJohnny Huang 	otp_soak(0);
5905010032bSJohnny Huang 	for (i = 16; i < strap_end; i += 2) {
59176d13988SJohnny Huang 		int option = (i - 16) / 2;
592a219f6deSJohnny Huang 
59376d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
59476d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
59576d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
59676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
597a219f6deSJohnny Huang 
598a219f6deSJohnny Huang 			if (bit_value == 0 && otpstrap[j].writeable_option == -1)
59976d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
60076d13988SJohnny Huang 			if (bit_value == 1)
60176d13988SJohnny Huang 				otpstrap[j].remain_times--;
60276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
60376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
60476d13988SJohnny Huang 		}
60576d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
60676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
607a219f6deSJohnny Huang 
608a219f6deSJohnny Huang 			if (bit_value == 0 && otpstrap[j].writeable_option == -1)
60976d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
61076d13988SJohnny Huang 			if (bit_value == 1)
61176d13988SJohnny Huang 				otpstrap[j].remain_times--;
61276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
61376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
61476d13988SJohnny Huang 		}
61576d13988SJohnny Huang 	}
6165010032bSJohnny Huang 
6175010032bSJohnny Huang 	if (info_cb.version != OTP_AST2600A0) {
6185010032bSJohnny Huang 		otp_read_config(28, &OTPSTRAP_RAW[0]);
6195010032bSJohnny Huang 		otp_read_config(29, &OTPSTRAP_RAW[1]);
6205010032bSJohnny Huang 		for (j = 0; j < 32; j++) {
6215010032bSJohnny Huang 			if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
6225010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
6235010032bSJohnny Huang 		}
6245010032bSJohnny Huang 		for (j = 32; j < 64; j++) {
6255010032bSJohnny Huang 			if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
6265010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
6275010032bSJohnny Huang 		}
6285010032bSJohnny Huang 	}
6295010032bSJohnny Huang 
63076d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
63176d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
63276d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
63376d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
63476d13988SJohnny Huang 			otpstrap[j].protected = 1;
63576d13988SJohnny Huang 	}
63676d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
63776d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
63876d13988SJohnny Huang 			otpstrap[j].protected = 1;
63976d13988SJohnny Huang 	}
64076d13988SJohnny Huang }
64176d13988SJohnny Huang 
642696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
64369d5fd8fSJohnny Huang {
64479e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
645a219f6deSJohnny Huang 	u32 *OTPCFG = (u32 *)image_layout->conf;
646a219f6deSJohnny Huang 	u32 *OTPCFG_IGNORE = (u32 *)image_layout->conf_ignore;
647a219f6deSJohnny Huang 	u32 mask;
648a219f6deSJohnny Huang 	u32 dw_offset;
649a219f6deSJohnny Huang 	u32 bit_offset;
650a219f6deSJohnny Huang 	u32 otp_value;
651a219f6deSJohnny Huang 	u32 otp_ignore;
652b458cd62SJohnny Huang 	int fail = 0;
65373f11549SJohnny Huang 	char valid_bit[20];
65466f2f8e5SJohnny Huang 	int i;
65573f11549SJohnny Huang 	int j;
65666f2f8e5SJohnny Huang 
657737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
65866f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
6593cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
6603cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
6613cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
6623cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
663b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
664696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
665b458cd62SJohnny Huang 
666a219f6deSJohnny Huang 		if (otp_ignore == mask)
667b458cd62SJohnny Huang 			continue;
668a219f6deSJohnny Huang 		else if (otp_ignore != 0)
669b458cd62SJohnny Huang 			fail = 1;
670b458cd62SJohnny Huang 
671a219f6deSJohnny Huang 		if (otp_value != conf_info[i].value &&
6723cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
6733cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
6743cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
675b458cd62SJohnny Huang 			continue;
676b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
677b458cd62SJohnny Huang 
6783cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
6793cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
68066f2f8e5SJohnny Huang 		} else {
681b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
6823cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
6833cb28812SJohnny Huang 			       conf_info[i].bit_offset);
68466f2f8e5SJohnny Huang 		}
685b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
686b458cd62SJohnny Huang 
687b458cd62SJohnny Huang 		if (fail) {
688696656c6SJohnny Huang 			printf("Ignore mask error\n");
689a219f6deSJohnny Huang 			continue;
690a219f6deSJohnny Huang 		}
6913cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
692b458cd62SJohnny Huang 			printf("Reserved\n");
6933cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
6943cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
695b458cd62SJohnny Huang 			printf("\n");
6963cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
697b458cd62SJohnny Huang 			if (otp_value != 0) {
69873f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
699a219f6deSJohnny Huang 					if (otp_value == (1 << j))
70073f11549SJohnny Huang 						valid_bit[j * 2] = '1';
701a219f6deSJohnny Huang 					else
70273f11549SJohnny Huang 						valid_bit[j * 2] = '0';
70373f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
70473f11549SJohnny Huang 				}
70573f11549SJohnny Huang 				valid_bit[15] = 0;
70673f11549SJohnny Huang 			} else {
70773f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
708b458cd62SJohnny Huang 			}
7093cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
710b458cd62SJohnny Huang 			printf("\n");
711b458cd62SJohnny Huang 		} else {
7123cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
713b458cd62SJohnny Huang 		}
714b458cd62SJohnny Huang 	}
715b458cd62SJohnny Huang 
716b458cd62SJohnny Huang 	if (fail)
717b458cd62SJohnny Huang 		return OTP_FAILURE;
718b458cd62SJohnny Huang 
71966f2f8e5SJohnny Huang 	return OTP_SUCCESS;
72066f2f8e5SJohnny Huang }
72166f2f8e5SJohnny Huang 
7222d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
72366f2f8e5SJohnny Huang {
72479e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
725a219f6deSJohnny Huang 	u32 OTPCFG[16];
726a219f6deSJohnny Huang 	u32 mask;
727a219f6deSJohnny Huang 	u32 dw_offset;
728a219f6deSJohnny Huang 	u32 bit_offset;
729a219f6deSJohnny Huang 	u32 otp_value;
73073f11549SJohnny Huang 	char valid_bit[20];
73166f2f8e5SJohnny Huang 	int i;
73273f11549SJohnny Huang 	int j;
73366f2f8e5SJohnny Huang 
734dacbba92SJohnny Huang 	otp_soak(0);
735bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
73666f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
73766f2f8e5SJohnny Huang 
738b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
739b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
7403cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
7413cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
7422d4b0742SJohnny Huang 			continue;
7433cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
7443cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
7453cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
746b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
747b458cd62SJohnny Huang 
748a219f6deSJohnny Huang 		if (otp_value != conf_info[i].value &&
7493cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
7503cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
7513cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
752b458cd62SJohnny Huang 			continue;
753b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
754b458cd62SJohnny Huang 
7553cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
7563cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
757b458cd62SJohnny Huang 		} else {
758b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
7593cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
7603cb28812SJohnny Huang 			       conf_info[i].bit_offset);
761b458cd62SJohnny Huang 		}
762b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
763b458cd62SJohnny Huang 
7643cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
765b458cd62SJohnny Huang 			printf("Reserved\n");
7663cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
7673cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
768b458cd62SJohnny Huang 			printf("\n");
7693cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
770b458cd62SJohnny Huang 			if (otp_value != 0) {
77173f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
772a219f6deSJohnny Huang 					if (otp_value == (1 << j))
77373f11549SJohnny Huang 						valid_bit[j * 2] = '1';
774a219f6deSJohnny Huang 					else
77573f11549SJohnny Huang 						valid_bit[j * 2] = '0';
77673f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
77773f11549SJohnny Huang 				}
77873f11549SJohnny Huang 				valid_bit[15] = 0;
77973f11549SJohnny Huang 			} else {
78073f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
781b458cd62SJohnny Huang 			}
7823cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
783b458cd62SJohnny Huang 			printf("\n");
784b458cd62SJohnny Huang 		} else {
7853cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
786b458cd62SJohnny Huang 		}
787b458cd62SJohnny Huang 	}
788b458cd62SJohnny Huang 	return OTP_SUCCESS;
78966f2f8e5SJohnny Huang }
79066f2f8e5SJohnny Huang 
7915010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout)
79276d13988SJohnny Huang {
79379e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
794a219f6deSJohnny Huang 	u32 *OTPSTRAP;
795a219f6deSJohnny Huang 	u32 *OTPSTRAP_REG_PRO;
796a219f6deSJohnny Huang 	u32 *OTPSTRAP_PRO;
797a219f6deSJohnny Huang 	u32 *OTPSTRAP_IGNORE;
79876d13988SJohnny Huang 	int i;
799a8bd6d8cSJohnny Huang 	int fail = 0;
800a219f6deSJohnny Huang 	u32 bit_offset;
801a219f6deSJohnny Huang 	u32 dw_offset;
802a219f6deSJohnny Huang 	u32 mask;
803a219f6deSJohnny Huang 	u32 otp_value;
804a219f6deSJohnny Huang 	u32 otp_reg_protect;
805a219f6deSJohnny Huang 	u32 otp_protect;
806a219f6deSJohnny Huang 	u32 otp_ignore;
80776d13988SJohnny Huang 
808a219f6deSJohnny Huang 	OTPSTRAP = (u32 *)image_layout->strap;
809a219f6deSJohnny Huang 	OTPSTRAP_PRO = (u32 *)image_layout->strap_pro;
810a219f6deSJohnny Huang 	OTPSTRAP_IGNORE = (u32 *)image_layout->strap_ignore;
8115010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
812696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
813a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
814696656c6SJohnny Huang 	} else {
815a219f6deSJohnny Huang 		OTPSTRAP_REG_PRO = (u32 *)image_layout->strap_reg_pro;
816de6b0cc4SJohnny Huang 		printf("BIT(hex)   Value       Reg_Protect Protect     Description\n");
817696656c6SJohnny Huang 	}
818de6b0cc4SJohnny Huang 	printf("__________________________________________________________________________________________\n");
819b458cd62SJohnny Huang 
8203cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
821696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
822a8bd6d8cSJohnny Huang 			dw_offset = 1;
8233cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
824a8bd6d8cSJohnny Huang 		} else {
825a8bd6d8cSJohnny Huang 			dw_offset = 0;
8263cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
827a8bd6d8cSJohnny Huang 		}
82876d13988SJohnny Huang 
8293cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
830a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
831a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
832696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
833a8bd6d8cSJohnny Huang 
8345010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
835696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
8365010032bSJohnny Huang 		else
8375010032bSJohnny Huang 			otp_reg_protect = 0;
838696656c6SJohnny Huang 
839a219f6deSJohnny Huang 		if (otp_ignore == mask)
840a8bd6d8cSJohnny Huang 			continue;
841a219f6deSJohnny Huang 		else if (otp_ignore != 0)
842a8bd6d8cSJohnny Huang 			fail = 1;
843a8bd6d8cSJohnny Huang 
844a219f6deSJohnny Huang 		if (otp_value != strap_info[i].value &&
8453cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
846a8bd6d8cSJohnny Huang 			continue;
847a8bd6d8cSJohnny Huang 
8483cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
8493cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
850a8bd6d8cSJohnny Huang 		} else {
851b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
8523cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
8533cb28812SJohnny Huang 			       strap_info[i].bit_offset);
854a8bd6d8cSJohnny Huang 		}
855a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
8565010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
857696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
858a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
859a8bd6d8cSJohnny Huang 
860a8bd6d8cSJohnny Huang 		if (fail) {
861696656c6SJohnny Huang 			printf("Ignore mask error\n");
862a8bd6d8cSJohnny Huang 		} else {
8633cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
8643cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
865a8bd6d8cSJohnny Huang 			else
866a8bd6d8cSJohnny Huang 				printf("Reserved\n");
867a8bd6d8cSJohnny Huang 		}
868a8bd6d8cSJohnny Huang 	}
869a8bd6d8cSJohnny Huang 
870a8bd6d8cSJohnny Huang 	if (fail)
87176d13988SJohnny Huang 		return OTP_FAILURE;
87276d13988SJohnny Huang 
87376d13988SJohnny Huang 	return OTP_SUCCESS;
87476d13988SJohnny Huang }
87576d13988SJohnny Huang 
876b458cd62SJohnny Huang static int otp_print_strap_info(int view)
87776d13988SJohnny Huang {
87879e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
87976d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
88007baa4e8SJohnny Huang 	int i, j;
881b458cd62SJohnny Huang 	int fail = 0;
882a219f6deSJohnny Huang 	u32 bit_offset;
883a219f6deSJohnny Huang 	u32 length;
884a219f6deSJohnny Huang 	u32 otp_value;
885a219f6deSJohnny Huang 	u32 otp_protect;
88676d13988SJohnny Huang 
887541eb887SJohnny Huang 	otp_strap_status(strap_status);
88876d13988SJohnny Huang 
889b458cd62SJohnny Huang 	if (view) {
89083655e91SJohnny Huang 		if (info_cb.version == OTP_AST2600A0)
89107baa4e8SJohnny Huang 			printf("BIT(hex) Value  Remains  Protect   Description\n");
89283655e91SJohnny Huang 		else
89383655e91SJohnny Huang 			printf("BIT(hex) Value  Remains  Reg_Protect Protect   Description\n");
89407baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
895b458cd62SJohnny Huang 	} else {
896b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
897b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
89876d13988SJohnny Huang 	}
8993cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
900b458cd62SJohnny Huang 		otp_value = 0;
9013cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
9023cb28812SJohnny Huang 		length = strap_info[i].length;
903b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
904c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
905c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
906b458cd62SJohnny Huang 		}
907a219f6deSJohnny Huang 		if (otp_value != strap_info[i].value &&
9083cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
909b458cd62SJohnny Huang 			continue;
910b458cd62SJohnny Huang 		if (view) {
911b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
9123cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
913b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
91407baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
91583655e91SJohnny Huang 				if (info_cb.version != OTP_AST2600A0)
916e1a7245eSJohnny Huang 					printf("0x%-10X", strap_status[bit_offset + j].reg_protected);
917e1a7245eSJohnny Huang 				printf("0x%-7X", strap_status[bit_offset + j].protected);
9183cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
919b458cd62SJohnny Huang 					printf(" Reserved\n");
920b458cd62SJohnny Huang 					continue;
921b458cd62SJohnny Huang 				}
922b458cd62SJohnny Huang 				if (length == 1) {
9233cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
924b458cd62SJohnny Huang 					continue;
92576d13988SJohnny Huang 				}
92676d13988SJohnny Huang 
927b458cd62SJohnny Huang 				if (j == 0)
9283cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
929b458cd62SJohnny Huang 				else if (j == length - 1)
930b458cd62SJohnny Huang 					printf("\\ \"\n");
931b458cd62SJohnny Huang 				else
932b458cd62SJohnny Huang 					printf("| \"\n");
93376d13988SJohnny Huang 			}
934b458cd62SJohnny Huang 		} else {
935c947ef08SJohnny Huang 			if (length == 1) {
9363cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
937b458cd62SJohnny Huang 			} else {
938b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
939b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
940b458cd62SJohnny Huang 			}
941b458cd62SJohnny Huang 
942b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
943b458cd62SJohnny Huang 
9443cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
9453cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
946b458cd62SJohnny Huang 			else
947b458cd62SJohnny Huang 				printf("Reserved\n");
948b458cd62SJohnny Huang 		}
949b458cd62SJohnny Huang 	}
950b458cd62SJohnny Huang 
951b458cd62SJohnny Huang 	if (fail)
952b458cd62SJohnny Huang 		return OTP_FAILURE;
953b458cd62SJohnny Huang 
954b458cd62SJohnny Huang 	return OTP_SUCCESS;
955b458cd62SJohnny Huang }
956b458cd62SJohnny Huang 
957a219f6deSJohnny Huang static void buf_print(u8 *buf, int len)
95869d5fd8fSJohnny Huang {
95969d5fd8fSJohnny Huang 	int i;
960a219f6deSJohnny Huang 
96169d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
96269d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
963a219f6deSJohnny Huang 		if (i % 16 == 0)
96469d5fd8fSJohnny Huang 			printf("%04X: ", i);
96569d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
966a219f6deSJohnny Huang 		if ((i + 1) % 16 == 0)
96769d5fd8fSJohnny Huang 			printf("\n");
96869d5fd8fSJohnny Huang 	}
96969d5fd8fSJohnny Huang }
97069d5fd8fSJohnny Huang 
971696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
97269d5fd8fSJohnny Huang {
97369d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
97479e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
9759a4fe690SJohnny Huang 	struct otpkey_type key_info;
976a219f6deSJohnny Huang 	u32 *buf;
977a219f6deSJohnny Huang 	u8 *byte_buf;
9789d998018SJohnny Huang 	char empty = 1;
97969d5fd8fSJohnny Huang 	int i = 0, len = 0;
9809a4fe690SJohnny Huang 	int j;
98154552c69SJohnny Huang 
982696656c6SJohnny Huang 	byte_buf = image_layout->data;
983a219f6deSJohnny Huang 	buf = (u32 *)byte_buf;
9849d998018SJohnny Huang 
9859d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
986a219f6deSJohnny Huang 		if (buf[i] != 0)
9879d998018SJohnny Huang 			empty = 0;
9889d998018SJohnny Huang 	}
9899d998018SJohnny Huang 	if (empty)
9909d998018SJohnny Huang 		return 0;
9919d998018SJohnny Huang 
9929d998018SJohnny Huang 	i = 0;
99369d5fd8fSJohnny Huang 	while (1) {
99469d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
99569d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
99669d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
99769d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
99869d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
99969d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
10009a4fe690SJohnny Huang 
10019a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
10029a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
10039a4fe690SJohnny Huang 				key_info = key_info_array[j];
10049a4fe690SJohnny Huang 				break;
10059a4fe690SJohnny Huang 			}
10069a4fe690SJohnny Huang 		}
10079a4fe690SJohnny Huang 
10087f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
100969d5fd8fSJohnny Huang 		printf("Key Type: ");
10109a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
10119a4fe690SJohnny Huang 
10129a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
101369d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
101469d5fd8fSJohnny Huang 			switch (key_length) {
101569d5fd8fSJohnny Huang 			case 0:
101669d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
101769d5fd8fSJohnny Huang 				break;
101869d5fd8fSJohnny Huang 			case 1:
101969d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
102069d5fd8fSJohnny Huang 				break;
102169d5fd8fSJohnny Huang 			case 2:
102269d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
102369d5fd8fSJohnny Huang 				break;
102469d5fd8fSJohnny Huang 			case 3:
102569d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
102669d5fd8fSJohnny Huang 				break;
102769d5fd8fSJohnny Huang 			}
1028181f72d8SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV ||
1029181f72d8SJohnny Huang 			   key_info.key_type == OTP_KEY_TYPE_RSA_PUB) {
103069d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
103169d5fd8fSJohnny Huang 			switch (key_length) {
103269d5fd8fSJohnny Huang 			case 0:
103369d5fd8fSJohnny Huang 				printf("RSA1024\n");
103469d5fd8fSJohnny Huang 				len = 0x100;
103569d5fd8fSJohnny Huang 				break;
103669d5fd8fSJohnny Huang 			case 1:
103769d5fd8fSJohnny Huang 				printf("RSA2048\n");
103869d5fd8fSJohnny Huang 				len = 0x200;
103969d5fd8fSJohnny Huang 				break;
104069d5fd8fSJohnny Huang 			case 2:
104169d5fd8fSJohnny Huang 				printf("RSA3072\n");
104269d5fd8fSJohnny Huang 				len = 0x300;
104369d5fd8fSJohnny Huang 				break;
104469d5fd8fSJohnny Huang 			case 3:
104569d5fd8fSJohnny Huang 				printf("RSA4096\n");
104669d5fd8fSJohnny Huang 				len = 0x400;
104769d5fd8fSJohnny Huang 				break;
104869d5fd8fSJohnny Huang 			}
104969d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
105069d5fd8fSJohnny Huang 		}
10519a4fe690SJohnny Huang 		if (key_info.need_id)
105269d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
105369d5fd8fSJohnny Huang 		printf("Key Value:\n");
10549a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
105569d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
10569a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
10579a4fe690SJohnny Huang 			printf("AES Key:\n");
10589a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
10595fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
10609a4fe690SJohnny Huang 				printf("AES IV:\n");
10619a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10629a4fe690SJohnny Huang 			}
10639a4fe690SJohnny Huang 
10649a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
10655fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
106669d5fd8fSJohnny Huang 				printf("AES Key:\n");
106769d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
106869d5fd8fSJohnny Huang 				printf("AES IV:\n");
106969d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10705fdde29fSJohnny Huang 			} else {
10719a4fe690SJohnny Huang 				printf("AES Key 1:\n");
10729a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
10739a4fe690SJohnny Huang 				printf("AES Key 2:\n");
10749a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
10759a4fe690SJohnny Huang 			}
1076181f72d8SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV) {
107769d5fd8fSJohnny Huang 			printf("RSA mod:\n");
107869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
107969d5fd8fSJohnny Huang 			printf("RSA exp:\n");
108069d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
1081181f72d8SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA_PUB) {
1082181f72d8SJohnny Huang 			printf("RSA mod:\n");
1083181f72d8SJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
1084181f72d8SJohnny Huang 			printf("RSA exp:\n");
1085a219f6deSJohnny Huang 			buf_print((u8 *)"\x01\x00\x01", 3);
108669d5fd8fSJohnny Huang 		}
108769d5fd8fSJohnny Huang 		if (last)
108869d5fd8fSJohnny Huang 			break;
108969d5fd8fSJohnny Huang 		i++;
109069d5fd8fSJohnny Huang 	}
109169d5fd8fSJohnny Huang 	return 0;
109269d5fd8fSJohnny Huang }
109369d5fd8fSJohnny Huang 
10945010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout)
109569d5fd8fSJohnny Huang {
1096a6d0d645SJohnny Huang 	int i, k;
1097d90825e2SJohnny Huang 	int pass = 0;
1098a219f6deSJohnny Huang 	u32 prog_address;
1099a219f6deSJohnny Huang 	u32 data[16];
1100a219f6deSJohnny Huang 	u32 compare[2];
1101a219f6deSJohnny Huang 	u32 *conf = (u32 *)image_layout->conf;
1102a219f6deSJohnny Huang 	u32 *conf_ignore = (u32 *)image_layout->conf_ignore;
1103a219f6deSJohnny Huang 	u32 data_masked;
1104a219f6deSJohnny Huang 	u32 buf_masked;
110569d5fd8fSJohnny Huang 
1106a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1107a6d0d645SJohnny Huang 
1108bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i++) {
110969d5fd8fSJohnny Huang 		prog_address = 0x800;
1110a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1111a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1112a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1113a6d0d645SJohnny Huang 	}
1114a6d0d645SJohnny Huang 
1115a6d0d645SJohnny Huang 	printf("Check writable...\n");
1116bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11175010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11185010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1119d90825e2SJohnny Huang 		if (data_masked == buf_masked)
112069d5fd8fSJohnny Huang 			continue;
1121d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1122a6d0d645SJohnny Huang 			continue;
1123a6d0d645SJohnny Huang 		} else {
1124a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1125a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
11265010032bSJohnny Huang 			printf("Input [%X] = %x\n", i, conf[i]);
11275010032bSJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~conf_ignore[i]);
11282a856b9aSJohnny Huang 			return OTP_FAILURE;
1129a6d0d645SJohnny Huang 		}
1130a6d0d645SJohnny Huang 	}
1131a6d0d645SJohnny Huang 
1132a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1133d90825e2SJohnny Huang 	otp_soak(0);
1134bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11355010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11365010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1137a6d0d645SJohnny Huang 		prog_address = 0x800;
1138a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1139a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1140bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1141bb34a7bfSJohnny Huang 			pass = 1;
1142a6d0d645SJohnny Huang 			continue;
1143bb34a7bfSJohnny Huang 		}
1144de6fbf1cSJohnny Huang 
1145de6fbf1cSJohnny Huang 		otp_soak(1);
11465010032bSJohnny Huang 		otp_prog_dw(conf[i], conf_ignore[i], prog_address);
1147a6d0d645SJohnny Huang 
114869d5fd8fSJohnny Huang 		pass = 0;
114969d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
11505010032bSJohnny Huang 			if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1151de6fbf1cSJohnny Huang 				otp_soak(2);
1152feea3fdfSJohnny Huang 				otp_prog_dw(compare[0], conf_ignore[i], prog_address);
11535010032bSJohnny Huang 				if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1154de6fbf1cSJohnny Huang 					otp_soak(1);
1155de6fbf1cSJohnny Huang 				} else {
1156de6fbf1cSJohnny Huang 					pass = 1;
1157de6fbf1cSJohnny Huang 					break;
1158de6fbf1cSJohnny Huang 				}
1159a6d0d645SJohnny Huang 			} else {
116069d5fd8fSJohnny Huang 				pass = 1;
116169d5fd8fSJohnny Huang 				break;
116269d5fd8fSJohnny Huang 			}
116369d5fd8fSJohnny Huang 		}
1164bb34a7bfSJohnny Huang 		if (pass == 0) {
1165bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
11665010032bSJohnny Huang 			       i, data[i], conf[i], conf_ignore[i]);
1167bb34a7bfSJohnny Huang 			break;
1168bb34a7bfSJohnny Huang 		}
1169a6d0d645SJohnny Huang 	}
1170a6d0d645SJohnny Huang 
1171de6fbf1cSJohnny Huang 	otp_soak(0);
117269d5fd8fSJohnny Huang 	if (!pass)
11732a856b9aSJohnny Huang 		return OTP_FAILURE;
1174a6d0d645SJohnny Huang 
11752a856b9aSJohnny Huang 	return OTP_SUCCESS;
117669d5fd8fSJohnny Huang }
117769d5fd8fSJohnny Huang 
1178eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit)
1179eda10d61SJohnny Huang {
11809901d43aSJohnny Huang 	int prog_flag = 0;
11819901d43aSJohnny Huang 
11829901d43aSJohnny Huang 	// ignore this bit
11839901d43aSJohnny Huang 	if (ibit == 1)
1184eda10d61SJohnny Huang 		return OTP_SUCCESS;
1185eda10d61SJohnny Huang 	printf("OTPSTRAP[%X]:\n", offset);
11869901d43aSJohnny Huang 
1187eda10d61SJohnny Huang 	if (bit == otpstrap->value) {
11889901d43aSJohnny Huang 		if (!pbit && !rpbit) {
1189eda10d61SJohnny Huang 			printf("    The value is same as before, skip it.\n");
1190eda10d61SJohnny Huang 			return OTP_PROG_SKIP;
1191eda10d61SJohnny Huang 		}
11929901d43aSJohnny Huang 		printf("    The value is same as before.\n");
11939901d43aSJohnny Huang 	} else {
11949901d43aSJohnny Huang 		prog_flag = 1;
11959901d43aSJohnny Huang 	}
11969901d43aSJohnny Huang 	if (otpstrap->protected == 1 && prog_flag) {
1197eda10d61SJohnny Huang 		printf("    This bit is protected and is not writable\n");
1198eda10d61SJohnny Huang 		return OTP_FAILURE;
1199eda10d61SJohnny Huang 	}
12009901d43aSJohnny Huang 	if (otpstrap->remain_times == 0 && prog_flag) {
1201eda10d61SJohnny Huang 		printf("    This bit is no remaining times to write.\n");
1202eda10d61SJohnny Huang 		return OTP_FAILURE;
1203eda10d61SJohnny Huang 	}
12049901d43aSJohnny Huang 	if (pbit == 1)
1205eda10d61SJohnny Huang 		printf("    This bit will be protected and become non-writable.\n");
12069901d43aSJohnny Huang 	if (rpbit == 1 && info_cb.version != OTP_AST2600A0)
1207eda10d61SJohnny Huang 		printf("    The relative register will be protected.\n");
12089901d43aSJohnny Huang 	if (prog_flag)
1209eda10d61SJohnny Huang 		printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", offset, otpstrap->writeable_option + 1, otpstrap->value, otpstrap->value ^ 1);
12109901d43aSJohnny Huang 
1211eda10d61SJohnny Huang 	return OTP_SUCCESS;
1212eda10d61SJohnny Huang }
1213eda10d61SJohnny Huang 
12145010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout)
121569d5fd8fSJohnny Huang {
121669d5fd8fSJohnny Huang 	int i;
1217a219f6deSJohnny Huang 	u32 *strap;
1218a219f6deSJohnny Huang 	u32 *strap_ignore;
1219a219f6deSJohnny Huang 	u32 *strap_reg_protect;
1220a219f6deSJohnny Huang 	u32 *strap_pro;
1221eda10d61SJohnny Huang 	int bit, pbit, ibit, rpbit;
122269d5fd8fSJohnny Huang 	int fail = 0;
1223eda10d61SJohnny Huang 	int ret;
122466f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
122569d5fd8fSJohnny Huang 
1226a219f6deSJohnny Huang 	strap = (u32 *)image_layout->strap;
1227a219f6deSJohnny Huang 	strap_pro = (u32 *)image_layout->strap_pro;
1228a219f6deSJohnny Huang 	strap_ignore = (u32 *)image_layout->strap_ignore;
1229a219f6deSJohnny Huang 	strap_reg_protect = (u32 *)image_layout->strap_reg_pro;
12305010032bSJohnny Huang 
1231541eb887SJohnny Huang 	otp_strap_status(otpstrap);
123269d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
123369d5fd8fSJohnny Huang 		if (i < 32) {
12345010032bSJohnny Huang 			bit = (strap[0] >> i) & 0x1;
1235eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> i) & 0x1;
12365010032bSJohnny Huang 			pbit = (strap_pro[0] >> i) & 0x1;
123769d5fd8fSJohnny Huang 		} else {
12385010032bSJohnny Huang 			bit = (strap[1] >> (i - 32)) & 0x1;
1239eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> (i - 32)) & 0x1;
12405010032bSJohnny Huang 			pbit = (strap_pro[1] >> (i - 32)) & 0x1;
12415010032bSJohnny Huang 		}
12425010032bSJohnny Huang 
12435010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1244a219f6deSJohnny Huang 			if (i < 32)
12455010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
1246a219f6deSJohnny Huang 			else
12475010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
12485010032bSJohnny Huang 		} else {
12495010032bSJohnny Huang 			rpbit = 0;
125069d5fd8fSJohnny Huang 		}
1251eda10d61SJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit);
1252eda10d61SJohnny Huang 
1253eda10d61SJohnny Huang 		if (ret == OTP_FAILURE)
125469d5fd8fSJohnny Huang 			fail = 1;
125569d5fd8fSJohnny Huang 	}
125669d5fd8fSJohnny Huang 	if (fail == 1)
1257a6af4a17SJohnny Huang 		return OTP_FAILURE;
12589901d43aSJohnny Huang 	else
1259eda10d61SJohnny Huang 		return OTP_SUCCESS;
126069d5fd8fSJohnny Huang }
126169d5fd8fSJohnny Huang 
12622a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
126369d5fd8fSJohnny Huang {
126469d5fd8fSJohnny Huang 	int i, j;
1265de6b0cc4SJohnny Huang 	int remains;
126666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
126769d5fd8fSJohnny Huang 
12682a856b9aSJohnny Huang 	if (start < 0 || start > 64)
12692a856b9aSJohnny Huang 		return OTP_USAGE;
12702a856b9aSJohnny Huang 
12712a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
12722a856b9aSJohnny Huang 		return OTP_USAGE;
12732a856b9aSJohnny Huang 
1274541eb887SJohnny Huang 	otp_strap_status(otpstrap);
127569d5fd8fSJohnny Huang 
1276de6b0cc4SJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1277de6b0cc4SJohnny Huang 		remains = 7;
127807baa4e8SJohnny Huang 		printf("BIT(hex)  Value  Option           Status\n");
1279de6b0cc4SJohnny Huang 	} else {
1280de6b0cc4SJohnny Huang 		remains = 6;
1281de6b0cc4SJohnny Huang 		printf("BIT(hex)  Value  Option         Reg_Protect Status\n");
1282de6b0cc4SJohnny Huang 	}
1283de6b0cc4SJohnny Huang 	printf("______________________________________________________________________________\n");
1284737ed20bSJohnny Huang 
1285cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
128607baa4e8SJohnny Huang 		printf("0x%-8X", i);
1287737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1288de6b0cc4SJohnny Huang 		for (j = 0; j < remains; j++)
1289737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1290737ed20bSJohnny Huang 		printf("   ");
1291a219f6deSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
1292de6b0cc4SJohnny Huang 			printf("%d           ", otpstrap[i].reg_protected);
129369d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1294737ed20bSJohnny Huang 			printf("protected and not writable");
129569d5fd8fSJohnny Huang 		} else {
1296737ed20bSJohnny Huang 			printf("not protected ");
1297a219f6deSJohnny Huang 			if (otpstrap[i].remain_times == 0)
1298737ed20bSJohnny Huang 				printf("and no remaining times to write.");
1299a219f6deSJohnny Huang 			else
1300737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
130169d5fd8fSJohnny Huang 		}
1302737ed20bSJohnny Huang 		printf("\n");
130369d5fd8fSJohnny Huang 	}
13042a856b9aSJohnny Huang 
13052a856b9aSJohnny Huang 	return OTP_SUCCESS;
130669d5fd8fSJohnny Huang }
130769d5fd8fSJohnny Huang 
13088848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value)
13098848d5dcSJohnny Huang {
13108848d5dcSJohnny Huang 	struct otpstrap_status otpstrap[64];
1311a219f6deSJohnny Huang 	u32 prog_address;
13128848d5dcSJohnny Huang 	int offset;
13138848d5dcSJohnny Huang 	int ret;
13148848d5dcSJohnny Huang 
13158848d5dcSJohnny Huang 	otp_strap_status(otpstrap);
13168848d5dcSJohnny Huang 
13178848d5dcSJohnny Huang 	ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
13188848d5dcSJohnny Huang 
1319a219f6deSJohnny Huang 	if (ret != OTP_SUCCESS)
13208848d5dcSJohnny Huang 		return ret;
13218848d5dcSJohnny Huang 
13228848d5dcSJohnny Huang 	prog_address = 0x800;
13238848d5dcSJohnny Huang 	if (bit_offset < 32) {
13248848d5dcSJohnny Huang 		offset = bit_offset;
13258848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200;
13268848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2;
13278848d5dcSJohnny Huang 
13288848d5dcSJohnny Huang 	} else {
13298848d5dcSJohnny Huang 		offset = (bit_offset - 32);
13308848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200;
13318848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2;
13328848d5dcSJohnny Huang 	}
13338848d5dcSJohnny Huang 
133483655e91SJohnny Huang 	return otp_prog_bit(1, prog_address, offset);
13358848d5dcSJohnny Huang }
13368848d5dcSJohnny Huang 
13375010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout)
133869d5fd8fSJohnny Huang {
1339a219f6deSJohnny Huang 	u32 *strap;
1340a219f6deSJohnny Huang 	u32 *strap_ignore;
1341a219f6deSJohnny Huang 	u32 *strap_pro;
1342a219f6deSJohnny Huang 	u32 *strap_reg_protect;
1343a219f6deSJohnny Huang 	u32 prog_address;
134483655e91SJohnny Huang 	int i;
1345eda10d61SJohnny Huang 	int bit, pbit, ibit, offset, rpbit;
134669d5fd8fSJohnny Huang 	int fail = 0;
134783655e91SJohnny Huang 	int ret;
13489901d43aSJohnny Huang 	int prog_flag = 0;
134966f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
135069d5fd8fSJohnny Huang 
1351a219f6deSJohnny Huang 	strap = (u32 *)image_layout->strap;
1352a219f6deSJohnny Huang 	strap_pro = (u32 *)image_layout->strap_pro;
1353a219f6deSJohnny Huang 	strap_ignore = (u32 *)image_layout->strap_ignore;
1354a219f6deSJohnny Huang 	strap_reg_protect = (u32 *)image_layout->strap_reg_pro;
13555010032bSJohnny Huang 
13567f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1357541eb887SJohnny Huang 	otp_strap_status(otpstrap);
135869d5fd8fSJohnny Huang 
13597f795e57SJohnny Huang 	printf("Check writable...\n");
13605010032bSJohnny Huang 	if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) {
13617f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
13627f795e57SJohnny Huang 		return OTP_FAILURE;
13637f795e57SJohnny Huang 	}
13647e22f42dSJohnny Huang 
136569d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
136669d5fd8fSJohnny Huang 		prog_address = 0x800;
136769d5fd8fSJohnny Huang 		if (i < 32) {
136869d5fd8fSJohnny Huang 			offset = i;
13695010032bSJohnny Huang 			bit = (strap[0] >> offset) & 0x1;
1370eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> offset) & 0x1;
13715010032bSJohnny Huang 			pbit = (strap_pro[0] >> offset) & 0x1;
137269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
137369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
137469d5fd8fSJohnny Huang 
137569d5fd8fSJohnny Huang 		} else {
137669d5fd8fSJohnny Huang 			offset = (i - 32);
13775010032bSJohnny Huang 			bit = (strap[1] >> offset) & 0x1;
1378eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> offset) & 0x1;
13795010032bSJohnny Huang 			pbit = (strap_pro[1] >> offset) & 0x1;
138069d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
138169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
138269d5fd8fSJohnny Huang 		}
13835010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1384a219f6deSJohnny Huang 			if (i < 32)
13855010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
1386a219f6deSJohnny Huang 			else
13875010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
13885010032bSJohnny Huang 		} else {
13895010032bSJohnny Huang 			rpbit = 0;
13905010032bSJohnny Huang 		}
139169d5fd8fSJohnny Huang 
1392a219f6deSJohnny Huang 		if (ibit == 1)
139369d5fd8fSJohnny Huang 			continue;
13949901d43aSJohnny Huang 		if (bit == otpstrap[i].value)
13959901d43aSJohnny Huang 			prog_flag = 0;
13969901d43aSJohnny Huang 		else
13979901d43aSJohnny Huang 			prog_flag = 1;
13989901d43aSJohnny Huang 
13999901d43aSJohnny Huang 		if (otpstrap[i].protected == 1 && prog_flag) {
140069d5fd8fSJohnny Huang 			fail = 1;
140169d5fd8fSJohnny Huang 			continue;
140269d5fd8fSJohnny Huang 		}
14039901d43aSJohnny Huang 		if (otpstrap[i].remain_times == 0 && prog_flag) {
140469d5fd8fSJohnny Huang 			fail = 1;
140569d5fd8fSJohnny Huang 			continue;
140669d5fd8fSJohnny Huang 		}
14077e22f42dSJohnny Huang 
14089901d43aSJohnny Huang 		if (prog_flag) {
140983655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
141083655e91SJohnny Huang 			if (!ret)
14112a856b9aSJohnny Huang 				return OTP_FAILURE;
14129901d43aSJohnny Huang 		}
141369d5fd8fSJohnny Huang 
14145010032bSJohnny Huang 		if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
141569d5fd8fSJohnny Huang 			prog_address = 0x800;
141669d5fd8fSJohnny Huang 			if (i < 32)
14175010032bSJohnny Huang 				prog_address |= 0x608;
141869d5fd8fSJohnny Huang 			else
14195010032bSJohnny Huang 				prog_address |= 0x60a;
14207e22f42dSJohnny Huang 
142183655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
142283655e91SJohnny Huang 			if (!ret)
14232a856b9aSJohnny Huang 				return OTP_FAILURE;
14245010032bSJohnny Huang 		}
14255010032bSJohnny Huang 
14265010032bSJohnny Huang 		if (pbit != 0) {
14275010032bSJohnny Huang 			prog_address = 0x800;
14285010032bSJohnny Huang 			if (i < 32)
14295010032bSJohnny Huang 				prog_address |= 0x60c;
14305010032bSJohnny Huang 			else
14315010032bSJohnny Huang 				prog_address |= 0x60e;
14325010032bSJohnny Huang 
143383655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
143483655e91SJohnny Huang 			if (!ret)
14355010032bSJohnny Huang 				return OTP_FAILURE;
14365010032bSJohnny Huang 		}
143769d5fd8fSJohnny Huang 	}
1438de6fbf1cSJohnny Huang 	otp_soak(0);
143969d5fd8fSJohnny Huang 	if (fail == 1)
14402a856b9aSJohnny Huang 		return OTP_FAILURE;
14412a856b9aSJohnny Huang 	return OTP_SUCCESS;
144269d5fd8fSJohnny Huang }
144369d5fd8fSJohnny Huang 
14445010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout)
14454c1c9b35SJohnny Huang {
144654552c69SJohnny Huang 	int i;
144754552c69SJohnny Huang 	int ret;
14485010032bSJohnny Huang 	int data_dw;
1449a219f6deSJohnny Huang 	u32 data[2048];
1450a219f6deSJohnny Huang 	u32 *buf;
1451a219f6deSJohnny Huang 	u32 *buf_ignore;
1452a219f6deSJohnny Huang 	u32 data_masked;
1453a219f6deSJohnny Huang 	u32 buf_masked;
14544c1c9b35SJohnny Huang 
1455a219f6deSJohnny Huang 	buf = (u32 *)image_layout->data;
1456a219f6deSJohnny Huang 	buf_ignore = (u32 *)image_layout->data_ignore;
14575010032bSJohnny Huang 
14585010032bSJohnny Huang 	data_dw = image_layout->data_length / 4;
14595010032bSJohnny Huang 
14604c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
14614c1c9b35SJohnny Huang 
1462a219f6deSJohnny Huang 	for (i = 0; i < data_dw - 2 ; i += 2)
1463d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
1464d90825e2SJohnny Huang 
14654c1c9b35SJohnny Huang 	printf("Check writable...\n");
146654552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
14675010032bSJohnny Huang 	for (i = 0; i < data_dw - 2; i++) {
1468696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1469696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
147054552c69SJohnny Huang 		if (data_masked == buf_masked)
14714c1c9b35SJohnny Huang 			continue;
1472d90825e2SJohnny Huang 		if (i % 2 == 0) {
147354552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
14744c1c9b35SJohnny Huang 				continue;
14754c1c9b35SJohnny Huang 			} else {
14764c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1477d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
14784c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1479696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
14802a856b9aSJohnny Huang 				return OTP_FAILURE;
148169d5fd8fSJohnny Huang 			}
1482d90825e2SJohnny Huang 		} else {
148354552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1484d90825e2SJohnny Huang 				continue;
1485d90825e2SJohnny Huang 			} else {
1486d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1487d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1488d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1489696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
14902a856b9aSJohnny Huang 				return OTP_FAILURE;
1491d90825e2SJohnny Huang 			}
1492d90825e2SJohnny Huang 		}
1493d90825e2SJohnny Huang 	}
149469d5fd8fSJohnny Huang 
1495d90825e2SJohnny Huang 	printf("Start Programing...\n");
1496d90825e2SJohnny Huang 
149754552c69SJohnny Huang 	// programing ecc region first
149854552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
1499696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
150054552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
150154552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1502696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
150354552c69SJohnny Huang 			return ret;
1504d90825e2SJohnny Huang 		}
1505d90825e2SJohnny Huang 	}
1506d90825e2SJohnny Huang 
150754552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
1508696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
150954552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
151054552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1511696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
151254552c69SJohnny Huang 			return ret;
1513d90825e2SJohnny Huang 		}
1514de6fbf1cSJohnny Huang 	}
1515de6fbf1cSJohnny Huang 	otp_soak(0);
15162a856b9aSJohnny Huang 	return OTP_SUCCESS;
1517d90825e2SJohnny Huang }
1518d90825e2SJohnny Huang 
1519a219f6deSJohnny Huang static int otp_image_verify(u8 *src_buf, u32 length, u8 *digest_buf)
1520696656c6SJohnny Huang {
1521696656c6SJohnny Huang 	sha256_context ctx;
1522696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
1523696656c6SJohnny Huang 
1524696656c6SJohnny Huang 	sha256_starts(&ctx);
1525696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
1526696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
1527696656c6SJohnny Huang 
1528696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
1529696656c6SJohnny Huang 		return 0;
1530696656c6SJohnny Huang 	return -1;
1531696656c6SJohnny Huang }
1532696656c6SJohnny Huang 
1533de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm)
153469d5fd8fSJohnny Huang {
153569d5fd8fSJohnny Huang 	int ret;
15369a4fe690SJohnny Huang 	int image_version = 0;
1537696656c6SJohnny Huang 	struct otp_header *otp_header;
1538696656c6SJohnny Huang 	struct otp_image_layout image_layout;
1539696656c6SJohnny Huang 	int image_size;
1540a219f6deSJohnny Huang 	u8 *buf;
1541a219f6deSJohnny Huang 	u8 *checksum;
154269d5fd8fSJohnny Huang 
1543696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
1544696656c6SJohnny Huang 	if (!otp_header) {
154569d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
15462a856b9aSJohnny Huang 		return OTP_FAILURE;
154769d5fd8fSJohnny Huang 	}
1548d90825e2SJohnny Huang 
1549696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
1550696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
1551696656c6SJohnny Huang 
1552696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
1553696656c6SJohnny Huang 
1554696656c6SJohnny Huang 	if (!buf) {
1555696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
1556696656c6SJohnny Huang 		return OTP_FAILURE;
1557696656c6SJohnny Huang 	}
1558696656c6SJohnny Huang 	otp_header = (struct otp_header *)buf;
1559696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
1560696656c6SJohnny Huang 
1561696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
1562696656c6SJohnny Huang 		puts("Image is invalid\n");
1563696656c6SJohnny Huang 		return OTP_FAILURE;
1564696656c6SJohnny Huang 	}
1565696656c6SJohnny Huang 
15665010032bSJohnny Huang 	image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
15675010032bSJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
15685010032bSJohnny Huang 	image_layout.data_ignore = image_layout.data + image_layout.data_length;
15695010032bSJohnny Huang 
15705010032bSJohnny Huang 	image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
1571696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
15725010032bSJohnny Huang 	image_layout.conf_ignore = image_layout.conf + image_layout.conf_length;
1573696656c6SJohnny Huang 
1574696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
1575696656c6SJohnny Huang 
1576696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
1577696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
15785010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
15795010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + image_layout.strap_length;
15805010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length;
1581696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
1582696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
15835010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
15845010032bSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
15855010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
15865010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
15875fdde29fSJohnny Huang 	} else if (!strcmp("A2", (char *)otp_header->otp_version)) {
15885fdde29fSJohnny Huang 		image_version = OTP_AST2600A2;
15895fdde29fSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
15905fdde29fSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
15915fdde29fSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
15925fdde29fSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
159364b66712SJohnny Huang 	} else if (!strcmp("A3", (char *)otp_header->otp_version)) {
159464b66712SJohnny Huang 		image_version = OTP_AST2600A3;
159564b66712SJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
159664b66712SJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
159764b66712SJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
159864b66712SJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
1599696656c6SJohnny Huang 	} else {
1600696656c6SJohnny Huang 		puts("Version is not supported\n");
1601696656c6SJohnny Huang 		return OTP_FAILURE;
1602696656c6SJohnny Huang 	}
1603696656c6SJohnny Huang 
16049a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
16059a4fe690SJohnny Huang 		puts("Version is not match\n");
16069a4fe690SJohnny Huang 		return OTP_FAILURE;
16079a4fe690SJohnny Huang 	}
16089a4fe690SJohnny Huang 
1609696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
1610696656c6SJohnny Huang 		puts("checksum is invalid\n");
1611696656c6SJohnny Huang 		return OTP_FAILURE;
1612d90825e2SJohnny Huang 	}
16137332532cSJohnny Huang 
161469d5fd8fSJohnny Huang 	if (!nconfirm) {
1615696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
16167f795e57SJohnny Huang 			printf("\nOTP data region :\n");
1617696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
161869d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16192a856b9aSJohnny Huang 				return OTP_FAILURE;
162069d5fd8fSJohnny Huang 			}
162169d5fd8fSJohnny Huang 		}
1622696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
16237332532cSJohnny Huang 			printf("\nOTP strap region :\n");
16245010032bSJohnny Huang 			if (otp_print_strap_image(&image_layout) < 0) {
16257332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
16267332532cSJohnny Huang 				return OTP_FAILURE;
16277332532cSJohnny Huang 			}
16287332532cSJohnny Huang 		}
1629696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
16307332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
1631696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
16327332532cSJohnny Huang 				printf("OTP config error, please check.\n");
16337332532cSJohnny Huang 				return OTP_FAILURE;
16347332532cSJohnny Huang 			}
16357332532cSJohnny Huang 		}
16367332532cSJohnny Huang 
163769d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
163869d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
163969d5fd8fSJohnny Huang 			printf(" Aborting\n");
16402a856b9aSJohnny Huang 			return OTP_FAILURE;
164169d5fd8fSJohnny Huang 		}
164269d5fd8fSJohnny Huang 	}
16437332532cSJohnny Huang 
16445010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_DATA) {
16455010032bSJohnny Huang 		printf("programing data region ...\n");
16465010032bSJohnny Huang 		ret = otp_prog_data(&image_layout);
16475010032bSJohnny Huang 		if (ret != 0) {
16485010032bSJohnny Huang 			printf("Error\n");
16495010032bSJohnny Huang 			return ret;
16505010032bSJohnny Huang 		}
1651a219f6deSJohnny Huang 		printf("Done\n");
16525010032bSJohnny Huang 	}
16535010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_STRAP) {
16545010032bSJohnny Huang 		printf("programing strap region ...\n");
16555010032bSJohnny Huang 		ret = otp_prog_strap(&image_layout);
16565010032bSJohnny Huang 		if (ret != 0) {
16575010032bSJohnny Huang 			printf("Error\n");
16585010032bSJohnny Huang 			return ret;
16595010032bSJohnny Huang 		}
1660a219f6deSJohnny Huang 		printf("Done\n");
16615010032bSJohnny Huang 	}
16625010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_CONFIG) {
16635010032bSJohnny Huang 		printf("programing configuration region ...\n");
16645010032bSJohnny Huang 		ret = otp_prog_conf(&image_layout);
16655010032bSJohnny Huang 		if (ret != 0) {
16665010032bSJohnny Huang 			printf("Error\n");
16675010032bSJohnny Huang 			return ret;
16685010032bSJohnny Huang 		}
16695010032bSJohnny Huang 		printf("Done\n");
16705010032bSJohnny Huang 	}
1671cd1610b4SJohnny Huang 
16727332532cSJohnny Huang 	return OTP_SUCCESS;
16732a856b9aSJohnny Huang }
16742a856b9aSJohnny Huang 
16752a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1676cd1610b4SJohnny Huang {
1677a219f6deSJohnny Huang 	u32 read[2];
1678a219f6deSJohnny Huang 	u32 prog_address = 0;
167966f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1680cd1610b4SJohnny Huang 	int otp_bit;
168183655e91SJohnny Huang 	int ret = 0;
1682cd1610b4SJohnny Huang 
1683dacbba92SJohnny Huang 	otp_soak(0);
1684cd1610b4SJohnny Huang 	switch (mode) {
1685a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1686a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1687cd1610b4SJohnny Huang 		prog_address = 0x800;
1688cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1689cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1690a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1691cd1610b4SJohnny Huang 		if (otp_bit == value) {
1692a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1693cd1610b4SJohnny Huang 			printf("No need to program\n");
16942a856b9aSJohnny Huang 			return OTP_SUCCESS;
1695cd1610b4SJohnny Huang 		}
1696cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1697a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1698cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
16992a856b9aSJohnny Huang 			return OTP_FAILURE;
1700cd1610b4SJohnny Huang 		}
1701a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1702cd1610b4SJohnny Huang 		break;
1703a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1704cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1705cd1610b4SJohnny Huang 
1706cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1707a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1708a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1709643b9cfdSJohnny Huang 
1710643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1711643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1712643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1713643b9cfdSJohnny Huang 				return OTP_FAILURE;
1714643b9cfdSJohnny Huang 			}
1715cd1610b4SJohnny Huang 		} else {
1716a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1717a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1718643b9cfdSJohnny Huang 
1719643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1720643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1721643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1722643b9cfdSJohnny Huang 				return OTP_FAILURE;
1723643b9cfdSJohnny Huang 			}
1724cd1610b4SJohnny Huang 		}
1725cd1610b4SJohnny Huang 		if (otp_bit == value) {
1726a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1727cd1610b4SJohnny Huang 			printf("No need to program\n");
17282a856b9aSJohnny Huang 			return OTP_SUCCESS;
1729cd1610b4SJohnny Huang 		}
1730643b9cfdSJohnny Huang 
1731a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1732cd1610b4SJohnny Huang 		break;
1733a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
17348848d5dcSJohnny Huang 		otp_strap_status(otpstrap);
17358848d5dcSJohnny Huang 		otp_print_strap(bit_offset, 1);
17368848d5dcSJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
17378848d5dcSJohnny Huang 		if (ret == OTP_FAILURE)
17388848d5dcSJohnny Huang 			return OTP_FAILURE;
17398848d5dcSJohnny Huang 		else if (ret == OTP_PROG_SKIP)
17408848d5dcSJohnny Huang 			return OTP_SUCCESS;
1741a6af4a17SJohnny Huang 
1742cd1610b4SJohnny Huang 		break;
1743cd1610b4SJohnny Huang 	}
1744cd1610b4SJohnny Huang 
1745cd1610b4SJohnny Huang 	if (!nconfirm) {
1746cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1747cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1748cd1610b4SJohnny Huang 			printf(" Aborting\n");
17492a856b9aSJohnny Huang 			return OTP_FAILURE;
1750cd1610b4SJohnny Huang 		}
1751cd1610b4SJohnny Huang 	}
1752cd1610b4SJohnny Huang 
1753cd1610b4SJohnny Huang 	switch (mode) {
1754a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
175583655e91SJohnny Huang 		ret =  otp_prog_strap_bit(bit_offset, value);
175683655e91SJohnny Huang 		break;
1757a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1758a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
175983655e91SJohnny Huang 		ret = otp_prog_bit(value, prog_address, bit_offset);
1760de6fbf1cSJohnny Huang 		break;
1761de6fbf1cSJohnny Huang 	}
1762de6fbf1cSJohnny Huang 	otp_soak(0);
176383655e91SJohnny Huang 	if (ret) {
17649009c25dSJohnny Huang 		printf("SUCCESS\n");
17652a856b9aSJohnny Huang 		return OTP_SUCCESS;
1766a219f6deSJohnny Huang 	}
1767a219f6deSJohnny Huang 
17689009c25dSJohnny Huang 	printf("OTP cannot be programed\n");
17699009c25dSJohnny Huang 	printf("FAILED\n");
17709009c25dSJohnny Huang 	return OTP_FAILURE;
17719009c25dSJohnny Huang }
1772cd1610b4SJohnny Huang 
17732a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
177469d5fd8fSJohnny Huang {
1775a219f6deSJohnny Huang 	u32 offset, count;
17762a856b9aSJohnny Huang 	int ret;
177769d5fd8fSJohnny Huang 
17782a856b9aSJohnny Huang 	if (argc == 4) {
17792a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17802a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
17812a856b9aSJohnny Huang 	} else if (argc == 3) {
17822a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17832a856b9aSJohnny Huang 		count = 1;
17842a856b9aSJohnny Huang 	} else {
178569d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
178669d5fd8fSJohnny Huang 	}
178769d5fd8fSJohnny Huang 
17882a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
17893d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
17902a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
17912a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
17923d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
17932a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
17942a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
17953d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
17962a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
17972a856b9aSJohnny Huang 	} else {
17982a856b9aSJohnny Huang 		return CMD_RET_USAGE;
179969d5fd8fSJohnny Huang 	}
180069d5fd8fSJohnny Huang 
18012a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18022a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18032a856b9aSJohnny Huang 	return CMD_RET_USAGE;
18042a856b9aSJohnny Huang }
18052a856b9aSJohnny Huang 
18062a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18072a856b9aSJohnny Huang {
18082a856b9aSJohnny Huang 	phys_addr_t addr;
18092a856b9aSJohnny Huang 	int ret;
18102a856b9aSJohnny Huang 
1811de6b0cc4SJohnny Huang 	if (argc == 3) {
1812ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
18132a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18142a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
18153d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1816de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 1);
1817de6b0cc4SJohnny Huang 	} else if (argc == 2) {
18182a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
18193d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1820de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 0);
18212a856b9aSJohnny Huang 	} else {
18222a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18232a856b9aSJohnny Huang 	}
18242a856b9aSJohnny Huang 
18252a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18262a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18272a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18282a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18292a856b9aSJohnny Huang 	else
18302a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18312a856b9aSJohnny Huang }
18322a856b9aSJohnny Huang 
18332a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18342a856b9aSJohnny Huang {
18352a856b9aSJohnny Huang 	int mode = 0;
18362a856b9aSJohnny Huang 	int nconfirm = 0;
18372a856b9aSJohnny Huang 	int otp_addr = 0;
18382a856b9aSJohnny Huang 	int bit_offset;
18392a856b9aSJohnny Huang 	int value;
18402a856b9aSJohnny Huang 	int ret;
18412a856b9aSJohnny Huang 
18422a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
18432a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18442a856b9aSJohnny Huang 
18452a856b9aSJohnny Huang 	/* Drop the pb cmd */
18462a856b9aSJohnny Huang 	argc--;
18472a856b9aSJohnny Huang 	argv++;
18482a856b9aSJohnny Huang 
18492a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1850a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
18512a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1852a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
18532a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1854a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1855cd1610b4SJohnny Huang 	else
18562a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18572a856b9aSJohnny Huang 
18582a856b9aSJohnny Huang 	/* Drop the region cmd */
18592a856b9aSJohnny Huang 	argc--;
18602a856b9aSJohnny Huang 	argv++;
18612a856b9aSJohnny Huang 
1862ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
1863cd1610b4SJohnny Huang 		nconfirm = 1;
18642a856b9aSJohnny Huang 		/* Drop the force option */
18652a856b9aSJohnny Huang 		argc--;
18662a856b9aSJohnny Huang 		argv++;
18672a856b9aSJohnny Huang 	}
1868cd1610b4SJohnny Huang 
1869a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
18702a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
18712a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
18720808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
18732a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1874cd1610b4SJohnny Huang 	} else {
18752a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
18762a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
18772a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
18780808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
18792a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18800808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
188178855207SJohnny Huang 			if (otp_addr >= 0x800)
18820808cc55SJohnny Huang 				return CMD_RET_USAGE;
18830808cc55SJohnny Huang 		} else {
188478855207SJohnny Huang 			if (otp_addr >= 0x20)
18850808cc55SJohnny Huang 				return CMD_RET_USAGE;
18860808cc55SJohnny Huang 		}
1887cd1610b4SJohnny Huang 	}
1888cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
18892a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1890cd1610b4SJohnny Huang 
18913d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18922a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
18932a856b9aSJohnny Huang 
18942a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18952a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18962a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18972a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18982a856b9aSJohnny Huang 	else
18992a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19002a856b9aSJohnny Huang }
19012a856b9aSJohnny Huang 
19022a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19032a856b9aSJohnny Huang {
19042a856b9aSJohnny Huang 	phys_addr_t addr;
19052a856b9aSJohnny Huang 	int otp_addr = 0;
19062a856b9aSJohnny Huang 
19072a856b9aSJohnny Huang 	if (argc != 3)
19082a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19092a856b9aSJohnny Huang 
19103d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19112a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
19122a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
19132a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
191469d5fd8fSJohnny Huang 		printf("Compare pass\n");
19152a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
1916a219f6deSJohnny Huang 	}
191769d5fd8fSJohnny Huang 	printf("Compare fail\n");
19182a856b9aSJohnny Huang 	return CMD_RET_FAILURE;
191969d5fd8fSJohnny Huang }
192069d5fd8fSJohnny Huang 
192166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
192266f2f8e5SJohnny Huang {
1923a8bd6d8cSJohnny Huang 	int view = 0;
19242d4b0742SJohnny Huang 	int input;
1925a8bd6d8cSJohnny Huang 
1926a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
192766f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
192866f2f8e5SJohnny Huang 
19292d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
19303d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19312d4b0742SJohnny Huang 		if (argc == 3) {
19322d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
19332d4b0742SJohnny Huang 			otp_print_conf_info(input);
19342d4b0742SJohnny Huang 		} else {
19352d4b0742SJohnny Huang 			otp_print_conf_info(-1);
19362d4b0742SJohnny Huang 		}
19372d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
19382d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
1939a8bd6d8cSJohnny Huang 			view = 1;
1940a8bd6d8cSJohnny Huang 			/* Drop the view option */
1941a8bd6d8cSJohnny Huang 			argc--;
1942a8bd6d8cSJohnny Huang 			argv++;
1943a8bd6d8cSJohnny Huang 		}
19443d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1945b458cd62SJohnny Huang 		otp_print_strap_info(view);
194666f2f8e5SJohnny Huang 	} else {
194766f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
194866f2f8e5SJohnny Huang 	}
19492d4b0742SJohnny Huang 
195066f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
195166f2f8e5SJohnny Huang }
195266f2f8e5SJohnny Huang 
1953*e14b073cSJohnny Huang static int _do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[], int preg)
1954737ed20bSJohnny Huang {
1955737ed20bSJohnny Huang 	int input;
1956737ed20bSJohnny Huang 	int bit_offset;
1957*e14b073cSJohnny Huang 	u32 prog_address;
195883655e91SJohnny Huang 	int ret;
1959*e14b073cSJohnny Huang 	char info[10];
1960*e14b073cSJohnny Huang 
1961*e14b073cSJohnny Huang 	if (preg) {
1962*e14b073cSJohnny Huang 		sprintf(info, "register ");
1963*e14b073cSJohnny Huang 		prog_address = 0xe08;
1964*e14b073cSJohnny Huang 	} else {
1965*e14b073cSJohnny Huang 		info[0] = 0;
1966*e14b073cSJohnny Huang 		prog_address = 0xe0c;
1967*e14b073cSJohnny Huang 	}
1968a219f6deSJohnny Huang 
1969737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1970737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1971737ed20bSJohnny Huang 
1972*e14b073cSJohnny Huang 	if (!strcmp(argv[1], "o")) {
1973737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1974737ed20bSJohnny Huang 	} else {
1975737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1976*e14b073cSJohnny Huang 		printf("OTPSTRAP[%d] %swill be protected\n", input, info);
1977737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1978737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1979737ed20bSJohnny Huang 			printf(" Aborting\n");
1980737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
1981737ed20bSJohnny Huang 		}
1982737ed20bSJohnny Huang 	}
1983737ed20bSJohnny Huang 
1984737ed20bSJohnny Huang 	if (input < 32) {
1985737ed20bSJohnny Huang 		bit_offset = input;
1986737ed20bSJohnny Huang 	} else if (input < 64) {
1987737ed20bSJohnny Huang 		bit_offset = input - 32;
1988*e14b073cSJohnny Huang 		prog_address += 2;
1989737ed20bSJohnny Huang 	} else {
1990737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1991737ed20bSJohnny Huang 	}
1992737ed20bSJohnny Huang 
1993*e14b073cSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1994*e14b073cSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
1995*e14b073cSJohnny Huang 		printf("OTPSTRAP[%d] %salready protected\n", input, info);
1996*e14b073cSJohnny Huang 		return CMD_RET_SUCCESS;
1997*e14b073cSJohnny Huang 	}
1998de6fbf1cSJohnny Huang 
199983655e91SJohnny Huang 	ret = otp_prog_bit(1, prog_address, bit_offset);
2000de6fbf1cSJohnny Huang 	otp_soak(0);
200183655e91SJohnny Huang 
200283655e91SJohnny Huang 	if (ret) {
2003*e14b073cSJohnny Huang 		printf("OTPSTRAP[%d] %sis protected\n", input, info);
2004737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2005737ed20bSJohnny Huang 	}
2006737ed20bSJohnny Huang 
2007*e14b073cSJohnny Huang 	printf("Protect OTPSTRAP[%d] %sfail\n", input, info);
2008737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2009737ed20bSJohnny Huang }
20109a4fe690SJohnny Huang 
2011*e14b073cSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2012*e14b073cSJohnny Huang {
2013*e14b073cSJohnny Huang 	return _do_otpprotect(cmdtp, flag, argc, argv, 0);
2014*e14b073cSJohnny Huang }
2015*e14b073cSJohnny Huang 
2016*e14b073cSJohnny Huang static int do_otprprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2017*e14b073cSJohnny Huang {
2018*e14b073cSJohnny Huang 	return _do_otpprotect(cmdtp, flag, argc, argv, 1);
2019*e14b073cSJohnny Huang }
2020*e14b073cSJohnny Huang 
2021f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2022f67375f7SJohnny Huang {
2023f67375f7SJohnny Huang 	printf("OTP tool version: %s\n", OTP_VER);
2024f67375f7SJohnny Huang 	printf("OTP info version: %s\n", OTP_INFO_VER);
2025f67375f7SJohnny Huang 
2026f67375f7SJohnny Huang 	return CMD_RET_SUCCESS;
2027f67375f7SJohnny Huang }
2028f67375f7SJohnny Huang 
20292a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
2030f67375f7SJohnny Huang 	U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""),
20312a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2032a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
2033de6b0cc4SJohnny Huang 	U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""),
20342a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2035737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
2036*e14b073cSJohnny Huang 	U_BOOT_CMD_MKENT(rprotect, 3, 0, do_otprprotect, "", ""),
20372a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
20382a856b9aSJohnny Huang };
20392a856b9aSJohnny Huang 
20402a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20412a856b9aSJohnny Huang {
20422a856b9aSJohnny Huang 	cmd_tbl_t *cp;
2043a219f6deSJohnny Huang 	u32 ver;
2044*e14b073cSJohnny Huang 	int ret;
20452a856b9aSJohnny Huang 
20462a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
20472a856b9aSJohnny Huang 
2048737ed20bSJohnny Huang 	/* Drop the otp command */
20492a856b9aSJohnny Huang 	argc--;
20502a856b9aSJohnny Huang 	argv++;
20512a856b9aSJohnny Huang 
2052a219f6deSJohnny Huang 	if (!cp || argc > cp->maxargs)
20532a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20542a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
20552a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20562a856b9aSJohnny Huang 
20570dae9d52SJohnny Huang 	ver = chip_version();
20580dae9d52SJohnny Huang 	switch (ver) {
20590dae9d52SJohnny Huang 	case OTP_AST2600A0:
2060696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
20619a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
20629a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
20639a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
20649a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
20659a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
20669a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
20670dae9d52SJohnny Huang 		break;
20680dae9d52SJohnny Huang 	case OTP_AST2600A1:
2069696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
20703cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
20713cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
20723cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
20733cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
20749a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
20759a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
20760dae9d52SJohnny Huang 		break;
20770dae9d52SJohnny Huang 	case OTP_AST2600A2:
20785fdde29fSJohnny Huang 		info_cb.version = OTP_AST2600A2;
20795fdde29fSJohnny Huang 		info_cb.conf_info = a2_conf_info;
20805fdde29fSJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
20815fdde29fSJohnny Huang 		info_cb.strap_info = a2_strap_info;
20825fdde29fSJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
20835fdde29fSJohnny Huang 		info_cb.key_info = a2_key_type;
20845fdde29fSJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a2_key_type);
20850dae9d52SJohnny Huang 		break;
208664b66712SJohnny Huang 	case OTP_AST2600A3:
208764b66712SJohnny Huang 		info_cb.version = OTP_AST2600A3;
208864b66712SJohnny Huang 		info_cb.conf_info = a2_conf_info;
208964b66712SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
209064b66712SJohnny Huang 		info_cb.strap_info = a2_strap_info;
209164b66712SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
2092181f72d8SJohnny Huang 		info_cb.key_info = a3_key_type;
2093181f72d8SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a3_key_type);
209464b66712SJohnny Huang 		break;
20950dae9d52SJohnny Huang 	default:
2096f1be5099SJohnny Huang 		printf("SOC is not supported\n");
20970dae9d52SJohnny Huang 		return CMD_RET_FAILURE;
20989a4fe690SJohnny Huang 	}
20999a4fe690SJohnny Huang 
2100*e14b073cSJohnny Huang 	ret = cp->cmd(cmdtp, flag, argc, argv);
2101*e14b073cSJohnny Huang 	writel(1, OTP_PROTECT_KEY); //password
2102*e14b073cSJohnny Huang 
2103*e14b073cSJohnny Huang 	return ret;
210469d5fd8fSJohnny Huang }
210569d5fd8fSJohnny Huang 
2106a219f6deSJohnny Huang U_BOOT_CMD(otp, 7, 0,  do_ast_otp,
210769d5fd8fSJohnny Huang 	   "ASPEED One-Time-Programmable sub-system",
2108f67375f7SJohnny Huang 	   "version\n"
2109f67375f7SJohnny Huang 	   "otp read conf|data <otp_dw_offset> <dw_count>\n"
21102a856b9aSJohnny Huang 	   "otp read strap <strap_bit_offset> <bit_count>\n"
21112d4b0742SJohnny Huang 	   "otp info strap [v]\n"
21122d4b0742SJohnny Huang 	   "otp info conf [otp_dw_offset]\n"
2113de6b0cc4SJohnny Huang 	   "otp prog [o] <addr>\n"
2114ed071a2bSJohnny Huang 	   "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2115ed071a2bSJohnny Huang 	   "otp pb strap [o] <bit_offset> <value>\n"
2116ed071a2bSJohnny Huang 	   "otp protect [o] <bit_offset>\n"
2117*e14b073cSJohnny Huang 	   "otp rprotect [o] <bit_offset>\n"
21182a856b9aSJohnny Huang 	   "otp cmp <addr> <otp_dw_offset>\n"
211969d5fd8fSJohnny Huang 	  );
2120