xref: /openbmc/u-boot/cmd/otp.c (revision 64b667120d2675877fca52d9fffb36317c46db1d)
169d5fd8fSJohnny Huang /*
269d5fd8fSJohnny Huang  *  This program is distributed in the hope that it will be useful,
369d5fd8fSJohnny Huang  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
469d5fd8fSJohnny Huang  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
569d5fd8fSJohnny Huang  *  GNU General Public License for more details.
669d5fd8fSJohnny Huang  *
769d5fd8fSJohnny Huang  *  You should have received a copy of the GNU General Public License
869d5fd8fSJohnny Huang  *  along with this program; if not, write to the Free Software
969d5fd8fSJohnny Huang  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1069d5fd8fSJohnny Huang  */
114c1c9b35SJohnny Huang #include <stdlib.h>
1269d5fd8fSJohnny Huang #include <common.h>
1369d5fd8fSJohnny Huang #include <console.h>
1469d5fd8fSJohnny Huang #include <bootretry.h>
1569d5fd8fSJohnny Huang #include <cli.h>
1669d5fd8fSJohnny Huang #include <command.h>
1769d5fd8fSJohnny Huang #include <console.h>
184c1c9b35SJohnny Huang #include <malloc.h>
1969d5fd8fSJohnny Huang #include <inttypes.h>
2069d5fd8fSJohnny Huang #include <mapmem.h>
2169d5fd8fSJohnny Huang #include <asm/io.h>
2269d5fd8fSJohnny Huang #include <linux/compiler.h>
23696656c6SJohnny Huang #include <u-boot/sha256.h>
240cee9a95SJohnny Huang #include "otp_info.h"
2569d5fd8fSJohnny Huang 
2669d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2769d5fd8fSJohnny Huang 
28*64b66712SJohnny Huang #define OTP_VER				"1.0.3"
29f67375f7SJohnny Huang 
3069d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
31dacbba92SJohnny Huang #define RETRY				20
327332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
337332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
347332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
3569d5fd8fSJohnny Huang 
362a856b9aSJohnny Huang #define OTP_USAGE			-1
372a856b9aSJohnny Huang #define OTP_FAILURE			-2
382a856b9aSJohnny Huang #define OTP_SUCCESS			0
392a856b9aSJohnny Huang 
40a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
41a6af4a17SJohnny Huang 
429a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA		1
439a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES		2
449a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT		3
459a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC		4
469a4fe690SJohnny Huang 
474c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
484c1c9b35SJohnny Huang #define PBWIDTH 60
494c1c9b35SJohnny Huang 
503d3688adSJohnny Huang #define OTP_BASE		0x1e6f2000
513d3688adSJohnny Huang #define OTP_PROTECT_KEY		OTP_BASE
523d3688adSJohnny Huang #define OTP_COMMAND		OTP_BASE + 0x4
533d3688adSJohnny Huang #define OTP_TIMING		OTP_BASE + 0x8
543d3688adSJohnny Huang #define OTP_ADDR		OTP_BASE + 0x10
553d3688adSJohnny Huang #define OTP_STATUS		OTP_BASE + 0x14
563d3688adSJohnny Huang #define OTP_COMPARE_1		OTP_BASE + 0x20
573d3688adSJohnny Huang #define OTP_COMPARE_2		OTP_BASE + 0x24
583d3688adSJohnny Huang #define OTP_COMPARE_3		OTP_BASE + 0x28
593d3688adSJohnny Huang #define OTP_COMPARE_4		OTP_BASE + 0x2c
603d3688adSJohnny Huang 
61696656c6SJohnny Huang #define OTP_MAGIC		"SOCOTP"
62696656c6SJohnny Huang #define CHECKSUM_LEN		32
63696656c6SJohnny Huang #define OTP_INC_DATA		(1 << 31)
64696656c6SJohnny Huang #define OTP_INC_CONFIG		(1 << 30)
65696656c6SJohnny Huang #define OTP_INC_STRAP		(1 << 29)
66696656c6SJohnny Huang #define OTP_ECC_EN		(1 << 28)
67696656c6SJohnny Huang #define OTP_REGION_SIZE(info)	((info >> 16) & 0xffff)
68696656c6SJohnny Huang #define OTP_REGION_OFFSET(info)	(info & 0xffff)
69696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info)	(info & 0xffff)
70696656c6SJohnny Huang 
71696656c6SJohnny Huang #define OTP_AST2600A0		0
72696656c6SJohnny Huang #define OTP_AST2600A1		1
730dae9d52SJohnny Huang #define OTP_AST2600A2		2
74*64b66712SJohnny Huang #define OTP_AST2600A3		3
75696656c6SJohnny Huang 
76696656c6SJohnny Huang struct otp_header {
77696656c6SJohnny Huang 	u8	otp_magic[8];
78696656c6SJohnny Huang 	u8	otp_version[8];
79696656c6SJohnny Huang 	u32	image_info;
80696656c6SJohnny Huang 	u32	data_info;
81696656c6SJohnny Huang 	u32	config_info;
82696656c6SJohnny Huang 	u32	strap_info;
83696656c6SJohnny Huang 	u32	checksum_offset;
84696656c6SJohnny Huang } __attribute__((packed));
85696656c6SJohnny Huang 
8666f2f8e5SJohnny Huang struct otpstrap_status {
8769d5fd8fSJohnny Huang 	int value;
8869d5fd8fSJohnny Huang 	int option_array[7];
8969d5fd8fSJohnny Huang 	int remain_times;
9069d5fd8fSJohnny Huang 	int writeable_option;
915010032bSJohnny Huang 	int reg_protected;
9269d5fd8fSJohnny Huang 	int protected;
9369d5fd8fSJohnny Huang };
9469d5fd8fSJohnny Huang 
9566f2f8e5SJohnny Huang struct otpconf_parse {
9666f2f8e5SJohnny Huang 	int dw_offset;
9766f2f8e5SJohnny Huang 	int bit;
9866f2f8e5SJohnny Huang 	int length;
9966f2f8e5SJohnny Huang 	int value;
100696656c6SJohnny Huang 	int ignore;
10166f2f8e5SJohnny Huang 	char status[80];
10266f2f8e5SJohnny Huang };
10366f2f8e5SJohnny Huang 
1049a4fe690SJohnny Huang struct otpkey_type {
1059a4fe690SJohnny Huang 	int value;
1069a4fe690SJohnny Huang 	int key_type;
1079a4fe690SJohnny Huang 	int need_id;
1089a4fe690SJohnny Huang 	char information[110];
1099a4fe690SJohnny Huang };
1109a4fe690SJohnny Huang 
1119a4fe690SJohnny Huang struct otp_info_cb {
1129a4fe690SJohnny Huang 	int version;
11379e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1149a4fe690SJohnny Huang 	int strap_info_len;
11579e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1169a4fe690SJohnny Huang 	int conf_info_len;
11779e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1189a4fe690SJohnny Huang 	int key_info_len;
1195010032bSJohnny Huang 
1209a4fe690SJohnny Huang };
1219a4fe690SJohnny Huang 
122696656c6SJohnny Huang struct otp_image_layout {
1235010032bSJohnny Huang 	int data_length;
1245010032bSJohnny Huang 	int conf_length;
1255010032bSJohnny Huang 	int strap_length;
126696656c6SJohnny Huang 	uint8_t *data;
127696656c6SJohnny Huang 	uint8_t *data_ignore;
128696656c6SJohnny Huang 	uint8_t *conf;
129696656c6SJohnny Huang 	uint8_t *conf_ignore;
130696656c6SJohnny Huang 	uint8_t *strap;
131696656c6SJohnny Huang 	uint8_t *strap_reg_pro;
132696656c6SJohnny Huang 	uint8_t *strap_pro;
133696656c6SJohnny Huang 	uint8_t *strap_ignore;
134696656c6SJohnny Huang };
135696656c6SJohnny Huang 
1369a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1379a4fe690SJohnny Huang 
13879e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
1399a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
1409a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1419a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
1429a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1439a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
1449a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1459a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
1469a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1479a4fe690SJohnny Huang };
1489a4fe690SJohnny Huang 
14979e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
1509a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1519a4fe690SJohnny 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"},
1529a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1539a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1549a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1559a4fe690SJohnny Huang };
1569a4fe690SJohnny Huang 
1575fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = {
1585fdde29fSJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1595fdde29fSJohnny 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"},
1605fdde29fSJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1615fdde29fSJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1625fdde29fSJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1635fdde29fSJohnny Huang };
1645fdde29fSJohnny Huang 
1659a4fe690SJohnny Huang static uint32_t  chip_version(void)
1669a4fe690SJohnny Huang {
167badd21c2SJohnny Huang 	u64 rev_id;
1689a4fe690SJohnny Huang 
169badd21c2SJohnny Huang 	rev_id = readl(ASPEED_REVISION_ID0);
170badd21c2SJohnny Huang 	rev_id = ((u64)readl(ASPEED_REVISION_ID1) << 32) | rev_id;
1719a4fe690SJohnny Huang 
172badd21c2SJohnny Huang 	if (rev_id == 0x0500030305000303) {
173badd21c2SJohnny Huang 		/* AST2600-A0 */
1740dae9d52SJohnny Huang 		return OTP_AST2600A0;
175badd21c2SJohnny Huang 	} else if (rev_id == 0x0501030305010303) {
176badd21c2SJohnny Huang 		/* AST2600-A1 */
1770dae9d52SJohnny Huang 		return OTP_AST2600A1;
178badd21c2SJohnny Huang 	} else if (rev_id == 0x0501020305010203) {
179badd21c2SJohnny Huang 		/* AST2620-A1 */
180badd21c2SJohnny Huang 		return OTP_AST2600A1;
181badd21c2SJohnny Huang 	} else if (rev_id == 0x0502030305010303) {
182badd21c2SJohnny Huang 		/* AST2600-A2 */
1830dae9d52SJohnny Huang 		return OTP_AST2600A2;
184badd21c2SJohnny Huang 	} else if (rev_id == 0x0502020305010203) {
185badd21c2SJohnny Huang 		/* AST2620-A2 */
186badd21c2SJohnny Huang 		return OTP_AST2600A2;
187badd21c2SJohnny Huang 	} else if (rev_id == 0x0502010305010103) {
188badd21c2SJohnny Huang 		/* AST2605-A2 */
1890dae9d52SJohnny Huang 		return OTP_AST2600A2;
190*64b66712SJohnny Huang 	} else if (rev_id == 0x0503030305030303) {
191*64b66712SJohnny Huang 		/* AST2600-A3 */
192*64b66712SJohnny Huang 		return OTP_AST2600A3;
193*64b66712SJohnny Huang 	} else if (rev_id == 0x0503020305030203) {
194*64b66712SJohnny Huang 		/* AST2620-A3 */
195*64b66712SJohnny Huang 		return OTP_AST2600A3;
1960dae9d52SJohnny Huang 	}
1970dae9d52SJohnny Huang 
1985fdde29fSJohnny Huang 	return -1;
1999a4fe690SJohnny Huang }
2009a4fe690SJohnny Huang 
2013d3688adSJohnny Huang static void wait_complete(void)
2023d3688adSJohnny Huang {
2033d3688adSJohnny Huang 	int reg;
2043d3688adSJohnny Huang 
2053d3688adSJohnny Huang 	do {
2063d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
2073d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
2083d3688adSJohnny Huang }
2093d3688adSJohnny Huang 
210dacbba92SJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
211dacbba92SJohnny Huang {
212dacbba92SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
213dacbba92SJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
214dacbba92SJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
215dacbba92SJohnny Huang 	wait_complete();
216dacbba92SJohnny Huang }
217dacbba92SJohnny Huang 
218dacbba92SJohnny Huang static void otp_soak(int soak)
219dacbba92SJohnny Huang {
220*64b66712SJohnny Huang 	if (info_cb.version == OTP_AST2600A2 || info_cb.version == OTP_AST2600A3) {
221dacbba92SJohnny Huang 		switch (soak) {
222dacbba92SJohnny Huang 		case 0: //default
223dacbba92SJohnny Huang 			otp_write(0x3000, 0x0210); // Write MRA
224dacbba92SJohnny Huang 			otp_write(0x5000, 0x2000); // Write MRB
225dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
226dacbba92SJohnny Huang 			break;
227dacbba92SJohnny Huang 		case 1: //normal program
228dacbba92SJohnny Huang 			otp_write(0x3000, 0x1200); // Write MRA
229feea3fdfSJohnny Huang 			otp_write(0x5000, 0x107F); // Write MRB
230dacbba92SJohnny Huang 			otp_write(0x1000, 0x1024); // Write MR
231feea3fdfSJohnny Huang 			writel(0x04191388, OTP_TIMING); // 200us
232dacbba92SJohnny Huang 			break;
233dacbba92SJohnny Huang 		case 2: //soak program
234dacbba92SJohnny Huang 			otp_write(0x3000, 0x1220); // Write MRA
235feea3fdfSJohnny Huang 			otp_write(0x5000, 0x2074); // Write MRB
236dacbba92SJohnny Huang 			otp_write(0x1000, 0x08a4); // Write MR
237feea3fdfSJohnny Huang 			writel(0x04193a98, OTP_TIMING); // 600us
238dacbba92SJohnny Huang 			break;
239dacbba92SJohnny Huang 		}
240dacbba92SJohnny Huang 	} else {
241dacbba92SJohnny Huang 		switch (soak) {
242dacbba92SJohnny Huang 		case 0: //default
243dacbba92SJohnny Huang 			otp_write(0x3000, 0x0); // Write MRA
244dacbba92SJohnny Huang 			otp_write(0x5000, 0x0); // Write MRB
245dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
246dacbba92SJohnny Huang 			break;
247dacbba92SJohnny Huang 		case 1: //normal program
248dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
249dacbba92SJohnny Huang 			otp_write(0x5000, 0x302f); // Write MRB
250dacbba92SJohnny Huang 			otp_write(0x1000, 0x4020); // Write MR
251feea3fdfSJohnny Huang 			writel(0x04190760, OTP_TIMING); // 75us
252dacbba92SJohnny Huang 			break;
253dacbba92SJohnny Huang 		case 2: //soak program
254dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
255dacbba92SJohnny Huang 			otp_write(0x5000, 0x1027); // Write MRB
256dacbba92SJohnny Huang 			otp_write(0x1000, 0x4820); // Write MR
257feea3fdfSJohnny Huang 			writel(0x041930d4, OTP_TIMING); // 500us
258dacbba92SJohnny Huang 			break;
259dacbba92SJohnny Huang 		}
260dacbba92SJohnny Huang 	}
261dacbba92SJohnny Huang 
262dacbba92SJohnny Huang 	wait_complete();
263dacbba92SJohnny Huang }
264dacbba92SJohnny Huang 
2652a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
26669d5fd8fSJohnny Huang {
2673d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
2683d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2693d3688adSJohnny Huang 	wait_complete();
2703d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
2713d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
27269d5fd8fSJohnny Huang }
27369d5fd8fSJohnny Huang 
2742a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
27569d5fd8fSJohnny Huang {
27669d5fd8fSJohnny Huang 	int config_offset;
27769d5fd8fSJohnny Huang 
27869d5fd8fSJohnny Huang 	config_offset = 0x800;
27969d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
28069d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
28169d5fd8fSJohnny Huang 
2823d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
2833d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2843d3688adSJohnny Huang 	wait_complete();
2853d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
28669d5fd8fSJohnny Huang }
28769d5fd8fSJohnny Huang 
28869d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
28969d5fd8fSJohnny Huang {
29069d5fd8fSJohnny Huang 	int i;
29169d5fd8fSJohnny Huang 	uint32_t ret[1];
29269d5fd8fSJohnny Huang 
29369d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
2942a856b9aSJohnny Huang 		return OTP_USAGE;
295dacbba92SJohnny Huang 	otp_soak(0);
29669d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
29769d5fd8fSJohnny Huang 		otp_read_config(i, ret);
298a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
29969d5fd8fSJohnny Huang 	}
30069d5fd8fSJohnny Huang 	printf("\n");
3012a856b9aSJohnny Huang 	return OTP_SUCCESS;
30269d5fd8fSJohnny Huang }
30369d5fd8fSJohnny Huang 
30469d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
30569d5fd8fSJohnny Huang {
30669d5fd8fSJohnny Huang 	int i;
30769d5fd8fSJohnny Huang 	uint32_t ret[2];
30869d5fd8fSJohnny Huang 
30969d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
3102a856b9aSJohnny Huang 		return OTP_USAGE;
311dacbba92SJohnny Huang 	otp_soak(0);
31269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
31369d5fd8fSJohnny Huang 		otp_read_data(i, ret);
31469d5fd8fSJohnny Huang 		if (i % 4 == 0)
31569d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
31669d5fd8fSJohnny Huang 		else
31769d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
31869d5fd8fSJohnny Huang 
31969d5fd8fSJohnny Huang 	}
32069d5fd8fSJohnny Huang 	printf("\n");
3212a856b9aSJohnny Huang 	return OTP_SUCCESS;
32269d5fd8fSJohnny Huang }
32369d5fd8fSJohnny Huang 
32469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
32569d5fd8fSJohnny Huang {
32669d5fd8fSJohnny Huang 	uint32_t ret;
32769d5fd8fSJohnny Huang 	uint32_t *buf;
32869d5fd8fSJohnny Huang 
32969d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
33069d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
33169d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
33269d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
33369d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
3343d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
3353d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
3363d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
3373d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
3383d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
3393d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
3403d3688adSJohnny Huang 	wait_complete();
3413d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
34269d5fd8fSJohnny Huang 	if (ret & 0x1)
34369d5fd8fSJohnny Huang 		return 0;
34469d5fd8fSJohnny Huang 	else
34569d5fd8fSJohnny Huang 		return -1;
34669d5fd8fSJohnny Huang }
34769d5fd8fSJohnny Huang 
348a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
34969d5fd8fSJohnny Huang {
35030a8c590SJohnny Huang 	uint32_t ret[2];
35169d5fd8fSJohnny Huang 
35230a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
3533d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
35430a8c590SJohnny Huang 	else
3553d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
35630a8c590SJohnny Huang 
3573d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3583d3688adSJohnny Huang 	wait_complete();
3593d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3603d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
36183655e91SJohnny Huang 
36230a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
36330a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
36469d5fd8fSJohnny Huang 			return 0;
36569d5fd8fSJohnny Huang 		else
36669d5fd8fSJohnny Huang 			return -1;
36730a8c590SJohnny Huang 	} else {
36830a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
36930a8c590SJohnny Huang 			return 0;
37030a8c590SJohnny Huang 		else
37130a8c590SJohnny Huang 			return -1;
37230a8c590SJohnny Huang 	}
37330a8c590SJohnny Huang 
37469d5fd8fSJohnny Huang }
37569d5fd8fSJohnny Huang 
376696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size)
3774c1c9b35SJohnny Huang {
3784c1c9b35SJohnny Huang 	uint32_t ret[2];
3794c1c9b35SJohnny Huang 
3804c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
3814c1c9b35SJohnny Huang 
3824c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
3833d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
3844c1c9b35SJohnny Huang 	else
3853d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
3863d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3873d3688adSJohnny Huang 	wait_complete();
3883d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3893d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
3904c1c9b35SJohnny Huang 	if (size == 1) {
3914c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
3924c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
393696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
3944c1c9b35SJohnny Huang 				compare[0] = 0;
3954c1c9b35SJohnny Huang 				return 0;
3964c1c9b35SJohnny Huang 			} else {
3974c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
3984c1c9b35SJohnny Huang 				return -1;
3994c1c9b35SJohnny Huang 			}
4004c1c9b35SJohnny Huang 
4014c1c9b35SJohnny Huang 		} else {
4024c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
403696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
4044c1c9b35SJohnny Huang 				compare[0] = ~0;
4054c1c9b35SJohnny Huang 				return 0;
4064c1c9b35SJohnny Huang 			} else {
407d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
4084c1c9b35SJohnny Huang 				return -1;
4094c1c9b35SJohnny Huang 			}
4104c1c9b35SJohnny Huang 		}
4114c1c9b35SJohnny Huang 	} else if (size == 2) {
4124c1c9b35SJohnny Huang 		// otp_addr should be even
413696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
4144c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4154c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4164c1c9b35SJohnny Huang 			compare[0] = 0;
4174c1c9b35SJohnny Huang 			compare[1] = ~0;
4184c1c9b35SJohnny Huang 			return 0;
4194c1c9b35SJohnny Huang 		} else {
4204c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4214c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4224c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
4234c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
4244c1c9b35SJohnny Huang 			return -1;
4254c1c9b35SJohnny Huang 		}
4264c1c9b35SJohnny Huang 	} else {
4274c1c9b35SJohnny Huang 		return -1;
4284c1c9b35SJohnny Huang 	}
4294c1c9b35SJohnny Huang }
4304c1c9b35SJohnny Huang 
43183655e91SJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
43283655e91SJohnny Huang {
43390965bb3SJohnny Huang 	otp_write(0x0, prog_bit);
43483655e91SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
43583655e91SJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
43683655e91SJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
43783655e91SJohnny Huang 	wait_complete();
43883655e91SJohnny Huang }
43983655e91SJohnny Huang 
44083655e91SJohnny Huang static void _otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
44183655e91SJohnny Huang {
44283655e91SJohnny Huang 	int prog_bit;
44383655e91SJohnny Huang 
44483655e91SJohnny Huang 	if (prog_address % 2 == 0) {
44583655e91SJohnny Huang 		if (value)
44683655e91SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
44783655e91SJohnny Huang 		else
44883655e91SJohnny Huang 			return;
44983655e91SJohnny Huang 	} else {
450*64b66712SJohnny Huang 		if (info_cb.version != OTP_AST2600A3)
45183655e91SJohnny Huang 			prog_address |= 1 << 15;
45283655e91SJohnny Huang 		if (!value)
45383655e91SJohnny Huang 			prog_bit = 0x1 << bit_offset;
45483655e91SJohnny Huang 		else
45583655e91SJohnny Huang 			return;
45683655e91SJohnny Huang 	}
45783655e91SJohnny Huang 	otp_prog(prog_address, prog_bit);
45883655e91SJohnny Huang }
45983655e91SJohnny Huang 
46083655e91SJohnny Huang static int otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
46183655e91SJohnny Huang {
46283655e91SJohnny Huang 	int pass;
46383655e91SJohnny Huang 	int i;
46483655e91SJohnny Huang 
46583655e91SJohnny Huang 	otp_soak(1);
46683655e91SJohnny Huang 	_otp_prog_bit(value, prog_address, bit_offset);
46783655e91SJohnny Huang 	pass = 0;
46883655e91SJohnny Huang 
46983655e91SJohnny Huang 	for (i = 0; i < RETRY; i++) {
47083655e91SJohnny Huang 		if (verify_bit(prog_address, bit_offset, value) != 0) {
47183655e91SJohnny Huang 			otp_soak(2);
47283655e91SJohnny Huang 			_otp_prog_bit(value, prog_address, bit_offset);
47383655e91SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
47483655e91SJohnny Huang 				otp_soak(1);
47583655e91SJohnny Huang 			} else {
47683655e91SJohnny Huang 				pass = 1;
47783655e91SJohnny Huang 				break;
47883655e91SJohnny Huang 			}
47983655e91SJohnny Huang 		} else {
48083655e91SJohnny Huang 			pass = 1;
48183655e91SJohnny Huang 			break;
48283655e91SJohnny Huang 		}
48383655e91SJohnny Huang 	}
48483655e91SJohnny Huang 
48583655e91SJohnny Huang 	return pass;
48683655e91SJohnny Huang }
48783655e91SJohnny Huang 
488696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address)
489d90825e2SJohnny Huang {
490d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
491d90825e2SJohnny Huang 
492d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
493696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
494d90825e2SJohnny Huang 			continue;
495d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
496d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
497d90825e2SJohnny Huang 			if (bit_value)
498d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
499d90825e2SJohnny Huang 			else
500d90825e2SJohnny Huang 				continue;
501d90825e2SJohnny Huang 		} else {
502*64b66712SJohnny Huang 			if (info_cb.version != OTP_AST2600A3)
503d90825e2SJohnny Huang 				prog_address |= 1 << 15;
504d90825e2SJohnny Huang 			if (bit_value)
505d90825e2SJohnny Huang 				continue;
506d90825e2SJohnny Huang 			else
507d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
508d90825e2SJohnny Huang 		}
509d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
510d90825e2SJohnny Huang 	}
511d90825e2SJohnny Huang }
512d90825e2SJohnny Huang 
51354552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
51454552c69SJohnny Huang {
51554552c69SJohnny Huang 	int pass;
51654552c69SJohnny Huang 	int i;
51754552c69SJohnny Huang 	uint32_t data0_masked;
51854552c69SJohnny Huang 	uint32_t data1_masked;
51954552c69SJohnny Huang 	uint32_t buf0_masked;
52054552c69SJohnny Huang 	uint32_t buf1_masked;
52154552c69SJohnny Huang 	uint32_t compare[2];
52254552c69SJohnny Huang 
52354552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
52454552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
52554552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
52654552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
52754552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
52854552c69SJohnny Huang 		return 0;
52954552c69SJohnny Huang 
53054552c69SJohnny Huang 	otp_soak(1);
53154552c69SJohnny Huang 	if (data0_masked != buf0_masked)
53254552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
53354552c69SJohnny Huang 	if (data1_masked != buf1_masked)
53454552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
53554552c69SJohnny Huang 
53654552c69SJohnny Huang 	pass = 0;
53754552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
53854552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
53954552c69SJohnny Huang 			otp_soak(2);
54054552c69SJohnny Huang 			if (compare[0] != 0) {
54154552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
54254552c69SJohnny Huang 			}
54354552c69SJohnny Huang 			if (compare[1] != ~0) {
5445537bc72SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1);
54554552c69SJohnny Huang 			}
54654552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
54754552c69SJohnny Huang 				otp_soak(1);
54854552c69SJohnny Huang 			} else {
54954552c69SJohnny Huang 				pass = 1;
55054552c69SJohnny Huang 				break;
55154552c69SJohnny Huang 			}
55254552c69SJohnny Huang 		} else {
55354552c69SJohnny Huang 			pass = 1;
55454552c69SJohnny Huang 			break;
55554552c69SJohnny Huang 		}
55654552c69SJohnny Huang 	}
55754552c69SJohnny Huang 
55854552c69SJohnny Huang 	if (!pass) {
55954552c69SJohnny Huang 		otp_soak(0);
56054552c69SJohnny Huang 		return OTP_FAILURE;
56154552c69SJohnny Huang 	}
56254552c69SJohnny Huang 	return OTP_SUCCESS;
56354552c69SJohnny Huang }
56454552c69SJohnny Huang 
565541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
56676d13988SJohnny Huang {
56776d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
5685010032bSJohnny Huang 	int strap_end;
56976d13988SJohnny Huang 	int i, j;
57076d13988SJohnny Huang 
5715010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
57276d13988SJohnny Huang 		for (j = 0; j < 64; j++) {
57376d13988SJohnny Huang 			otpstrap[j].value = 0;
57476d13988SJohnny Huang 			otpstrap[j].remain_times = 7;
57576d13988SJohnny Huang 			otpstrap[j].writeable_option = -1;
57676d13988SJohnny Huang 			otpstrap[j].protected = 0;
57776d13988SJohnny Huang 		}
5785010032bSJohnny Huang 		strap_end = 30;
5795010032bSJohnny Huang 	} else {
5805010032bSJohnny Huang 		for (j = 0; j < 64; j++) {
5815010032bSJohnny Huang 			otpstrap[j].value = 0;
5825010032bSJohnny Huang 			otpstrap[j].remain_times = 6;
5835010032bSJohnny Huang 			otpstrap[j].writeable_option = -1;
5845010032bSJohnny Huang 			otpstrap[j].reg_protected = 0;
5855010032bSJohnny Huang 			otpstrap[j].protected = 0;
5865010032bSJohnny Huang 		}
5875010032bSJohnny Huang 		strap_end = 28;
5885010032bSJohnny Huang 	}
58976d13988SJohnny Huang 
590dacbba92SJohnny Huang 	otp_soak(0);
5915010032bSJohnny Huang 	for (i = 16; i < strap_end; i += 2) {
59276d13988SJohnny Huang 		int option = (i - 16) / 2;
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);
59776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
59876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
59976d13988SJohnny Huang 			}
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);
60776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
60876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
60976d13988SJohnny Huang 			}
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 	}
6305010032bSJohnny Huang 
63176d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
63276d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
63376d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
63476d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
63576d13988SJohnny Huang 			otpstrap[j].protected = 1;
63676d13988SJohnny Huang 	}
63776d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
63876d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
63976d13988SJohnny Huang 			otpstrap[j].protected = 1;
64076d13988SJohnny Huang 	}
64176d13988SJohnny Huang }
64276d13988SJohnny Huang 
643696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
64469d5fd8fSJohnny Huang {
64579e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
646696656c6SJohnny Huang 	uint32_t *OTPCFG = (uint32_t *)image_layout->conf;
647696656c6SJohnny Huang 	uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore;
648b458cd62SJohnny Huang 	uint32_t mask;
649b458cd62SJohnny Huang 	uint32_t dw_offset;
650b458cd62SJohnny Huang 	uint32_t bit_offset;
651b458cd62SJohnny Huang 	uint32_t otp_value;
652696656c6SJohnny Huang 	uint32_t otp_ignore;
653b458cd62SJohnny Huang 	int fail = 0;
65473f11549SJohnny Huang 	char valid_bit[20];
65566f2f8e5SJohnny Huang 	int i;
65673f11549SJohnny Huang 	int j;
65766f2f8e5SJohnny Huang 
658737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
65966f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
6603cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
6613cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
6623cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
6633cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
664b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
665696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
666b458cd62SJohnny Huang 
667696656c6SJohnny Huang 		if (otp_ignore == mask) {
668b458cd62SJohnny Huang 			continue;
669696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
670b458cd62SJohnny Huang 			fail = 1;
671b458cd62SJohnny Huang 		}
672b458cd62SJohnny Huang 
6733cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
6743cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
6753cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
6763cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
677b458cd62SJohnny Huang 			continue;
678b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
679b458cd62SJohnny Huang 
6803cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
6813cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
68266f2f8e5SJohnny Huang 		} else {
683b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
6843cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
6853cb28812SJohnny Huang 			       conf_info[i].bit_offset);
68666f2f8e5SJohnny Huang 		}
687b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
688b458cd62SJohnny Huang 
689b458cd62SJohnny Huang 		if (fail) {
690696656c6SJohnny Huang 			printf("Ignore mask error\n");
691b458cd62SJohnny Huang 		} else {
6923cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
693b458cd62SJohnny Huang 				printf("Reserved\n");
6943cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
6953cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
696b458cd62SJohnny Huang 				printf("\n");
6973cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
698b458cd62SJohnny Huang 				if (otp_value != 0) {
69973f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
70073f11549SJohnny Huang 						if (otp_value == (1 << j)) {
70173f11549SJohnny Huang 							valid_bit[j * 2] = '1';
702b458cd62SJohnny Huang 						} else {
70373f11549SJohnny Huang 							valid_bit[j * 2] = '0';
70473f11549SJohnny Huang 						}
70573f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
70673f11549SJohnny Huang 					}
70773f11549SJohnny Huang 					valid_bit[15] = 0;
70873f11549SJohnny Huang 				} else {
70973f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
710b458cd62SJohnny Huang 				}
7113cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
712b458cd62SJohnny Huang 				printf("\n");
713b458cd62SJohnny Huang 			} else {
7143cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
715b458cd62SJohnny Huang 			}
716b458cd62SJohnny Huang 		}
717b458cd62SJohnny Huang 	}
718b458cd62SJohnny Huang 
719b458cd62SJohnny Huang 	if (fail)
720b458cd62SJohnny Huang 		return OTP_FAILURE;
721b458cd62SJohnny Huang 
72266f2f8e5SJohnny Huang 	return OTP_SUCCESS;
72366f2f8e5SJohnny Huang }
72466f2f8e5SJohnny Huang 
7252d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
72666f2f8e5SJohnny Huang {
72779e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
728bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
729b458cd62SJohnny Huang 	uint32_t mask;
730b458cd62SJohnny Huang 	uint32_t dw_offset;
731b458cd62SJohnny Huang 	uint32_t bit_offset;
732b458cd62SJohnny Huang 	uint32_t otp_value;
73373f11549SJohnny Huang 	char valid_bit[20];
73466f2f8e5SJohnny Huang 	int i;
73573f11549SJohnny Huang 	int j;
73666f2f8e5SJohnny Huang 
737dacbba92SJohnny Huang 	otp_soak(0);
738bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
73966f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
74066f2f8e5SJohnny Huang 
74166f2f8e5SJohnny Huang 
742b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
743b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
7443cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
7453cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
7462d4b0742SJohnny Huang 			continue;
7473cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
7483cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
7493cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
750b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
751b458cd62SJohnny Huang 
7523cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
7533cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
7543cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
7553cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
756b458cd62SJohnny Huang 			continue;
757b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
758b458cd62SJohnny Huang 
7593cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
7603cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
761b458cd62SJohnny Huang 		} else {
762b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
7633cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
7643cb28812SJohnny Huang 			       conf_info[i].bit_offset);
765b458cd62SJohnny Huang 		}
766b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
767b458cd62SJohnny Huang 
7683cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
769b458cd62SJohnny Huang 			printf("Reserved\n");
7703cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
7713cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
772b458cd62SJohnny Huang 			printf("\n");
7733cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
774b458cd62SJohnny Huang 			if (otp_value != 0) {
77573f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
77673f11549SJohnny Huang 					if (otp_value == (1 << j)) {
77773f11549SJohnny Huang 						valid_bit[j * 2] = '1';
778b458cd62SJohnny Huang 					} else {
77973f11549SJohnny Huang 						valid_bit[j * 2] = '0';
78073f11549SJohnny Huang 					}
78173f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
78273f11549SJohnny Huang 				}
78373f11549SJohnny Huang 				valid_bit[15] = 0;
78473f11549SJohnny Huang 			} else {
78573f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
786b458cd62SJohnny Huang 			}
7873cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
788b458cd62SJohnny Huang 			printf("\n");
789b458cd62SJohnny Huang 		} else {
7903cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
791b458cd62SJohnny Huang 		}
792b458cd62SJohnny Huang 	}
793b458cd62SJohnny Huang 	return OTP_SUCCESS;
79466f2f8e5SJohnny Huang }
79566f2f8e5SJohnny Huang 
7965010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout)
79776d13988SJohnny Huang {
79879e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
799696656c6SJohnny Huang 	uint32_t *OTPSTRAP;
800696656c6SJohnny Huang 	uint32_t *OTPSTRAP_REG_PRO;
801696656c6SJohnny Huang 	uint32_t *OTPSTRAP_PRO;
802696656c6SJohnny Huang 	uint32_t *OTPSTRAP_IGNORE;
80376d13988SJohnny Huang 	int i;
804a8bd6d8cSJohnny Huang 	int fail = 0;
805a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
806a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
807a8bd6d8cSJohnny Huang 	uint32_t mask;
808a8bd6d8cSJohnny Huang 	uint32_t otp_value;
809696656c6SJohnny Huang 	uint32_t otp_reg_protect;
810a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
811696656c6SJohnny Huang 	uint32_t otp_ignore;
81276d13988SJohnny Huang 
813696656c6SJohnny Huang 	OTPSTRAP = (uint32_t *)image_layout->strap;
814696656c6SJohnny Huang 	OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro;
815696656c6SJohnny Huang 	OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore;
8165010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
817696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
818a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
819696656c6SJohnny Huang 	} else {
820696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro;
821de6b0cc4SJohnny Huang 		printf("BIT(hex)   Value       Reg_Protect Protect     Description\n");
822696656c6SJohnny Huang 	}
823de6b0cc4SJohnny Huang 	printf("__________________________________________________________________________________________\n");
824b458cd62SJohnny Huang 
8253cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
826696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
827a8bd6d8cSJohnny Huang 			dw_offset = 1;
8283cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
829a8bd6d8cSJohnny Huang 		} else {
830a8bd6d8cSJohnny Huang 			dw_offset = 0;
8313cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
832a8bd6d8cSJohnny Huang 		}
83376d13988SJohnny Huang 
8343cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
835a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
836a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
837696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
838a8bd6d8cSJohnny Huang 
8395010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
840696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
8415010032bSJohnny Huang 		else
8425010032bSJohnny Huang 			otp_reg_protect = 0;
843696656c6SJohnny Huang 
844696656c6SJohnny Huang 		if (otp_ignore == mask) {
845a8bd6d8cSJohnny Huang 			continue;
846696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
847a8bd6d8cSJohnny Huang 			fail = 1;
848a8bd6d8cSJohnny Huang 		}
849a8bd6d8cSJohnny Huang 
8503cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
8513cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
852a8bd6d8cSJohnny Huang 			continue;
853a8bd6d8cSJohnny Huang 
8543cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
8553cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
856a8bd6d8cSJohnny Huang 		} else {
857b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
8583cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
8593cb28812SJohnny Huang 			       strap_info[i].bit_offset);
860a8bd6d8cSJohnny Huang 		}
861a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
8625010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
863696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
864a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
865a8bd6d8cSJohnny Huang 
866a8bd6d8cSJohnny Huang 		if (fail) {
867696656c6SJohnny Huang 			printf("Ignore mask error\n");
868a8bd6d8cSJohnny Huang 		} else {
8693cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
8703cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
871a8bd6d8cSJohnny Huang 			else
872a8bd6d8cSJohnny Huang 				printf("Reserved\n");
873a8bd6d8cSJohnny Huang 		}
874a8bd6d8cSJohnny Huang 	}
875a8bd6d8cSJohnny Huang 
876a8bd6d8cSJohnny Huang 	if (fail)
87776d13988SJohnny Huang 		return OTP_FAILURE;
87876d13988SJohnny Huang 
87976d13988SJohnny Huang 	return OTP_SUCCESS;
88076d13988SJohnny Huang }
88176d13988SJohnny Huang 
882b458cd62SJohnny Huang static int otp_print_strap_info(int view)
88376d13988SJohnny Huang {
88479e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
88576d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
88607baa4e8SJohnny Huang 	int i, j;
887b458cd62SJohnny Huang 	int fail = 0;
888b458cd62SJohnny Huang 	uint32_t bit_offset;
889b458cd62SJohnny Huang 	uint32_t length;
890b458cd62SJohnny Huang 	uint32_t otp_value;
891b458cd62SJohnny Huang 	uint32_t otp_protect;
89276d13988SJohnny Huang 
893541eb887SJohnny Huang 	otp_strap_status(strap_status);
89476d13988SJohnny Huang 
895b458cd62SJohnny Huang 	if (view) {
89683655e91SJohnny Huang 		if (info_cb.version == OTP_AST2600A0)
89707baa4e8SJohnny Huang 			printf("BIT(hex) Value  Remains  Protect   Description\n");
89883655e91SJohnny Huang 		else
89983655e91SJohnny Huang 			printf("BIT(hex) Value  Remains  Reg_Protect Protect   Description\n");
90007baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
901b458cd62SJohnny Huang 	} else {
902b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
903b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
90476d13988SJohnny Huang 	}
9053cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
906b458cd62SJohnny Huang 		otp_value = 0;
9073cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
9083cb28812SJohnny Huang 		length = strap_info[i].length;
909b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
910c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
911c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
912b458cd62SJohnny Huang 		}
9133cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
9143cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
915b458cd62SJohnny Huang 			continue;
916b458cd62SJohnny Huang 		if (view) {
917b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
9183cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
919b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
92007baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
92183655e91SJohnny Huang 				if (info_cb.version != OTP_AST2600A0)
922e1a7245eSJohnny Huang 					printf("0x%-10X", strap_status[bit_offset + j].reg_protected);
923e1a7245eSJohnny Huang 				printf("0x%-7X", strap_status[bit_offset + j].protected);
9243cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
925b458cd62SJohnny Huang 					printf(" Reserved\n");
926b458cd62SJohnny Huang 					continue;
927b458cd62SJohnny Huang 				}
928b458cd62SJohnny Huang 				if (length == 1) {
9293cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
930b458cd62SJohnny Huang 					continue;
93176d13988SJohnny Huang 				}
93276d13988SJohnny Huang 
933b458cd62SJohnny Huang 				if (j == 0)
9343cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
935b458cd62SJohnny Huang 				else if (j == length - 1)
936b458cd62SJohnny Huang 					printf("\\ \"\n");
937b458cd62SJohnny Huang 				else
938b458cd62SJohnny Huang 					printf("| \"\n");
93976d13988SJohnny Huang 			}
940b458cd62SJohnny Huang 		} else {
941c947ef08SJohnny Huang 			if (length == 1) {
9423cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
943b458cd62SJohnny Huang 			} else {
944b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
945b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
946b458cd62SJohnny Huang 			}
947b458cd62SJohnny Huang 
948b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
949b458cd62SJohnny Huang 
9503cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
9513cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
952b458cd62SJohnny Huang 			else
953b458cd62SJohnny Huang 				printf("Reserved\n");
954b458cd62SJohnny Huang 		}
955b458cd62SJohnny Huang 	}
956b458cd62SJohnny Huang 
957b458cd62SJohnny Huang 	if (fail)
958b458cd62SJohnny Huang 		return OTP_FAILURE;
959b458cd62SJohnny Huang 
960b458cd62SJohnny Huang 	return OTP_SUCCESS;
961b458cd62SJohnny Huang }
962b458cd62SJohnny Huang 
963696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len)
96469d5fd8fSJohnny Huang {
96569d5fd8fSJohnny Huang 	int i;
96669d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
96769d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
96869d5fd8fSJohnny Huang 		if (i % 16 == 0) {
96969d5fd8fSJohnny Huang 			printf("%04X: ", i);
97069d5fd8fSJohnny Huang 		}
97169d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
97269d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
97369d5fd8fSJohnny Huang 			printf("\n");
97469d5fd8fSJohnny Huang 		}
97569d5fd8fSJohnny Huang 	}
97669d5fd8fSJohnny Huang }
97769d5fd8fSJohnny Huang 
978696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
97969d5fd8fSJohnny Huang {
98069d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
98179e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
9829a4fe690SJohnny Huang 	struct otpkey_type key_info;
983696656c6SJohnny Huang 	uint32_t *buf;
984696656c6SJohnny Huang 	uint8_t *byte_buf;
9859d998018SJohnny Huang 	char empty = 1;
98669d5fd8fSJohnny Huang 	int i = 0, len = 0;
9879a4fe690SJohnny Huang 	int j;
98854552c69SJohnny Huang 
989696656c6SJohnny Huang 	byte_buf = image_layout->data;
990696656c6SJohnny Huang 	buf = (uint32_t *)byte_buf;
9919d998018SJohnny Huang 
9929d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
9939d998018SJohnny Huang 		if (buf[i] != 0) {
9949d998018SJohnny Huang 			empty = 0;
9959d998018SJohnny Huang 		}
9969d998018SJohnny Huang 	}
9979d998018SJohnny Huang 	if (empty)
9989d998018SJohnny Huang 		return 0;
9999d998018SJohnny Huang 
10009d998018SJohnny Huang 	i = 0;
100169d5fd8fSJohnny Huang 	while (1) {
100269d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
100369d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
100469d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
100569d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
100669d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
100769d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
10089a4fe690SJohnny Huang 
10099a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
10109a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
10119a4fe690SJohnny Huang 				key_info = key_info_array[j];
10129a4fe690SJohnny Huang 				break;
10139a4fe690SJohnny Huang 			}
10149a4fe690SJohnny Huang 		}
10159a4fe690SJohnny Huang 
10167f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
101769d5fd8fSJohnny Huang 		printf("Key Type: ");
10189a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
10199a4fe690SJohnny Huang 
10209a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
102169d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
102269d5fd8fSJohnny Huang 			switch (key_length) {
102369d5fd8fSJohnny Huang 			case 0:
102469d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
102569d5fd8fSJohnny Huang 				break;
102669d5fd8fSJohnny Huang 			case 1:
102769d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
102869d5fd8fSJohnny Huang 				break;
102969d5fd8fSJohnny Huang 			case 2:
103069d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
103169d5fd8fSJohnny Huang 				break;
103269d5fd8fSJohnny Huang 			case 3:
103369d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
103469d5fd8fSJohnny Huang 				break;
103569d5fd8fSJohnny Huang 			}
10369a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
103769d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
103869d5fd8fSJohnny Huang 			switch (key_length) {
103969d5fd8fSJohnny Huang 			case 0:
104069d5fd8fSJohnny Huang 				printf("RSA1024\n");
104169d5fd8fSJohnny Huang 				len = 0x100;
104269d5fd8fSJohnny Huang 				break;
104369d5fd8fSJohnny Huang 			case 1:
104469d5fd8fSJohnny Huang 				printf("RSA2048\n");
104569d5fd8fSJohnny Huang 				len = 0x200;
104669d5fd8fSJohnny Huang 				break;
104769d5fd8fSJohnny Huang 			case 2:
104869d5fd8fSJohnny Huang 				printf("RSA3072\n");
104969d5fd8fSJohnny Huang 				len = 0x300;
105069d5fd8fSJohnny Huang 				break;
105169d5fd8fSJohnny Huang 			case 3:
105269d5fd8fSJohnny Huang 				printf("RSA4096\n");
105369d5fd8fSJohnny Huang 				len = 0x400;
105469d5fd8fSJohnny Huang 				break;
105569d5fd8fSJohnny Huang 			}
105669d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
105769d5fd8fSJohnny Huang 		}
10589a4fe690SJohnny Huang 		if (key_info.need_id)
105969d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
106069d5fd8fSJohnny Huang 		printf("Key Value:\n");
10619a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
106269d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
10639a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
10649a4fe690SJohnny Huang 			printf("AES Key:\n");
10659a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
10665fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
10679a4fe690SJohnny Huang 				printf("AES IV:\n");
10689a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10699a4fe690SJohnny Huang 			}
10709a4fe690SJohnny Huang 
10719a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
10725fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
107369d5fd8fSJohnny Huang 				printf("AES Key:\n");
107469d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
107569d5fd8fSJohnny Huang 				printf("AES IV:\n");
107669d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10775fdde29fSJohnny Huang 			} else {
10789a4fe690SJohnny Huang 				printf("AES Key 1:\n");
10799a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
10809a4fe690SJohnny Huang 				printf("AES Key 2:\n");
10819a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
10829a4fe690SJohnny Huang 			}
108369d5fd8fSJohnny Huang 
10849a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
108569d5fd8fSJohnny Huang 			printf("RSA mod:\n");
108669d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
108769d5fd8fSJohnny Huang 			printf("RSA exp:\n");
108869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
108969d5fd8fSJohnny Huang 		}
109069d5fd8fSJohnny Huang 		if (last)
109169d5fd8fSJohnny Huang 			break;
109269d5fd8fSJohnny Huang 		i++;
109369d5fd8fSJohnny Huang 	}
109469d5fd8fSJohnny Huang 	return 0;
109569d5fd8fSJohnny Huang }
109669d5fd8fSJohnny Huang 
10975010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout)
109869d5fd8fSJohnny Huang {
1099a6d0d645SJohnny Huang 	int i, k;
1100d90825e2SJohnny Huang 	int pass = 0;
1101a6d0d645SJohnny Huang 	uint32_t prog_address;
1102bb34a7bfSJohnny Huang 	uint32_t data[16];
1103a6d0d645SJohnny Huang 	uint32_t compare[2];
11045010032bSJohnny Huang 	uint32_t *conf = (uint32_t *)image_layout->conf;
11055010032bSJohnny Huang 	uint32_t *conf_ignore = (uint32_t *)image_layout->conf_ignore;
1106d90825e2SJohnny Huang 	uint32_t data_masked;
1107d90825e2SJohnny Huang 	uint32_t buf_masked;
110869d5fd8fSJohnny Huang 
1109a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1110a6d0d645SJohnny Huang 
1111bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
111269d5fd8fSJohnny Huang 		prog_address = 0x800;
1113a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1114a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1115a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1116a6d0d645SJohnny Huang 	}
1117a6d0d645SJohnny Huang 
1118a6d0d645SJohnny Huang 	printf("Check writable...\n");
1119bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11205010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11215010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1122d90825e2SJohnny Huang 		if (data_masked == buf_masked)
112369d5fd8fSJohnny Huang 			continue;
1124d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1125a6d0d645SJohnny Huang 			continue;
1126a6d0d645SJohnny Huang 		} else {
1127a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1128a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
11295010032bSJohnny Huang 			printf("Input [%X] = %x\n", i, conf[i]);
11305010032bSJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~conf_ignore[i]);
11312a856b9aSJohnny Huang 			return OTP_FAILURE;
1132a6d0d645SJohnny Huang 		}
1133a6d0d645SJohnny Huang 	}
1134a6d0d645SJohnny Huang 
1135a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1136d90825e2SJohnny Huang 	otp_soak(0);
1137bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11385010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11395010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1140a6d0d645SJohnny Huang 		prog_address = 0x800;
1141a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1142a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1143bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1144bb34a7bfSJohnny Huang 			pass = 1;
1145a6d0d645SJohnny Huang 			continue;
1146bb34a7bfSJohnny Huang 		}
1147de6fbf1cSJohnny Huang 
1148a6d0d645SJohnny Huang 
1149de6fbf1cSJohnny Huang 		otp_soak(1);
11505010032bSJohnny Huang 		otp_prog_dw(conf[i], conf_ignore[i], prog_address);
1151a6d0d645SJohnny Huang 
115269d5fd8fSJohnny Huang 		pass = 0;
115369d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
11545010032bSJohnny Huang 			if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1155de6fbf1cSJohnny Huang 				otp_soak(2);
1156feea3fdfSJohnny Huang 				otp_prog_dw(compare[0], conf_ignore[i], prog_address);
11575010032bSJohnny Huang 				if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1158de6fbf1cSJohnny Huang 					otp_soak(1);
1159de6fbf1cSJohnny Huang 				} else {
1160de6fbf1cSJohnny Huang 					pass = 1;
1161de6fbf1cSJohnny Huang 					break;
1162de6fbf1cSJohnny Huang 				}
1163a6d0d645SJohnny Huang 			} else {
116469d5fd8fSJohnny Huang 				pass = 1;
116569d5fd8fSJohnny Huang 				break;
116669d5fd8fSJohnny Huang 			}
116769d5fd8fSJohnny Huang 		}
1168bb34a7bfSJohnny Huang 		if (pass == 0) {
1169bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
11705010032bSJohnny Huang 			       i, data[i], conf[i], conf_ignore[i]);
1171bb34a7bfSJohnny Huang 			break;
1172bb34a7bfSJohnny Huang 		}
1173a6d0d645SJohnny Huang 	}
1174a6d0d645SJohnny Huang 
1175de6fbf1cSJohnny Huang 	otp_soak(0);
117669d5fd8fSJohnny Huang 	if (!pass)
11772a856b9aSJohnny Huang 		return OTP_FAILURE;
1178a6d0d645SJohnny Huang 
11792a856b9aSJohnny Huang 	return OTP_SUCCESS;
1180d90825e2SJohnny Huang 
118169d5fd8fSJohnny Huang }
118269d5fd8fSJohnny Huang 
1183eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit)
1184eda10d61SJohnny Huang {
1185eda10d61SJohnny Huang 	if (ibit == 1) {
1186eda10d61SJohnny Huang 		return OTP_SUCCESS;
1187eda10d61SJohnny Huang 	} else {
1188eda10d61SJohnny Huang 		printf("OTPSTRAP[%X]:\n", offset);
1189eda10d61SJohnny Huang 	}
1190eda10d61SJohnny Huang 	if (bit == otpstrap->value) {
1191eda10d61SJohnny Huang 		printf("    The value is same as before, skip it.\n");
1192eda10d61SJohnny Huang 		return OTP_PROG_SKIP;
1193eda10d61SJohnny Huang 	}
1194eda10d61SJohnny Huang 	if (otpstrap->protected == 1) {
1195eda10d61SJohnny Huang 		printf("    This bit is protected and is not writable\n");
1196eda10d61SJohnny Huang 		return OTP_FAILURE;
1197eda10d61SJohnny Huang 	}
1198eda10d61SJohnny Huang 	if (otpstrap->remain_times == 0) {
1199eda10d61SJohnny Huang 		printf("    This bit is no remaining times to write.\n");
1200eda10d61SJohnny Huang 		return OTP_FAILURE;
1201eda10d61SJohnny Huang 	}
1202eda10d61SJohnny Huang 	if (pbit == 1) {
1203eda10d61SJohnny Huang 		printf("    This bit will be protected and become non-writable.\n");
1204eda10d61SJohnny Huang 	}
1205eda10d61SJohnny Huang 	if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
1206eda10d61SJohnny Huang 		printf("    The relative register will be protected.\n");
1207eda10d61SJohnny Huang 	}
1208eda10d61SJohnny 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);
1209eda10d61SJohnny Huang 	return OTP_SUCCESS;
1210eda10d61SJohnny Huang }
1211eda10d61SJohnny Huang 
12125010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout)
121369d5fd8fSJohnny Huang {
121469d5fd8fSJohnny Huang 	int i;
12155010032bSJohnny Huang 	uint32_t *strap;
12165010032bSJohnny Huang 	uint32_t *strap_ignore;
12175010032bSJohnny Huang 	uint32_t *strap_reg_protect;
12185010032bSJohnny Huang 	uint32_t *strap_pro;
1219eda10d61SJohnny Huang 	int bit, pbit, ibit, rpbit;
122069d5fd8fSJohnny Huang 	int fail = 0;
1221a6af4a17SJohnny Huang 	int skip = -1;
1222eda10d61SJohnny Huang 	int ret;
122366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
122469d5fd8fSJohnny Huang 
12255010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
12265010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
12275010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
12285010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
12295010032bSJohnny Huang 
1230541eb887SJohnny Huang 	otp_strap_status(otpstrap);
123169d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
123269d5fd8fSJohnny Huang 		if (i < 32) {
12335010032bSJohnny Huang 			bit = (strap[0] >> i) & 0x1;
1234eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> i) & 0x1;
12355010032bSJohnny Huang 			pbit = (strap_pro[0] >> i) & 0x1;
123669d5fd8fSJohnny Huang 		} else {
12375010032bSJohnny Huang 			bit = (strap[1] >> (i - 32)) & 0x1;
1238eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> (i - 32)) & 0x1;
12395010032bSJohnny Huang 			pbit = (strap_pro[1] >> (i - 32)) & 0x1;
12405010032bSJohnny Huang 		}
12415010032bSJohnny Huang 
12425010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
12435010032bSJohnny Huang 			if (i < 32) {
12445010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
12455010032bSJohnny Huang 			} else {
12465010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
12475010032bSJohnny Huang 			}
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 		if (ret == OTP_PROG_SKIP) {
1253a6af4a17SJohnny Huang 			if (skip == -1)
1254a6af4a17SJohnny Huang 				skip = 1;
125569d5fd8fSJohnny Huang 			continue;
1256a6af4a17SJohnny Huang 		} else {
1257eda10d61SJohnny Huang 			skip = 1;
125869d5fd8fSJohnny Huang 		}
1259eda10d61SJohnny Huang 
1260eda10d61SJohnny Huang 		if (ret == OTP_FAILURE)
126169d5fd8fSJohnny Huang 			fail = 1;
126269d5fd8fSJohnny Huang 	}
126369d5fd8fSJohnny Huang 	if (fail == 1)
1264a6af4a17SJohnny Huang 		return OTP_FAILURE;
1265a6af4a17SJohnny Huang 	else if (skip == 1)
1266a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
12677e22f42dSJohnny Huang 
1268eda10d61SJohnny Huang 	return OTP_SUCCESS;
126969d5fd8fSJohnny Huang }
127069d5fd8fSJohnny Huang 
12712a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
127269d5fd8fSJohnny Huang {
127369d5fd8fSJohnny Huang 	int i, j;
1274de6b0cc4SJohnny Huang 	int remains;
127566f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
127669d5fd8fSJohnny Huang 
12772a856b9aSJohnny Huang 	if (start < 0 || start > 64)
12782a856b9aSJohnny Huang 		return OTP_USAGE;
12792a856b9aSJohnny Huang 
12802a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
12812a856b9aSJohnny Huang 		return OTP_USAGE;
12822a856b9aSJohnny Huang 
1283541eb887SJohnny Huang 	otp_strap_status(otpstrap);
128469d5fd8fSJohnny Huang 
1285de6b0cc4SJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1286de6b0cc4SJohnny Huang 		remains = 7;
128707baa4e8SJohnny Huang 		printf("BIT(hex)  Value  Option           Status\n");
1288de6b0cc4SJohnny Huang 	} else {
1289de6b0cc4SJohnny Huang 		remains = 6;
1290de6b0cc4SJohnny Huang 		printf("BIT(hex)  Value  Option         Reg_Protect Status\n");
1291de6b0cc4SJohnny Huang 	}
1292de6b0cc4SJohnny Huang 	printf("______________________________________________________________________________\n");
1293737ed20bSJohnny Huang 
1294cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
129507baa4e8SJohnny Huang 		printf("0x%-8X", i);
1296737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1297de6b0cc4SJohnny Huang 		for (j = 0; j < remains; j++)
1298737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1299737ed20bSJohnny Huang 		printf("   ");
1300de6b0cc4SJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1301de6b0cc4SJohnny Huang 			printf("%d           ", otpstrap[i].reg_protected);
1302de6b0cc4SJohnny Huang 		}
130369d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1304737ed20bSJohnny Huang 			printf("protected and not writable");
130569d5fd8fSJohnny Huang 		} else {
1306737ed20bSJohnny Huang 			printf("not protected ");
130769d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1308737ed20bSJohnny Huang 				printf("and no remaining times to write.");
130969d5fd8fSJohnny Huang 			} else {
1310737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
131169d5fd8fSJohnny Huang 			}
131269d5fd8fSJohnny Huang 		}
1313737ed20bSJohnny Huang 		printf("\n");
131469d5fd8fSJohnny Huang 	}
13152a856b9aSJohnny Huang 
13162a856b9aSJohnny Huang 	return OTP_SUCCESS;
131769d5fd8fSJohnny Huang }
131869d5fd8fSJohnny Huang 
13198848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value)
13208848d5dcSJohnny Huang {
13218848d5dcSJohnny Huang 	struct otpstrap_status otpstrap[64];
132283655e91SJohnny Huang 	uint32_t prog_address;
13238848d5dcSJohnny Huang 	int offset;
13248848d5dcSJohnny Huang 	int ret;
13258848d5dcSJohnny Huang 
13268848d5dcSJohnny Huang 
13278848d5dcSJohnny Huang 	otp_strap_status(otpstrap);
13288848d5dcSJohnny Huang 
13298848d5dcSJohnny Huang 	ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
13308848d5dcSJohnny Huang 
13318848d5dcSJohnny Huang 	if (ret != OTP_SUCCESS) {
13328848d5dcSJohnny Huang 		return ret;
13338848d5dcSJohnny Huang 	}
13348848d5dcSJohnny Huang 
13358848d5dcSJohnny Huang 	prog_address = 0x800;
13368848d5dcSJohnny Huang 	if (bit_offset < 32) {
13378848d5dcSJohnny Huang 		offset = bit_offset;
13388848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200;
13398848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2;
13408848d5dcSJohnny Huang 
13418848d5dcSJohnny Huang 	} else {
13428848d5dcSJohnny Huang 		offset = (bit_offset - 32);
13438848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200;
13448848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2;
13458848d5dcSJohnny Huang 	}
13468848d5dcSJohnny Huang 
13478848d5dcSJohnny Huang 
134883655e91SJohnny Huang 	return otp_prog_bit(1, prog_address, offset);
13498848d5dcSJohnny Huang }
13508848d5dcSJohnny Huang 
13515010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout)
135269d5fd8fSJohnny Huang {
13535010032bSJohnny Huang 	uint32_t *strap;
13545010032bSJohnny Huang 	uint32_t *strap_ignore;
13555010032bSJohnny Huang 	uint32_t *strap_pro;
13565010032bSJohnny Huang 	uint32_t *strap_reg_protect;
135783655e91SJohnny Huang 	uint32_t prog_address;
135883655e91SJohnny Huang 	int i;
1359eda10d61SJohnny Huang 	int bit, pbit, ibit, offset, rpbit;
136069d5fd8fSJohnny Huang 	int fail = 0;
136183655e91SJohnny Huang 	int ret;
136266f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
136369d5fd8fSJohnny Huang 
13645010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
13655010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
13665010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
13675010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
13685010032bSJohnny Huang 
13697f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1370541eb887SJohnny Huang 	otp_strap_status(otpstrap);
137169d5fd8fSJohnny Huang 
13727f795e57SJohnny Huang 	printf("Check writable...\n");
13735010032bSJohnny Huang 	if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) {
13747f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
13757f795e57SJohnny Huang 		return OTP_FAILURE;
13767f795e57SJohnny Huang 	}
13777e22f42dSJohnny Huang 
137869d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
137969d5fd8fSJohnny Huang 		prog_address = 0x800;
138069d5fd8fSJohnny Huang 		if (i < 32) {
138169d5fd8fSJohnny Huang 			offset = i;
13825010032bSJohnny Huang 			bit = (strap[0] >> offset) & 0x1;
1383eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> offset) & 0x1;
13845010032bSJohnny Huang 			pbit = (strap_pro[0] >> offset) & 0x1;
138569d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
138669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
138769d5fd8fSJohnny Huang 
138869d5fd8fSJohnny Huang 		} else {
138969d5fd8fSJohnny Huang 			offset = (i - 32);
13905010032bSJohnny Huang 			bit = (strap[1] >> offset) & 0x1;
1391eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> offset) & 0x1;
13925010032bSJohnny Huang 			pbit = (strap_pro[1] >> offset) & 0x1;
139369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
139469d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
139569d5fd8fSJohnny Huang 		}
13965010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
13975010032bSJohnny Huang 			if (i < 32) {
13985010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
13995010032bSJohnny Huang 			} else {
14005010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
14015010032bSJohnny Huang 			}
14025010032bSJohnny Huang 		} else {
14035010032bSJohnny Huang 			rpbit = 0;
14045010032bSJohnny Huang 		}
140569d5fd8fSJohnny Huang 
1406eda10d61SJohnny Huang 		if (ibit == 1) {
140769d5fd8fSJohnny Huang 			continue;
140869d5fd8fSJohnny Huang 		}
140969d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
141069d5fd8fSJohnny Huang 			continue;
141169d5fd8fSJohnny Huang 		}
141269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
141369d5fd8fSJohnny Huang 			fail = 1;
141469d5fd8fSJohnny Huang 			continue;
141569d5fd8fSJohnny Huang 		}
141669d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
141769d5fd8fSJohnny Huang 			fail = 1;
141869d5fd8fSJohnny Huang 			continue;
141969d5fd8fSJohnny Huang 		}
14207e22f42dSJohnny Huang 
142183655e91SJohnny Huang 		ret = otp_prog_bit(1, prog_address, offset);
142283655e91SJohnny Huang 		if (!ret)
14232a856b9aSJohnny Huang 			return OTP_FAILURE;
142469d5fd8fSJohnny Huang 
14255010032bSJohnny Huang 		if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
142669d5fd8fSJohnny Huang 			prog_address = 0x800;
142769d5fd8fSJohnny Huang 			if (i < 32)
14285010032bSJohnny Huang 				prog_address |= 0x608;
142969d5fd8fSJohnny Huang 			else
14305010032bSJohnny Huang 				prog_address |= 0x60a;
14317e22f42dSJohnny Huang 
143283655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
143383655e91SJohnny Huang 			if (!ret)
14342a856b9aSJohnny Huang 				return OTP_FAILURE;
14355010032bSJohnny Huang 		}
14365010032bSJohnny Huang 
14375010032bSJohnny Huang 		if (pbit != 0) {
14385010032bSJohnny Huang 			prog_address = 0x800;
14395010032bSJohnny Huang 			if (i < 32)
14405010032bSJohnny Huang 				prog_address |= 0x60c;
14415010032bSJohnny Huang 			else
14425010032bSJohnny Huang 				prog_address |= 0x60e;
14435010032bSJohnny Huang 
144483655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
144583655e91SJohnny Huang 			if (!ret)
14465010032bSJohnny Huang 				return OTP_FAILURE;
14475010032bSJohnny Huang 		}
144869d5fd8fSJohnny Huang 
144969d5fd8fSJohnny Huang 	}
1450de6fbf1cSJohnny Huang 	otp_soak(0);
145169d5fd8fSJohnny Huang 	if (fail == 1)
14522a856b9aSJohnny Huang 		return OTP_FAILURE;
145369d5fd8fSJohnny Huang 	else
14542a856b9aSJohnny Huang 		return OTP_SUCCESS;
145569d5fd8fSJohnny Huang 
145669d5fd8fSJohnny Huang }
145769d5fd8fSJohnny Huang 
14585010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout)
14594c1c9b35SJohnny Huang {
146054552c69SJohnny Huang 	int i;
146154552c69SJohnny Huang 	int ret;
14625010032bSJohnny Huang 	int data_dw;
1463d90825e2SJohnny Huang 	uint32_t data[2048];
14645010032bSJohnny Huang 	uint32_t *buf;
14655010032bSJohnny Huang 	uint32_t *buf_ignore;
14664c1c9b35SJohnny Huang 
146754552c69SJohnny Huang 	uint32_t data_masked;
146854552c69SJohnny Huang 	uint32_t buf_masked;
14694c1c9b35SJohnny Huang 
14705010032bSJohnny Huang 	buf = (uint32_t *)image_layout->data;
14715010032bSJohnny Huang 	buf_ignore = (uint32_t *)image_layout->data_ignore;
14725010032bSJohnny Huang 
14735010032bSJohnny Huang 	data_dw = image_layout->data_length / 4;
14745010032bSJohnny Huang 
14754c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
14764c1c9b35SJohnny Huang 
14775010032bSJohnny Huang 	for (i = 0; i < data_dw - 2 ; i += 2) {
1478d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
14794c1c9b35SJohnny Huang 	}
1480d90825e2SJohnny Huang 
14814c1c9b35SJohnny Huang 	printf("Check writable...\n");
148254552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
14835010032bSJohnny Huang 	for (i = 0; i < data_dw - 2; i++) {
1484696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1485696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
148654552c69SJohnny Huang 		if (data_masked == buf_masked)
14874c1c9b35SJohnny Huang 			continue;
1488d90825e2SJohnny Huang 		if (i % 2 == 0) {
148954552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
14904c1c9b35SJohnny Huang 				continue;
14914c1c9b35SJohnny Huang 			} else {
14924c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1493d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
14944c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1495696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
14962a856b9aSJohnny Huang 				return OTP_FAILURE;
149769d5fd8fSJohnny Huang 			}
1498d90825e2SJohnny Huang 		} else {
149954552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1500d90825e2SJohnny Huang 				continue;
1501d90825e2SJohnny Huang 			} else {
1502d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1503d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1504d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1505696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
15062a856b9aSJohnny Huang 				return OTP_FAILURE;
1507d90825e2SJohnny Huang 			}
1508d90825e2SJohnny Huang 		}
1509d90825e2SJohnny Huang 	}
151069d5fd8fSJohnny Huang 
1511d90825e2SJohnny Huang 	printf("Start Programing...\n");
1512d90825e2SJohnny Huang 
151354552c69SJohnny Huang 	// programing ecc region first
151454552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
1515696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
151654552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
151754552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1518696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
151954552c69SJohnny Huang 			return ret;
1520d90825e2SJohnny Huang 		}
1521d90825e2SJohnny Huang 	}
1522d90825e2SJohnny Huang 
152354552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
1524696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
152554552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
152654552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1527696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
152854552c69SJohnny Huang 			return ret;
1529d90825e2SJohnny Huang 		}
1530de6fbf1cSJohnny Huang 	}
1531de6fbf1cSJohnny Huang 	otp_soak(0);
15322a856b9aSJohnny Huang 	return OTP_SUCCESS;
1533d90825e2SJohnny Huang 
1534d90825e2SJohnny Huang }
1535d90825e2SJohnny Huang 
1536696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf)
1537696656c6SJohnny Huang {
1538696656c6SJohnny Huang 	sha256_context ctx;
1539696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
1540696656c6SJohnny Huang 
1541696656c6SJohnny Huang 	sha256_starts(&ctx);
1542696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
1543696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
1544696656c6SJohnny Huang 
1545696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
1546696656c6SJohnny Huang 		return 0;
1547696656c6SJohnny Huang 	else
1548696656c6SJohnny Huang 		return -1;
1549696656c6SJohnny Huang 
1550696656c6SJohnny Huang }
1551696656c6SJohnny Huang 
1552de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm)
155369d5fd8fSJohnny Huang {
155469d5fd8fSJohnny Huang 	int ret;
15559a4fe690SJohnny Huang 	int image_version = 0;
1556696656c6SJohnny Huang 	struct otp_header *otp_header;
1557696656c6SJohnny Huang 	struct otp_image_layout image_layout;
1558696656c6SJohnny Huang 	int image_size;
1559696656c6SJohnny Huang 	uint8_t *buf;
1560696656c6SJohnny Huang 	uint8_t *checksum;
156169d5fd8fSJohnny Huang 
1562696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
1563696656c6SJohnny Huang 	if (!otp_header) {
156469d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
15652a856b9aSJohnny Huang 		return OTP_FAILURE;
156669d5fd8fSJohnny Huang 	}
1567d90825e2SJohnny Huang 
1568696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
1569696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
1570696656c6SJohnny Huang 
1571696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
1572696656c6SJohnny Huang 
1573696656c6SJohnny Huang 	if (!buf) {
1574696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
1575696656c6SJohnny Huang 		return OTP_FAILURE;
1576696656c6SJohnny Huang 	}
1577696656c6SJohnny Huang 	otp_header = (struct otp_header *) buf;
1578696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
1579696656c6SJohnny Huang 
1580696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
1581696656c6SJohnny Huang 		puts("Image is invalid\n");
1582696656c6SJohnny Huang 		return OTP_FAILURE;
1583696656c6SJohnny Huang 	}
1584696656c6SJohnny Huang 
1585696656c6SJohnny Huang 
15865010032bSJohnny Huang 	image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
15875010032bSJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
15885010032bSJohnny Huang 	image_layout.data_ignore = image_layout.data + image_layout.data_length;
15895010032bSJohnny Huang 
15905010032bSJohnny Huang 	image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
1591696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
15925010032bSJohnny Huang 	image_layout.conf_ignore = image_layout.conf + image_layout.conf_length;
1593696656c6SJohnny Huang 
1594696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
1595696656c6SJohnny Huang 
1596696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
1597696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
15985010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
15995010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + image_layout.strap_length;
16005010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length;
1601696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
1602696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
16035010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
16045010032bSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
16055010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
16065010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
16075fdde29fSJohnny Huang 	} else if (!strcmp("A2", (char *)otp_header->otp_version)) {
16085fdde29fSJohnny Huang 		image_version = OTP_AST2600A2;
16095fdde29fSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
16105fdde29fSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
16115fdde29fSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
16125fdde29fSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
1613*64b66712SJohnny Huang 	} else if (!strcmp("A3", (char *)otp_header->otp_version)) {
1614*64b66712SJohnny Huang 		image_version = OTP_AST2600A3;
1615*64b66712SJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
1616*64b66712SJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
1617*64b66712SJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
1618*64b66712SJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
1619696656c6SJohnny Huang 	} else {
1620696656c6SJohnny Huang 		puts("Version is not supported\n");
1621696656c6SJohnny Huang 		return OTP_FAILURE;
1622696656c6SJohnny Huang 	}
1623696656c6SJohnny Huang 
16249a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
16259a4fe690SJohnny Huang 		puts("Version is not match\n");
16269a4fe690SJohnny Huang 		return OTP_FAILURE;
16279a4fe690SJohnny Huang 	}
16289a4fe690SJohnny Huang 
1629696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
1630696656c6SJohnny Huang 		puts("checksum is invalid\n");
1631696656c6SJohnny Huang 		return OTP_FAILURE;
1632d90825e2SJohnny Huang 	}
16337332532cSJohnny Huang 
163469d5fd8fSJohnny Huang 	if (!nconfirm) {
1635696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
16367f795e57SJohnny Huang 			printf("\nOTP data region :\n");
1637696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
163869d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16392a856b9aSJohnny Huang 				return OTP_FAILURE;
164069d5fd8fSJohnny Huang 			}
164169d5fd8fSJohnny Huang 		}
1642696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
16437332532cSJohnny Huang 			printf("\nOTP strap region :\n");
16445010032bSJohnny Huang 			if (otp_print_strap_image(&image_layout) < 0) {
16457332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
16467332532cSJohnny Huang 				return OTP_FAILURE;
16477332532cSJohnny Huang 			}
16487332532cSJohnny Huang 		}
1649696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
16507332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
1651696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
16527332532cSJohnny Huang 				printf("OTP config error, please check.\n");
16537332532cSJohnny Huang 				return OTP_FAILURE;
16547332532cSJohnny Huang 			}
16557332532cSJohnny Huang 		}
16567332532cSJohnny Huang 
165769d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
165869d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
165969d5fd8fSJohnny Huang 			printf(" Aborting\n");
16602a856b9aSJohnny Huang 			return OTP_FAILURE;
166169d5fd8fSJohnny Huang 		}
166269d5fd8fSJohnny Huang 	}
16637332532cSJohnny Huang 
16645010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_DATA) {
16655010032bSJohnny Huang 		printf("programing data region ...\n");
16665010032bSJohnny Huang 		ret = otp_prog_data(&image_layout);
16675010032bSJohnny Huang 		if (ret != 0) {
16685010032bSJohnny Huang 			printf("Error\n");
16695010032bSJohnny Huang 			return ret;
16705010032bSJohnny Huang 		} else {
16715010032bSJohnny Huang 			printf("Done\n");
16725010032bSJohnny Huang 		}
16735010032bSJohnny Huang 	}
16745010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_STRAP) {
16755010032bSJohnny Huang 		printf("programing strap region ...\n");
16765010032bSJohnny Huang 		ret = otp_prog_strap(&image_layout);
16775010032bSJohnny Huang 		if (ret != 0) {
16785010032bSJohnny Huang 			printf("Error\n");
16795010032bSJohnny Huang 			return ret;
16805010032bSJohnny Huang 		} else {
16815010032bSJohnny Huang 			printf("Done\n");
16825010032bSJohnny Huang 		}
16835010032bSJohnny Huang 	}
16845010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_CONFIG) {
16855010032bSJohnny Huang 		printf("programing configuration region ...\n");
16865010032bSJohnny Huang 		ret = otp_prog_conf(&image_layout);
16875010032bSJohnny Huang 		if (ret != 0) {
16885010032bSJohnny Huang 			printf("Error\n");
16895010032bSJohnny Huang 			return ret;
16905010032bSJohnny Huang 		}
16915010032bSJohnny Huang 		printf("Done\n");
16925010032bSJohnny Huang 	}
1693cd1610b4SJohnny Huang 
16947332532cSJohnny Huang 	return OTP_SUCCESS;
16952a856b9aSJohnny Huang }
16962a856b9aSJohnny Huang 
16972a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1698cd1610b4SJohnny Huang {
1699a6af4a17SJohnny Huang 	uint32_t read[2];
1700d90825e2SJohnny Huang 	uint32_t prog_address = 0;
170166f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1702cd1610b4SJohnny Huang 	int otp_bit;
170383655e91SJohnny Huang 	int ret = 0;
1704cd1610b4SJohnny Huang 
1705dacbba92SJohnny Huang 	otp_soak(0);
1706cd1610b4SJohnny Huang 	switch (mode) {
1707a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1708a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1709cd1610b4SJohnny Huang 		prog_address = 0x800;
1710cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1711cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1712a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1713cd1610b4SJohnny Huang 		if (otp_bit == value) {
1714a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1715cd1610b4SJohnny Huang 			printf("No need to program\n");
17162a856b9aSJohnny Huang 			return OTP_SUCCESS;
1717cd1610b4SJohnny Huang 		}
1718cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1719a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1720cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
17212a856b9aSJohnny Huang 			return OTP_FAILURE;
1722cd1610b4SJohnny Huang 		}
1723a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1724cd1610b4SJohnny Huang 		break;
1725a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1726cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1727cd1610b4SJohnny Huang 
1728cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1729a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1730a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1731643b9cfdSJohnny Huang 
1732643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1733643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1734643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1735643b9cfdSJohnny Huang 				return OTP_FAILURE;
1736643b9cfdSJohnny Huang 			}
1737cd1610b4SJohnny Huang 		} else {
1738a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1739a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1740643b9cfdSJohnny Huang 
1741643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1742643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1743643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1744643b9cfdSJohnny Huang 				return OTP_FAILURE;
1745643b9cfdSJohnny Huang 			}
1746cd1610b4SJohnny Huang 		}
1747cd1610b4SJohnny Huang 		if (otp_bit == value) {
1748a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1749cd1610b4SJohnny Huang 			printf("No need to program\n");
17502a856b9aSJohnny Huang 			return OTP_SUCCESS;
1751cd1610b4SJohnny Huang 		}
1752643b9cfdSJohnny Huang 
1753a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1754cd1610b4SJohnny Huang 		break;
1755a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
17568848d5dcSJohnny Huang 		otp_strap_status(otpstrap);
17578848d5dcSJohnny Huang 		otp_print_strap(bit_offset, 1);
17588848d5dcSJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
17598848d5dcSJohnny Huang 		if (ret == OTP_FAILURE)
17608848d5dcSJohnny Huang 			return OTP_FAILURE;
17618848d5dcSJohnny Huang 		else if (ret == OTP_PROG_SKIP)
17628848d5dcSJohnny Huang 			return OTP_SUCCESS;
1763a6af4a17SJohnny Huang 
1764cd1610b4SJohnny Huang 		break;
1765cd1610b4SJohnny Huang 	}
1766cd1610b4SJohnny Huang 
1767cd1610b4SJohnny Huang 	if (!nconfirm) {
1768cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1769cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1770cd1610b4SJohnny Huang 			printf(" Aborting\n");
17712a856b9aSJohnny Huang 			return OTP_FAILURE;
1772cd1610b4SJohnny Huang 		}
1773cd1610b4SJohnny Huang 	}
1774cd1610b4SJohnny Huang 
1775cd1610b4SJohnny Huang 	switch (mode) {
1776a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
177783655e91SJohnny Huang 		ret =  otp_prog_strap_bit(bit_offset, value);
177883655e91SJohnny Huang 		break;
1779a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1780a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
178183655e91SJohnny Huang 		ret = otp_prog_bit(value, prog_address, bit_offset);
1782de6fbf1cSJohnny Huang 		break;
1783de6fbf1cSJohnny Huang 	}
1784de6fbf1cSJohnny Huang 	otp_soak(0);
178583655e91SJohnny Huang 	if (ret) {
17869009c25dSJohnny Huang 		printf("SUCCESS\n");
17872a856b9aSJohnny Huang 		return OTP_SUCCESS;
17889009c25dSJohnny Huang 	} else {
17899009c25dSJohnny Huang 		printf("OTP cannot be programed\n");
17909009c25dSJohnny Huang 		printf("FAILED\n");
17919009c25dSJohnny Huang 		return OTP_FAILURE;
17929009c25dSJohnny Huang 	}
1793cd1610b4SJohnny Huang 
17942a856b9aSJohnny Huang 	return OTP_USAGE;
1795cd1610b4SJohnny Huang }
1796cd1610b4SJohnny Huang 
17972a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
179869d5fd8fSJohnny Huang {
17992a856b9aSJohnny Huang 	uint32_t offset, count;
18002a856b9aSJohnny Huang 	int ret;
180169d5fd8fSJohnny Huang 
18022a856b9aSJohnny Huang 	if (argc == 4) {
18032a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
18042a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
18052a856b9aSJohnny Huang 	} else if (argc == 3) {
18062a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
18072a856b9aSJohnny Huang 		count = 1;
18082a856b9aSJohnny Huang 	} else {
180969d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
181069d5fd8fSJohnny Huang 	}
181169d5fd8fSJohnny Huang 
181269d5fd8fSJohnny Huang 
18132a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
18143d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18152a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
18162a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
18173d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18182a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
18192a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
18203d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18212a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
18222a856b9aSJohnny Huang 	} else {
18232a856b9aSJohnny Huang 		return CMD_RET_USAGE;
182469d5fd8fSJohnny Huang 	}
182569d5fd8fSJohnny Huang 
18262a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18272a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18282a856b9aSJohnny Huang 	else
18292a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18302a856b9aSJohnny Huang 
18312a856b9aSJohnny Huang }
18322a856b9aSJohnny Huang 
18332a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18342a856b9aSJohnny Huang {
18352a856b9aSJohnny Huang 	phys_addr_t addr;
18362a856b9aSJohnny Huang 	int ret;
18372a856b9aSJohnny Huang 
1838de6b0cc4SJohnny Huang 	if (argc == 3) {
1839ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
18402a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18412a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
18423d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1843de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 1);
1844de6b0cc4SJohnny Huang 	} else if (argc == 2) {
18452a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
18463d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1847de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 0);
18482a856b9aSJohnny Huang 	} else {
18492a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18502a856b9aSJohnny Huang 	}
18512a856b9aSJohnny Huang 
18522a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18532a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18542a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18552a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18562a856b9aSJohnny Huang 	else
18572a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18582a856b9aSJohnny Huang }
18592a856b9aSJohnny Huang 
18602a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18612a856b9aSJohnny Huang {
18622a856b9aSJohnny Huang 	int mode = 0;
18632a856b9aSJohnny Huang 	int nconfirm = 0;
18642a856b9aSJohnny Huang 	int otp_addr = 0;
18652a856b9aSJohnny Huang 	int bit_offset;
18662a856b9aSJohnny Huang 	int value;
18672a856b9aSJohnny Huang 	int ret;
18682a856b9aSJohnny Huang 
18692a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
18702a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18712a856b9aSJohnny Huang 
18722a856b9aSJohnny Huang 	/* Drop the pb cmd */
18732a856b9aSJohnny Huang 	argc--;
18742a856b9aSJohnny Huang 	argv++;
18752a856b9aSJohnny Huang 
18762a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1877a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
18782a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1879a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
18802a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1881a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1882cd1610b4SJohnny Huang 	else
18832a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18842a856b9aSJohnny Huang 
18852a856b9aSJohnny Huang 	/* Drop the region cmd */
18862a856b9aSJohnny Huang 	argc--;
18872a856b9aSJohnny Huang 	argv++;
18882a856b9aSJohnny Huang 
1889ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
1890cd1610b4SJohnny Huang 		nconfirm = 1;
18912a856b9aSJohnny Huang 		/* Drop the force option */
18922a856b9aSJohnny Huang 		argc--;
18932a856b9aSJohnny Huang 		argv++;
18942a856b9aSJohnny Huang 	}
1895cd1610b4SJohnny Huang 
1896a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
18972a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
18982a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
18990808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
19002a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1901cd1610b4SJohnny Huang 	} else {
19022a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
19032a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
19042a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
19050808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
19062a856b9aSJohnny Huang 			return CMD_RET_USAGE;
19070808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
190878855207SJohnny Huang 			if (otp_addr >= 0x800)
19090808cc55SJohnny Huang 				return CMD_RET_USAGE;
19100808cc55SJohnny Huang 		} else {
191178855207SJohnny Huang 			if (otp_addr >= 0x20)
19120808cc55SJohnny Huang 				return CMD_RET_USAGE;
19130808cc55SJohnny Huang 		}
1914cd1610b4SJohnny Huang 	}
1915cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
19162a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1917cd1610b4SJohnny Huang 
19183d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19192a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
19202a856b9aSJohnny Huang 
19212a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19222a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19232a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
19242a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19252a856b9aSJohnny Huang 	else
19262a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19272a856b9aSJohnny Huang }
19282a856b9aSJohnny Huang 
19292a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19302a856b9aSJohnny Huang {
19312a856b9aSJohnny Huang 	phys_addr_t addr;
19322a856b9aSJohnny Huang 	int otp_addr = 0;
19332a856b9aSJohnny Huang 
19342a856b9aSJohnny Huang 	if (argc != 3)
19352a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19362a856b9aSJohnny Huang 
19373d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19382a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
19392a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
19402a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
194169d5fd8fSJohnny Huang 		printf("Compare pass\n");
19422a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
194369d5fd8fSJohnny Huang 	} else {
194469d5fd8fSJohnny Huang 		printf("Compare fail\n");
19452a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
194669d5fd8fSJohnny Huang 	}
194769d5fd8fSJohnny Huang }
194869d5fd8fSJohnny Huang 
194966f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
195066f2f8e5SJohnny Huang {
1951a8bd6d8cSJohnny Huang 	int view = 0;
19522d4b0742SJohnny Huang 	int input;
1953a8bd6d8cSJohnny Huang 
1954a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
195566f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
195666f2f8e5SJohnny Huang 
19572d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
195866f2f8e5SJohnny Huang 
19593d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19602d4b0742SJohnny Huang 		if (argc == 3) {
19612d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
19622d4b0742SJohnny Huang 			otp_print_conf_info(input);
19632d4b0742SJohnny Huang 		} else {
19642d4b0742SJohnny Huang 			otp_print_conf_info(-1);
19652d4b0742SJohnny Huang 		}
19662d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
19672d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
1968a8bd6d8cSJohnny Huang 			view = 1;
1969a8bd6d8cSJohnny Huang 			/* Drop the view option */
1970a8bd6d8cSJohnny Huang 			argc--;
1971a8bd6d8cSJohnny Huang 			argv++;
1972a8bd6d8cSJohnny Huang 		}
19733d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1974b458cd62SJohnny Huang 		otp_print_strap_info(view);
197566f2f8e5SJohnny Huang 	} else {
197666f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
197766f2f8e5SJohnny Huang 	}
19782d4b0742SJohnny Huang 
197966f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
198066f2f8e5SJohnny Huang }
198166f2f8e5SJohnny Huang 
1982737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1983737ed20bSJohnny Huang {
1984737ed20bSJohnny Huang 	int input;
1985737ed20bSJohnny Huang 	int bit_offset;
1986737ed20bSJohnny Huang 	int prog_address;
198783655e91SJohnny Huang 	int ret;
1988737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1989737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1990737ed20bSJohnny Huang 
1991ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
1992737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1993737ed20bSJohnny Huang 	} else {
1994737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1995737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
1996737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1997737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1998737ed20bSJohnny Huang 			printf(" Aborting\n");
1999737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2000737ed20bSJohnny Huang 		}
2001737ed20bSJohnny Huang 	}
2002737ed20bSJohnny Huang 
2003737ed20bSJohnny Huang 	prog_address = 0x800;
2004737ed20bSJohnny Huang 	if (input < 32) {
2005737ed20bSJohnny Huang 		bit_offset = input;
2006737ed20bSJohnny Huang 		prog_address |= 0x60c;
2007737ed20bSJohnny Huang 	} else if (input < 64) {
2008737ed20bSJohnny Huang 		bit_offset = input - 32;
2009737ed20bSJohnny Huang 		prog_address |= 0x60e;
2010737ed20bSJohnny Huang 	} else {
2011737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2012737ed20bSJohnny Huang 	}
2013737ed20bSJohnny Huang 
2014737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2015737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2016737ed20bSJohnny Huang 	}
2017de6fbf1cSJohnny Huang 
201883655e91SJohnny Huang 	ret = otp_prog_bit(1, prog_address, bit_offset);
2019de6fbf1cSJohnny Huang 	otp_soak(0);
202083655e91SJohnny Huang 
202183655e91SJohnny Huang 	if (ret) {
2022737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2023737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2024737ed20bSJohnny Huang 	}
2025737ed20bSJohnny Huang 
2026737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2027737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2028737ed20bSJohnny Huang 
2029737ed20bSJohnny Huang }
20309a4fe690SJohnny Huang 
2031f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2032f67375f7SJohnny Huang {
2033f67375f7SJohnny Huang 	printf("OTP tool version: %s\n", OTP_VER);
2034f67375f7SJohnny Huang 	printf("OTP info version: %s\n", OTP_INFO_VER);
2035f67375f7SJohnny Huang 
2036f67375f7SJohnny Huang 	return CMD_RET_SUCCESS;
2037f67375f7SJohnny Huang }
2038f67375f7SJohnny Huang 
20392a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
2040f67375f7SJohnny Huang 	U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""),
20412a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2042a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
2043de6b0cc4SJohnny Huang 	U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""),
20442a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2045737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
20462a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
20472a856b9aSJohnny Huang };
20482a856b9aSJohnny Huang 
20492a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20502a856b9aSJohnny Huang {
20512a856b9aSJohnny Huang 	cmd_tbl_t *cp;
20520dae9d52SJohnny Huang 	uint32_t ver;
20532a856b9aSJohnny Huang 
20542a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
20552a856b9aSJohnny Huang 
2056737ed20bSJohnny Huang 	/* Drop the otp command */
20572a856b9aSJohnny Huang 	argc--;
20582a856b9aSJohnny Huang 	argv++;
20592a856b9aSJohnny Huang 
20602a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
20612a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20622a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
20632a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20642a856b9aSJohnny Huang 
20650dae9d52SJohnny Huang 	ver = chip_version();
20660dae9d52SJohnny Huang 	switch (ver) {
20670dae9d52SJohnny Huang 	case OTP_AST2600A0:
2068696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
20699a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
20709a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
20719a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
20729a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
20739a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
20749a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
20750dae9d52SJohnny Huang 		break;
20760dae9d52SJohnny Huang 	case OTP_AST2600A1:
2077696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
20783cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
20793cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
20803cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
20813cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
20829a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
20839a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
20840dae9d52SJohnny Huang 		break;
20850dae9d52SJohnny Huang 	case OTP_AST2600A2:
20865fdde29fSJohnny Huang 		info_cb.version = OTP_AST2600A2;
20875fdde29fSJohnny Huang 		info_cb.conf_info = a2_conf_info;
20885fdde29fSJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
20895fdde29fSJohnny Huang 		info_cb.strap_info = a2_strap_info;
20905fdde29fSJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
20915fdde29fSJohnny Huang 		info_cb.key_info = a2_key_type;
20925fdde29fSJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a2_key_type);
20930dae9d52SJohnny Huang 		break;
2094*64b66712SJohnny Huang 	case OTP_AST2600A3:
2095*64b66712SJohnny Huang 		info_cb.version = OTP_AST2600A3;
2096*64b66712SJohnny Huang 		info_cb.conf_info = a2_conf_info;
2097*64b66712SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
2098*64b66712SJohnny Huang 		info_cb.strap_info = a2_strap_info;
2099*64b66712SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
2100*64b66712SJohnny Huang 		info_cb.key_info = a2_key_type;
2101*64b66712SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a2_key_type);
2102*64b66712SJohnny Huang 		break;
21030dae9d52SJohnny Huang 	default:
2104f1be5099SJohnny Huang 		printf("SOC is not supported\n");
21050dae9d52SJohnny Huang 		return CMD_RET_FAILURE;
21069a4fe690SJohnny Huang 	}
21079a4fe690SJohnny Huang 
21082a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
210969d5fd8fSJohnny Huang }
211069d5fd8fSJohnny Huang 
211169d5fd8fSJohnny Huang U_BOOT_CMD(
211269d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
211369d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
2114f67375f7SJohnny Huang 	"version\n"
2115f67375f7SJohnny Huang 	"otp read conf|data <otp_dw_offset> <dw_count>\n"
21162a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
21172d4b0742SJohnny Huang 	"otp info strap [v]\n"
21182d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2119de6b0cc4SJohnny Huang 	"otp prog [o] <addr>\n"
2120ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2121ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2122ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
21232a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
212469d5fd8fSJohnny Huang );
2125