xref: /openbmc/u-boot/cmd/otp.c (revision 90965bb3f02660c4f1666d0037c4a2a64b6213fd)
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 
280dae9d52SJohnny Huang #define OTP_VER				"1.0.1"
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
74696656c6SJohnny Huang 
75696656c6SJohnny Huang struct otp_header {
76696656c6SJohnny Huang 	u8	otp_magic[8];
77696656c6SJohnny Huang 	u8	otp_version[8];
78696656c6SJohnny Huang 	u32	image_info;
79696656c6SJohnny Huang 	u32	data_info;
80696656c6SJohnny Huang 	u32	config_info;
81696656c6SJohnny Huang 	u32	strap_info;
82696656c6SJohnny Huang 	u32	checksum_offset;
83696656c6SJohnny Huang } __attribute__((packed));
84696656c6SJohnny Huang 
8566f2f8e5SJohnny Huang struct otpstrap_status {
8669d5fd8fSJohnny Huang 	int value;
8769d5fd8fSJohnny Huang 	int option_array[7];
8869d5fd8fSJohnny Huang 	int remain_times;
8969d5fd8fSJohnny Huang 	int writeable_option;
905010032bSJohnny Huang 	int reg_protected;
9169d5fd8fSJohnny Huang 	int protected;
9269d5fd8fSJohnny Huang };
9369d5fd8fSJohnny Huang 
9466f2f8e5SJohnny Huang struct otpconf_parse {
9566f2f8e5SJohnny Huang 	int dw_offset;
9666f2f8e5SJohnny Huang 	int bit;
9766f2f8e5SJohnny Huang 	int length;
9866f2f8e5SJohnny Huang 	int value;
99696656c6SJohnny Huang 	int ignore;
10066f2f8e5SJohnny Huang 	char status[80];
10166f2f8e5SJohnny Huang };
10266f2f8e5SJohnny Huang 
1039a4fe690SJohnny Huang struct otpkey_type {
1049a4fe690SJohnny Huang 	int value;
1059a4fe690SJohnny Huang 	int key_type;
1069a4fe690SJohnny Huang 	int need_id;
1079a4fe690SJohnny Huang 	char information[110];
1089a4fe690SJohnny Huang };
1099a4fe690SJohnny Huang 
1109a4fe690SJohnny Huang struct otp_info_cb {
1119a4fe690SJohnny Huang 	int version;
11279e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1139a4fe690SJohnny Huang 	int strap_info_len;
11479e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1159a4fe690SJohnny Huang 	int conf_info_len;
11679e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1179a4fe690SJohnny Huang 	int key_info_len;
1185010032bSJohnny Huang 
1199a4fe690SJohnny Huang };
1209a4fe690SJohnny Huang 
121696656c6SJohnny Huang struct otp_image_layout {
1225010032bSJohnny Huang 	int data_length;
1235010032bSJohnny Huang 	int conf_length;
1245010032bSJohnny Huang 	int strap_length;
125696656c6SJohnny Huang 	uint8_t *data;
126696656c6SJohnny Huang 	uint8_t *data_ignore;
127696656c6SJohnny Huang 	uint8_t *conf;
128696656c6SJohnny Huang 	uint8_t *conf_ignore;
129696656c6SJohnny Huang 	uint8_t *strap;
130696656c6SJohnny Huang 	uint8_t *strap_reg_pro;
131696656c6SJohnny Huang 	uint8_t *strap_pro;
132696656c6SJohnny Huang 	uint8_t *strap_ignore;
133696656c6SJohnny Huang };
134696656c6SJohnny Huang 
1359a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1369a4fe690SJohnny Huang 
13779e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
1389a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
1399a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1409a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
1419a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1429a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
1439a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1449a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
1459a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1469a4fe690SJohnny Huang };
1479a4fe690SJohnny Huang 
14879e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
1499a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1509a4fe690SJohnny 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"},
1519a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1529a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1539a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1549a4fe690SJohnny Huang };
1559a4fe690SJohnny Huang 
1565fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = {
1575fdde29fSJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
1585fdde29fSJohnny 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"},
1595fdde29fSJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
1605fdde29fSJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
1615fdde29fSJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
1625fdde29fSJohnny Huang };
1635fdde29fSJohnny Huang 
1649a4fe690SJohnny Huang static uint32_t  chip_version(void)
1659a4fe690SJohnny Huang {
166badd21c2SJohnny Huang 	u64 rev_id;
1679a4fe690SJohnny Huang 
168badd21c2SJohnny Huang 	rev_id = readl(ASPEED_REVISION_ID0);
169badd21c2SJohnny Huang 	rev_id = ((u64)readl(ASPEED_REVISION_ID1) << 32) | rev_id;
1709a4fe690SJohnny Huang 
171badd21c2SJohnny Huang 	if (rev_id == 0x0500030305000303) {
172badd21c2SJohnny Huang 		/* AST2600-A0 */
1730dae9d52SJohnny Huang 		return OTP_AST2600A0;
174badd21c2SJohnny Huang 	} else if (rev_id == 0x0501030305010303) {
175badd21c2SJohnny Huang 		/* AST2600-A1 */
1760dae9d52SJohnny Huang 		return OTP_AST2600A1;
177badd21c2SJohnny Huang 	} else if (rev_id == 0x0501020305010203) {
178badd21c2SJohnny Huang 		/* AST2620-A1 */
179badd21c2SJohnny Huang 		return OTP_AST2600A1;
180badd21c2SJohnny Huang 	} else if (rev_id == 0x0502030305010303) {
181badd21c2SJohnny Huang 		/* AST2600-A2 */
1820dae9d52SJohnny Huang 		return OTP_AST2600A2;
183badd21c2SJohnny Huang 	} else if (rev_id == 0x0502020305010203) {
184badd21c2SJohnny Huang 		/* AST2620-A2 */
185badd21c2SJohnny Huang 		return OTP_AST2600A2;
186badd21c2SJohnny Huang 	} else if (rev_id == 0x0502010305010103) {
187badd21c2SJohnny Huang 		/* AST2605-A2 */
1880dae9d52SJohnny Huang 		return OTP_AST2600A2;
1890dae9d52SJohnny Huang 	}
1900dae9d52SJohnny Huang 
1915fdde29fSJohnny Huang 	return -1;
1929a4fe690SJohnny Huang }
1939a4fe690SJohnny Huang 
1943d3688adSJohnny Huang static void wait_complete(void)
1953d3688adSJohnny Huang {
1963d3688adSJohnny Huang 	int reg;
1973d3688adSJohnny Huang 
1983d3688adSJohnny Huang 	do {
1993d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
2003d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
2013d3688adSJohnny Huang }
2023d3688adSJohnny Huang 
203dacbba92SJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
204dacbba92SJohnny Huang {
205dacbba92SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
206dacbba92SJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
207dacbba92SJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
208dacbba92SJohnny Huang 	wait_complete();
209dacbba92SJohnny Huang }
210dacbba92SJohnny Huang 
211dacbba92SJohnny Huang static void otp_soak(int soak)
212dacbba92SJohnny Huang {
213dacbba92SJohnny Huang 	if (info_cb.version == OTP_AST2600A2) {
214dacbba92SJohnny Huang 		switch (soak) {
215dacbba92SJohnny Huang 		case 0: //default
216dacbba92SJohnny Huang 			otp_write(0x3000, 0x0210); // Write MRA
217dacbba92SJohnny Huang 			otp_write(0x5000, 0x2000); // Write MRB
218dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
219dacbba92SJohnny Huang 			break;
220dacbba92SJohnny Huang 		case 1: //normal program
221dacbba92SJohnny Huang 			otp_write(0x3000, 0x1200); // Write MRA
222feea3fdfSJohnny Huang 			otp_write(0x5000, 0x107F); // Write MRB
223dacbba92SJohnny Huang 			otp_write(0x1000, 0x1024); // Write MR
224feea3fdfSJohnny Huang 			writel(0x04191388, OTP_TIMING); // 200us
225dacbba92SJohnny Huang 			break;
226dacbba92SJohnny Huang 		case 2: //soak program
227dacbba92SJohnny Huang 			otp_write(0x3000, 0x1220); // Write MRA
228feea3fdfSJohnny Huang 			otp_write(0x5000, 0x2074); // Write MRB
229dacbba92SJohnny Huang 			otp_write(0x1000, 0x08a4); // Write MR
230feea3fdfSJohnny Huang 			writel(0x04193a98, OTP_TIMING); // 600us
231dacbba92SJohnny Huang 			break;
232dacbba92SJohnny Huang 		}
233dacbba92SJohnny Huang 	} else {
234dacbba92SJohnny Huang 		switch (soak) {
235dacbba92SJohnny Huang 		case 0: //default
236dacbba92SJohnny Huang 			otp_write(0x3000, 0x0); // Write MRA
237dacbba92SJohnny Huang 			otp_write(0x5000, 0x0); // Write MRB
238dacbba92SJohnny Huang 			otp_write(0x1000, 0x0); // Write MR
239dacbba92SJohnny Huang 			break;
240dacbba92SJohnny Huang 		case 1: //normal program
241dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
242dacbba92SJohnny Huang 			otp_write(0x5000, 0x302f); // Write MRB
243dacbba92SJohnny Huang 			otp_write(0x1000, 0x4020); // Write MR
244feea3fdfSJohnny Huang 			writel(0x04190760, OTP_TIMING); // 75us
245dacbba92SJohnny Huang 			break;
246dacbba92SJohnny Huang 		case 2: //soak program
247dacbba92SJohnny Huang 			otp_write(0x3000, 0x4021); // Write MRA
248dacbba92SJohnny Huang 			otp_write(0x5000, 0x1027); // Write MRB
249dacbba92SJohnny Huang 			otp_write(0x1000, 0x4820); // Write MR
250feea3fdfSJohnny Huang 			writel(0x041930d4, OTP_TIMING); // 500us
251dacbba92SJohnny Huang 			break;
252dacbba92SJohnny Huang 		}
253dacbba92SJohnny Huang 	}
254dacbba92SJohnny Huang 
255dacbba92SJohnny Huang 	wait_complete();
256dacbba92SJohnny Huang }
257dacbba92SJohnny Huang 
2582a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
25969d5fd8fSJohnny Huang {
2603d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
2613d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2623d3688adSJohnny Huang 	wait_complete();
2633d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
2643d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
26569d5fd8fSJohnny Huang }
26669d5fd8fSJohnny Huang 
2672a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
26869d5fd8fSJohnny Huang {
26969d5fd8fSJohnny Huang 	int config_offset;
27069d5fd8fSJohnny Huang 
27169d5fd8fSJohnny Huang 	config_offset = 0x800;
27269d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
27369d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
27469d5fd8fSJohnny Huang 
2753d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
2763d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
2773d3688adSJohnny Huang 	wait_complete();
2783d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
27969d5fd8fSJohnny Huang }
28069d5fd8fSJohnny Huang 
28169d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
28269d5fd8fSJohnny Huang {
28369d5fd8fSJohnny Huang 	int i;
28469d5fd8fSJohnny Huang 	uint32_t ret[1];
28569d5fd8fSJohnny Huang 
28669d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
2872a856b9aSJohnny Huang 		return OTP_USAGE;
288dacbba92SJohnny Huang 	otp_soak(0);
28969d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
29069d5fd8fSJohnny Huang 		otp_read_config(i, ret);
291a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
29269d5fd8fSJohnny Huang 	}
29369d5fd8fSJohnny Huang 	printf("\n");
2942a856b9aSJohnny Huang 	return OTP_SUCCESS;
29569d5fd8fSJohnny Huang }
29669d5fd8fSJohnny Huang 
29769d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
29869d5fd8fSJohnny Huang {
29969d5fd8fSJohnny Huang 	int i;
30069d5fd8fSJohnny Huang 	uint32_t ret[2];
30169d5fd8fSJohnny Huang 
30269d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
3032a856b9aSJohnny Huang 		return OTP_USAGE;
304dacbba92SJohnny Huang 	otp_soak(0);
30569d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
30669d5fd8fSJohnny Huang 		otp_read_data(i, ret);
30769d5fd8fSJohnny Huang 		if (i % 4 == 0)
30869d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
30969d5fd8fSJohnny Huang 		else
31069d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
31169d5fd8fSJohnny Huang 
31269d5fd8fSJohnny Huang 	}
31369d5fd8fSJohnny Huang 	printf("\n");
3142a856b9aSJohnny Huang 	return OTP_SUCCESS;
31569d5fd8fSJohnny Huang }
31669d5fd8fSJohnny Huang 
31769d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
31869d5fd8fSJohnny Huang {
31969d5fd8fSJohnny Huang 	uint32_t ret;
32069d5fd8fSJohnny Huang 	uint32_t *buf;
32169d5fd8fSJohnny Huang 
32269d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
32369d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
32469d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
32569d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
32669d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
3273d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
3283d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
3293d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
3303d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
3313d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
3323d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
3333d3688adSJohnny Huang 	wait_complete();
3343d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
33569d5fd8fSJohnny Huang 	if (ret & 0x1)
33669d5fd8fSJohnny Huang 		return 0;
33769d5fd8fSJohnny Huang 	else
33869d5fd8fSJohnny Huang 		return -1;
33969d5fd8fSJohnny Huang }
34069d5fd8fSJohnny Huang 
341a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
34269d5fd8fSJohnny Huang {
34330a8c590SJohnny Huang 	uint32_t ret[2];
34469d5fd8fSJohnny Huang 
34530a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
3463d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
34730a8c590SJohnny Huang 	else
3483d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
34930a8c590SJohnny Huang 
3503d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3513d3688adSJohnny Huang 	wait_complete();
3523d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3533d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
35483655e91SJohnny Huang 
35530a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
35630a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
35769d5fd8fSJohnny Huang 			return 0;
35869d5fd8fSJohnny Huang 		else
35969d5fd8fSJohnny Huang 			return -1;
36030a8c590SJohnny Huang 	} else {
36130a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
36230a8c590SJohnny Huang 			return 0;
36330a8c590SJohnny Huang 		else
36430a8c590SJohnny Huang 			return -1;
36530a8c590SJohnny Huang 	}
36630a8c590SJohnny Huang 
36769d5fd8fSJohnny Huang }
36869d5fd8fSJohnny Huang 
369696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size)
3704c1c9b35SJohnny Huang {
3714c1c9b35SJohnny Huang 	uint32_t ret[2];
3724c1c9b35SJohnny Huang 
3734c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
3744c1c9b35SJohnny Huang 
3754c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
3763d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
3774c1c9b35SJohnny Huang 	else
3783d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
3793d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
3803d3688adSJohnny Huang 	wait_complete();
3813d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
3823d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
3834c1c9b35SJohnny Huang 	if (size == 1) {
3844c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
3854c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
386696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
3874c1c9b35SJohnny Huang 				compare[0] = 0;
3884c1c9b35SJohnny Huang 				return 0;
3894c1c9b35SJohnny Huang 			} else {
3904c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
3914c1c9b35SJohnny Huang 				return -1;
3924c1c9b35SJohnny Huang 			}
3934c1c9b35SJohnny Huang 
3944c1c9b35SJohnny Huang 		} else {
3954c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
396696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
3974c1c9b35SJohnny Huang 				compare[0] = ~0;
3984c1c9b35SJohnny Huang 				return 0;
3994c1c9b35SJohnny Huang 			} else {
400d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
4014c1c9b35SJohnny Huang 				return -1;
4024c1c9b35SJohnny Huang 			}
4034c1c9b35SJohnny Huang 		}
4044c1c9b35SJohnny Huang 	} else if (size == 2) {
4054c1c9b35SJohnny Huang 		// otp_addr should be even
406696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
4074c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4084c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4094c1c9b35SJohnny Huang 			compare[0] = 0;
4104c1c9b35SJohnny Huang 			compare[1] = ~0;
4114c1c9b35SJohnny Huang 			return 0;
4124c1c9b35SJohnny Huang 		} else {
4134c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4144c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4154c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
4164c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
4174c1c9b35SJohnny Huang 			return -1;
4184c1c9b35SJohnny Huang 		}
4194c1c9b35SJohnny Huang 	} else {
4204c1c9b35SJohnny Huang 		return -1;
4214c1c9b35SJohnny Huang 	}
4224c1c9b35SJohnny Huang }
4234c1c9b35SJohnny Huang 
42483655e91SJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
42583655e91SJohnny Huang {
426*90965bb3SJohnny Huang 	otp_write(0x0, prog_bit);
42783655e91SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
42883655e91SJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
42983655e91SJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
43083655e91SJohnny Huang 	wait_complete();
43183655e91SJohnny Huang }
43283655e91SJohnny Huang 
43383655e91SJohnny Huang static void _otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
43483655e91SJohnny Huang {
43583655e91SJohnny Huang 	int prog_bit;
43683655e91SJohnny Huang 
43783655e91SJohnny Huang 	if (prog_address % 2 == 0) {
43883655e91SJohnny Huang 		if (value)
43983655e91SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
44083655e91SJohnny Huang 		else
44183655e91SJohnny Huang 			return;
44283655e91SJohnny Huang 	} else {
44383655e91SJohnny Huang 		prog_address |= 1 << 15;
44483655e91SJohnny Huang 		if (!value)
44583655e91SJohnny Huang 			prog_bit = 0x1 << bit_offset;
44683655e91SJohnny Huang 		else
44783655e91SJohnny Huang 			return;
44883655e91SJohnny Huang 	}
44983655e91SJohnny Huang 	otp_prog(prog_address, prog_bit);
45083655e91SJohnny Huang }
45183655e91SJohnny Huang 
45283655e91SJohnny Huang static int otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
45383655e91SJohnny Huang {
45483655e91SJohnny Huang 	int pass;
45583655e91SJohnny Huang 	int i;
45683655e91SJohnny Huang 
45783655e91SJohnny Huang 	otp_soak(1);
45883655e91SJohnny Huang 	_otp_prog_bit(value, prog_address, bit_offset);
45983655e91SJohnny Huang 	pass = 0;
46083655e91SJohnny Huang 
46183655e91SJohnny Huang 	for (i = 0; i < RETRY; i++) {
46283655e91SJohnny Huang 		if (verify_bit(prog_address, bit_offset, value) != 0) {
46383655e91SJohnny Huang 			otp_soak(2);
46483655e91SJohnny Huang 			_otp_prog_bit(value, prog_address, bit_offset);
46583655e91SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
46683655e91SJohnny Huang 				otp_soak(1);
46783655e91SJohnny Huang 			} else {
46883655e91SJohnny Huang 				pass = 1;
46983655e91SJohnny Huang 				break;
47083655e91SJohnny Huang 			}
47183655e91SJohnny Huang 		} else {
47283655e91SJohnny Huang 			pass = 1;
47383655e91SJohnny Huang 			break;
47483655e91SJohnny Huang 		}
47583655e91SJohnny Huang 	}
47683655e91SJohnny Huang 
47783655e91SJohnny Huang 	return pass;
47883655e91SJohnny Huang }
47983655e91SJohnny Huang 
480696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address)
481d90825e2SJohnny Huang {
482d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
483d90825e2SJohnny Huang 
484d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
485696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
486d90825e2SJohnny Huang 			continue;
487d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
488d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
489d90825e2SJohnny Huang 			if (bit_value)
490d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
491d90825e2SJohnny Huang 			else
492d90825e2SJohnny Huang 				continue;
493d90825e2SJohnny Huang 		} else {
494d90825e2SJohnny Huang 			prog_address |= 1 << 15;
495d90825e2SJohnny Huang 			if (bit_value)
496d90825e2SJohnny Huang 				continue;
497d90825e2SJohnny Huang 			else
498d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
499d90825e2SJohnny Huang 		}
500d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
501d90825e2SJohnny Huang 	}
502d90825e2SJohnny Huang }
503d90825e2SJohnny Huang 
50454552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
50554552c69SJohnny Huang {
50654552c69SJohnny Huang 	int pass;
50754552c69SJohnny Huang 	int i;
50854552c69SJohnny Huang 	uint32_t data0_masked;
50954552c69SJohnny Huang 	uint32_t data1_masked;
51054552c69SJohnny Huang 	uint32_t buf0_masked;
51154552c69SJohnny Huang 	uint32_t buf1_masked;
51254552c69SJohnny Huang 	uint32_t compare[2];
51354552c69SJohnny Huang 
51454552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
51554552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
51654552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
51754552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
51854552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
51954552c69SJohnny Huang 		return 0;
52054552c69SJohnny Huang 
52154552c69SJohnny Huang 	otp_soak(1);
52254552c69SJohnny Huang 	if (data0_masked != buf0_masked)
52354552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
52454552c69SJohnny Huang 	if (data1_masked != buf1_masked)
52554552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
52654552c69SJohnny Huang 
52754552c69SJohnny Huang 	pass = 0;
52854552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
52954552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
53054552c69SJohnny Huang 			otp_soak(2);
53154552c69SJohnny Huang 			if (compare[0] != 0) {
53254552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
53354552c69SJohnny Huang 			}
53454552c69SJohnny Huang 			if (compare[1] != ~0) {
5355537bc72SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1);
53654552c69SJohnny Huang 			}
53754552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
53854552c69SJohnny Huang 				otp_soak(1);
53954552c69SJohnny Huang 			} else {
54054552c69SJohnny Huang 				pass = 1;
54154552c69SJohnny Huang 				break;
54254552c69SJohnny Huang 			}
54354552c69SJohnny Huang 		} else {
54454552c69SJohnny Huang 			pass = 1;
54554552c69SJohnny Huang 			break;
54654552c69SJohnny Huang 		}
54754552c69SJohnny Huang 	}
54854552c69SJohnny Huang 
54954552c69SJohnny Huang 	if (!pass) {
55054552c69SJohnny Huang 		otp_soak(0);
55154552c69SJohnny Huang 		return OTP_FAILURE;
55254552c69SJohnny Huang 	}
55354552c69SJohnny Huang 	return OTP_SUCCESS;
55454552c69SJohnny Huang }
55554552c69SJohnny Huang 
556541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
55776d13988SJohnny Huang {
55876d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
5595010032bSJohnny Huang 	int strap_end;
56076d13988SJohnny Huang 	int i, j;
56176d13988SJohnny Huang 
5625010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
56376d13988SJohnny Huang 		for (j = 0; j < 64; j++) {
56476d13988SJohnny Huang 			otpstrap[j].value = 0;
56576d13988SJohnny Huang 			otpstrap[j].remain_times = 7;
56676d13988SJohnny Huang 			otpstrap[j].writeable_option = -1;
56776d13988SJohnny Huang 			otpstrap[j].protected = 0;
56876d13988SJohnny Huang 		}
5695010032bSJohnny Huang 		strap_end = 30;
5705010032bSJohnny Huang 	} else {
5715010032bSJohnny Huang 		for (j = 0; j < 64; j++) {
5725010032bSJohnny Huang 			otpstrap[j].value = 0;
5735010032bSJohnny Huang 			otpstrap[j].remain_times = 6;
5745010032bSJohnny Huang 			otpstrap[j].writeable_option = -1;
5755010032bSJohnny Huang 			otpstrap[j].reg_protected = 0;
5765010032bSJohnny Huang 			otpstrap[j].protected = 0;
5775010032bSJohnny Huang 		}
5785010032bSJohnny Huang 		strap_end = 28;
5795010032bSJohnny Huang 	}
58076d13988SJohnny Huang 
581dacbba92SJohnny Huang 	otp_soak(0);
5825010032bSJohnny Huang 	for (i = 16; i < strap_end; i += 2) {
58376d13988SJohnny Huang 		int option = (i - 16) / 2;
58476d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
58576d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
58676d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
58776d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
58876d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
58976d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
59076d13988SJohnny Huang 			}
59176d13988SJohnny Huang 			if (bit_value == 1)
59276d13988SJohnny Huang 				otpstrap[j].remain_times --;
59376d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
59476d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
59576d13988SJohnny Huang 		}
59676d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
59776d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
59876d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
59976d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
60076d13988SJohnny Huang 			}
60176d13988SJohnny Huang 			if (bit_value == 1)
60276d13988SJohnny Huang 				otpstrap[j].remain_times --;
60376d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
60476d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
60576d13988SJohnny Huang 		}
60676d13988SJohnny Huang 	}
6075010032bSJohnny Huang 
6085010032bSJohnny Huang 	if (info_cb.version != OTP_AST2600A0) {
6095010032bSJohnny Huang 		otp_read_config(28, &OTPSTRAP_RAW[0]);
6105010032bSJohnny Huang 		otp_read_config(29, &OTPSTRAP_RAW[1]);
6115010032bSJohnny Huang 		for (j = 0; j < 32; j++) {
6125010032bSJohnny Huang 			if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
6135010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
6145010032bSJohnny Huang 		}
6155010032bSJohnny Huang 		for (j = 32; j < 64; j++) {
6165010032bSJohnny Huang 			if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
6175010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
6185010032bSJohnny Huang 		}
6195010032bSJohnny Huang 
6205010032bSJohnny Huang 	}
6215010032bSJohnny Huang 
62276d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
62376d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
62476d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
62576d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
62676d13988SJohnny Huang 			otpstrap[j].protected = 1;
62776d13988SJohnny Huang 	}
62876d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
62976d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
63076d13988SJohnny Huang 			otpstrap[j].protected = 1;
63176d13988SJohnny Huang 	}
63276d13988SJohnny Huang }
63376d13988SJohnny Huang 
634696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
63569d5fd8fSJohnny Huang {
63679e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
637696656c6SJohnny Huang 	uint32_t *OTPCFG = (uint32_t *)image_layout->conf;
638696656c6SJohnny Huang 	uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore;
639b458cd62SJohnny Huang 	uint32_t mask;
640b458cd62SJohnny Huang 	uint32_t dw_offset;
641b458cd62SJohnny Huang 	uint32_t bit_offset;
642b458cd62SJohnny Huang 	uint32_t otp_value;
643696656c6SJohnny Huang 	uint32_t otp_ignore;
644b458cd62SJohnny Huang 	int fail = 0;
64573f11549SJohnny Huang 	char valid_bit[20];
64666f2f8e5SJohnny Huang 	int i;
64773f11549SJohnny Huang 	int j;
64866f2f8e5SJohnny Huang 
649737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
65066f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
6513cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
6523cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
6533cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
6543cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
655b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
656696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
657b458cd62SJohnny Huang 
658696656c6SJohnny Huang 		if (otp_ignore == mask) {
659b458cd62SJohnny Huang 			continue;
660696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
661b458cd62SJohnny Huang 			fail = 1;
662b458cd62SJohnny Huang 		}
663b458cd62SJohnny Huang 
6643cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
6653cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
6663cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
6673cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
668b458cd62SJohnny Huang 			continue;
669b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
670b458cd62SJohnny Huang 
6713cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
6723cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
67366f2f8e5SJohnny Huang 		} else {
674b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
6753cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
6763cb28812SJohnny Huang 			       conf_info[i].bit_offset);
67766f2f8e5SJohnny Huang 		}
678b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
679b458cd62SJohnny Huang 
680b458cd62SJohnny Huang 		if (fail) {
681696656c6SJohnny Huang 			printf("Ignore mask error\n");
682b458cd62SJohnny Huang 		} else {
6833cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
684b458cd62SJohnny Huang 				printf("Reserved\n");
6853cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
6863cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
687b458cd62SJohnny Huang 				printf("\n");
6883cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
689b458cd62SJohnny Huang 				if (otp_value != 0) {
69073f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
69173f11549SJohnny Huang 						if (otp_value == (1 << j)) {
69273f11549SJohnny Huang 							valid_bit[j * 2] = '1';
693b458cd62SJohnny Huang 						} else {
69473f11549SJohnny Huang 							valid_bit[j * 2] = '0';
69573f11549SJohnny Huang 						}
69673f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
69773f11549SJohnny Huang 					}
69873f11549SJohnny Huang 					valid_bit[15] = 0;
69973f11549SJohnny Huang 				} else {
70073f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
701b458cd62SJohnny Huang 				}
7023cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
703b458cd62SJohnny Huang 				printf("\n");
704b458cd62SJohnny Huang 			} else {
7053cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
706b458cd62SJohnny Huang 			}
707b458cd62SJohnny Huang 		}
708b458cd62SJohnny Huang 	}
709b458cd62SJohnny Huang 
710b458cd62SJohnny Huang 	if (fail)
711b458cd62SJohnny Huang 		return OTP_FAILURE;
712b458cd62SJohnny Huang 
71366f2f8e5SJohnny Huang 	return OTP_SUCCESS;
71466f2f8e5SJohnny Huang }
71566f2f8e5SJohnny Huang 
7162d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
71766f2f8e5SJohnny Huang {
71879e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
719bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
720b458cd62SJohnny Huang 	uint32_t mask;
721b458cd62SJohnny Huang 	uint32_t dw_offset;
722b458cd62SJohnny Huang 	uint32_t bit_offset;
723b458cd62SJohnny Huang 	uint32_t otp_value;
72473f11549SJohnny Huang 	char valid_bit[20];
72566f2f8e5SJohnny Huang 	int i;
72673f11549SJohnny Huang 	int j;
72766f2f8e5SJohnny Huang 
728dacbba92SJohnny Huang 	otp_soak(0);
729bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
73066f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
73166f2f8e5SJohnny Huang 
73266f2f8e5SJohnny Huang 
733b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
734b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
7353cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
7363cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
7372d4b0742SJohnny Huang 			continue;
7383cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
7393cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
7403cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
741b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
742b458cd62SJohnny Huang 
7433cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
7443cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
7453cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
7463cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
747b458cd62SJohnny Huang 			continue;
748b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
749b458cd62SJohnny Huang 
7503cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
7513cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
752b458cd62SJohnny Huang 		} else {
753b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
7543cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
7553cb28812SJohnny Huang 			       conf_info[i].bit_offset);
756b458cd62SJohnny Huang 		}
757b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
758b458cd62SJohnny Huang 
7593cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
760b458cd62SJohnny Huang 			printf("Reserved\n");
7613cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
7623cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
763b458cd62SJohnny Huang 			printf("\n");
7643cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
765b458cd62SJohnny Huang 			if (otp_value != 0) {
76673f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
76773f11549SJohnny Huang 					if (otp_value == (1 << j)) {
76873f11549SJohnny Huang 						valid_bit[j * 2] = '1';
769b458cd62SJohnny Huang 					} else {
77073f11549SJohnny Huang 						valid_bit[j * 2] = '0';
77173f11549SJohnny Huang 					}
77273f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
77373f11549SJohnny Huang 				}
77473f11549SJohnny Huang 				valid_bit[15] = 0;
77573f11549SJohnny Huang 			} else {
77673f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
777b458cd62SJohnny Huang 			}
7783cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
779b458cd62SJohnny Huang 			printf("\n");
780b458cd62SJohnny Huang 		} else {
7813cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
782b458cd62SJohnny Huang 		}
783b458cd62SJohnny Huang 	}
784b458cd62SJohnny Huang 	return OTP_SUCCESS;
78566f2f8e5SJohnny Huang }
78666f2f8e5SJohnny Huang 
7875010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout)
78876d13988SJohnny Huang {
78979e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
790696656c6SJohnny Huang 	uint32_t *OTPSTRAP;
791696656c6SJohnny Huang 	uint32_t *OTPSTRAP_REG_PRO;
792696656c6SJohnny Huang 	uint32_t *OTPSTRAP_PRO;
793696656c6SJohnny Huang 	uint32_t *OTPSTRAP_IGNORE;
79476d13988SJohnny Huang 	int i;
795a8bd6d8cSJohnny Huang 	int fail = 0;
796a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
797a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
798a8bd6d8cSJohnny Huang 	uint32_t mask;
799a8bd6d8cSJohnny Huang 	uint32_t otp_value;
800696656c6SJohnny Huang 	uint32_t otp_reg_protect;
801a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
802696656c6SJohnny Huang 	uint32_t otp_ignore;
80376d13988SJohnny Huang 
804696656c6SJohnny Huang 	OTPSTRAP = (uint32_t *)image_layout->strap;
805696656c6SJohnny Huang 	OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro;
806696656c6SJohnny Huang 	OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore;
8075010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
808696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
809a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
810696656c6SJohnny Huang 	} else {
811696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro;
812de6b0cc4SJohnny Huang 		printf("BIT(hex)   Value       Reg_Protect Protect     Description\n");
813696656c6SJohnny Huang 	}
814de6b0cc4SJohnny Huang 	printf("__________________________________________________________________________________________\n");
815b458cd62SJohnny Huang 
8163cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
817696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
818a8bd6d8cSJohnny Huang 			dw_offset = 1;
8193cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
820a8bd6d8cSJohnny Huang 		} else {
821a8bd6d8cSJohnny Huang 			dw_offset = 0;
8223cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
823a8bd6d8cSJohnny Huang 		}
82476d13988SJohnny Huang 
8253cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
826a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
827a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
828696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
829a8bd6d8cSJohnny Huang 
8305010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
831696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
8325010032bSJohnny Huang 		else
8335010032bSJohnny Huang 			otp_reg_protect = 0;
834696656c6SJohnny Huang 
835696656c6SJohnny Huang 		if (otp_ignore == mask) {
836a8bd6d8cSJohnny Huang 			continue;
837696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
838a8bd6d8cSJohnny Huang 			fail = 1;
839a8bd6d8cSJohnny Huang 		}
840a8bd6d8cSJohnny Huang 
8413cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
8423cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
843a8bd6d8cSJohnny Huang 			continue;
844a8bd6d8cSJohnny Huang 
8453cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
8463cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
847a8bd6d8cSJohnny Huang 		} else {
848b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
8493cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
8503cb28812SJohnny Huang 			       strap_info[i].bit_offset);
851a8bd6d8cSJohnny Huang 		}
852a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
8535010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
854696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
855a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
856a8bd6d8cSJohnny Huang 
857a8bd6d8cSJohnny Huang 		if (fail) {
858696656c6SJohnny Huang 			printf("Ignore mask error\n");
859a8bd6d8cSJohnny Huang 		} else {
8603cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
8613cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
862a8bd6d8cSJohnny Huang 			else
863a8bd6d8cSJohnny Huang 				printf("Reserved\n");
864a8bd6d8cSJohnny Huang 		}
865a8bd6d8cSJohnny Huang 	}
866a8bd6d8cSJohnny Huang 
867a8bd6d8cSJohnny Huang 	if (fail)
86876d13988SJohnny Huang 		return OTP_FAILURE;
86976d13988SJohnny Huang 
87076d13988SJohnny Huang 	return OTP_SUCCESS;
87176d13988SJohnny Huang }
87276d13988SJohnny Huang 
873b458cd62SJohnny Huang static int otp_print_strap_info(int view)
87476d13988SJohnny Huang {
87579e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
87676d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
87707baa4e8SJohnny Huang 	int i, j;
878b458cd62SJohnny Huang 	int fail = 0;
879b458cd62SJohnny Huang 	uint32_t bit_offset;
880b458cd62SJohnny Huang 	uint32_t length;
881b458cd62SJohnny Huang 	uint32_t otp_value;
882b458cd62SJohnny Huang 	uint32_t otp_protect;
88376d13988SJohnny Huang 
884541eb887SJohnny Huang 	otp_strap_status(strap_status);
88576d13988SJohnny Huang 
886b458cd62SJohnny Huang 	if (view) {
88783655e91SJohnny Huang 		if (info_cb.version == OTP_AST2600A0)
88807baa4e8SJohnny Huang 			printf("BIT(hex) Value  Remains  Protect   Description\n");
88983655e91SJohnny Huang 		else
89083655e91SJohnny Huang 			printf("BIT(hex) Value  Remains  Reg_Protect Protect   Description\n");
89107baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
892b458cd62SJohnny Huang 	} else {
893b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
894b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
89576d13988SJohnny Huang 	}
8963cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
897b458cd62SJohnny Huang 		otp_value = 0;
8983cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
8993cb28812SJohnny Huang 		length = strap_info[i].length;
900b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
901c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
902c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
903b458cd62SJohnny Huang 		}
9043cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
9053cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
906b458cd62SJohnny Huang 			continue;
907b458cd62SJohnny Huang 		if (view) {
908b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
9093cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
910b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
91107baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
91283655e91SJohnny Huang 				if (info_cb.version != OTP_AST2600A0)
913e1a7245eSJohnny Huang 					printf("0x%-10X", strap_status[bit_offset + j].reg_protected);
914e1a7245eSJohnny Huang 				printf("0x%-7X", strap_status[bit_offset + j].protected);
9153cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
916b458cd62SJohnny Huang 					printf(" Reserved\n");
917b458cd62SJohnny Huang 					continue;
918b458cd62SJohnny Huang 				}
919b458cd62SJohnny Huang 				if (length == 1) {
9203cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
921b458cd62SJohnny Huang 					continue;
92276d13988SJohnny Huang 				}
92376d13988SJohnny Huang 
924b458cd62SJohnny Huang 				if (j == 0)
9253cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
926b458cd62SJohnny Huang 				else if (j == length - 1)
927b458cd62SJohnny Huang 					printf("\\ \"\n");
928b458cd62SJohnny Huang 				else
929b458cd62SJohnny Huang 					printf("| \"\n");
93076d13988SJohnny Huang 			}
931b458cd62SJohnny Huang 		} else {
932c947ef08SJohnny Huang 			if (length == 1) {
9333cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
934b458cd62SJohnny Huang 			} else {
935b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
936b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
937b458cd62SJohnny Huang 			}
938b458cd62SJohnny Huang 
939b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
940b458cd62SJohnny Huang 
9413cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
9423cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
943b458cd62SJohnny Huang 			else
944b458cd62SJohnny Huang 				printf("Reserved\n");
945b458cd62SJohnny Huang 		}
946b458cd62SJohnny Huang 	}
947b458cd62SJohnny Huang 
948b458cd62SJohnny Huang 	if (fail)
949b458cd62SJohnny Huang 		return OTP_FAILURE;
950b458cd62SJohnny Huang 
951b458cd62SJohnny Huang 	return OTP_SUCCESS;
952b458cd62SJohnny Huang }
953b458cd62SJohnny Huang 
954696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len)
95569d5fd8fSJohnny Huang {
95669d5fd8fSJohnny Huang 	int i;
95769d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
95869d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
95969d5fd8fSJohnny Huang 		if (i % 16 == 0) {
96069d5fd8fSJohnny Huang 			printf("%04X: ", i);
96169d5fd8fSJohnny Huang 		}
96269d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
96369d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
96469d5fd8fSJohnny Huang 			printf("\n");
96569d5fd8fSJohnny Huang 		}
96669d5fd8fSJohnny Huang 	}
96769d5fd8fSJohnny Huang }
96869d5fd8fSJohnny Huang 
969696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
97069d5fd8fSJohnny Huang {
97169d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
97279e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
9739a4fe690SJohnny Huang 	struct otpkey_type key_info;
974696656c6SJohnny Huang 	uint32_t *buf;
975696656c6SJohnny Huang 	uint8_t *byte_buf;
9769d998018SJohnny Huang 	char empty = 1;
97769d5fd8fSJohnny Huang 	int i = 0, len = 0;
9789a4fe690SJohnny Huang 	int j;
97954552c69SJohnny Huang 
980696656c6SJohnny Huang 	byte_buf = image_layout->data;
981696656c6SJohnny Huang 	buf = (uint32_t *)byte_buf;
9829d998018SJohnny Huang 
9839d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
9849d998018SJohnny Huang 		if (buf[i] != 0) {
9859d998018SJohnny Huang 			empty = 0;
9869d998018SJohnny Huang 		}
9879d998018SJohnny Huang 	}
9889d998018SJohnny Huang 	if (empty)
9899d998018SJohnny Huang 		return 0;
9909d998018SJohnny Huang 
9919d998018SJohnny Huang 	i = 0;
99269d5fd8fSJohnny Huang 	while (1) {
99369d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
99469d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
99569d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
99669d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
99769d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
99869d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
9999a4fe690SJohnny Huang 
10009a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
10019a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
10029a4fe690SJohnny Huang 				key_info = key_info_array[j];
10039a4fe690SJohnny Huang 				break;
10049a4fe690SJohnny Huang 			}
10059a4fe690SJohnny Huang 		}
10069a4fe690SJohnny Huang 
10077f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
100869d5fd8fSJohnny Huang 		printf("Key Type: ");
10099a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
10109a4fe690SJohnny Huang 
10119a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
101269d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
101369d5fd8fSJohnny Huang 			switch (key_length) {
101469d5fd8fSJohnny Huang 			case 0:
101569d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
101669d5fd8fSJohnny Huang 				break;
101769d5fd8fSJohnny Huang 			case 1:
101869d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
101969d5fd8fSJohnny Huang 				break;
102069d5fd8fSJohnny Huang 			case 2:
102169d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
102269d5fd8fSJohnny Huang 				break;
102369d5fd8fSJohnny Huang 			case 3:
102469d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
102569d5fd8fSJohnny Huang 				break;
102669d5fd8fSJohnny Huang 			}
10279a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
102869d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
102969d5fd8fSJohnny Huang 			switch (key_length) {
103069d5fd8fSJohnny Huang 			case 0:
103169d5fd8fSJohnny Huang 				printf("RSA1024\n");
103269d5fd8fSJohnny Huang 				len = 0x100;
103369d5fd8fSJohnny Huang 				break;
103469d5fd8fSJohnny Huang 			case 1:
103569d5fd8fSJohnny Huang 				printf("RSA2048\n");
103669d5fd8fSJohnny Huang 				len = 0x200;
103769d5fd8fSJohnny Huang 				break;
103869d5fd8fSJohnny Huang 			case 2:
103969d5fd8fSJohnny Huang 				printf("RSA3072\n");
104069d5fd8fSJohnny Huang 				len = 0x300;
104169d5fd8fSJohnny Huang 				break;
104269d5fd8fSJohnny Huang 			case 3:
104369d5fd8fSJohnny Huang 				printf("RSA4096\n");
104469d5fd8fSJohnny Huang 				len = 0x400;
104569d5fd8fSJohnny Huang 				break;
104669d5fd8fSJohnny Huang 			}
104769d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
104869d5fd8fSJohnny Huang 		}
10499a4fe690SJohnny Huang 		if (key_info.need_id)
105069d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
105169d5fd8fSJohnny Huang 		printf("Key Value:\n");
10529a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
105369d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
10549a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
10559a4fe690SJohnny Huang 			printf("AES Key:\n");
10569a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
10575fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
10589a4fe690SJohnny Huang 				printf("AES IV:\n");
10599a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10609a4fe690SJohnny Huang 			}
10619a4fe690SJohnny Huang 
10629a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
10635fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
106469d5fd8fSJohnny Huang 				printf("AES Key:\n");
106569d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
106669d5fd8fSJohnny Huang 				printf("AES IV:\n");
106769d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
10685fdde29fSJohnny Huang 			} else {
10699a4fe690SJohnny Huang 				printf("AES Key 1:\n");
10709a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
10719a4fe690SJohnny Huang 				printf("AES Key 2:\n");
10729a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
10739a4fe690SJohnny Huang 			}
107469d5fd8fSJohnny Huang 
10759a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
107669d5fd8fSJohnny Huang 			printf("RSA mod:\n");
107769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
107869d5fd8fSJohnny Huang 			printf("RSA exp:\n");
107969d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
108069d5fd8fSJohnny Huang 		}
108169d5fd8fSJohnny Huang 		if (last)
108269d5fd8fSJohnny Huang 			break;
108369d5fd8fSJohnny Huang 		i++;
108469d5fd8fSJohnny Huang 	}
108569d5fd8fSJohnny Huang 	return 0;
108669d5fd8fSJohnny Huang }
108769d5fd8fSJohnny Huang 
10885010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout)
108969d5fd8fSJohnny Huang {
1090a6d0d645SJohnny Huang 	int i, k;
1091d90825e2SJohnny Huang 	int pass = 0;
1092a6d0d645SJohnny Huang 	uint32_t prog_address;
1093bb34a7bfSJohnny Huang 	uint32_t data[16];
1094a6d0d645SJohnny Huang 	uint32_t compare[2];
10955010032bSJohnny Huang 	uint32_t *conf = (uint32_t *)image_layout->conf;
10965010032bSJohnny Huang 	uint32_t *conf_ignore = (uint32_t *)image_layout->conf_ignore;
1097d90825e2SJohnny Huang 	uint32_t data_masked;
1098d90825e2SJohnny Huang 	uint32_t buf_masked;
109969d5fd8fSJohnny Huang 
1100a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1101a6d0d645SJohnny Huang 
1102bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
110369d5fd8fSJohnny Huang 		prog_address = 0x800;
1104a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1105a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1106a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1107a6d0d645SJohnny Huang 	}
1108a6d0d645SJohnny Huang 
1109a6d0d645SJohnny Huang 	printf("Check writable...\n");
1110bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11115010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11125010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1113d90825e2SJohnny Huang 		if (data_masked == buf_masked)
111469d5fd8fSJohnny Huang 			continue;
1115d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1116a6d0d645SJohnny Huang 			continue;
1117a6d0d645SJohnny Huang 		} else {
1118a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1119a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
11205010032bSJohnny Huang 			printf("Input [%X] = %x\n", i, conf[i]);
11215010032bSJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~conf_ignore[i]);
11222a856b9aSJohnny Huang 			return OTP_FAILURE;
1123a6d0d645SJohnny Huang 		}
1124a6d0d645SJohnny Huang 	}
1125a6d0d645SJohnny Huang 
1126a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1127d90825e2SJohnny Huang 	otp_soak(0);
1128bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
11295010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
11305010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1131a6d0d645SJohnny Huang 		prog_address = 0x800;
1132a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1133a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1134bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1135bb34a7bfSJohnny Huang 			pass = 1;
1136a6d0d645SJohnny Huang 			continue;
1137bb34a7bfSJohnny Huang 		}
1138de6fbf1cSJohnny Huang 
1139a6d0d645SJohnny Huang 
1140de6fbf1cSJohnny Huang 		otp_soak(1);
11415010032bSJohnny Huang 		otp_prog_dw(conf[i], conf_ignore[i], prog_address);
1142a6d0d645SJohnny Huang 
114369d5fd8fSJohnny Huang 		pass = 0;
114469d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
11455010032bSJohnny Huang 			if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1146de6fbf1cSJohnny Huang 				otp_soak(2);
1147feea3fdfSJohnny Huang 				otp_prog_dw(compare[0], conf_ignore[i], prog_address);
11485010032bSJohnny Huang 				if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1149de6fbf1cSJohnny Huang 					otp_soak(1);
1150de6fbf1cSJohnny Huang 				} else {
1151de6fbf1cSJohnny Huang 					pass = 1;
1152de6fbf1cSJohnny Huang 					break;
1153de6fbf1cSJohnny Huang 				}
1154a6d0d645SJohnny Huang 			} else {
115569d5fd8fSJohnny Huang 				pass = 1;
115669d5fd8fSJohnny Huang 				break;
115769d5fd8fSJohnny Huang 			}
115869d5fd8fSJohnny Huang 		}
1159bb34a7bfSJohnny Huang 		if (pass == 0) {
1160bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
11615010032bSJohnny Huang 			       i, data[i], conf[i], conf_ignore[i]);
1162bb34a7bfSJohnny Huang 			break;
1163bb34a7bfSJohnny Huang 		}
1164a6d0d645SJohnny Huang 	}
1165a6d0d645SJohnny Huang 
1166de6fbf1cSJohnny Huang 	otp_soak(0);
116769d5fd8fSJohnny Huang 	if (!pass)
11682a856b9aSJohnny Huang 		return OTP_FAILURE;
1169a6d0d645SJohnny Huang 
11702a856b9aSJohnny Huang 	return OTP_SUCCESS;
1171d90825e2SJohnny Huang 
117269d5fd8fSJohnny Huang }
117369d5fd8fSJohnny Huang 
1174eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit)
1175eda10d61SJohnny Huang {
1176eda10d61SJohnny Huang 	if (ibit == 1) {
1177eda10d61SJohnny Huang 		return OTP_SUCCESS;
1178eda10d61SJohnny Huang 	} else {
1179eda10d61SJohnny Huang 		printf("OTPSTRAP[%X]:\n", offset);
1180eda10d61SJohnny Huang 	}
1181eda10d61SJohnny Huang 	if (bit == otpstrap->value) {
1182eda10d61SJohnny Huang 		printf("    The value is same as before, skip it.\n");
1183eda10d61SJohnny Huang 		return OTP_PROG_SKIP;
1184eda10d61SJohnny Huang 	}
1185eda10d61SJohnny Huang 	if (otpstrap->protected == 1) {
1186eda10d61SJohnny Huang 		printf("    This bit is protected and is not writable\n");
1187eda10d61SJohnny Huang 		return OTP_FAILURE;
1188eda10d61SJohnny Huang 	}
1189eda10d61SJohnny Huang 	if (otpstrap->remain_times == 0) {
1190eda10d61SJohnny Huang 		printf("    This bit is no remaining times to write.\n");
1191eda10d61SJohnny Huang 		return OTP_FAILURE;
1192eda10d61SJohnny Huang 	}
1193eda10d61SJohnny Huang 	if (pbit == 1) {
1194eda10d61SJohnny Huang 		printf("    This bit will be protected and become non-writable.\n");
1195eda10d61SJohnny Huang 	}
1196eda10d61SJohnny Huang 	if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
1197eda10d61SJohnny Huang 		printf("    The relative register will be protected.\n");
1198eda10d61SJohnny Huang 	}
1199eda10d61SJohnny 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);
1200eda10d61SJohnny Huang 	return OTP_SUCCESS;
1201eda10d61SJohnny Huang }
1202eda10d61SJohnny Huang 
12035010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout)
120469d5fd8fSJohnny Huang {
120569d5fd8fSJohnny Huang 	int i;
12065010032bSJohnny Huang 	uint32_t *strap;
12075010032bSJohnny Huang 	uint32_t *strap_ignore;
12085010032bSJohnny Huang 	uint32_t *strap_reg_protect;
12095010032bSJohnny Huang 	uint32_t *strap_pro;
1210eda10d61SJohnny Huang 	int bit, pbit, ibit, rpbit;
121169d5fd8fSJohnny Huang 	int fail = 0;
1212a6af4a17SJohnny Huang 	int skip = -1;
1213eda10d61SJohnny Huang 	int ret;
121466f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
121569d5fd8fSJohnny Huang 
12165010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
12175010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
12185010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
12195010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
12205010032bSJohnny Huang 
1221541eb887SJohnny Huang 	otp_strap_status(otpstrap);
122269d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
122369d5fd8fSJohnny Huang 		if (i < 32) {
12245010032bSJohnny Huang 			bit = (strap[0] >> i) & 0x1;
1225eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> i) & 0x1;
12265010032bSJohnny Huang 			pbit = (strap_pro[0] >> i) & 0x1;
122769d5fd8fSJohnny Huang 		} else {
12285010032bSJohnny Huang 			bit = (strap[1] >> (i - 32)) & 0x1;
1229eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> (i - 32)) & 0x1;
12305010032bSJohnny Huang 			pbit = (strap_pro[1] >> (i - 32)) & 0x1;
12315010032bSJohnny Huang 		}
12325010032bSJohnny Huang 
12335010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
12345010032bSJohnny Huang 			if (i < 32) {
12355010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
12365010032bSJohnny Huang 			} else {
12375010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
12385010032bSJohnny Huang 			}
12395010032bSJohnny Huang 		} else {
12405010032bSJohnny Huang 			rpbit = 0;
124169d5fd8fSJohnny Huang 		}
1242eda10d61SJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit);
1243eda10d61SJohnny Huang 		if (ret == OTP_PROG_SKIP) {
1244a6af4a17SJohnny Huang 			if (skip == -1)
1245a6af4a17SJohnny Huang 				skip = 1;
124669d5fd8fSJohnny Huang 			continue;
1247a6af4a17SJohnny Huang 		} else {
1248eda10d61SJohnny Huang 			skip = 1;
124969d5fd8fSJohnny Huang 		}
1250eda10d61SJohnny Huang 
1251eda10d61SJohnny Huang 		if (ret == OTP_FAILURE)
125269d5fd8fSJohnny Huang 			fail = 1;
125369d5fd8fSJohnny Huang 	}
125469d5fd8fSJohnny Huang 	if (fail == 1)
1255a6af4a17SJohnny Huang 		return OTP_FAILURE;
1256a6af4a17SJohnny Huang 	else if (skip == 1)
1257a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
12587e22f42dSJohnny Huang 
1259eda10d61SJohnny Huang 	return OTP_SUCCESS;
126069d5fd8fSJohnny Huang }
126169d5fd8fSJohnny Huang 
12622a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
126369d5fd8fSJohnny Huang {
126469d5fd8fSJohnny Huang 	int i, j;
1265de6b0cc4SJohnny Huang 	int remains;
126666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
126769d5fd8fSJohnny Huang 
12682a856b9aSJohnny Huang 	if (start < 0 || start > 64)
12692a856b9aSJohnny Huang 		return OTP_USAGE;
12702a856b9aSJohnny Huang 
12712a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
12722a856b9aSJohnny Huang 		return OTP_USAGE;
12732a856b9aSJohnny Huang 
1274541eb887SJohnny Huang 	otp_strap_status(otpstrap);
127569d5fd8fSJohnny Huang 
1276de6b0cc4SJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1277de6b0cc4SJohnny Huang 		remains = 7;
127807baa4e8SJohnny Huang 		printf("BIT(hex)  Value  Option           Status\n");
1279de6b0cc4SJohnny Huang 	} else {
1280de6b0cc4SJohnny Huang 		remains = 6;
1281de6b0cc4SJohnny Huang 		printf("BIT(hex)  Value  Option         Reg_Protect Status\n");
1282de6b0cc4SJohnny Huang 	}
1283de6b0cc4SJohnny Huang 	printf("______________________________________________________________________________\n");
1284737ed20bSJohnny Huang 
1285cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
128607baa4e8SJohnny Huang 		printf("0x%-8X", i);
1287737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1288de6b0cc4SJohnny Huang 		for (j = 0; j < remains; j++)
1289737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1290737ed20bSJohnny Huang 		printf("   ");
1291de6b0cc4SJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1292de6b0cc4SJohnny Huang 			printf("%d           ", otpstrap[i].reg_protected);
1293de6b0cc4SJohnny Huang 		}
129469d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1295737ed20bSJohnny Huang 			printf("protected and not writable");
129669d5fd8fSJohnny Huang 		} else {
1297737ed20bSJohnny Huang 			printf("not protected ");
129869d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1299737ed20bSJohnny Huang 				printf("and no remaining times to write.");
130069d5fd8fSJohnny Huang 			} else {
1301737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
130269d5fd8fSJohnny Huang 			}
130369d5fd8fSJohnny Huang 		}
1304737ed20bSJohnny Huang 		printf("\n");
130569d5fd8fSJohnny Huang 	}
13062a856b9aSJohnny Huang 
13072a856b9aSJohnny Huang 	return OTP_SUCCESS;
130869d5fd8fSJohnny Huang }
130969d5fd8fSJohnny Huang 
13108848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value)
13118848d5dcSJohnny Huang {
13128848d5dcSJohnny Huang 	struct otpstrap_status otpstrap[64];
131383655e91SJohnny Huang 	uint32_t prog_address;
13148848d5dcSJohnny Huang 	int offset;
13158848d5dcSJohnny Huang 	int ret;
13168848d5dcSJohnny Huang 
13178848d5dcSJohnny Huang 
13188848d5dcSJohnny Huang 	otp_strap_status(otpstrap);
13198848d5dcSJohnny Huang 
13208848d5dcSJohnny Huang 	ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
13218848d5dcSJohnny Huang 
13228848d5dcSJohnny Huang 	if (ret != OTP_SUCCESS) {
13238848d5dcSJohnny Huang 		return ret;
13248848d5dcSJohnny Huang 	}
13258848d5dcSJohnny Huang 
13268848d5dcSJohnny Huang 	prog_address = 0x800;
13278848d5dcSJohnny Huang 	if (bit_offset < 32) {
13288848d5dcSJohnny Huang 		offset = bit_offset;
13298848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200;
13308848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2;
13318848d5dcSJohnny Huang 
13328848d5dcSJohnny Huang 	} else {
13338848d5dcSJohnny Huang 		offset = (bit_offset - 32);
13348848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200;
13358848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2;
13368848d5dcSJohnny Huang 	}
13378848d5dcSJohnny Huang 
13388848d5dcSJohnny Huang 
133983655e91SJohnny Huang 	return otp_prog_bit(1, prog_address, offset);
13408848d5dcSJohnny Huang }
13418848d5dcSJohnny Huang 
13425010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout)
134369d5fd8fSJohnny Huang {
13445010032bSJohnny Huang 	uint32_t *strap;
13455010032bSJohnny Huang 	uint32_t *strap_ignore;
13465010032bSJohnny Huang 	uint32_t *strap_pro;
13475010032bSJohnny Huang 	uint32_t *strap_reg_protect;
134883655e91SJohnny Huang 	uint32_t prog_address;
134983655e91SJohnny Huang 	int i;
1350eda10d61SJohnny Huang 	int bit, pbit, ibit, offset, rpbit;
135169d5fd8fSJohnny Huang 	int fail = 0;
135283655e91SJohnny Huang 	int ret;
135366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
135469d5fd8fSJohnny Huang 
13555010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
13565010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
13575010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
13585010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
13595010032bSJohnny Huang 
13607f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1361541eb887SJohnny Huang 	otp_strap_status(otpstrap);
136269d5fd8fSJohnny Huang 
13637f795e57SJohnny Huang 	printf("Check writable...\n");
13645010032bSJohnny Huang 	if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) {
13657f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
13667f795e57SJohnny Huang 		return OTP_FAILURE;
13677f795e57SJohnny Huang 	}
13687e22f42dSJohnny Huang 
136969d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
137069d5fd8fSJohnny Huang 		prog_address = 0x800;
137169d5fd8fSJohnny Huang 		if (i < 32) {
137269d5fd8fSJohnny Huang 			offset = i;
13735010032bSJohnny Huang 			bit = (strap[0] >> offset) & 0x1;
1374eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> offset) & 0x1;
13755010032bSJohnny Huang 			pbit = (strap_pro[0] >> offset) & 0x1;
137669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
137769d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
137869d5fd8fSJohnny Huang 
137969d5fd8fSJohnny Huang 		} else {
138069d5fd8fSJohnny Huang 			offset = (i - 32);
13815010032bSJohnny Huang 			bit = (strap[1] >> offset) & 0x1;
1382eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> offset) & 0x1;
13835010032bSJohnny Huang 			pbit = (strap_pro[1] >> offset) & 0x1;
138469d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
138569d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
138669d5fd8fSJohnny Huang 		}
13875010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
13885010032bSJohnny Huang 			if (i < 32) {
13895010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
13905010032bSJohnny Huang 			} else {
13915010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
13925010032bSJohnny Huang 			}
13935010032bSJohnny Huang 		} else {
13945010032bSJohnny Huang 			rpbit = 0;
13955010032bSJohnny Huang 		}
139669d5fd8fSJohnny Huang 
1397eda10d61SJohnny Huang 		if (ibit == 1) {
139869d5fd8fSJohnny Huang 			continue;
139969d5fd8fSJohnny Huang 		}
140069d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
140169d5fd8fSJohnny Huang 			continue;
140269d5fd8fSJohnny Huang 		}
140369d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
140469d5fd8fSJohnny Huang 			fail = 1;
140569d5fd8fSJohnny Huang 			continue;
140669d5fd8fSJohnny Huang 		}
140769d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
140869d5fd8fSJohnny Huang 			fail = 1;
140969d5fd8fSJohnny Huang 			continue;
141069d5fd8fSJohnny Huang 		}
14117e22f42dSJohnny Huang 
141283655e91SJohnny Huang 		ret = otp_prog_bit(1, prog_address, offset);
141383655e91SJohnny Huang 		if (!ret)
14142a856b9aSJohnny Huang 			return OTP_FAILURE;
141569d5fd8fSJohnny Huang 
14165010032bSJohnny Huang 		if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
141769d5fd8fSJohnny Huang 			prog_address = 0x800;
141869d5fd8fSJohnny Huang 			if (i < 32)
14195010032bSJohnny Huang 				prog_address |= 0x608;
142069d5fd8fSJohnny Huang 			else
14215010032bSJohnny Huang 				prog_address |= 0x60a;
14227e22f42dSJohnny Huang 
142383655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
142483655e91SJohnny Huang 			if (!ret)
14252a856b9aSJohnny Huang 				return OTP_FAILURE;
14265010032bSJohnny Huang 		}
14275010032bSJohnny Huang 
14285010032bSJohnny Huang 		if (pbit != 0) {
14295010032bSJohnny Huang 			prog_address = 0x800;
14305010032bSJohnny Huang 			if (i < 32)
14315010032bSJohnny Huang 				prog_address |= 0x60c;
14325010032bSJohnny Huang 			else
14335010032bSJohnny Huang 				prog_address |= 0x60e;
14345010032bSJohnny Huang 
143583655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
143683655e91SJohnny Huang 			if (!ret)
14375010032bSJohnny Huang 				return OTP_FAILURE;
14385010032bSJohnny Huang 		}
143969d5fd8fSJohnny Huang 
144069d5fd8fSJohnny Huang 	}
1441de6fbf1cSJohnny Huang 	otp_soak(0);
144269d5fd8fSJohnny Huang 	if (fail == 1)
14432a856b9aSJohnny Huang 		return OTP_FAILURE;
144469d5fd8fSJohnny Huang 	else
14452a856b9aSJohnny Huang 		return OTP_SUCCESS;
144669d5fd8fSJohnny Huang 
144769d5fd8fSJohnny Huang }
144869d5fd8fSJohnny Huang 
14495010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout)
14504c1c9b35SJohnny Huang {
145154552c69SJohnny Huang 	int i;
145254552c69SJohnny Huang 	int ret;
14535010032bSJohnny Huang 	int data_dw;
1454d90825e2SJohnny Huang 	uint32_t data[2048];
14555010032bSJohnny Huang 	uint32_t *buf;
14565010032bSJohnny Huang 	uint32_t *buf_ignore;
14574c1c9b35SJohnny Huang 
145854552c69SJohnny Huang 	uint32_t data_masked;
145954552c69SJohnny Huang 	uint32_t buf_masked;
14604c1c9b35SJohnny Huang 
14615010032bSJohnny Huang 	buf = (uint32_t *)image_layout->data;
14625010032bSJohnny Huang 	buf_ignore = (uint32_t *)image_layout->data_ignore;
14635010032bSJohnny Huang 
14645010032bSJohnny Huang 	data_dw = image_layout->data_length / 4;
14655010032bSJohnny Huang 
14664c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
14674c1c9b35SJohnny Huang 
14685010032bSJohnny Huang 	for (i = 0; i < data_dw - 2 ; i += 2) {
1469d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
14704c1c9b35SJohnny Huang 	}
1471d90825e2SJohnny Huang 
14724c1c9b35SJohnny Huang 	printf("Check writable...\n");
147354552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
14745010032bSJohnny Huang 	for (i = 0; i < data_dw - 2; i++) {
1475696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1476696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
147754552c69SJohnny Huang 		if (data_masked == buf_masked)
14784c1c9b35SJohnny Huang 			continue;
1479d90825e2SJohnny Huang 		if (i % 2 == 0) {
148054552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
14814c1c9b35SJohnny Huang 				continue;
14824c1c9b35SJohnny Huang 			} else {
14834c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1484d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
14854c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1486696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
14872a856b9aSJohnny Huang 				return OTP_FAILURE;
148869d5fd8fSJohnny Huang 			}
1489d90825e2SJohnny Huang 		} else {
149054552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1491d90825e2SJohnny Huang 				continue;
1492d90825e2SJohnny Huang 			} else {
1493d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1494d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1495d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1496696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
14972a856b9aSJohnny Huang 				return OTP_FAILURE;
1498d90825e2SJohnny Huang 			}
1499d90825e2SJohnny Huang 		}
1500d90825e2SJohnny Huang 	}
150169d5fd8fSJohnny Huang 
1502d90825e2SJohnny Huang 	printf("Start Programing...\n");
1503d90825e2SJohnny Huang 
150454552c69SJohnny Huang 	// programing ecc region first
150554552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
1506696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
150754552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
150854552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1509696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
151054552c69SJohnny Huang 			return ret;
1511d90825e2SJohnny Huang 		}
1512d90825e2SJohnny Huang 	}
1513d90825e2SJohnny Huang 
151454552c69SJohnny Huang 	for (i = 0; i < 1792; 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 		}
1521de6fbf1cSJohnny Huang 	}
1522de6fbf1cSJohnny Huang 	otp_soak(0);
15232a856b9aSJohnny Huang 	return OTP_SUCCESS;
1524d90825e2SJohnny Huang 
1525d90825e2SJohnny Huang }
1526d90825e2SJohnny Huang 
1527696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf)
1528696656c6SJohnny Huang {
1529696656c6SJohnny Huang 	sha256_context ctx;
1530696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
1531696656c6SJohnny Huang 
1532696656c6SJohnny Huang 	sha256_starts(&ctx);
1533696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
1534696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
1535696656c6SJohnny Huang 
1536696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
1537696656c6SJohnny Huang 		return 0;
1538696656c6SJohnny Huang 	else
1539696656c6SJohnny Huang 		return -1;
1540696656c6SJohnny Huang 
1541696656c6SJohnny Huang }
1542696656c6SJohnny Huang 
1543de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm)
154469d5fd8fSJohnny Huang {
154569d5fd8fSJohnny Huang 	int ret;
15469a4fe690SJohnny Huang 	int image_version = 0;
1547696656c6SJohnny Huang 	struct otp_header *otp_header;
1548696656c6SJohnny Huang 	struct otp_image_layout image_layout;
1549696656c6SJohnny Huang 	int image_size;
1550696656c6SJohnny Huang 	uint8_t *buf;
1551696656c6SJohnny Huang 	uint8_t *checksum;
155269d5fd8fSJohnny Huang 
1553696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
1554696656c6SJohnny Huang 	if (!otp_header) {
155569d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
15562a856b9aSJohnny Huang 		return OTP_FAILURE;
155769d5fd8fSJohnny Huang 	}
1558d90825e2SJohnny Huang 
1559696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
1560696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
1561696656c6SJohnny Huang 
1562696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
1563696656c6SJohnny Huang 
1564696656c6SJohnny Huang 	if (!buf) {
1565696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
1566696656c6SJohnny Huang 		return OTP_FAILURE;
1567696656c6SJohnny Huang 	}
1568696656c6SJohnny Huang 	otp_header = (struct otp_header *) buf;
1569696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
1570696656c6SJohnny Huang 
1571696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
1572696656c6SJohnny Huang 		puts("Image is invalid\n");
1573696656c6SJohnny Huang 		return OTP_FAILURE;
1574696656c6SJohnny Huang 	}
1575696656c6SJohnny Huang 
1576696656c6SJohnny Huang 
15775010032bSJohnny Huang 	image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
15785010032bSJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
15795010032bSJohnny Huang 	image_layout.data_ignore = image_layout.data + image_layout.data_length;
15805010032bSJohnny Huang 
15815010032bSJohnny Huang 	image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
1582696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
15835010032bSJohnny Huang 	image_layout.conf_ignore = image_layout.conf + image_layout.conf_length;
1584696656c6SJohnny Huang 
1585696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
1586696656c6SJohnny Huang 
1587696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
1588696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
15895010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
15905010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + image_layout.strap_length;
15915010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length;
1592696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
1593696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
15945010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
15955010032bSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
15965010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
15975010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
15985fdde29fSJohnny Huang 	} else if (!strcmp("A2", (char *)otp_header->otp_version)) {
15995fdde29fSJohnny Huang 		image_version = OTP_AST2600A2;
16005fdde29fSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
16015fdde29fSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
16025fdde29fSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
16035fdde29fSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
1604696656c6SJohnny Huang 	} else {
1605696656c6SJohnny Huang 		puts("Version is not supported\n");
1606696656c6SJohnny Huang 		return OTP_FAILURE;
1607696656c6SJohnny Huang 	}
1608696656c6SJohnny Huang 
16099a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
16109a4fe690SJohnny Huang 		puts("Version is not match\n");
16119a4fe690SJohnny Huang 		return OTP_FAILURE;
16129a4fe690SJohnny Huang 	}
16139a4fe690SJohnny Huang 
1614696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
1615696656c6SJohnny Huang 		puts("checksum is invalid\n");
1616696656c6SJohnny Huang 		return OTP_FAILURE;
1617d90825e2SJohnny Huang 	}
16187332532cSJohnny Huang 
161969d5fd8fSJohnny Huang 	if (!nconfirm) {
1620696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
16217f795e57SJohnny Huang 			printf("\nOTP data region :\n");
1622696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
162369d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16242a856b9aSJohnny Huang 				return OTP_FAILURE;
162569d5fd8fSJohnny Huang 			}
162669d5fd8fSJohnny Huang 		}
1627696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
16287332532cSJohnny Huang 			printf("\nOTP strap region :\n");
16295010032bSJohnny Huang 			if (otp_print_strap_image(&image_layout) < 0) {
16307332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
16317332532cSJohnny Huang 				return OTP_FAILURE;
16327332532cSJohnny Huang 			}
16337332532cSJohnny Huang 		}
1634696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
16357332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
1636696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
16377332532cSJohnny Huang 				printf("OTP config error, please check.\n");
16387332532cSJohnny Huang 				return OTP_FAILURE;
16397332532cSJohnny Huang 			}
16407332532cSJohnny Huang 		}
16417332532cSJohnny Huang 
164269d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
164369d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
164469d5fd8fSJohnny Huang 			printf(" Aborting\n");
16452a856b9aSJohnny Huang 			return OTP_FAILURE;
164669d5fd8fSJohnny Huang 		}
164769d5fd8fSJohnny Huang 	}
16487332532cSJohnny Huang 
16495010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_DATA) {
16505010032bSJohnny Huang 		printf("programing data region ...\n");
16515010032bSJohnny Huang 		ret = otp_prog_data(&image_layout);
16525010032bSJohnny Huang 		if (ret != 0) {
16535010032bSJohnny Huang 			printf("Error\n");
16545010032bSJohnny Huang 			return ret;
16555010032bSJohnny Huang 		} else {
16565010032bSJohnny Huang 			printf("Done\n");
16575010032bSJohnny Huang 		}
16585010032bSJohnny Huang 	}
16595010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_STRAP) {
16605010032bSJohnny Huang 		printf("programing strap region ...\n");
16615010032bSJohnny Huang 		ret = otp_prog_strap(&image_layout);
16625010032bSJohnny Huang 		if (ret != 0) {
16635010032bSJohnny Huang 			printf("Error\n");
16645010032bSJohnny Huang 			return ret;
16655010032bSJohnny Huang 		} else {
16665010032bSJohnny Huang 			printf("Done\n");
16675010032bSJohnny Huang 		}
16685010032bSJohnny Huang 	}
16695010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_CONFIG) {
16705010032bSJohnny Huang 		printf("programing configuration region ...\n");
16715010032bSJohnny Huang 		ret = otp_prog_conf(&image_layout);
16725010032bSJohnny Huang 		if (ret != 0) {
16735010032bSJohnny Huang 			printf("Error\n");
16745010032bSJohnny Huang 			return ret;
16755010032bSJohnny Huang 		}
16765010032bSJohnny Huang 		printf("Done\n");
16775010032bSJohnny Huang 	}
1678cd1610b4SJohnny Huang 
16797332532cSJohnny Huang 	return OTP_SUCCESS;
16802a856b9aSJohnny Huang }
16812a856b9aSJohnny Huang 
16822a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1683cd1610b4SJohnny Huang {
1684a6af4a17SJohnny Huang 	uint32_t read[2];
1685d90825e2SJohnny Huang 	uint32_t prog_address = 0;
168666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1687cd1610b4SJohnny Huang 	int otp_bit;
168883655e91SJohnny Huang 	int ret = 0;
1689cd1610b4SJohnny Huang 
1690dacbba92SJohnny Huang 	otp_soak(0);
1691cd1610b4SJohnny Huang 	switch (mode) {
1692a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1693a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1694cd1610b4SJohnny Huang 		prog_address = 0x800;
1695cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1696cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1697a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1698cd1610b4SJohnny Huang 		if (otp_bit == value) {
1699a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1700cd1610b4SJohnny Huang 			printf("No need to program\n");
17012a856b9aSJohnny Huang 			return OTP_SUCCESS;
1702cd1610b4SJohnny Huang 		}
1703cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1704a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1705cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
17062a856b9aSJohnny Huang 			return OTP_FAILURE;
1707cd1610b4SJohnny Huang 		}
1708a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1709cd1610b4SJohnny Huang 		break;
1710a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1711cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1712cd1610b4SJohnny Huang 
1713cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1714a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1715a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1716643b9cfdSJohnny Huang 
1717643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1718643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1719643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1720643b9cfdSJohnny Huang 				return OTP_FAILURE;
1721643b9cfdSJohnny Huang 			}
1722cd1610b4SJohnny Huang 		} else {
1723a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1724a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1725643b9cfdSJohnny Huang 
1726643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1727643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1728643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1729643b9cfdSJohnny Huang 				return OTP_FAILURE;
1730643b9cfdSJohnny Huang 			}
1731cd1610b4SJohnny Huang 		}
1732cd1610b4SJohnny Huang 		if (otp_bit == value) {
1733a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1734cd1610b4SJohnny Huang 			printf("No need to program\n");
17352a856b9aSJohnny Huang 			return OTP_SUCCESS;
1736cd1610b4SJohnny Huang 		}
1737643b9cfdSJohnny Huang 
1738a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1739cd1610b4SJohnny Huang 		break;
1740a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
17418848d5dcSJohnny Huang 		otp_strap_status(otpstrap);
17428848d5dcSJohnny Huang 		otp_print_strap(bit_offset, 1);
17438848d5dcSJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
17448848d5dcSJohnny Huang 		if (ret == OTP_FAILURE)
17458848d5dcSJohnny Huang 			return OTP_FAILURE;
17468848d5dcSJohnny Huang 		else if (ret == OTP_PROG_SKIP)
17478848d5dcSJohnny Huang 			return OTP_SUCCESS;
1748a6af4a17SJohnny Huang 
1749cd1610b4SJohnny Huang 		break;
1750cd1610b4SJohnny Huang 	}
1751cd1610b4SJohnny Huang 
1752cd1610b4SJohnny Huang 	if (!nconfirm) {
1753cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1754cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1755cd1610b4SJohnny Huang 			printf(" Aborting\n");
17562a856b9aSJohnny Huang 			return OTP_FAILURE;
1757cd1610b4SJohnny Huang 		}
1758cd1610b4SJohnny Huang 	}
1759cd1610b4SJohnny Huang 
1760cd1610b4SJohnny Huang 	switch (mode) {
1761a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
176283655e91SJohnny Huang 		ret =  otp_prog_strap_bit(bit_offset, value);
176383655e91SJohnny Huang 		break;
1764a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1765a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
176683655e91SJohnny Huang 		ret = otp_prog_bit(value, prog_address, bit_offset);
1767de6fbf1cSJohnny Huang 		break;
1768de6fbf1cSJohnny Huang 	}
1769de6fbf1cSJohnny Huang 	otp_soak(0);
177083655e91SJohnny Huang 	if (ret) {
17719009c25dSJohnny Huang 		printf("SUCCESS\n");
17722a856b9aSJohnny Huang 		return OTP_SUCCESS;
17739009c25dSJohnny Huang 	} else {
17749009c25dSJohnny Huang 		printf("OTP cannot be programed\n");
17759009c25dSJohnny Huang 		printf("FAILED\n");
17769009c25dSJohnny Huang 		return OTP_FAILURE;
17779009c25dSJohnny Huang 	}
1778cd1610b4SJohnny Huang 
17792a856b9aSJohnny Huang 	return OTP_USAGE;
1780cd1610b4SJohnny Huang }
1781cd1610b4SJohnny Huang 
17822a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
178369d5fd8fSJohnny Huang {
17842a856b9aSJohnny Huang 	uint32_t offset, count;
17852a856b9aSJohnny Huang 	int ret;
178669d5fd8fSJohnny Huang 
17872a856b9aSJohnny Huang 	if (argc == 4) {
17882a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17892a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
17902a856b9aSJohnny Huang 	} else if (argc == 3) {
17912a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
17922a856b9aSJohnny Huang 		count = 1;
17932a856b9aSJohnny Huang 	} else {
179469d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
179569d5fd8fSJohnny Huang 	}
179669d5fd8fSJohnny Huang 
179769d5fd8fSJohnny Huang 
17982a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
17993d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18002a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
18012a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
18023d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18032a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
18042a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
18053d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
18062a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
18072a856b9aSJohnny Huang 	} else {
18082a856b9aSJohnny Huang 		return CMD_RET_USAGE;
180969d5fd8fSJohnny Huang 	}
181069d5fd8fSJohnny Huang 
18112a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18122a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18132a856b9aSJohnny Huang 	else
18142a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18152a856b9aSJohnny Huang 
18162a856b9aSJohnny Huang }
18172a856b9aSJohnny Huang 
18182a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18192a856b9aSJohnny Huang {
18202a856b9aSJohnny Huang 	phys_addr_t addr;
18212a856b9aSJohnny Huang 	int ret;
18222a856b9aSJohnny Huang 
1823de6b0cc4SJohnny Huang 	if (argc == 3) {
1824ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
18252a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18262a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
18273d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1828de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 1);
1829de6b0cc4SJohnny Huang 	} else if (argc == 2) {
18302a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
18313d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1832de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 0);
18332a856b9aSJohnny Huang 	} else {
18342a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18352a856b9aSJohnny Huang 	}
18362a856b9aSJohnny Huang 
18372a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18382a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18392a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
18402a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
18412a856b9aSJohnny Huang 	else
18422a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18432a856b9aSJohnny Huang }
18442a856b9aSJohnny Huang 
18452a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18462a856b9aSJohnny Huang {
18472a856b9aSJohnny Huang 	int mode = 0;
18482a856b9aSJohnny Huang 	int nconfirm = 0;
18492a856b9aSJohnny Huang 	int otp_addr = 0;
18502a856b9aSJohnny Huang 	int bit_offset;
18512a856b9aSJohnny Huang 	int value;
18522a856b9aSJohnny Huang 	int ret;
18532a856b9aSJohnny Huang 
18542a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
18552a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18562a856b9aSJohnny Huang 
18572a856b9aSJohnny Huang 	/* Drop the pb cmd */
18582a856b9aSJohnny Huang 	argc--;
18592a856b9aSJohnny Huang 	argv++;
18602a856b9aSJohnny Huang 
18612a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1862a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
18632a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1864a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
18652a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1866a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1867cd1610b4SJohnny Huang 	else
18682a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18692a856b9aSJohnny Huang 
18702a856b9aSJohnny Huang 	/* Drop the region cmd */
18712a856b9aSJohnny Huang 	argc--;
18722a856b9aSJohnny Huang 	argv++;
18732a856b9aSJohnny Huang 
1874ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
1875cd1610b4SJohnny Huang 		nconfirm = 1;
18762a856b9aSJohnny Huang 		/* Drop the force option */
18772a856b9aSJohnny Huang 		argc--;
18782a856b9aSJohnny Huang 		argv++;
18792a856b9aSJohnny Huang 	}
1880cd1610b4SJohnny Huang 
1881a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
18822a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
18832a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
18840808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
18852a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1886cd1610b4SJohnny Huang 	} else {
18872a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
18882a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
18892a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
18900808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
18912a856b9aSJohnny Huang 			return CMD_RET_USAGE;
18920808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
189378855207SJohnny Huang 			if (otp_addr >= 0x800)
18940808cc55SJohnny Huang 				return CMD_RET_USAGE;
18950808cc55SJohnny Huang 		} else {
189678855207SJohnny Huang 			if (otp_addr >= 0x20)
18970808cc55SJohnny Huang 				return CMD_RET_USAGE;
18980808cc55SJohnny Huang 		}
1899cd1610b4SJohnny Huang 	}
1900cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
19012a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1902cd1610b4SJohnny Huang 
19033d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19042a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
19052a856b9aSJohnny Huang 
19062a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19072a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19082a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
19092a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19102a856b9aSJohnny Huang 	else
19112a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19122a856b9aSJohnny Huang }
19132a856b9aSJohnny Huang 
19142a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19152a856b9aSJohnny Huang {
19162a856b9aSJohnny Huang 	phys_addr_t addr;
19172a856b9aSJohnny Huang 	int otp_addr = 0;
19182a856b9aSJohnny Huang 
19192a856b9aSJohnny Huang 	if (argc != 3)
19202a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19212a856b9aSJohnny Huang 
19223d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19232a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
19242a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
19252a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
192669d5fd8fSJohnny Huang 		printf("Compare pass\n");
19272a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
192869d5fd8fSJohnny Huang 	} else {
192969d5fd8fSJohnny Huang 		printf("Compare fail\n");
19302a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
193169d5fd8fSJohnny Huang 	}
193269d5fd8fSJohnny Huang }
193369d5fd8fSJohnny Huang 
193466f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
193566f2f8e5SJohnny Huang {
1936a8bd6d8cSJohnny Huang 	int view = 0;
19372d4b0742SJohnny Huang 	int input;
1938a8bd6d8cSJohnny Huang 
1939a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
194066f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
194166f2f8e5SJohnny Huang 
19422d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
194366f2f8e5SJohnny Huang 
19443d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19452d4b0742SJohnny Huang 		if (argc == 3) {
19462d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
19472d4b0742SJohnny Huang 			otp_print_conf_info(input);
19482d4b0742SJohnny Huang 		} else {
19492d4b0742SJohnny Huang 			otp_print_conf_info(-1);
19502d4b0742SJohnny Huang 		}
19512d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
19522d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
1953a8bd6d8cSJohnny Huang 			view = 1;
1954a8bd6d8cSJohnny Huang 			/* Drop the view option */
1955a8bd6d8cSJohnny Huang 			argc--;
1956a8bd6d8cSJohnny Huang 			argv++;
1957a8bd6d8cSJohnny Huang 		}
19583d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
1959b458cd62SJohnny Huang 		otp_print_strap_info(view);
196066f2f8e5SJohnny Huang 	} else {
196166f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
196266f2f8e5SJohnny Huang 	}
19632d4b0742SJohnny Huang 
196466f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
196566f2f8e5SJohnny Huang }
196666f2f8e5SJohnny Huang 
1967737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1968737ed20bSJohnny Huang {
1969737ed20bSJohnny Huang 	int input;
1970737ed20bSJohnny Huang 	int bit_offset;
1971737ed20bSJohnny Huang 	int prog_address;
197283655e91SJohnny Huang 	int ret;
1973737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1974737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1975737ed20bSJohnny Huang 
1976ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
1977737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1978737ed20bSJohnny Huang 	} else {
1979737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1980737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
1981737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1982737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1983737ed20bSJohnny Huang 			printf(" Aborting\n");
1984737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
1985737ed20bSJohnny Huang 		}
1986737ed20bSJohnny Huang 	}
1987737ed20bSJohnny Huang 
1988737ed20bSJohnny Huang 	prog_address = 0x800;
1989737ed20bSJohnny Huang 	if (input < 32) {
1990737ed20bSJohnny Huang 		bit_offset = input;
1991737ed20bSJohnny Huang 		prog_address |= 0x60c;
1992737ed20bSJohnny Huang 	} else if (input < 64) {
1993737ed20bSJohnny Huang 		bit_offset = input - 32;
1994737ed20bSJohnny Huang 		prog_address |= 0x60e;
1995737ed20bSJohnny Huang 	} else {
1996737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1997737ed20bSJohnny Huang 	}
1998737ed20bSJohnny Huang 
1999737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2000737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2001737ed20bSJohnny Huang 	}
2002de6fbf1cSJohnny Huang 
200383655e91SJohnny Huang 	ret = otp_prog_bit(1, prog_address, bit_offset);
2004de6fbf1cSJohnny Huang 	otp_soak(0);
200583655e91SJohnny Huang 
200683655e91SJohnny Huang 	if (ret) {
2007737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2008737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2009737ed20bSJohnny Huang 	}
2010737ed20bSJohnny Huang 
2011737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2012737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2013737ed20bSJohnny Huang 
2014737ed20bSJohnny Huang }
20159a4fe690SJohnny Huang 
2016f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2017f67375f7SJohnny Huang {
2018f67375f7SJohnny Huang 	printf("OTP tool version: %s\n", OTP_VER);
2019f67375f7SJohnny Huang 	printf("OTP info version: %s\n", OTP_INFO_VER);
2020f67375f7SJohnny Huang 
2021f67375f7SJohnny Huang 	return CMD_RET_SUCCESS;
2022f67375f7SJohnny Huang }
2023f67375f7SJohnny Huang 
20242a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
2025f67375f7SJohnny Huang 	U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""),
20262a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2027a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
2028de6b0cc4SJohnny Huang 	U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""),
20292a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2030737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
20312a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
20322a856b9aSJohnny Huang };
20332a856b9aSJohnny Huang 
20342a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20352a856b9aSJohnny Huang {
20362a856b9aSJohnny Huang 	cmd_tbl_t *cp;
20370dae9d52SJohnny Huang 	uint32_t ver;
20382a856b9aSJohnny Huang 
20392a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
20402a856b9aSJohnny Huang 
2041737ed20bSJohnny Huang 	/* Drop the otp command */
20422a856b9aSJohnny Huang 	argc--;
20432a856b9aSJohnny Huang 	argv++;
20442a856b9aSJohnny Huang 
20452a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
20462a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20472a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
20482a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20492a856b9aSJohnny Huang 
20500dae9d52SJohnny Huang 	ver = chip_version();
20510dae9d52SJohnny Huang 	switch (ver) {
20520dae9d52SJohnny Huang 	case OTP_AST2600A0:
2053696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
20549a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
20559a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
20569a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
20579a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
20589a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
20599a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
20600dae9d52SJohnny Huang 		break;
20610dae9d52SJohnny Huang 	case OTP_AST2600A1:
2062696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
20633cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
20643cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
20653cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
20663cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
20679a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
20689a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
20690dae9d52SJohnny Huang 		break;
20700dae9d52SJohnny Huang 	case OTP_AST2600A2:
20715fdde29fSJohnny Huang 		info_cb.version = OTP_AST2600A2;
20725fdde29fSJohnny Huang 		info_cb.conf_info = a2_conf_info;
20735fdde29fSJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
20745fdde29fSJohnny Huang 		info_cb.strap_info = a2_strap_info;
20755fdde29fSJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
20765fdde29fSJohnny Huang 		info_cb.key_info = a2_key_type;
20775fdde29fSJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a2_key_type);
20780dae9d52SJohnny Huang 		break;
20790dae9d52SJohnny Huang 	default:
2080f1be5099SJohnny Huang 		printf("SOC is not supported\n");
20810dae9d52SJohnny Huang 		return CMD_RET_FAILURE;
20829a4fe690SJohnny Huang 	}
20839a4fe690SJohnny Huang 
20842a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
208569d5fd8fSJohnny Huang }
208669d5fd8fSJohnny Huang 
208769d5fd8fSJohnny Huang U_BOOT_CMD(
208869d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
208969d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
2090f67375f7SJohnny Huang 	"version\n"
2091f67375f7SJohnny Huang 	"otp read conf|data <otp_dw_offset> <dw_count>\n"
20922a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
20932d4b0742SJohnny Huang 	"otp info strap [v]\n"
20942d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2095de6b0cc4SJohnny Huang 	"otp prog [o] <addr>\n"
2096ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2097ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2098ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
20992a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
210069d5fd8fSJohnny Huang );
2101