xref: /openbmc/u-boot/cmd/otp.c (revision e1f9e54e3b75b328753f121b9f857117fdec7a4a)
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  */
1169d5fd8fSJohnny Huang 
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>
1869d5fd8fSJohnny Huang 
1969d5fd8fSJohnny Huang #include <inttypes.h>
2069d5fd8fSJohnny Huang #include <mapmem.h>
2169d5fd8fSJohnny Huang #include <asm/io.h>
2269d5fd8fSJohnny Huang #include <linux/compiler.h>
2369d5fd8fSJohnny Huang 
2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2569d5fd8fSJohnny Huang 
2669d5fd8fSJohnny Huang #define OTP_PASSWD	0x349fe38a
2769d5fd8fSJohnny Huang #define RETRY		3
2869d5fd8fSJohnny Huang #define MODE_CONF	1
2969d5fd8fSJohnny Huang #define MODE_STRAP	2
3069d5fd8fSJohnny Huang #define MODE_DATA	3
3169d5fd8fSJohnny Huang #define MODE_ALL	4
3269d5fd8fSJohnny Huang 
33*e1f9e54eSJohnny Huang #define DISABLE_SECREG_PROG		BIT(0)
34*e1f9e54eSJohnny Huang #define ENABLE_SEC_BOOT			BIT(1)
35*e1f9e54eSJohnny Huang #define INIT_PROG_DONE			BIT(2)
36*e1f9e54eSJohnny Huang #define ENABLE_USERREG_ECC		BIT(3)
37*e1f9e54eSJohnny Huang #define ENABLE_SECREG_ECC		BIT(4)
38*e1f9e54eSJohnny Huang #define DISABLE_LOW_SEC_KEY		BIT(5)
39*e1f9e54eSJohnny Huang #define IGNORE_SEC_BOOT_HWSTRAP		BIT(6)
40*e1f9e54eSJohnny Huang #define SEC_BOOT_MDOES(x)		(x >> 7)
41*e1f9e54eSJohnny Huang #define   SEC_MODE1			0x0
42*e1f9e54eSJohnny Huang #define   SEC_MODE2			0x1
43*e1f9e54eSJohnny Huang #define OTP_BIT_CELL_MODES(x)		((x >> 8) & 0x3)
44*e1f9e54eSJohnny Huang #define   SINGLE_CELL_MODE		0x0
45*e1f9e54eSJohnny Huang #define   DIFFERENTIAL_MODE		0x1
46*e1f9e54eSJohnny Huang #define   DIFFERENTIAL_REDUDANT_MODE	0x2
47*e1f9e54eSJohnny Huang #define CRYPTO_MODES(x)			((x >> 10) & 0x3)
48*e1f9e54eSJohnny Huang #define   CRYPTO_RSA1024		0x0
49*e1f9e54eSJohnny Huang #define   CRYPTO_RSA2048		0x1
50*e1f9e54eSJohnny Huang #define   CRYPTO_RSA3072		0x2
51*e1f9e54eSJohnny Huang #define   CRYPTO_RSA4096		0x3
52*e1f9e54eSJohnny Huang #define HASH_MODES(x)			((x >> 12) & 0x3)
53*e1f9e54eSJohnny Huang #define   HASH_SAH224			0x0
54*e1f9e54eSJohnny Huang #define   HASH_SAH256			0x1
55*e1f9e54eSJohnny Huang #define   HASH_SAH384			0x2
56*e1f9e54eSJohnny Huang #define   HASH_SAH512			0x3
57*e1f9e54eSJohnny Huang #define SECREG_SIZE(x)			((x >> 16) & 0x3f)
58*e1f9e54eSJohnny Huang #define WRITE_PROTECT_SECREG		BIT(22)
59*e1f9e54eSJohnny Huang #define WRITE_PROTECT_USERREG		BIT(23)
60*e1f9e54eSJohnny Huang #define WRITE_PROTECT_CONFREG		BIT(24)
61*e1f9e54eSJohnny Huang #define WRITE_PROTECT_STRAPREG		BIT(25)
62*e1f9e54eSJohnny Huang #define ENABLE_COPY_TO_SRAM		BIT(26)
63*e1f9e54eSJohnny Huang #define ENABLE_IMAGE_ENC		BIT(27)
64*e1f9e54eSJohnny Huang #define WRITE_PROTECT_KEY_RETIRE	BIT(29)
65*e1f9e54eSJohnny Huang #define ENABLE_SIPROM_RED		BIT(30)
66*e1f9e54eSJohnny Huang #define ENABLE_SIPROM_MLOCK		BIT(31)
67*e1f9e54eSJohnny Huang 
68*e1f9e54eSJohnny Huang #define VENDER_ID(x) 			(x & 0xFFFF)
69*e1f9e54eSJohnny Huang #define KEY_REVISION(x)			((x >> 16) & 0xFFFF)
70*e1f9e54eSJohnny Huang 
71*e1f9e54eSJohnny Huang #define SEC_BOOT_HEADER_OFFSET(x)	(x & 0xFFFF)
72*e1f9e54eSJohnny Huang 
73*e1f9e54eSJohnny Huang #define KEYS_VALID_BITS(x)		(x & 0xff)
74*e1f9e54eSJohnny Huang #define KEYS_RETIRE_BITS(x)		((x >> 16) & 0xff)
7569d5fd8fSJohnny Huang struct otpstrap {
7669d5fd8fSJohnny Huang 	int value;
7769d5fd8fSJohnny Huang 	int option_array[7];
7869d5fd8fSJohnny Huang 	int remain_times;
7969d5fd8fSJohnny Huang 	int writeable_option;
8069d5fd8fSJohnny Huang 	int protected;
8169d5fd8fSJohnny Huang };
8269d5fd8fSJohnny Huang 
8369d5fd8fSJohnny Huang static int otp_read_data(uint32_t offset, uint32_t *data)
8469d5fd8fSJohnny Huang {
8569d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
8669d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
8769d5fd8fSJohnny Huang 	udelay(2);
8869d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
8969d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
9069d5fd8fSJohnny Huang 	return 1;
9169d5fd8fSJohnny Huang }
9269d5fd8fSJohnny Huang 
9369d5fd8fSJohnny Huang static int otp_read_config(uint32_t offset, uint32_t *data)
9469d5fd8fSJohnny Huang {
9569d5fd8fSJohnny Huang 	int config_offset;
9669d5fd8fSJohnny Huang 
9769d5fd8fSJohnny Huang 	config_offset = 0x800;
9869d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
9969d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
10069d5fd8fSJohnny Huang 
10169d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
10269d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
10369d5fd8fSJohnny Huang 	udelay(2);
10469d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
10569d5fd8fSJohnny Huang 
10669d5fd8fSJohnny Huang 	return 1;
10769d5fd8fSJohnny Huang }
10869d5fd8fSJohnny Huang 
10969d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
11069d5fd8fSJohnny Huang {
11169d5fd8fSJohnny Huang 	int i;
11269d5fd8fSJohnny Huang 	uint32_t ret[1];
11369d5fd8fSJohnny Huang 
11469d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
11569d5fd8fSJohnny Huang 		return -1;
11669d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
11769d5fd8fSJohnny Huang 		otp_read_config(i, ret);
11869d5fd8fSJohnny Huang 		printf("OTPCFG%d: %08X\n", i, ret[0]);
11969d5fd8fSJohnny Huang 	}
12069d5fd8fSJohnny Huang 	printf("\n");
12169d5fd8fSJohnny Huang 	return 1;
12269d5fd8fSJohnny Huang }
12369d5fd8fSJohnny Huang 
12469d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
12569d5fd8fSJohnny Huang {
12669d5fd8fSJohnny Huang 	int i;
12769d5fd8fSJohnny Huang 	uint32_t ret[2];
12869d5fd8fSJohnny Huang 
12969d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
13069d5fd8fSJohnny Huang 		return -1;
13169d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
13269d5fd8fSJohnny Huang 		otp_read_data(i, ret);
13369d5fd8fSJohnny Huang 		if (i % 4 == 0)
13469d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
13569d5fd8fSJohnny Huang 		else
13669d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
13769d5fd8fSJohnny Huang 
13869d5fd8fSJohnny Huang 	}
13969d5fd8fSJohnny Huang 	printf("\n");
14069d5fd8fSJohnny Huang 	return 1;
14169d5fd8fSJohnny Huang }
14269d5fd8fSJohnny Huang 
14369d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
14469d5fd8fSJohnny Huang {
14569d5fd8fSJohnny Huang 	uint32_t ret;
14669d5fd8fSJohnny Huang 	uint32_t *buf;
14769d5fd8fSJohnny Huang 
14869d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
14969d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
15069d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
15169d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
15269d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
15369d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
15469d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
15569d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
15669d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
15769d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
15869d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
15969d5fd8fSJohnny Huang 	udelay(10);
16069d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
16169d5fd8fSJohnny Huang 	if (ret & 0x1)
16269d5fd8fSJohnny Huang 		return 0;
16369d5fd8fSJohnny Huang 	else
16469d5fd8fSJohnny Huang 		return -1;
16569d5fd8fSJohnny Huang }
16669d5fd8fSJohnny Huang 
16769d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
16869d5fd8fSJohnny Huang {
16969d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
17069d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
17169d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
17269d5fd8fSJohnny Huang 	udelay(100);
17369d5fd8fSJohnny Huang }
17469d5fd8fSJohnny Huang 
17569d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
17669d5fd8fSJohnny Huang {
17769d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
17869d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
17969d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
18069d5fd8fSJohnny Huang 	udelay(85);
18169d5fd8fSJohnny Huang }
18269d5fd8fSJohnny Huang 
18369d5fd8fSJohnny Huang static int prog_verify(uint32_t otp_addr, int bit_offset, int value)
18469d5fd8fSJohnny Huang {
18569d5fd8fSJohnny Huang 	int ret;
18669d5fd8fSJohnny Huang 
18769d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
18869d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
18969d5fd8fSJohnny Huang 	udelay(2);
19069d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
19169d5fd8fSJohnny Huang 	// printf("prog_verify = %x\n", ret);
19269d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
19369d5fd8fSJohnny Huang 		return 0;
19469d5fd8fSJohnny Huang 	else
19569d5fd8fSJohnny Huang 		return -1;
19669d5fd8fSJohnny Huang }
19769d5fd8fSJohnny Huang 
19869d5fd8fSJohnny Huang static int otp_conf_parse(uint32_t *OTPCFG)
19969d5fd8fSJohnny Huang {
20069d5fd8fSJohnny Huang 	int tmp, i, pass;
20169d5fd8fSJohnny Huang 
20269d5fd8fSJohnny Huang 	printf("OTPCFG0-D[0]\n");
203*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & DISABLE_SECREG_PROG)
20469d5fd8fSJohnny Huang 		printf("  Disable Secure Region programming\n");
20569d5fd8fSJohnny Huang 	else
20669d5fd8fSJohnny Huang 		printf("  Enable Secure Region programming\n");
20769d5fd8fSJohnny Huang 	printf("OTPCFG0-D[1]\n");
208*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_SEC_BOOT)
20969d5fd8fSJohnny Huang 		printf("  Enable Secure Boot\n");
21069d5fd8fSJohnny Huang 	else
21169d5fd8fSJohnny Huang 		printf("  Disable Secure Boot\n");
21269d5fd8fSJohnny Huang 	printf("OTPCFG0-D[3]\n");
213*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_USERREG_ECC)
21469d5fd8fSJohnny Huang 		printf("  User region ECC enable\n");
21569d5fd8fSJohnny Huang 	else
21669d5fd8fSJohnny Huang 		printf("  User region ECC disable\n");
21769d5fd8fSJohnny Huang 	printf("OTPCFG0-D[4]\n");
218*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_SECREG_ECC)
21969d5fd8fSJohnny Huang 		printf("  Secure Region ECC enable\n");
22069d5fd8fSJohnny Huang 	else
22169d5fd8fSJohnny Huang 		printf("  Secure Region ECC disable\n");
22269d5fd8fSJohnny Huang 	printf("OTPCFG0-D[5]\n");
223*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & DISABLE_LOW_SEC_KEY)
22469d5fd8fSJohnny Huang 		printf("  Disable low security key\n");
22569d5fd8fSJohnny Huang 	else
22669d5fd8fSJohnny Huang 		printf("  Enable low security key\n");
22769d5fd8fSJohnny Huang 	printf("OTPCFG0-D[6]\n");
228*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & IGNORE_SEC_BOOT_HWSTRAP)
22969d5fd8fSJohnny Huang 		printf("  Ignore Secure Boot hardware strap\n");
23069d5fd8fSJohnny Huang 	else
23169d5fd8fSJohnny Huang 		printf("  Do not ignore Secure Boot hardware strap\n");
23269d5fd8fSJohnny Huang 	printf("OTPCFG0-D[7]\n");
233*e1f9e54eSJohnny Huang 	if (SEC_BOOT_MDOES(OTPCFG[0]) == SEC_MODE1)
234*e1f9e54eSJohnny Huang 		printf("  Secure Boot Mode: 1\n");
235*e1f9e54eSJohnny Huang 	else
236*e1f9e54eSJohnny Huang 		printf("  Secure Boot Mode: 2\n");
23769d5fd8fSJohnny Huang 	printf("OTPCFG0-D[9:8]\n");
23869d5fd8fSJohnny Huang 	printf("  OTP bit cell mode : ");
239*e1f9e54eSJohnny Huang 	tmp = OTP_BIT_CELL_MODES(OTPCFG[0]);
240*e1f9e54eSJohnny Huang 	if (tmp == SINGLE_CELL_MODE) {
24169d5fd8fSJohnny Huang 		printf("Single cell mode (recommended)\n");
242*e1f9e54eSJohnny Huang 	} else if (tmp == DIFFERENTIAL_MODE) {
24369d5fd8fSJohnny Huang 		printf("Differnetial mode\n");
244*e1f9e54eSJohnny Huang 	} else if (tmp == DIFFERENTIAL_REDUDANT_MODE) {
24569d5fd8fSJohnny Huang 		printf("Differential-redundant mode\n");
24669d5fd8fSJohnny Huang 	} else {
24769d5fd8fSJohnny Huang 		printf("Value error\n");
24869d5fd8fSJohnny Huang 		return -1;
24969d5fd8fSJohnny Huang 	}
25069d5fd8fSJohnny Huang 	printf("OTPCFG0-D[11:10]\n");
25169d5fd8fSJohnny Huang 	printf("  RSA mode : ");
252*e1f9e54eSJohnny Huang 	tmp = CRYPTO_MODES(OTPCFG[0]);
253*e1f9e54eSJohnny Huang 	if (tmp == CRYPTO_RSA1024) {
25469d5fd8fSJohnny Huang 		printf("RSA1024\n");
255*e1f9e54eSJohnny Huang 	} else if (tmp == CRYPTO_RSA2048) {
25669d5fd8fSJohnny Huang 		printf("RSA2048\n");
257*e1f9e54eSJohnny Huang 	} else if (tmp == CRYPTO_RSA3072) {
25869d5fd8fSJohnny Huang 		printf("RSA3072\n");
25969d5fd8fSJohnny Huang 	} else {
26069d5fd8fSJohnny Huang 		printf("RSA4096\n");
26169d5fd8fSJohnny Huang 	}
26269d5fd8fSJohnny Huang 	printf("OTPCFG0-D[13:12]\n");
26369d5fd8fSJohnny Huang 	printf("  SHA mode : ");
264*e1f9e54eSJohnny Huang 	tmp = HASH_MODES(OTPCFG[0]);
265*e1f9e54eSJohnny Huang 	if (tmp == HASH_SAH224) {
26669d5fd8fSJohnny Huang 		printf("SHA224\n");
267*e1f9e54eSJohnny Huang 	} else if (tmp == HASH_SAH256) {
26869d5fd8fSJohnny Huang 		printf("SHA256\n");
269*e1f9e54eSJohnny Huang 	} else if (tmp == HASH_SAH384) {
27069d5fd8fSJohnny Huang 		printf("SHA384\n");
27169d5fd8fSJohnny Huang 	} else {
27269d5fd8fSJohnny Huang 		printf("SHA512\n");
27369d5fd8fSJohnny Huang 	}
27469d5fd8fSJohnny Huang 
27569d5fd8fSJohnny Huang 	printf("OTPCFG0-D[21:16]\n");
276*e1f9e54eSJohnny Huang 	printf("  Secure Region size (DW): %x\n", SECREG_SIZE(OTPCFG[0]));
27769d5fd8fSJohnny Huang 
27869d5fd8fSJohnny Huang 	printf("OTPCFG0-D[22]\n");
279*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & WRITE_PROTECT_SECREG)
28069d5fd8fSJohnny Huang 		printf("  Secure Region : Write Protect\n");
28169d5fd8fSJohnny Huang 	else
28269d5fd8fSJohnny Huang 		printf("  Secure Region : Writable\n");
28369d5fd8fSJohnny Huang 	printf("OTPCFG0-D[23]\n");
284*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & WRITE_PROTECT_USERREG)
28569d5fd8fSJohnny Huang 		printf("  User Region : Write Protect\n");
28669d5fd8fSJohnny Huang 	else
28769d5fd8fSJohnny Huang 		printf("  User Region : Writable\n");
28869d5fd8fSJohnny Huang 	printf("OTPCFG0-D[24]\n");
289*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & WRITE_PROTECT_CONFREG)
29069d5fd8fSJohnny Huang 		printf("  Configure Region : Write Protect\n");
29169d5fd8fSJohnny Huang 	else
29269d5fd8fSJohnny Huang 		printf("  Configure Region : Writable\n");
29369d5fd8fSJohnny Huang 	printf("OTPCFG0-D[25]\n");
294*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & WRITE_PROTECT_STRAPREG)
29569d5fd8fSJohnny Huang 		printf("  OTP strap Region : Write Protect\n");
29669d5fd8fSJohnny Huang 	else
29769d5fd8fSJohnny Huang 		printf("  OTP strap Region : Writable\n");
29869d5fd8fSJohnny Huang 	printf("OTPCFG0-D[26]\n");
299*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_COPY_TO_SRAM)
30069d5fd8fSJohnny Huang 		printf("  Copy Boot Image to Internal SRAM\n");
30169d5fd8fSJohnny Huang 	else
30269d5fd8fSJohnny Huang 		printf("  Disable Copy Boot Image to Internal SRAM\n");
30369d5fd8fSJohnny Huang 	printf("OTPCFG0-D[27]\n");
304*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_IMAGE_ENC)
30569d5fd8fSJohnny Huang 		printf("  Enable image encryption\n");
30669d5fd8fSJohnny Huang 	else
30769d5fd8fSJohnny Huang 		printf("  Disable image encryption\n");
30869d5fd8fSJohnny Huang 	printf("OTPCFG0-D[29]\n");
309*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & WRITE_PROTECT_KEY_RETIRE)
31069d5fd8fSJohnny Huang 		printf("  OTP key retire Region : Write Protect\n");
31169d5fd8fSJohnny Huang 	else
31269d5fd8fSJohnny Huang 		printf("  OTP key retire Region : Writable\n");
31369d5fd8fSJohnny Huang 	printf("OTPCFG0-D[30]\n");
314*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_SIPROM_RED)
31569d5fd8fSJohnny Huang 		printf("  SIPROM RED_EN redundancy repair enable\n");
31669d5fd8fSJohnny Huang 	else
31769d5fd8fSJohnny Huang 		printf("  SIPROM RED_EN redundancy repair disable\n");
31869d5fd8fSJohnny Huang 	printf("OTPCFG0-D[31]\n");
319*e1f9e54eSJohnny Huang 	if (OTPCFG[0] & ENABLE_SIPROM_MLOCK)
32069d5fd8fSJohnny Huang 		printf("  SIPROM Mlock memory lock enable\n");
32169d5fd8fSJohnny Huang 	else
32269d5fd8fSJohnny Huang 		printf("  SIPROM Mlock memory lock disable\n");
32369d5fd8fSJohnny Huang 
32469d5fd8fSJohnny Huang 	printf("OTPCFG2-D[15:0]\n");
325*e1f9e54eSJohnny Huang 	printf("  Vender ID : %x\n", VENDER_ID(OTPCFG[2]));
32669d5fd8fSJohnny Huang 
32769d5fd8fSJohnny Huang 	printf("OTPCFG2-D[31:16]\n");
328*e1f9e54eSJohnny Huang 	printf("  Key Revision : %x\n", KEY_REVISION(OTPCFG[2]));
32969d5fd8fSJohnny Huang 
33069d5fd8fSJohnny Huang 	printf("OTPCFG3-D[15:0]\n");
331*e1f9e54eSJohnny Huang 	printf("  Secure boot header offset : %x\n",
332*e1f9e54eSJohnny Huang 	       SEC_BOOT_HEADER_OFFSET(OTPCFG[3]));
33369d5fd8fSJohnny Huang 
33469d5fd8fSJohnny Huang 	printf("OTPCFG4-D[7:0]\n");
335*e1f9e54eSJohnny Huang 	tmp = KEYS_VALID_BITS(OTPCFG[4]);
336*e1f9e54eSJohnny Huang 	if (tmp != 0) {
33769d5fd8fSJohnny Huang 		for (i = 0; i < 7; i++) {
33869d5fd8fSJohnny Huang 			if (tmp == (1 << i)) {
339*e1f9e54eSJohnny Huang 				pass = i + 1;
34069d5fd8fSJohnny Huang 			}
34169d5fd8fSJohnny Huang 		}
342*e1f9e54eSJohnny Huang 	} else {
343*e1f9e54eSJohnny Huang 		pass = 0;
344*e1f9e54eSJohnny Huang 	}
345*e1f9e54eSJohnny Huang 	printf("  Keys valid  : %d\n", pass);
34669d5fd8fSJohnny Huang 
34769d5fd8fSJohnny Huang 	printf("OTPCFG4-D[23:16]\n");
348*e1f9e54eSJohnny Huang 	tmp = KEYS_RETIRE_BITS(OTPCFG[4]);
349*e1f9e54eSJohnny Huang 	if (tmp != 0) {
35069d5fd8fSJohnny Huang 		for (i = 0; i < 7; i++) {
35169d5fd8fSJohnny Huang 			if (tmp == (1 << i)) {
352*e1f9e54eSJohnny Huang 				pass = i + 1;
35369d5fd8fSJohnny Huang 			}
35469d5fd8fSJohnny Huang 		}
355*e1f9e54eSJohnny Huang 	} else {
356*e1f9e54eSJohnny Huang 		pass = 0;
35769d5fd8fSJohnny Huang 	}
35869d5fd8fSJohnny Huang 	printf("  Keys Retire ID : %d\n", pass);
35969d5fd8fSJohnny Huang 
36069d5fd8fSJohnny Huang 	printf("OTPCFG5-D[31:0]\n");
36169d5fd8fSJohnny Huang 	printf("  User define data, random number low : %x\n", OTPCFG[5]);
36269d5fd8fSJohnny Huang 
36369d5fd8fSJohnny Huang 	printf("OTPCFG6-D[31:0]\n");
36469d5fd8fSJohnny Huang 	printf("  User define data, random number high : %x\n", OTPCFG[6]);
36569d5fd8fSJohnny Huang 
36669d5fd8fSJohnny Huang 	printf("OTPCFG8-D[31:0]\n");
36769d5fd8fSJohnny Huang 	printf("  Redundancy Repair : %x\n", OTPCFG[8]);
36869d5fd8fSJohnny Huang 
36969d5fd8fSJohnny Huang 	printf("OTPCFG10-D[31:0]\n");
37069d5fd8fSJohnny Huang 	printf("  Manifest ID low : %x\n", OTPCFG[10]);
37169d5fd8fSJohnny Huang 
37269d5fd8fSJohnny Huang 	printf("OTPCFG11-D[31:0]\n");
37369d5fd8fSJohnny Huang 	printf("  Manifest ID high : %x\n", OTPCFG[11]);
37469d5fd8fSJohnny Huang 	return 0;
37569d5fd8fSJohnny Huang 
37669d5fd8fSJohnny Huang }
37769d5fd8fSJohnny Huang 
37869d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
37969d5fd8fSJohnny Huang {
38069d5fd8fSJohnny Huang 	int i;
38169d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
38269d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
38369d5fd8fSJohnny Huang 		if (i % 16 == 0) {
38469d5fd8fSJohnny Huang 			printf("%04X: ", i);
38569d5fd8fSJohnny Huang 		}
38669d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
38769d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
38869d5fd8fSJohnny Huang 			printf("\n");
38969d5fd8fSJohnny Huang 		}
39069d5fd8fSJohnny Huang 	}
39169d5fd8fSJohnny Huang }
39269d5fd8fSJohnny Huang 
39369d5fd8fSJohnny Huang static int otp_data_parse(uint32_t *buf, int dw_count)
39469d5fd8fSJohnny Huang {
39569d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
39669d5fd8fSJohnny Huang 	char *byte_buf;
39769d5fd8fSJohnny Huang 	int i = 0, len = 0;
39869d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
39969d5fd8fSJohnny Huang 	while (1) {
40069d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
40169d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
40269d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
40369d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
40469d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
40569d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
40669d5fd8fSJohnny Huang 		printf("Key[%d]:\n", i);
40769d5fd8fSJohnny Huang 		printf("Key Type: ");
40869d5fd8fSJohnny Huang 		switch (key_type) {
40969d5fd8fSJohnny Huang 		case 0:
41069d5fd8fSJohnny Huang 			printf("AES-256 as OEM platform key for image encryption/decryption\n");
41169d5fd8fSJohnny Huang 			break;
41269d5fd8fSJohnny Huang 		case 1:
41369d5fd8fSJohnny Huang 			printf("AES-256 as secret vault key\n");
41469d5fd8fSJohnny Huang 			break;
41569d5fd8fSJohnny Huang 		case 4:
41669d5fd8fSJohnny Huang 			printf("HMAC as encrypted OEM HMAC keys in Mode 1\n");
41769d5fd8fSJohnny Huang 			break;
41869d5fd8fSJohnny Huang 		case 8:
41969d5fd8fSJohnny Huang 			printf("RSA-public as OEM DSS public keys in Mode 2\n");
42069d5fd8fSJohnny Huang 			break;
42169d5fd8fSJohnny Huang 		case 9:
42269d5fd8fSJohnny Huang 			printf("RSA-public as SOC public key\n");
42369d5fd8fSJohnny Huang 			break;
42469d5fd8fSJohnny Huang 		case 10:
42569d5fd8fSJohnny Huang 			printf("RSA-public as AES key decryption key\n");
42669d5fd8fSJohnny Huang 			break;
42769d5fd8fSJohnny Huang 		case 13:
42869d5fd8fSJohnny Huang 			printf("RSA-private as SOC private key\n");
42969d5fd8fSJohnny Huang 			break;
43069d5fd8fSJohnny Huang 		case 14:
43169d5fd8fSJohnny Huang 			printf("RSA-private as AES key decryption key\n");
43269d5fd8fSJohnny Huang 			break;
43369d5fd8fSJohnny Huang 		default:
43469d5fd8fSJohnny Huang 			printf("key_type error: %x\n", key_type);
43569d5fd8fSJohnny Huang 			return -1;
43669d5fd8fSJohnny Huang 		}
43769d5fd8fSJohnny Huang 		if (key_type == 4) {
43869d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
43969d5fd8fSJohnny Huang 			switch (key_length) {
44069d5fd8fSJohnny Huang 			case 0:
44169d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
44269d5fd8fSJohnny Huang 				break;
44369d5fd8fSJohnny Huang 			case 1:
44469d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
44569d5fd8fSJohnny Huang 				break;
44669d5fd8fSJohnny Huang 			case 2:
44769d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
44869d5fd8fSJohnny Huang 				break;
44969d5fd8fSJohnny Huang 			case 3:
45069d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
45169d5fd8fSJohnny Huang 				break;
45269d5fd8fSJohnny Huang 			}
45369d5fd8fSJohnny Huang 		} else if (key_type != 0 || key_type != 1) {
45469d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
45569d5fd8fSJohnny Huang 			switch (key_length) {
45669d5fd8fSJohnny Huang 			case 0:
45769d5fd8fSJohnny Huang 				printf("RSA1024\n");
45869d5fd8fSJohnny Huang 				len = 0x100;
45969d5fd8fSJohnny Huang 				break;
46069d5fd8fSJohnny Huang 			case 1:
46169d5fd8fSJohnny Huang 				printf("RSA2048\n");
46269d5fd8fSJohnny Huang 				len = 0x200;
46369d5fd8fSJohnny Huang 				break;
46469d5fd8fSJohnny Huang 			case 2:
46569d5fd8fSJohnny Huang 				printf("RSA3072\n");
46669d5fd8fSJohnny Huang 				len = 0x300;
46769d5fd8fSJohnny Huang 				break;
46869d5fd8fSJohnny Huang 			case 3:
46969d5fd8fSJohnny Huang 				printf("RSA4096\n");
47069d5fd8fSJohnny Huang 				len = 0x400;
47169d5fd8fSJohnny Huang 				break;
47269d5fd8fSJohnny Huang 			}
47369d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
47469d5fd8fSJohnny Huang 		}
47569d5fd8fSJohnny Huang 		if (key_type == 4 || key_type == 8)
47669d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
47769d5fd8fSJohnny Huang 		printf("Key Value:\n");
47869d5fd8fSJohnny Huang 		if (key_type == 4) {
47969d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
48069d5fd8fSJohnny Huang 		} else if (key_type == 0 || key_type == 1) {
48169d5fd8fSJohnny Huang 			printf("AES Key:\n");
48269d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
48369d5fd8fSJohnny Huang 			printf("AES IV:\n");
48469d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + 0x20], 0x10);
48569d5fd8fSJohnny Huang 
48669d5fd8fSJohnny Huang 		} else {
48769d5fd8fSJohnny Huang 			printf("RSA mod:\n");
48869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
48969d5fd8fSJohnny Huang 			printf("RSA exp:\n");
49069d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
49169d5fd8fSJohnny Huang 		}
49269d5fd8fSJohnny Huang 		if (last)
49369d5fd8fSJohnny Huang 			break;
49469d5fd8fSJohnny Huang 		i++;
49569d5fd8fSJohnny Huang 	}
49669d5fd8fSJohnny Huang 	return 0;
49769d5fd8fSJohnny Huang }
49869d5fd8fSJohnny Huang 
49969d5fd8fSJohnny Huang static int otp_prog_conf(uint32_t *buf, int otp_addr, int dw_count)
50069d5fd8fSJohnny Huang {
50169d5fd8fSJohnny Huang 	int i, j, k, bit_value;
50269d5fd8fSJohnny Huang 	int pass, soak;
50369d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
50469d5fd8fSJohnny Huang 
50569d5fd8fSJohnny Huang 	for (i = 0; i < dw_count; i++) {
50669d5fd8fSJohnny Huang 		prog_address = 0x800;
50769d5fd8fSJohnny Huang 		prog_address |= ((i + otp_addr) / 8) * 0x200;
50869d5fd8fSJohnny Huang 		prog_address |= ((i + otp_addr) % 8) * 0x2;
50969d5fd8fSJohnny Huang 		for (j = 0; j < 32; j++) {
51069d5fd8fSJohnny Huang 			bit_value = (buf[i] >> j) & 0x1;
51169d5fd8fSJohnny Huang 			if (bit_value)
51269d5fd8fSJohnny Huang 				prog_bit = ~(0x1 << j);
51369d5fd8fSJohnny Huang 			else
51469d5fd8fSJohnny Huang 				continue;
51569d5fd8fSJohnny Huang 			pass = 0;
51669d5fd8fSJohnny Huang 			soak = 0;
5174b65a65dSJohnny Huang 			otp_write(0x3000, 0x4061); // Write MRA
5184b65a65dSJohnny Huang 			otp_write(0x5000, 0x302f); // Write MRB
5194b65a65dSJohnny Huang 			otp_write(0x1000, 0x4020); // Write MR
5204b65a65dSJohnny Huang 			writel(0x04190760, 0x1e602008); //normal program
52169d5fd8fSJohnny Huang 			for (k = 0; k < RETRY; k++) {
52269d5fd8fSJohnny Huang 				if (!soak) {
52369d5fd8fSJohnny Huang 					otp_prog(prog_address, prog_bit);
52469d5fd8fSJohnny Huang 					if (prog_verify(prog_address, j, bit_value) == 0) {
52569d5fd8fSJohnny Huang 						pass = 1;
52669d5fd8fSJohnny Huang 						break;
52769d5fd8fSJohnny Huang 					}
52869d5fd8fSJohnny Huang 					soak = 1;
5294b65a65dSJohnny Huang 					otp_write(0x3000, 0x4021); // Write MRA
5304b65a65dSJohnny Huang 					otp_write(0x5000, 0x1027); // Write MRB
5314b65a65dSJohnny Huang 					otp_write(0x1000, 0x4820); // Write MR
53269d5fd8fSJohnny Huang 					writel(0x041930d4, 0x1e602008); //soak program
5334b65a65dSJohnny Huang 				}
53469d5fd8fSJohnny Huang 				otp_prog(prog_address, prog_bit);
53569d5fd8fSJohnny Huang 				if (prog_verify(prog_address, j, bit_value) == 0) {
53669d5fd8fSJohnny Huang 					pass = 1;
53769d5fd8fSJohnny Huang 					break;
53869d5fd8fSJohnny Huang 				}
53969d5fd8fSJohnny Huang 			}
54069d5fd8fSJohnny Huang 			if (!pass)
54169d5fd8fSJohnny Huang 				return -1;
54269d5fd8fSJohnny Huang 		}
54369d5fd8fSJohnny Huang 	}
54469d5fd8fSJohnny Huang 	return 0;
54569d5fd8fSJohnny Huang }
54669d5fd8fSJohnny Huang 
54769d5fd8fSJohnny Huang static void otp_strp_status(struct otpstrap *otpstrap)
54869d5fd8fSJohnny Huang {
54969d5fd8fSJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
55069d5fd8fSJohnny Huang 	int i, j;
55169d5fd8fSJohnny Huang 
55269d5fd8fSJohnny Huang 	for (j = 0; j < 64; j++) {
55369d5fd8fSJohnny Huang 		otpstrap[j].value = 0;
55469d5fd8fSJohnny Huang 		otpstrap[j].remain_times = 7;
55569d5fd8fSJohnny Huang 		otpstrap[j].writeable_option = -1;
55669d5fd8fSJohnny Huang 		otpstrap[j].protected = 0;
55769d5fd8fSJohnny Huang 	}
55869d5fd8fSJohnny Huang 
55969d5fd8fSJohnny Huang 	for (i = 16; i < 30; i += 2) {
56069d5fd8fSJohnny Huang 		int option = (i - 16) / 2;
56169d5fd8fSJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
56269d5fd8fSJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
56369d5fd8fSJohnny Huang 		for (j = 0; j < 32; j++) {
56469d5fd8fSJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
56569d5fd8fSJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
56669d5fd8fSJohnny Huang 				otpstrap[j].writeable_option = option;
56769d5fd8fSJohnny Huang 			}
56869d5fd8fSJohnny Huang 			if (bit_value == 1)
56969d5fd8fSJohnny Huang 				otpstrap[j].remain_times --;
57069d5fd8fSJohnny Huang 			otpstrap[j].value ^= bit_value;
57169d5fd8fSJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
57269d5fd8fSJohnny Huang 		}
57369d5fd8fSJohnny Huang 		for (j = 32; j < 64; j++) {
57469d5fd8fSJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
57569d5fd8fSJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
57669d5fd8fSJohnny Huang 				otpstrap[j].writeable_option = option;
57769d5fd8fSJohnny Huang 			}
57869d5fd8fSJohnny Huang 			if (bit_value == 1)
57969d5fd8fSJohnny Huang 				otpstrap[j].remain_times --;
58069d5fd8fSJohnny Huang 			otpstrap[j].value ^= bit_value;
58169d5fd8fSJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
58269d5fd8fSJohnny Huang 		}
58369d5fd8fSJohnny Huang 	}
58469d5fd8fSJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
58569d5fd8fSJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
58669d5fd8fSJohnny Huang 	for (j = 0; j < 32; j++) {
58769d5fd8fSJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
58869d5fd8fSJohnny Huang 			otpstrap[j].protected = 1;
58969d5fd8fSJohnny Huang 	}
59069d5fd8fSJohnny Huang 	for (j = 32; j < 64; j++) {
59169d5fd8fSJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
59269d5fd8fSJohnny Huang 			otpstrap[j].protected = 1;
59369d5fd8fSJohnny Huang 	}
59469d5fd8fSJohnny Huang }
59569d5fd8fSJohnny Huang 
59669d5fd8fSJohnny Huang static int otp_strap_parse(uint32_t *buf)
59769d5fd8fSJohnny Huang {
59869d5fd8fSJohnny Huang 	int i;
59969d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
60069d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
60169d5fd8fSJohnny Huang 	int bit, pbit, kbit;
60269d5fd8fSJohnny Huang 	int fail = 0;
60369d5fd8fSJohnny Huang 	struct otpstrap otpstrap[64];
60469d5fd8fSJohnny Huang 
60569d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
60669d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
60769d5fd8fSJohnny Huang 		if (i < 32) {
60869d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
60969d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
61069d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
61169d5fd8fSJohnny Huang 		} else {
61269d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
61369d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
61469d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
61569d5fd8fSJohnny Huang 		}
61669d5fd8fSJohnny Huang 
61769d5fd8fSJohnny Huang 		if (kbit == 1) {
61869d5fd8fSJohnny Huang 			continue;
61969d5fd8fSJohnny Huang 		} else {
62069d5fd8fSJohnny Huang 			printf("OTPSTRAP[%d]:\n", i);
62169d5fd8fSJohnny Huang 		}
62269d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
62369d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
62469d5fd8fSJohnny Huang 			continue;
62569d5fd8fSJohnny Huang 		}
62669d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
62769d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
62869d5fd8fSJohnny Huang 			fail = 1;
62969d5fd8fSJohnny Huang 			continue;
63069d5fd8fSJohnny Huang 		}
63169d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
63269d5fd8fSJohnny Huang 			printf("    This bit is no remaining number of times to write.\n");
63369d5fd8fSJohnny Huang 			fail = 1;
63469d5fd8fSJohnny Huang 			continue;
63569d5fd8fSJohnny Huang 		}
63669d5fd8fSJohnny Huang 		if (pbit == 1) {
63769d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
63869d5fd8fSJohnny Huang 		}
63969d5fd8fSJohnny Huang 		printf("    Write 1 to OTPSTRAP[%d] OPTION[%d], that value becomes frome %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1);
64069d5fd8fSJohnny Huang 	}
64169d5fd8fSJohnny Huang 	if (fail == 1)
64269d5fd8fSJohnny Huang 		return -1;
64369d5fd8fSJohnny Huang 	else
64469d5fd8fSJohnny Huang 		return 0;
64569d5fd8fSJohnny Huang }
64669d5fd8fSJohnny Huang 
64769d5fd8fSJohnny Huang static void otp_print_strap(void)
64869d5fd8fSJohnny Huang {
64969d5fd8fSJohnny Huang 	int i, j;
65069d5fd8fSJohnny Huang 	struct otpstrap otpstrap[64];
65169d5fd8fSJohnny Huang 
65269d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
65369d5fd8fSJohnny Huang 
65469d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
65569d5fd8fSJohnny Huang 		printf("OTPSTRAP[%d]:\n", i);
65669d5fd8fSJohnny Huang 		printf("  OTP Option value: ");
65769d5fd8fSJohnny Huang 		for (j = 1; j <= 7; j++)
65869d5fd8fSJohnny Huang 			printf("[%d]:%d ", j, otpstrap[i].option_array[j - 1]);
65969d5fd8fSJohnny Huang 		printf("\n");
66069d5fd8fSJohnny Huang 		printf("  OTP Value: %d\n", otpstrap[i].value);
66169d5fd8fSJohnny Huang 		printf("  Status:\n");
66269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
66369d5fd8fSJohnny Huang 			printf("    OTPSTRAP[%d] is protected and is not writable\n", i);
66469d5fd8fSJohnny Huang 		} else {
66569d5fd8fSJohnny Huang 			printf("    OTPSTRAP[%d] is not protected ", i);
66669d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
66769d5fd8fSJohnny Huang 				printf("and no remaining number of times to write.\n");
66869d5fd8fSJohnny Huang 			} else {
66969d5fd8fSJohnny Huang 				printf("and still can write %d number of times\n", otpstrap[i].remain_times);
67069d5fd8fSJohnny Huang 			}
67169d5fd8fSJohnny Huang 		}
67269d5fd8fSJohnny Huang 	}
67369d5fd8fSJohnny Huang }
67469d5fd8fSJohnny Huang 
67569d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
67669d5fd8fSJohnny Huang {
67769d5fd8fSJohnny Huang 	int i, j;
67869d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
67969d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
68069d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
68169d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
68269d5fd8fSJohnny Huang 	int fail = 0;
68369d5fd8fSJohnny Huang 	int pass, soak;
68469d5fd8fSJohnny Huang 	struct otpstrap otpstrap[64];
68569d5fd8fSJohnny Huang 
68669d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
68769d5fd8fSJohnny Huang 
68869d5fd8fSJohnny Huang 	otp_write(0x3000, 0x4061); // Write MRA
68969d5fd8fSJohnny Huang 	otp_write(0x5000, 0x302f); // Write MRB
69069d5fd8fSJohnny Huang 	otp_write(0x1000, 0x4020); // Write MR
69169d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
69269d5fd8fSJohnny Huang 		prog_address = 0x800;
69369d5fd8fSJohnny Huang 		if (i < 32) {
69469d5fd8fSJohnny Huang 			offset = i;
69569d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
69669d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
69769d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
69869d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
69969d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
70069d5fd8fSJohnny Huang 
70169d5fd8fSJohnny Huang 		} else {
70269d5fd8fSJohnny Huang 			offset = (i - 32);
70369d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
70469d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
70569d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
70669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
70769d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
70869d5fd8fSJohnny Huang 		}
70969d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
71069d5fd8fSJohnny Huang 
71169d5fd8fSJohnny Huang 		if (kbit == 1) {
71269d5fd8fSJohnny Huang 			continue;
71369d5fd8fSJohnny Huang 		}
71469d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
71569d5fd8fSJohnny Huang 			continue;
71669d5fd8fSJohnny Huang 		}
71769d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
71869d5fd8fSJohnny Huang 			fail = 1;
71969d5fd8fSJohnny Huang 			continue;
72069d5fd8fSJohnny Huang 		}
72169d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
72269d5fd8fSJohnny Huang 			fail = 1;
72369d5fd8fSJohnny Huang 			continue;
72469d5fd8fSJohnny Huang 		}
72569d5fd8fSJohnny Huang 		pass = 0;
72669d5fd8fSJohnny Huang 		soak = 0;
7274b65a65dSJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
7284b65a65dSJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
7294b65a65dSJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
7304b65a65dSJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
73169d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
73269d5fd8fSJohnny Huang 			if (!soak) {
73369d5fd8fSJohnny Huang 				otp_prog(prog_address, prog_bit);
73469d5fd8fSJohnny Huang 				if (prog_verify(prog_address, offset, 1) == 0) {
73569d5fd8fSJohnny Huang 					pass = 1;
73669d5fd8fSJohnny Huang 					break;
73769d5fd8fSJohnny Huang 				}
73869d5fd8fSJohnny Huang 				soak = 1;
7394b65a65dSJohnny Huang 				otp_write(0x3000, 0x4021); // Write MRA
7404b65a65dSJohnny Huang 				otp_write(0x5000, 0x1027); // Write MRB
7414b65a65dSJohnny Huang 				otp_write(0x1000, 0x4820); // Write MR
74269d5fd8fSJohnny Huang 				writel(0x041930d4, 0x1e602008); //soak program
7434b65a65dSJohnny Huang 			}
74469d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
74569d5fd8fSJohnny Huang 			if (prog_verify(prog_address, offset, 1) == 0) {
74669d5fd8fSJohnny Huang 				pass = 1;
74769d5fd8fSJohnny Huang 				break;
74869d5fd8fSJohnny Huang 			}
74969d5fd8fSJohnny Huang 		}
75069d5fd8fSJohnny Huang 		if (!pass)
75169d5fd8fSJohnny Huang 			return -1;
75269d5fd8fSJohnny Huang 
75369d5fd8fSJohnny Huang 		if (pbit == 0)
75469d5fd8fSJohnny Huang 			continue;
75569d5fd8fSJohnny Huang 		prog_address = 0x800;
75669d5fd8fSJohnny Huang 		if (i < 32)
75769d5fd8fSJohnny Huang 			prog_address |= 0x60c;
75869d5fd8fSJohnny Huang 		else
75969d5fd8fSJohnny Huang 			prog_address |= 0x60e;
76069d5fd8fSJohnny Huang 
76169d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
76269d5fd8fSJohnny Huang 			if (!soak) {
76369d5fd8fSJohnny Huang 				writel(0x04190760, 0x1e602008); //normal program
76469d5fd8fSJohnny Huang 				otp_prog(prog_address, prog_bit);
76569d5fd8fSJohnny Huang 				if (prog_verify(prog_address, offset, 1) == 0) {
76669d5fd8fSJohnny Huang 					pass = 1;
76769d5fd8fSJohnny Huang 					break;
76869d5fd8fSJohnny Huang 				}
76969d5fd8fSJohnny Huang 				soak = 1;
77069d5fd8fSJohnny Huang 			}
77169d5fd8fSJohnny Huang 			writel(0x041930d4, 0x1e602008); //soak program
77269d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
77369d5fd8fSJohnny Huang 			if (prog_verify(prog_address, offset, 1) == 0) {
77469d5fd8fSJohnny Huang 				pass = 1;
77569d5fd8fSJohnny Huang 				break;
77669d5fd8fSJohnny Huang 			}
77769d5fd8fSJohnny Huang 		}
77869d5fd8fSJohnny Huang 		if (!pass)
77969d5fd8fSJohnny Huang 			return -1;
78069d5fd8fSJohnny Huang 
78169d5fd8fSJohnny Huang 	}
78269d5fd8fSJohnny Huang 	if (fail == 1)
78369d5fd8fSJohnny Huang 		return -1;
78469d5fd8fSJohnny Huang 	else
78569d5fd8fSJohnny Huang 		return 0;
78669d5fd8fSJohnny Huang 
78769d5fd8fSJohnny Huang }
78869d5fd8fSJohnny Huang 
78969d5fd8fSJohnny Huang static int otp_prog_data(uint32_t *buf, int otp_addr, int dw_count)
79069d5fd8fSJohnny Huang {
79169d5fd8fSJohnny Huang 	int i, j, k, bit_value;
79269d5fd8fSJohnny Huang 	int pass, soak;
79369d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
79469d5fd8fSJohnny Huang 
79569d5fd8fSJohnny Huang 	for (i = 0; i < dw_count; i++) {
79669d5fd8fSJohnny Huang 		prog_address = i + otp_addr;
79769d5fd8fSJohnny Huang 		for (j = 0; j < 32; j++) {
79869d5fd8fSJohnny Huang 			bit_value = (buf[i] >> j) & 0x1;
79969d5fd8fSJohnny Huang 			if (prog_address % 2 == 0) {
80069d5fd8fSJohnny Huang 				prog_address |= 1 << 15;
80169d5fd8fSJohnny Huang 				if (bit_value)
80269d5fd8fSJohnny Huang 					prog_bit = ~(0x1 << j);
80369d5fd8fSJohnny Huang 				else
80469d5fd8fSJohnny Huang 					continue;
80569d5fd8fSJohnny Huang 			} else {
80669d5fd8fSJohnny Huang 				prog_address |= 1 << 15;
80769d5fd8fSJohnny Huang 				// printf("bit_value = %x\n", bit_value);
80869d5fd8fSJohnny Huang 				if (bit_value)
80969d5fd8fSJohnny Huang 					continue;
81069d5fd8fSJohnny Huang 				else
81169d5fd8fSJohnny Huang 					prog_bit = 0x1 << j;
81269d5fd8fSJohnny Huang 			}
81369d5fd8fSJohnny Huang 			pass = 0;
81469d5fd8fSJohnny Huang 			soak = 0;
8154b65a65dSJohnny Huang 			otp_write(0x3000, 0x4061); // Write MRA
8164b65a65dSJohnny Huang 			otp_write(0x5000, 0x302f); // Write MRB
8174b65a65dSJohnny Huang 			otp_write(0x1000, 0x4020); // Write MR
8184b65a65dSJohnny Huang 			writel(0x04190760, 0x1e602008); //normal program
81969d5fd8fSJohnny Huang 			for (k = 0; k < RETRY; k++) {
82069d5fd8fSJohnny Huang 				if (!soak) {
82169d5fd8fSJohnny Huang 					// printf("prog_address = %x\n", prog_address);
82269d5fd8fSJohnny Huang 					// printf("prog_bit = %x\n", prog_bit);
82369d5fd8fSJohnny Huang 					otp_prog(prog_address, prog_bit);
82469d5fd8fSJohnny Huang 					if (prog_verify(prog_address, j, bit_value) == 0) {
82569d5fd8fSJohnny Huang 						pass = 1;
82669d5fd8fSJohnny Huang 						break;
82769d5fd8fSJohnny Huang 					}
82869d5fd8fSJohnny Huang 					soak = 1;
8294b65a65dSJohnny Huang 					otp_write(0x3000, 0x4021); // Write MRA
8304b65a65dSJohnny Huang 					otp_write(0x5000, 0x1027); // Write MRB
8314b65a65dSJohnny Huang 					otp_write(0x1000, 0x4820); // Write MR
83269d5fd8fSJohnny Huang 					writel(0x041930d4, 0x1e602008); //soak program
8334b65a65dSJohnny Huang 				}
83469d5fd8fSJohnny Huang 				otp_prog(prog_address, prog_bit);
83569d5fd8fSJohnny Huang 				if (prog_verify(prog_address, j, bit_value) == 0) {
83669d5fd8fSJohnny Huang 					pass = 1;
83769d5fd8fSJohnny Huang 					break;
83869d5fd8fSJohnny Huang 				}
83969d5fd8fSJohnny Huang 			}
84069d5fd8fSJohnny Huang 			if (!pass)
84169d5fd8fSJohnny Huang 				return -1;
84269d5fd8fSJohnny Huang 		}
84369d5fd8fSJohnny Huang 	}
84469d5fd8fSJohnny Huang 	return 0;
84569d5fd8fSJohnny Huang }
84669d5fd8fSJohnny Huang 
84769d5fd8fSJohnny Huang static int do_otp_prog(int mode, int addr, int otp_addr, int dw_count, int nconfirm)
84869d5fd8fSJohnny Huang {
84969d5fd8fSJohnny Huang 	int ret;
85069d5fd8fSJohnny Huang 	uint32_t *buf;
85169d5fd8fSJohnny Huang 
85269d5fd8fSJohnny Huang 	buf = map_physmem(addr, dw_count * 4, MAP_WRBACK);
85369d5fd8fSJohnny Huang 	if (!buf) {
85469d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
85569d5fd8fSJohnny Huang 		return 1;
85669d5fd8fSJohnny Huang 	}
85769d5fd8fSJohnny Huang 	if (!nconfirm) {
85869d5fd8fSJohnny Huang 		if (mode == MODE_CONF) {
85969d5fd8fSJohnny Huang 			if (otp_conf_parse(buf) < 0) {
86069d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
86169d5fd8fSJohnny Huang 				return -1;
86269d5fd8fSJohnny Huang 			}
86369d5fd8fSJohnny Huang 		} else if (mode == MODE_DATA) {
86469d5fd8fSJohnny Huang 			if (otp_data_parse(buf, dw_count) < 0) {
86569d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
86669d5fd8fSJohnny Huang 				return -1;
86769d5fd8fSJohnny Huang 			}
86869d5fd8fSJohnny Huang 		} else if (mode == MODE_STRAP) {
86969d5fd8fSJohnny Huang 			if (otp_strap_parse(buf) < 0) {
87069d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
87169d5fd8fSJohnny Huang 				return -1;
87269d5fd8fSJohnny Huang 			}
87369d5fd8fSJohnny Huang 		} else if (mode == MODE_ALL) {
87469d5fd8fSJohnny Huang 			if (otp_conf_parse(buf) < 0) {
87569d5fd8fSJohnny Huang 				printf("OTP config error, please check.\n");
87669d5fd8fSJohnny Huang 				return -1;
87769d5fd8fSJohnny Huang 			}
87869d5fd8fSJohnny Huang 			if (otp_strap_parse(&buf[12]) < 0) {
87969d5fd8fSJohnny Huang 				printf("OTP strap error, please check.\n");
88069d5fd8fSJohnny Huang 				return -1;
88169d5fd8fSJohnny Huang 			}
88269d5fd8fSJohnny Huang 			if (otp_data_parse(&buf[18], dw_count - 18) < 0) {
88369d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
88469d5fd8fSJohnny Huang 				return -1;
88569d5fd8fSJohnny Huang 			}
88669d5fd8fSJohnny Huang 		}
88769d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
88869d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
88969d5fd8fSJohnny Huang 			printf(" Aborting\n");
89069d5fd8fSJohnny Huang 			return 1;
89169d5fd8fSJohnny Huang 		}
89269d5fd8fSJohnny Huang 	}
89369d5fd8fSJohnny Huang 	if (mode == MODE_CONF) {
89469d5fd8fSJohnny Huang 		return otp_prog_conf(buf, otp_addr, dw_count);
89569d5fd8fSJohnny Huang 	} else if (mode == MODE_STRAP) {
89669d5fd8fSJohnny Huang 		return otp_prog_strap(buf);
89769d5fd8fSJohnny Huang 	} else if (mode == MODE_DATA) {
89869d5fd8fSJohnny Huang 		return otp_prog_data(buf, otp_addr, dw_count);
89969d5fd8fSJohnny Huang 	} else if (mode == MODE_ALL) {
90069d5fd8fSJohnny Huang 		printf("programing data region ... ");
90169d5fd8fSJohnny Huang 		ret = otp_prog_data(&buf[16], 0, dw_count - 18);
90269d5fd8fSJohnny Huang 		if (ret < 0) {
90369d5fd8fSJohnny Huang 			printf("Error\n");
90469d5fd8fSJohnny Huang 			return ret;
90569d5fd8fSJohnny Huang 		} else {
90669d5fd8fSJohnny Huang 			printf("Done\n");
90769d5fd8fSJohnny Huang 		}
90869d5fd8fSJohnny Huang 		printf("programing strap region ... ");
90969d5fd8fSJohnny Huang 		ret = otp_prog_strap(&buf[12]);
91069d5fd8fSJohnny Huang 		if (ret < 0) {
91169d5fd8fSJohnny Huang 			printf("Error\n");
91269d5fd8fSJohnny Huang 			return ret;
91369d5fd8fSJohnny Huang 		} else {
91469d5fd8fSJohnny Huang 			printf("Done\n");
91569d5fd8fSJohnny Huang 		}
91669d5fd8fSJohnny Huang 		printf("programing configuration region ... ");
91769d5fd8fSJohnny Huang 		ret = otp_prog_conf(buf, 0, 12);
91869d5fd8fSJohnny Huang 		if (ret < 0) {
91969d5fd8fSJohnny Huang 			printf("Error\n");
92069d5fd8fSJohnny Huang 			return ret;
92169d5fd8fSJohnny Huang 		}
92269d5fd8fSJohnny Huang 		printf("Done\n");
92369d5fd8fSJohnny Huang 		return ret;
92469d5fd8fSJohnny Huang 	}
92569d5fd8fSJohnny Huang 	return 0;
92669d5fd8fSJohnny Huang }
92769d5fd8fSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc,
92869d5fd8fSJohnny Huang 		      char *const argv[])
92969d5fd8fSJohnny Huang {
93069d5fd8fSJohnny Huang 	char *cmd;
93169d5fd8fSJohnny Huang 	int mode = 0;
93269d5fd8fSJohnny Huang 	int nconfirm = 0;
93369d5fd8fSJohnny Huang 	uint32_t addr, dw_count, otp_addr;
93469d5fd8fSJohnny Huang 
93569d5fd8fSJohnny Huang 
93669d5fd8fSJohnny Huang 
93769d5fd8fSJohnny Huang 	if (argc < 2) {
93869d5fd8fSJohnny Huang usage:
93969d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
94069d5fd8fSJohnny Huang 	}
94169d5fd8fSJohnny Huang 
94269d5fd8fSJohnny Huang 	cmd = argv[1];
94369d5fd8fSJohnny Huang 	if (!strcmp(cmd, "read")) {
94469d5fd8fSJohnny Huang 		if (!strcmp(argv[2], "conf"))
94569d5fd8fSJohnny Huang 			mode = MODE_CONF;
94669d5fd8fSJohnny Huang 		else if (!strcmp(argv[2], "data"))
94769d5fd8fSJohnny Huang 			mode = MODE_DATA;
94869d5fd8fSJohnny Huang 		else if (!strcmp(argv[2], "strap"))
94969d5fd8fSJohnny Huang 			mode = MODE_STRAP;
95069d5fd8fSJohnny Huang 		else
95169d5fd8fSJohnny Huang 			goto usage;
95269d5fd8fSJohnny Huang 
95369d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
95469d5fd8fSJohnny Huang 		otp_addr = simple_strtoul(argv[3], NULL, 16);
95569d5fd8fSJohnny Huang 		dw_count = simple_strtoul(argv[4], NULL, 16);
95669d5fd8fSJohnny Huang 		if (mode == MODE_CONF) {
95769d5fd8fSJohnny Huang 			otp_print_config(otp_addr, dw_count);
95869d5fd8fSJohnny Huang 		} else if (mode == MODE_DATA) {
95969d5fd8fSJohnny Huang 			otp_print_data(otp_addr, dw_count);
96069d5fd8fSJohnny Huang 		} else if (mode == MODE_STRAP) {
96169d5fd8fSJohnny Huang 			otp_print_strap();
96269d5fd8fSJohnny Huang 		}
96369d5fd8fSJohnny Huang 	} else if (!strcmp(cmd, "prog")) {
96469d5fd8fSJohnny Huang 		if (!strcmp(argv[2], "conf"))
96569d5fd8fSJohnny Huang 			mode = MODE_CONF;
96669d5fd8fSJohnny Huang 		else if (!strcmp(argv[2], "strap"))
96769d5fd8fSJohnny Huang 			mode = MODE_STRAP;
96869d5fd8fSJohnny Huang 		else if (!strcmp(argv[2], "data"))
96969d5fd8fSJohnny Huang 			mode = MODE_DATA;
97069d5fd8fSJohnny Huang 		else if (!strcmp(argv[2], "all"))
97169d5fd8fSJohnny Huang 			mode = MODE_ALL;
97269d5fd8fSJohnny Huang 		else
97369d5fd8fSJohnny Huang 			goto usage;
97469d5fd8fSJohnny Huang 
97569d5fd8fSJohnny Huang 		if (!strcmp(argv[3], "f"))
97669d5fd8fSJohnny Huang 			nconfirm = 1;
97769d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
97869d5fd8fSJohnny Huang 		addr = simple_strtoul(argv[3 + nconfirm], NULL, 16);
97969d5fd8fSJohnny Huang 		otp_addr = simple_strtoul(argv[4 + nconfirm], NULL, 16);
98069d5fd8fSJohnny Huang 		dw_count = simple_strtoul(argv[5 + nconfirm], NULL, 16);
98169d5fd8fSJohnny Huang 		return do_otp_prog(mode, addr, otp_addr, dw_count, nconfirm);
98269d5fd8fSJohnny Huang 	} else if (!strcmp(cmd, "comp")) {
98369d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
98469d5fd8fSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
98569d5fd8fSJohnny Huang 		otp_addr = simple_strtoul(argv[3], NULL, 16);
98669d5fd8fSJohnny Huang 		if (otp_compare(otp_addr, addr) >= 0) {
98769d5fd8fSJohnny Huang 			printf("Compare pass\n");
98869d5fd8fSJohnny Huang 		} else {
98969d5fd8fSJohnny Huang 			printf("Compare fail\n");
99069d5fd8fSJohnny Huang 		}
99169d5fd8fSJohnny Huang 	} else {
99269d5fd8fSJohnny Huang 		goto usage;
99369d5fd8fSJohnny Huang 	}
99469d5fd8fSJohnny Huang 
99569d5fd8fSJohnny Huang 
99669d5fd8fSJohnny Huang 	return 0;
99769d5fd8fSJohnny Huang }
99869d5fd8fSJohnny Huang 
99969d5fd8fSJohnny Huang 
100069d5fd8fSJohnny Huang U_BOOT_CMD(
100169d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
100269d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
100369d5fd8fSJohnny Huang 	"read conf|strap|data <otp_addr> <dw_count>\n"
100469d5fd8fSJohnny Huang 	"otp prog conf|strap|data|all [f] <addr> <otp_addr> <dw_count>\n"
100569d5fd8fSJohnny Huang 	"otp comp <addr> <otp_addr>"
100669d5fd8fSJohnny Huang );
1007