xref: /openbmc/u-boot/cmd/otp.c (revision de6b0cc4e4b628818dbbc19dbc572ffc67a735a4)
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>
2469d5fd8fSJohnny Huang 
2569d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2669d5fd8fSJohnny Huang 
2769d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
2869d5fd8fSJohnny Huang #define RETRY				3
297332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
307332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
317332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
3269d5fd8fSJohnny Huang 
332a856b9aSJohnny Huang #define OTP_USAGE			-1
342a856b9aSJohnny Huang #define OTP_FAILURE			-2
352a856b9aSJohnny Huang #define OTP_SUCCESS			0
362a856b9aSJohnny Huang 
37a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
38a6af4a17SJohnny Huang 
399a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA		1
409a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES		2
419a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT		3
429a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC		4
439a4fe690SJohnny Huang 
449a4fe690SJohnny Huang 
45a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
46b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
47b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4876d13988SJohnny Huang 
494c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
504c1c9b35SJohnny Huang #define PBWIDTH 60
514c1c9b35SJohnny Huang 
523d3688adSJohnny Huang #define OTP_BASE		0x1e6f2000
533d3688adSJohnny Huang #define OTP_PROTECT_KEY		OTP_BASE
543d3688adSJohnny Huang #define OTP_COMMAND		OTP_BASE + 0x4
553d3688adSJohnny Huang #define OTP_TIMING		OTP_BASE + 0x8
563d3688adSJohnny Huang #define OTP_ADDR		OTP_BASE + 0x10
573d3688adSJohnny Huang #define OTP_STATUS		OTP_BASE + 0x14
583d3688adSJohnny Huang #define OTP_COMPARE_1		OTP_BASE + 0x20
593d3688adSJohnny Huang #define OTP_COMPARE_2		OTP_BASE + 0x24
603d3688adSJohnny Huang #define OTP_COMPARE_3		OTP_BASE + 0x28
613d3688adSJohnny Huang #define OTP_COMPARE_4		OTP_BASE + 0x2c
623d3688adSJohnny Huang 
63696656c6SJohnny Huang #define OTP_MAGIC		"SOCOTP"
64696656c6SJohnny Huang #define CHECKSUM_LEN		32
65696656c6SJohnny Huang #define OTP_INC_DATA		(1 << 31)
66696656c6SJohnny Huang #define OTP_INC_CONFIG		(1 << 30)
67696656c6SJohnny Huang #define OTP_INC_STRAP		(1 << 29)
68696656c6SJohnny Huang #define OTP_ECC_EN		(1 << 28)
69696656c6SJohnny Huang #define OTP_REGION_SIZE(info)	((info >> 16) & 0xffff)
70696656c6SJohnny Huang #define OTP_REGION_OFFSET(info)	(info & 0xffff)
71696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info)	(info & 0xffff)
72696656c6SJohnny Huang 
73696656c6SJohnny Huang #define OTP_AST2600A0		0
74696656c6SJohnny Huang #define OTP_AST2600A1		1
75696656c6SJohnny Huang 
76696656c6SJohnny Huang struct otp_header {
77696656c6SJohnny Huang 	u8	otp_magic[8];
78696656c6SJohnny Huang 	u8	otp_version[8];
79696656c6SJohnny Huang 	u32	image_info;
80696656c6SJohnny Huang 	u32	data_info;
81696656c6SJohnny Huang 	u32	config_info;
82696656c6SJohnny Huang 	u32	strap_info;
83696656c6SJohnny Huang 	u32	checksum_offset;
84696656c6SJohnny Huang } __attribute__((packed));
85696656c6SJohnny Huang 
8666f2f8e5SJohnny Huang struct otpstrap_status {
8769d5fd8fSJohnny Huang 	int value;
8869d5fd8fSJohnny Huang 	int option_array[7];
8969d5fd8fSJohnny Huang 	int remain_times;
9069d5fd8fSJohnny Huang 	int writeable_option;
915010032bSJohnny Huang 	int reg_protected;
9269d5fd8fSJohnny Huang 	int protected;
9369d5fd8fSJohnny Huang };
9469d5fd8fSJohnny Huang 
9566f2f8e5SJohnny Huang struct otpconf_parse {
9666f2f8e5SJohnny Huang 	int dw_offset;
9766f2f8e5SJohnny Huang 	int bit;
9866f2f8e5SJohnny Huang 	int length;
9966f2f8e5SJohnny Huang 	int value;
100696656c6SJohnny Huang 	int ignore;
10166f2f8e5SJohnny Huang 	char status[80];
10266f2f8e5SJohnny Huang };
10366f2f8e5SJohnny Huang 
104a8bd6d8cSJohnny Huang struct otpstrap_info {
10579e42a59SJoel Stanley 	int8_t bit_offset;
10679e42a59SJoel Stanley 	int8_t length;
10779e42a59SJoel Stanley 	int8_t value;
10879e42a59SJoel Stanley 	char *information;
109a8bd6d8cSJohnny Huang };
110a8bd6d8cSJohnny Huang 
111a8bd6d8cSJohnny Huang struct otpconf_info {
11279e42a59SJoel Stanley 	int8_t dw_offset;
11379e42a59SJoel Stanley 	int8_t bit_offset;
11479e42a59SJoel Stanley 	int8_t length;
11579e42a59SJoel Stanley 	int8_t value;
11679e42a59SJoel Stanley 	char *information;
117a8bd6d8cSJohnny Huang };
118a8bd6d8cSJohnny Huang 
1199a4fe690SJohnny Huang struct otpkey_type {
1209a4fe690SJohnny Huang 	int value;
1219a4fe690SJohnny Huang 	int key_type;
1229a4fe690SJohnny Huang 	int need_id;
1239a4fe690SJohnny Huang 	char information[110];
1249a4fe690SJohnny Huang };
1259a4fe690SJohnny Huang 
1269a4fe690SJohnny Huang struct otp_info_cb {
1279a4fe690SJohnny Huang 	int version;
12879e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1299a4fe690SJohnny Huang 	int strap_info_len;
13079e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1319a4fe690SJohnny Huang 	int conf_info_len;
13279e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1339a4fe690SJohnny Huang 	int key_info_len;
1345010032bSJohnny Huang 
1359a4fe690SJohnny Huang };
1369a4fe690SJohnny Huang 
137696656c6SJohnny Huang struct otp_image_layout {
1385010032bSJohnny Huang 	int data_length;
1395010032bSJohnny Huang 	int conf_length;
1405010032bSJohnny Huang 	int strap_length;
141696656c6SJohnny Huang 	uint8_t *data;
142696656c6SJohnny Huang 	uint8_t *data_ignore;
143696656c6SJohnny Huang 	uint8_t *conf;
144696656c6SJohnny Huang 	uint8_t *conf_ignore;
145696656c6SJohnny Huang 	uint8_t *strap;
146696656c6SJohnny Huang 	uint8_t *strap_reg_pro;
147696656c6SJohnny Huang 	uint8_t *strap_pro;
148696656c6SJohnny Huang 	uint8_t *strap_ignore;
149696656c6SJohnny Huang };
150696656c6SJohnny Huang 
1519a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1529a4fe690SJohnny Huang 
15379e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = {
15491448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
15591448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
15691448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
15791448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
15891448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
15991448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
16091448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
16191448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
162541eb887SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
16391448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
16491448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
16591448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
16691448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
16791448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
16891448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
16991448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
17091448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
17191448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
17291448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
17391448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
17491448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
17591448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
17691448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
17791448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
17891448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
17991448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
18091448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
18191448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
18291448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
18391448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
18491448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
18591448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
18691448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
18791448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
18891448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
18991448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
19091448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
19191448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
19291448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
19391448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
19491448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
19591448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
19691448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
19791448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
19891448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
19991448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
20091448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
20191448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
20291448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
20391448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
20491448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
20591448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
20691448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
20791448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
20891448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
20991448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
21091448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
21191448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
21291448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
21391448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
21491448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
21591448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
21691448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
21791448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
21891448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
21991448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
22091448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
22191448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
22291448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
22391448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
22491448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
22591448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
22691448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
22791448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
22891448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
22991448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
23091448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
23191448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
23291448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
23391448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
23491448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
23591448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
23691448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
23791448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
23891448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
23991448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
24091448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
24191448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
24291448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
24391448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
24491448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
24591448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
24691448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
24791448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
24891448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
24991448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
25091448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
25191448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
25291448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
25391448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
25491448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
25591448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
25691448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
25791448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
25891448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
25991448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
26091448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
26191448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
26291448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
26376d13988SJohnny Huang };
2649a4fe690SJohnny Huang 
26579e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = {
2663cb28812SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
2673cb28812SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
2683cb28812SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
2693cb28812SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
2703cb28812SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
2713cb28812SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
2723cb28812SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
2733cb28812SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
2743cb28812SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
2753cb28812SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
2763cb28812SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
2773cb28812SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
2783cb28812SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
2793cb28812SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
2803cb28812SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
2813cb28812SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
2823cb28812SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
2833cb28812SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
2843cb28812SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
2853cb28812SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
2863cb28812SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
2873cb28812SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
2883cb28812SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
2893cb28812SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
2903cb28812SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
2913cb28812SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
2923cb28812SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
2933cb28812SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
2943cb28812SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
2953cb28812SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
2963cb28812SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
2973cb28812SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
2983cb28812SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
2993cb28812SJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
3003cb28812SJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
3013cb28812SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
3023cb28812SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
3033cb28812SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
3043cb28812SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
3053cb28812SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
3063cb28812SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
3073cb28812SJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
3083cb28812SJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
3093cb28812SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
3103cb28812SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
3113cb28812SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
3123cb28812SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
3133cb28812SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
3143cb28812SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
3153cb28812SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
3163cb28812SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
3173cb28812SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
3183cb28812SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
3193cb28812SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
3203cb28812SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
3213cb28812SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
3223cb28812SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
3233cb28812SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
3243cb28812SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
3253cb28812SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
3263cb28812SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
3273cb28812SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
3283cb28812SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
3293cb28812SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
3303cb28812SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
3313cb28812SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
3323cb28812SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
3333cb28812SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
3343cb28812SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
3353cb28812SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
3363cb28812SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
3373cb28812SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
3383cb28812SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
3393cb28812SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
3403cb28812SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
3413cb28812SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
3423cb28812SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
3433cb28812SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
3443cb28812SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
3453cb28812SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
3463cb28812SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
3473cb28812SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
3483cb28812SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
3493cb28812SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
3503cb28812SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
3513cb28812SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
3523cb28812SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
3533cb28812SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
3543cb28812SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
3553cb28812SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
3563cb28812SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
3573cb28812SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
3583cb28812SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
3593cb28812SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
3603cb28812SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
3613cb28812SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
3623cb28812SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
3633cb28812SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
3643cb28812SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
3653cb28812SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
3663cb28812SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
3673cb28812SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
3683cb28812SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
3693cb28812SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
3703cb28812SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
3713cb28812SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
3723cb28812SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
3733cb28812SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
3743cb28812SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
3753cb28812SJohnny Huang };
3763cb28812SJohnny Huang 
37779e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = {
37891448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
37991448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
38091448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
38191448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
38291448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
38391448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
38491448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
38591448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
38691448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
38791448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
38891448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
38991448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
39091448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
39191448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
39291448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
39391448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
39491448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
395541eb887SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
39691448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
39791448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
39891448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
39991448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
40091448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
40191448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
40291448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
40391448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
40491448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
40591448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
40691448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
40791448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
40891448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
40991448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
41091448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
41191448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
41291448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
41391448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
41491448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
41591448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
41691448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
41791448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
41891448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
41991448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
42091448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
42191448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
4223cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
4233cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
4243cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
4253cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
4263cb28812SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
4273cb28812SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
4283cb28812SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
4293cb28812SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
4303cb28812SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
4313cb28812SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
4323cb28812SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
4333cb28812SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
4343cb28812SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
4353cb28812SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
4363cb28812SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
4373cb28812SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
4383cb28812SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
4393cb28812SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
4403cb28812SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
4413cb28812SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
4423cb28812SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
4433cb28812SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
4443cb28812SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
4453cb28812SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
4463cb28812SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
4473cb28812SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
4483cb28812SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
4493cb28812SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
4503cb28812SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
4513cb28812SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
4523cb28812SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
4533cb28812SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
4543cb28812SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
4553cb28812SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
4563cb28812SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
4573cb28812SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
4583cb28812SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
4593cb28812SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
4603cb28812SJohnny Huang };
4613cb28812SJohnny Huang 
46279e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = {
4633cb28812SJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
4643cb28812SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
4653cb28812SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
4663cb28812SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
4673cb28812SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
4683cb28812SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
4693cb28812SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
4703cb28812SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
4713cb28812SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
4723cb28812SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
4733cb28812SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
4743cb28812SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
4753cb28812SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
4763cb28812SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
4773cb28812SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
4783cb28812SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
4793cb28812SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
4803cb28812SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
4813cb28812SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
4823cb28812SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
4833cb28812SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
4843cb28812SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
4853cb28812SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
4863cb28812SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
4873cb28812SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
4883cb28812SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
489bb34a7bfSJohnny Huang 	{ 0, 14, 1,  0, "Disable Patch code" },
490bb34a7bfSJohnny Huang 	{ 0, 14, 1,  1, "Enable Patch code" },
491bb34a7bfSJohnny Huang 	{ 0, 15, 1,  OTP_REG_RESERVED, "" },
4923cb28812SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
4933cb28812SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
4943cb28812SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
4953cb28812SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
4963cb28812SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
4973cb28812SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
4983cb28812SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
4993cb28812SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
5003cb28812SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
5013cb28812SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
5023cb28812SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
5033cb28812SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
5043cb28812SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
5053cb28812SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
5063cb28812SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
5073cb28812SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
5083cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
5093cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
5103cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
5113cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
51291448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
51391448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
51491448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
51573f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
51673f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
51791448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
51891448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
51991448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
52091448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
52191448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
52291448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
52391448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
52491448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
52591448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
52691448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
52791448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
52891448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
52991448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
53091448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
53191448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
53291448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
53391448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
53491448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
53591448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
53691448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
53791448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
53891448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
53991448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
54091448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
54191448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
54291448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
54391448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
54491448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
545bb34a7bfSJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" },
546bb34a7bfSJohnny Huang 	{ 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" },
547bb34a7bfSJohnny Huang 	{ 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" }
548b458cd62SJohnny Huang };
5499a4fe690SJohnny Huang 
55079e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
5519a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
5529a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5539a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
5549a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5559a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
5569a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5579a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
5589a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5599a4fe690SJohnny Huang };
5609a4fe690SJohnny Huang 
56179e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
5629a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5639a4fe690SJohnny 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"},
5649a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5659a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5669a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5679a4fe690SJohnny Huang };
5689a4fe690SJohnny Huang 
5699a4fe690SJohnny Huang static uint32_t chip_version(void)
5709a4fe690SJohnny Huang {
5719a4fe690SJohnny Huang 	uint32_t rev_id;
5729a4fe690SJohnny Huang 
5739a4fe690SJohnny Huang 	rev_id = (readl(0x1e6e2004) >> 16) & 0xff ;
5749a4fe690SJohnny Huang 
5759a4fe690SJohnny Huang 	return rev_id;
5769a4fe690SJohnny Huang }
5779a4fe690SJohnny Huang 
5783d3688adSJohnny Huang static void wait_complete(void)
5793d3688adSJohnny Huang {
5803d3688adSJohnny Huang 	int reg;
5813d3688adSJohnny Huang 
5823d3688adSJohnny Huang 	do {
5833d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
5843d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
5853d3688adSJohnny Huang }
5863d3688adSJohnny Huang 
5872a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
58869d5fd8fSJohnny Huang {
5893d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
5903d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
5913d3688adSJohnny Huang 	wait_complete();
5923d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
5933d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
59469d5fd8fSJohnny Huang }
59569d5fd8fSJohnny Huang 
5962a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
59769d5fd8fSJohnny Huang {
59869d5fd8fSJohnny Huang 	int config_offset;
59969d5fd8fSJohnny Huang 
60069d5fd8fSJohnny Huang 	config_offset = 0x800;
60169d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
60269d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
60369d5fd8fSJohnny Huang 
6043d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
6053d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6063d3688adSJohnny Huang 	wait_complete();
6073d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
60869d5fd8fSJohnny Huang }
60969d5fd8fSJohnny Huang 
61069d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
61169d5fd8fSJohnny Huang {
61269d5fd8fSJohnny Huang 	int i;
61369d5fd8fSJohnny Huang 	uint32_t ret[1];
61469d5fd8fSJohnny Huang 
61569d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
6162a856b9aSJohnny Huang 		return OTP_USAGE;
61769d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
61869d5fd8fSJohnny Huang 		otp_read_config(i, ret);
619a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
62069d5fd8fSJohnny Huang 	}
62169d5fd8fSJohnny Huang 	printf("\n");
6222a856b9aSJohnny Huang 	return OTP_SUCCESS;
62369d5fd8fSJohnny Huang }
62469d5fd8fSJohnny Huang 
62569d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
62669d5fd8fSJohnny Huang {
62769d5fd8fSJohnny Huang 	int i;
62869d5fd8fSJohnny Huang 	uint32_t ret[2];
62969d5fd8fSJohnny Huang 
63069d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
6312a856b9aSJohnny Huang 		return OTP_USAGE;
63269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
63369d5fd8fSJohnny Huang 		otp_read_data(i, ret);
63469d5fd8fSJohnny Huang 		if (i % 4 == 0)
63569d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
63669d5fd8fSJohnny Huang 		else
63769d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
63869d5fd8fSJohnny Huang 
63969d5fd8fSJohnny Huang 	}
64069d5fd8fSJohnny Huang 	printf("\n");
6412a856b9aSJohnny Huang 	return OTP_SUCCESS;
64269d5fd8fSJohnny Huang }
64369d5fd8fSJohnny Huang 
64469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
64569d5fd8fSJohnny Huang {
64669d5fd8fSJohnny Huang 	uint32_t ret;
64769d5fd8fSJohnny Huang 	uint32_t *buf;
64869d5fd8fSJohnny Huang 
64969d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
65069d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
65169d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
65269d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
65369d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
6543d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
6553d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
6563d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
6573d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
6583d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
6593d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
6603d3688adSJohnny Huang 	wait_complete();
6613d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
66269d5fd8fSJohnny Huang 	if (ret & 0x1)
66369d5fd8fSJohnny Huang 		return 0;
66469d5fd8fSJohnny Huang 	else
66569d5fd8fSJohnny Huang 		return -1;
66669d5fd8fSJohnny Huang }
66769d5fd8fSJohnny Huang 
66869d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
66969d5fd8fSJohnny Huang {
6703d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6713d3688adSJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
6723d3688adSJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
6733d3688adSJohnny Huang 	wait_complete();
67469d5fd8fSJohnny Huang }
67569d5fd8fSJohnny Huang 
67669d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
67769d5fd8fSJohnny Huang {
6783d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6793d3688adSJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
6803d3688adSJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
6813d3688adSJohnny Huang 	wait_complete();
68269d5fd8fSJohnny Huang }
68369d5fd8fSJohnny Huang 
684a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
68569d5fd8fSJohnny Huang {
68630a8c590SJohnny Huang 	uint32_t ret[2];
68769d5fd8fSJohnny Huang 
68830a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
6893d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
69030a8c590SJohnny Huang 	else
6913d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
69230a8c590SJohnny Huang 
6933d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6943d3688adSJohnny Huang 	wait_complete();
6953d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
6963d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
697a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
69830a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
69930a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
70069d5fd8fSJohnny Huang 			return 0;
70169d5fd8fSJohnny Huang 		else
70269d5fd8fSJohnny Huang 			return -1;
70330a8c590SJohnny Huang 	} else {
70430a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
70530a8c590SJohnny Huang 			return 0;
70630a8c590SJohnny Huang 		else
70730a8c590SJohnny Huang 			return -1;
70830a8c590SJohnny Huang 	}
70930a8c590SJohnny Huang 
71069d5fd8fSJohnny Huang }
71169d5fd8fSJohnny Huang 
712696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size)
7134c1c9b35SJohnny Huang {
7144c1c9b35SJohnny Huang 	uint32_t ret[2];
7154c1c9b35SJohnny Huang 
7164c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
7174c1c9b35SJohnny Huang 
7184c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
7193d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
7204c1c9b35SJohnny Huang 	else
7213d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
7223d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
7233d3688adSJohnny Huang 	wait_complete();
7243d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
7253d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
7264c1c9b35SJohnny Huang 	if (size == 1) {
7274c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
7284c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
729696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
7304c1c9b35SJohnny Huang 				compare[0] = 0;
7314c1c9b35SJohnny Huang 				return 0;
7324c1c9b35SJohnny Huang 			} else {
7334c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
7344c1c9b35SJohnny Huang 				return -1;
7354c1c9b35SJohnny Huang 			}
7364c1c9b35SJohnny Huang 
7374c1c9b35SJohnny Huang 		} else {
7384c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
739696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
7404c1c9b35SJohnny Huang 				compare[0] = ~0;
7414c1c9b35SJohnny Huang 				return 0;
7424c1c9b35SJohnny Huang 			} else {
743d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
7444c1c9b35SJohnny Huang 				return -1;
7454c1c9b35SJohnny Huang 			}
7464c1c9b35SJohnny Huang 		}
7474c1c9b35SJohnny Huang 	} else if (size == 2) {
7484c1c9b35SJohnny Huang 		// otp_addr should be even
749696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
7504c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7514c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7524c1c9b35SJohnny Huang 			compare[0] = 0;
7534c1c9b35SJohnny Huang 			compare[1] = ~0;
7544c1c9b35SJohnny Huang 			return 0;
7554c1c9b35SJohnny Huang 		} else {
7564c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7574c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7584c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
7594c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
7604c1c9b35SJohnny Huang 			return -1;
7614c1c9b35SJohnny Huang 		}
7624c1c9b35SJohnny Huang 	} else {
7634c1c9b35SJohnny Huang 		return -1;
7644c1c9b35SJohnny Huang 	}
7654c1c9b35SJohnny Huang }
7664c1c9b35SJohnny Huang 
7677e22f42dSJohnny Huang static void otp_soak(int soak)
768d90825e2SJohnny Huang {
769de6fbf1cSJohnny Huang 	switch (soak) {
770de6fbf1cSJohnny Huang 	case 0: //default
771de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x0); // Write MRA
772de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x0); // Write MRB
773de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x0); // Write MR
774de6fbf1cSJohnny Huang 		break;
775de6fbf1cSJohnny Huang 	case 1: //normal program
776de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
777de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
778de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
779de6fbf1cSJohnny Huang 		writel(0x04190760, OTP_TIMING);
780de6fbf1cSJohnny Huang 		break;
781de6fbf1cSJohnny Huang 	case 2: //soak program
782d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
783d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
784d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
785de6fbf1cSJohnny Huang 		writel(0x041930d4, OTP_TIMING);
786de6fbf1cSJohnny Huang 		break;
787d90825e2SJohnny Huang 	}
788de6fbf1cSJohnny Huang 
7893d3688adSJohnny Huang 	wait_complete();
790d90825e2SJohnny Huang }
791d90825e2SJohnny Huang 
792696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address)
793d90825e2SJohnny Huang {
794d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
795d90825e2SJohnny Huang 
796d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
797696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
798d90825e2SJohnny Huang 			continue;
799d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
800d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
801d90825e2SJohnny Huang 			if (bit_value)
802d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
803d90825e2SJohnny Huang 			else
804d90825e2SJohnny Huang 				continue;
805d90825e2SJohnny Huang 		} else {
806d90825e2SJohnny Huang 			prog_address |= 1 << 15;
807d90825e2SJohnny Huang 			if (bit_value)
808d90825e2SJohnny Huang 				continue;
809d90825e2SJohnny Huang 			else
810d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
811d90825e2SJohnny Huang 		}
812d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
813d90825e2SJohnny Huang 	}
814d90825e2SJohnny Huang }
815d90825e2SJohnny Huang 
81654552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
81754552c69SJohnny Huang {
81854552c69SJohnny Huang 	int pass;
81954552c69SJohnny Huang 	int i;
82054552c69SJohnny Huang 	uint32_t data0_masked;
82154552c69SJohnny Huang 	uint32_t data1_masked;
82254552c69SJohnny Huang 	uint32_t buf0_masked;
82354552c69SJohnny Huang 	uint32_t buf1_masked;
82454552c69SJohnny Huang 	uint32_t compare[2];
82554552c69SJohnny Huang 
82654552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
82754552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
82854552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
82954552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
83054552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
83154552c69SJohnny Huang 		return 0;
83254552c69SJohnny Huang 
83354552c69SJohnny Huang 	otp_soak(1);
83454552c69SJohnny Huang 	if (data0_masked != buf0_masked)
83554552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
83654552c69SJohnny Huang 	if (data1_masked != buf1_masked)
83754552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
83854552c69SJohnny Huang 
83954552c69SJohnny Huang 	pass = 0;
84054552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
84154552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
84254552c69SJohnny Huang 			otp_soak(2);
84354552c69SJohnny Huang 			if (compare[0] != 0) {
84454552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
84554552c69SJohnny Huang 			}
84654552c69SJohnny Huang 			if (compare[1] != ~0) {
84754552c69SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1);
84854552c69SJohnny Huang 			}
84954552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
85054552c69SJohnny Huang 				otp_soak(1);
85154552c69SJohnny Huang 			} else {
85254552c69SJohnny Huang 				pass = 1;
85354552c69SJohnny Huang 				break;
85454552c69SJohnny Huang 			}
85554552c69SJohnny Huang 		} else {
85654552c69SJohnny Huang 			pass = 1;
85754552c69SJohnny Huang 			break;
85854552c69SJohnny Huang 		}
85954552c69SJohnny Huang 	}
86054552c69SJohnny Huang 
86154552c69SJohnny Huang 	if (!pass) {
86254552c69SJohnny Huang 		otp_soak(0);
86354552c69SJohnny Huang 		return OTP_FAILURE;
86454552c69SJohnny Huang 	}
86554552c69SJohnny Huang 	return OTP_SUCCESS;
86654552c69SJohnny Huang }
86754552c69SJohnny Huang 
86876d13988SJohnny Huang 
869541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
87076d13988SJohnny Huang {
87176d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
8725010032bSJohnny Huang 	int strap_end;
87376d13988SJohnny Huang 	int i, j;
87476d13988SJohnny Huang 
8755010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
87676d13988SJohnny Huang 		for (j = 0; j < 64; j++) {
87776d13988SJohnny Huang 			otpstrap[j].value = 0;
87876d13988SJohnny Huang 			otpstrap[j].remain_times = 7;
87976d13988SJohnny Huang 			otpstrap[j].writeable_option = -1;
88076d13988SJohnny Huang 			otpstrap[j].protected = 0;
88176d13988SJohnny Huang 		}
8825010032bSJohnny Huang 		strap_end = 30;
8835010032bSJohnny Huang 	} else {
8845010032bSJohnny Huang 		for (j = 0; j < 64; j++) {
8855010032bSJohnny Huang 			otpstrap[j].value = 0;
8865010032bSJohnny Huang 			otpstrap[j].remain_times = 6;
8875010032bSJohnny Huang 			otpstrap[j].writeable_option = -1;
8885010032bSJohnny Huang 			otpstrap[j].reg_protected = 0;
8895010032bSJohnny Huang 			otpstrap[j].protected = 0;
8905010032bSJohnny Huang 		}
8915010032bSJohnny Huang 		strap_end = 28;
8925010032bSJohnny Huang 	}
89376d13988SJohnny Huang 
8945010032bSJohnny Huang 	for (i = 16; i < strap_end; i += 2) {
89576d13988SJohnny Huang 		int option = (i - 16) / 2;
89676d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
89776d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
89876d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
89976d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
90076d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
90176d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
90276d13988SJohnny Huang 			}
90376d13988SJohnny Huang 			if (bit_value == 1)
90476d13988SJohnny Huang 				otpstrap[j].remain_times --;
90576d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
90676d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
90776d13988SJohnny Huang 		}
90876d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
90976d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
91076d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
91176d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
91276d13988SJohnny Huang 			}
91376d13988SJohnny Huang 			if (bit_value == 1)
91476d13988SJohnny Huang 				otpstrap[j].remain_times --;
91576d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
91676d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
91776d13988SJohnny Huang 		}
91876d13988SJohnny Huang 	}
9195010032bSJohnny Huang 
9205010032bSJohnny Huang 	if (info_cb.version != OTP_AST2600A0) {
9215010032bSJohnny Huang 		otp_read_config(28, &OTPSTRAP_RAW[0]);
9225010032bSJohnny Huang 		otp_read_config(29, &OTPSTRAP_RAW[1]);
9235010032bSJohnny Huang 		for (j = 0; j < 32; j++) {
9245010032bSJohnny Huang 			if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
9255010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
9265010032bSJohnny Huang 		}
9275010032bSJohnny Huang 		for (j = 32; j < 64; j++) {
9285010032bSJohnny Huang 			if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
9295010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
9305010032bSJohnny Huang 		}
9315010032bSJohnny Huang 
9325010032bSJohnny Huang 	}
9335010032bSJohnny Huang 
93476d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
93576d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
93676d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
93776d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
93876d13988SJohnny Huang 			otpstrap[j].protected = 1;
93976d13988SJohnny Huang 	}
94076d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
94176d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
94276d13988SJohnny Huang 			otpstrap[j].protected = 1;
94376d13988SJohnny Huang 	}
94476d13988SJohnny Huang }
94576d13988SJohnny Huang 
946696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
94769d5fd8fSJohnny Huang {
94879e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
949696656c6SJohnny Huang 	uint32_t *OTPCFG = (uint32_t *)image_layout->conf;
950696656c6SJohnny Huang 	uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore;
951b458cd62SJohnny Huang 	uint32_t mask;
952b458cd62SJohnny Huang 	uint32_t dw_offset;
953b458cd62SJohnny Huang 	uint32_t bit_offset;
954b458cd62SJohnny Huang 	uint32_t otp_value;
955696656c6SJohnny Huang 	uint32_t otp_ignore;
956b458cd62SJohnny Huang 	int fail = 0;
95773f11549SJohnny Huang 	char valid_bit[20];
95866f2f8e5SJohnny Huang 	int i;
95973f11549SJohnny Huang 	int j;
96066f2f8e5SJohnny Huang 
961737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
96266f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
9633cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
9643cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
9653cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
9663cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
967b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
968696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
969b458cd62SJohnny Huang 
970696656c6SJohnny Huang 		if (otp_ignore == mask) {
971b458cd62SJohnny Huang 			continue;
972696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
973b458cd62SJohnny Huang 			fail = 1;
974b458cd62SJohnny Huang 		}
975b458cd62SJohnny Huang 
9763cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
9773cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
9783cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
9793cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
980b458cd62SJohnny Huang 			continue;
981b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
982b458cd62SJohnny Huang 
9833cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
9843cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
98566f2f8e5SJohnny Huang 		} else {
986b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9873cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
9883cb28812SJohnny Huang 			       conf_info[i].bit_offset);
98966f2f8e5SJohnny Huang 		}
990b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
991b458cd62SJohnny Huang 
992b458cd62SJohnny Huang 		if (fail) {
993696656c6SJohnny Huang 			printf("Ignore mask error\n");
994b458cd62SJohnny Huang 		} else {
9953cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
996b458cd62SJohnny Huang 				printf("Reserved\n");
9973cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
9983cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
999b458cd62SJohnny Huang 				printf("\n");
10003cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1001b458cd62SJohnny Huang 				if (otp_value != 0) {
100273f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
100373f11549SJohnny Huang 						if (otp_value == (1 << j)) {
100473f11549SJohnny Huang 							valid_bit[j * 2] = '1';
1005b458cd62SJohnny Huang 						} else {
100673f11549SJohnny Huang 							valid_bit[j * 2] = '0';
100773f11549SJohnny Huang 						}
100873f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
100973f11549SJohnny Huang 					}
101073f11549SJohnny Huang 					valid_bit[15] = 0;
101173f11549SJohnny Huang 				} else {
101273f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1013b458cd62SJohnny Huang 				}
10143cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
1015b458cd62SJohnny Huang 				printf("\n");
1016b458cd62SJohnny Huang 			} else {
10173cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
1018b458cd62SJohnny Huang 			}
1019b458cd62SJohnny Huang 		}
1020b458cd62SJohnny Huang 	}
1021b458cd62SJohnny Huang 
1022b458cd62SJohnny Huang 	if (fail)
1023b458cd62SJohnny Huang 		return OTP_FAILURE;
1024b458cd62SJohnny Huang 
102566f2f8e5SJohnny Huang 	return OTP_SUCCESS;
102666f2f8e5SJohnny Huang }
102766f2f8e5SJohnny Huang 
10282d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
102966f2f8e5SJohnny Huang {
103079e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
1031bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
1032b458cd62SJohnny Huang 	uint32_t mask;
1033b458cd62SJohnny Huang 	uint32_t dw_offset;
1034b458cd62SJohnny Huang 	uint32_t bit_offset;
1035b458cd62SJohnny Huang 	uint32_t otp_value;
103673f11549SJohnny Huang 	char valid_bit[20];
103766f2f8e5SJohnny Huang 	int i;
103873f11549SJohnny Huang 	int j;
103966f2f8e5SJohnny Huang 
1040bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
104166f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
104266f2f8e5SJohnny Huang 
104366f2f8e5SJohnny Huang 
1044b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
1045b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
10463cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
10473cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
10482d4b0742SJohnny Huang 			continue;
10493cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
10503cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
10513cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
1052b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
1053b458cd62SJohnny Huang 
10543cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
10553cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
10563cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
10573cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
1058b458cd62SJohnny Huang 			continue;
1059b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
1060b458cd62SJohnny Huang 
10613cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
10623cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
1063b458cd62SJohnny Huang 		} else {
1064b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
10653cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
10663cb28812SJohnny Huang 			       conf_info[i].bit_offset);
1067b458cd62SJohnny Huang 		}
1068b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
1069b458cd62SJohnny Huang 
10703cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
1071b458cd62SJohnny Huang 			printf("Reserved\n");
10723cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
10733cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
1074b458cd62SJohnny Huang 			printf("\n");
10753cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1076b458cd62SJohnny Huang 			if (otp_value != 0) {
107773f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
107873f11549SJohnny Huang 					if (otp_value == (1 << j)) {
107973f11549SJohnny Huang 						valid_bit[j * 2] = '1';
1080b458cd62SJohnny Huang 					} else {
108173f11549SJohnny Huang 						valid_bit[j * 2] = '0';
108273f11549SJohnny Huang 					}
108373f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
108473f11549SJohnny Huang 				}
108573f11549SJohnny Huang 				valid_bit[15] = 0;
108673f11549SJohnny Huang 			} else {
108773f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1088b458cd62SJohnny Huang 			}
10893cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
1090b458cd62SJohnny Huang 			printf("\n");
1091b458cd62SJohnny Huang 		} else {
10923cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
1093b458cd62SJohnny Huang 		}
1094b458cd62SJohnny Huang 	}
1095b458cd62SJohnny Huang 	return OTP_SUCCESS;
109666f2f8e5SJohnny Huang }
109766f2f8e5SJohnny Huang 
10985010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout)
109976d13988SJohnny Huang {
110079e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
1101696656c6SJohnny Huang 	uint32_t *OTPSTRAP;
1102696656c6SJohnny Huang 	uint32_t *OTPSTRAP_REG_PRO;
1103696656c6SJohnny Huang 	uint32_t *OTPSTRAP_PRO;
1104696656c6SJohnny Huang 	uint32_t *OTPSTRAP_IGNORE;
110576d13988SJohnny Huang 	int i;
1106a8bd6d8cSJohnny Huang 	int fail = 0;
1107a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
1108a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
1109a8bd6d8cSJohnny Huang 	uint32_t mask;
1110a8bd6d8cSJohnny Huang 	uint32_t otp_value;
1111696656c6SJohnny Huang 	uint32_t otp_reg_protect;
1112a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
1113696656c6SJohnny Huang 	uint32_t otp_ignore;
111476d13988SJohnny Huang 
1115696656c6SJohnny Huang 	OTPSTRAP = (uint32_t *)image_layout->strap;
1116696656c6SJohnny Huang 	OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro;
1117696656c6SJohnny Huang 	OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore;
11185010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1119696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
1120a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
1121696656c6SJohnny Huang 	} else {
1122696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro;
1123*de6b0cc4SJohnny Huang 		printf("BIT(hex)   Value       Reg_Protect Protect     Description\n");
1124696656c6SJohnny Huang 	}
1125*de6b0cc4SJohnny Huang 	printf("__________________________________________________________________________________________\n");
1126b458cd62SJohnny Huang 
11273cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1128696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
1129a8bd6d8cSJohnny Huang 			dw_offset = 1;
11303cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
1131a8bd6d8cSJohnny Huang 		} else {
1132a8bd6d8cSJohnny Huang 			dw_offset = 0;
11333cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
1134a8bd6d8cSJohnny Huang 		}
113576d13988SJohnny Huang 
11363cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
1137a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
1138a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
1139696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
1140a8bd6d8cSJohnny Huang 
11415010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
1142696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
11435010032bSJohnny Huang 		else
11445010032bSJohnny Huang 			otp_reg_protect = 0;
1145696656c6SJohnny Huang 
1146696656c6SJohnny Huang 		if (otp_ignore == mask) {
1147a8bd6d8cSJohnny Huang 			continue;
1148696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
1149a8bd6d8cSJohnny Huang 			fail = 1;
1150a8bd6d8cSJohnny Huang 		}
1151a8bd6d8cSJohnny Huang 
11523cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
11533cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1154a8bd6d8cSJohnny Huang 			continue;
1155a8bd6d8cSJohnny Huang 
11563cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
11573cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
1158a8bd6d8cSJohnny Huang 		} else {
1159b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
11603cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
11613cb28812SJohnny Huang 			       strap_info[i].bit_offset);
1162a8bd6d8cSJohnny Huang 		}
1163a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
11645010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
1165696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
1166a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
1167a8bd6d8cSJohnny Huang 
1168a8bd6d8cSJohnny Huang 		if (fail) {
1169696656c6SJohnny Huang 			printf("Ignore mask error\n");
1170a8bd6d8cSJohnny Huang 		} else {
11713cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
11723cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1173a8bd6d8cSJohnny Huang 			else
1174a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1175a8bd6d8cSJohnny Huang 		}
1176a8bd6d8cSJohnny Huang 	}
1177a8bd6d8cSJohnny Huang 
1178a8bd6d8cSJohnny Huang 	if (fail)
117976d13988SJohnny Huang 		return OTP_FAILURE;
118076d13988SJohnny Huang 
118176d13988SJohnny Huang 	return OTP_SUCCESS;
118276d13988SJohnny Huang }
118376d13988SJohnny Huang 
1184b458cd62SJohnny Huang static int otp_print_strap_info(int view)
118576d13988SJohnny Huang {
118679e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
118776d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
118807baa4e8SJohnny Huang 	int i, j;
1189b458cd62SJohnny Huang 	int fail = 0;
1190b458cd62SJohnny Huang 	uint32_t bit_offset;
1191b458cd62SJohnny Huang 	uint32_t length;
1192b458cd62SJohnny Huang 	uint32_t otp_value;
1193b458cd62SJohnny Huang 	uint32_t otp_protect;
119476d13988SJohnny Huang 
1195541eb887SJohnny Huang 	otp_strap_status(strap_status);
119676d13988SJohnny Huang 
1197b458cd62SJohnny Huang 	if (view) {
119807baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
119907baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
120007baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
120107baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
1202b458cd62SJohnny Huang 	} else {
1203b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
1204b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
120576d13988SJohnny Huang 	}
12063cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1207b458cd62SJohnny Huang 		otp_value = 0;
12083cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
12093cb28812SJohnny Huang 		length = strap_info[i].length;
1210b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
1211c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
1212c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
1213b458cd62SJohnny Huang 		}
12143cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
12153cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1216b458cd62SJohnny Huang 			continue;
1217b458cd62SJohnny Huang 		if (view) {
1218b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
12193cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
1220b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
122107baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
1222b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
12233cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
1224b458cd62SJohnny Huang 					printf(" Reserved\n");
1225b458cd62SJohnny Huang 					continue;
1226b458cd62SJohnny Huang 				}
1227b458cd62SJohnny Huang 				if (length == 1) {
12283cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
1229b458cd62SJohnny Huang 					continue;
123076d13988SJohnny Huang 				}
123176d13988SJohnny Huang 
1232b458cd62SJohnny Huang 				if (j == 0)
12333cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
1234b458cd62SJohnny Huang 				else if (j == length - 1)
1235b458cd62SJohnny Huang 					printf("\\ \"\n");
1236b458cd62SJohnny Huang 				else
1237b458cd62SJohnny Huang 					printf("| \"\n");
123876d13988SJohnny Huang 			}
1239b458cd62SJohnny Huang 		} else {
1240c947ef08SJohnny Huang 			if (length == 1) {
12413cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
1242b458cd62SJohnny Huang 			} else {
1243b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1244b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1245b458cd62SJohnny Huang 			}
1246b458cd62SJohnny Huang 
1247b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1248b458cd62SJohnny Huang 
12493cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
12503cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1251b458cd62SJohnny Huang 			else
1252b458cd62SJohnny Huang 				printf("Reserved\n");
1253b458cd62SJohnny Huang 		}
1254b458cd62SJohnny Huang 	}
1255b458cd62SJohnny Huang 
1256b458cd62SJohnny Huang 	if (fail)
1257b458cd62SJohnny Huang 		return OTP_FAILURE;
1258b458cd62SJohnny Huang 
1259b458cd62SJohnny Huang 	return OTP_SUCCESS;
1260b458cd62SJohnny Huang }
1261b458cd62SJohnny Huang 
1262696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len)
126369d5fd8fSJohnny Huang {
126469d5fd8fSJohnny Huang 	int i;
126569d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
126669d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
126769d5fd8fSJohnny Huang 		if (i % 16 == 0) {
126869d5fd8fSJohnny Huang 			printf("%04X: ", i);
126969d5fd8fSJohnny Huang 		}
127069d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
127169d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
127269d5fd8fSJohnny Huang 			printf("\n");
127369d5fd8fSJohnny Huang 		}
127469d5fd8fSJohnny Huang 	}
127569d5fd8fSJohnny Huang }
127669d5fd8fSJohnny Huang 
1277696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
127869d5fd8fSJohnny Huang {
127969d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
128079e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
12819a4fe690SJohnny Huang 	struct otpkey_type key_info;
1282696656c6SJohnny Huang 	uint32_t *buf;
1283696656c6SJohnny Huang 	uint8_t *byte_buf;
12849d998018SJohnny Huang 	char empty = 1;
128569d5fd8fSJohnny Huang 	int i = 0, len = 0;
12869a4fe690SJohnny Huang 	int j;
128754552c69SJohnny Huang 
1288696656c6SJohnny Huang 	byte_buf = image_layout->data;
1289696656c6SJohnny Huang 	buf = (uint32_t *)byte_buf;
12909d998018SJohnny Huang 
12919d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
12929d998018SJohnny Huang 		if (buf[i] != 0) {
12939d998018SJohnny Huang 			empty = 0;
12949d998018SJohnny Huang 		}
12959d998018SJohnny Huang 	}
12969d998018SJohnny Huang 	if (empty)
12979d998018SJohnny Huang 		return 0;
12989d998018SJohnny Huang 
12999d998018SJohnny Huang 	i = 0;
130069d5fd8fSJohnny Huang 	while (1) {
130169d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
130269d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
130369d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
130469d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
130569d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
130669d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
13079a4fe690SJohnny Huang 
13089a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
13099a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
13109a4fe690SJohnny Huang 				key_info = key_info_array[j];
13119a4fe690SJohnny Huang 				break;
13129a4fe690SJohnny Huang 			}
13139a4fe690SJohnny Huang 		}
13149a4fe690SJohnny Huang 
13157f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
131669d5fd8fSJohnny Huang 		printf("Key Type: ");
13179a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
13189a4fe690SJohnny Huang 
13199a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
132069d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
132169d5fd8fSJohnny Huang 			switch (key_length) {
132269d5fd8fSJohnny Huang 			case 0:
132369d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
132469d5fd8fSJohnny Huang 				break;
132569d5fd8fSJohnny Huang 			case 1:
132669d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
132769d5fd8fSJohnny Huang 				break;
132869d5fd8fSJohnny Huang 			case 2:
132969d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
133069d5fd8fSJohnny Huang 				break;
133169d5fd8fSJohnny Huang 			case 3:
133269d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
133369d5fd8fSJohnny Huang 				break;
133469d5fd8fSJohnny Huang 			}
13359a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
133669d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
133769d5fd8fSJohnny Huang 			switch (key_length) {
133869d5fd8fSJohnny Huang 			case 0:
133969d5fd8fSJohnny Huang 				printf("RSA1024\n");
134069d5fd8fSJohnny Huang 				len = 0x100;
134169d5fd8fSJohnny Huang 				break;
134269d5fd8fSJohnny Huang 			case 1:
134369d5fd8fSJohnny Huang 				printf("RSA2048\n");
134469d5fd8fSJohnny Huang 				len = 0x200;
134569d5fd8fSJohnny Huang 				break;
134669d5fd8fSJohnny Huang 			case 2:
134769d5fd8fSJohnny Huang 				printf("RSA3072\n");
134869d5fd8fSJohnny Huang 				len = 0x300;
134969d5fd8fSJohnny Huang 				break;
135069d5fd8fSJohnny Huang 			case 3:
135169d5fd8fSJohnny Huang 				printf("RSA4096\n");
135269d5fd8fSJohnny Huang 				len = 0x400;
135369d5fd8fSJohnny Huang 				break;
135469d5fd8fSJohnny Huang 			}
135569d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
135669d5fd8fSJohnny Huang 		}
13579a4fe690SJohnny Huang 		if (key_info.need_id)
135869d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
135969d5fd8fSJohnny Huang 		printf("Key Value:\n");
13609a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
136169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
13629a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
13639a4fe690SJohnny Huang 			printf("AES Key:\n");
13649a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
13659a4fe690SJohnny Huang 			if (info_cb.version == 0) {
13669a4fe690SJohnny Huang 				printf("AES IV:\n");
13679a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
13689a4fe690SJohnny Huang 			}
13699a4fe690SJohnny Huang 
13709a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
13719a4fe690SJohnny Huang 			if (info_cb.version == 0) {
137269d5fd8fSJohnny Huang 				printf("AES Key:\n");
137369d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
137469d5fd8fSJohnny Huang 				printf("AES IV:\n");
137569d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
13769a4fe690SJohnny Huang 			} else if (info_cb.version == 1) {
13779a4fe690SJohnny Huang 				printf("AES Key 1:\n");
13789a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
13799a4fe690SJohnny Huang 				printf("AES Key 2:\n");
13809a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
13819a4fe690SJohnny Huang 			}
138269d5fd8fSJohnny Huang 
13839a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
138469d5fd8fSJohnny Huang 			printf("RSA mod:\n");
138569d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
138669d5fd8fSJohnny Huang 			printf("RSA exp:\n");
138769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
138869d5fd8fSJohnny Huang 		}
138969d5fd8fSJohnny Huang 		if (last)
139069d5fd8fSJohnny Huang 			break;
139169d5fd8fSJohnny Huang 		i++;
139269d5fd8fSJohnny Huang 	}
139369d5fd8fSJohnny Huang 	return 0;
139469d5fd8fSJohnny Huang }
139569d5fd8fSJohnny Huang 
13965010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout)
139769d5fd8fSJohnny Huang {
1398a6d0d645SJohnny Huang 	int i, k;
1399d90825e2SJohnny Huang 	int pass = 0;
1400a6d0d645SJohnny Huang 	uint32_t prog_address;
1401bb34a7bfSJohnny Huang 	uint32_t data[16];
1402a6d0d645SJohnny Huang 	uint32_t compare[2];
14035010032bSJohnny Huang 	uint32_t *conf = (uint32_t *)image_layout->conf;
14045010032bSJohnny Huang 	uint32_t *conf_ignore = (uint32_t *)image_layout->conf_ignore;
1405d90825e2SJohnny Huang 	uint32_t data_masked;
1406d90825e2SJohnny Huang 	uint32_t buf_masked;
140769d5fd8fSJohnny Huang 
1408a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1409a6d0d645SJohnny Huang 
1410bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
141169d5fd8fSJohnny Huang 		prog_address = 0x800;
1412a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1413a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1414a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1415a6d0d645SJohnny Huang 	}
1416a6d0d645SJohnny Huang 
1417a6d0d645SJohnny Huang 	printf("Check writable...\n");
1418bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
14195010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
14205010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1421d90825e2SJohnny Huang 		if (data_masked == buf_masked)
142269d5fd8fSJohnny Huang 			continue;
1423d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1424a6d0d645SJohnny Huang 			continue;
1425a6d0d645SJohnny Huang 		} else {
1426a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1427a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
14285010032bSJohnny Huang 			printf("Input [%X] = %x\n", i, conf[i]);
14295010032bSJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~conf_ignore[i]);
14302a856b9aSJohnny Huang 			return OTP_FAILURE;
1431a6d0d645SJohnny Huang 		}
1432a6d0d645SJohnny Huang 	}
1433a6d0d645SJohnny Huang 
1434a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1435d90825e2SJohnny Huang 	otp_soak(0);
1436bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
14375010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
14385010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1439a6d0d645SJohnny Huang 		prog_address = 0x800;
1440a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1441a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1442bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1443bb34a7bfSJohnny Huang 			pass = 1;
1444a6d0d645SJohnny Huang 			continue;
1445bb34a7bfSJohnny Huang 		}
1446de6fbf1cSJohnny Huang 
1447a6d0d645SJohnny Huang 
1448de6fbf1cSJohnny Huang 		otp_soak(1);
14495010032bSJohnny Huang 		otp_prog_dw(conf[i], conf_ignore[i], prog_address);
1450a6d0d645SJohnny Huang 
145169d5fd8fSJohnny Huang 		pass = 0;
145269d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
14535010032bSJohnny Huang 			if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1454de6fbf1cSJohnny Huang 				otp_soak(2);
1455a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
14565010032bSJohnny Huang 				if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1457de6fbf1cSJohnny Huang 					otp_soak(1);
1458de6fbf1cSJohnny Huang 				} else {
1459de6fbf1cSJohnny Huang 					pass = 1;
1460de6fbf1cSJohnny Huang 					break;
1461de6fbf1cSJohnny Huang 				}
1462a6d0d645SJohnny Huang 			} else {
146369d5fd8fSJohnny Huang 				pass = 1;
146469d5fd8fSJohnny Huang 				break;
146569d5fd8fSJohnny Huang 			}
146669d5fd8fSJohnny Huang 		}
1467bb34a7bfSJohnny Huang 		if (pass == 0) {
1468bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
14695010032bSJohnny Huang 			       i, data[i], conf[i], conf_ignore[i]);
1470bb34a7bfSJohnny Huang 			break;
1471bb34a7bfSJohnny Huang 		}
1472a6d0d645SJohnny Huang 	}
1473a6d0d645SJohnny Huang 
1474de6fbf1cSJohnny Huang 	otp_soak(0);
147569d5fd8fSJohnny Huang 	if (!pass)
14762a856b9aSJohnny Huang 		return OTP_FAILURE;
1477a6d0d645SJohnny Huang 
14782a856b9aSJohnny Huang 	return OTP_SUCCESS;
1479d90825e2SJohnny Huang 
148069d5fd8fSJohnny Huang }
148169d5fd8fSJohnny Huang 
1482eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit)
1483eda10d61SJohnny Huang {
1484eda10d61SJohnny Huang 	if (ibit == 1) {
1485eda10d61SJohnny Huang 		return OTP_SUCCESS;
1486eda10d61SJohnny Huang 	} else {
1487eda10d61SJohnny Huang 		printf("OTPSTRAP[%X]:\n", offset);
1488eda10d61SJohnny Huang 	}
1489eda10d61SJohnny Huang 	if (bit == otpstrap->value) {
1490eda10d61SJohnny Huang 		printf("    The value is same as before, skip it.\n");
1491eda10d61SJohnny Huang 		return OTP_PROG_SKIP;
1492eda10d61SJohnny Huang 	}
1493eda10d61SJohnny Huang 	if (otpstrap->protected == 1) {
1494eda10d61SJohnny Huang 		printf("    This bit is protected and is not writable\n");
1495eda10d61SJohnny Huang 		return OTP_FAILURE;
1496eda10d61SJohnny Huang 	}
1497eda10d61SJohnny Huang 	if (otpstrap->remain_times == 0) {
1498eda10d61SJohnny Huang 		printf("    This bit is no remaining times to write.\n");
1499eda10d61SJohnny Huang 		return OTP_FAILURE;
1500eda10d61SJohnny Huang 	}
1501eda10d61SJohnny Huang 	if (pbit == 1) {
1502eda10d61SJohnny Huang 		printf("    This bit will be protected and become non-writable.\n");
1503eda10d61SJohnny Huang 	}
1504eda10d61SJohnny Huang 	if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
1505eda10d61SJohnny Huang 		printf("    The relative register will be protected.\n");
1506eda10d61SJohnny Huang 	}
1507eda10d61SJohnny 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);
1508eda10d61SJohnny Huang 	return OTP_SUCCESS;
1509eda10d61SJohnny Huang }
1510eda10d61SJohnny Huang 
151169d5fd8fSJohnny Huang 
15125010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout)
151369d5fd8fSJohnny Huang {
151469d5fd8fSJohnny Huang 	int i;
15155010032bSJohnny Huang 	uint32_t *strap;
15165010032bSJohnny Huang 	uint32_t *strap_ignore;
15175010032bSJohnny Huang 	uint32_t *strap_reg_protect;
15185010032bSJohnny Huang 	uint32_t *strap_pro;
1519eda10d61SJohnny Huang 	int bit, pbit, ibit, rpbit;
152069d5fd8fSJohnny Huang 	int fail = 0;
1521a6af4a17SJohnny Huang 	int skip = -1;
1522eda10d61SJohnny Huang 	int ret;
152366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
152469d5fd8fSJohnny Huang 
15255010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
15265010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
15275010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
15285010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
15295010032bSJohnny Huang 
1530541eb887SJohnny Huang 	otp_strap_status(otpstrap);
153169d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
153269d5fd8fSJohnny Huang 		if (i < 32) {
15335010032bSJohnny Huang 			bit = (strap[0] >> i) & 0x1;
1534eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> i) & 0x1;
15355010032bSJohnny Huang 			pbit = (strap_pro[0] >> i) & 0x1;
153669d5fd8fSJohnny Huang 		} else {
15375010032bSJohnny Huang 			bit = (strap[1] >> (i - 32)) & 0x1;
1538eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> (i - 32)) & 0x1;
15395010032bSJohnny Huang 			pbit = (strap_pro[1] >> (i - 32)) & 0x1;
15405010032bSJohnny Huang 		}
15415010032bSJohnny Huang 
15425010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
15435010032bSJohnny Huang 			if (i < 32) {
15445010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
15455010032bSJohnny Huang 			} else {
15465010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
15475010032bSJohnny Huang 			}
15485010032bSJohnny Huang 		} else {
15495010032bSJohnny Huang 			rpbit = 0;
155069d5fd8fSJohnny Huang 		}
1551eda10d61SJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit);
1552eda10d61SJohnny Huang 		if (ret == OTP_PROG_SKIP) {
1553a6af4a17SJohnny Huang 			if (skip == -1)
1554a6af4a17SJohnny Huang 				skip = 1;
155569d5fd8fSJohnny Huang 			continue;
1556a6af4a17SJohnny Huang 		} else {
1557eda10d61SJohnny Huang 			skip = 1;
155869d5fd8fSJohnny Huang 		}
1559eda10d61SJohnny Huang 
1560eda10d61SJohnny Huang 		if (ret == OTP_FAILURE)
156169d5fd8fSJohnny Huang 			fail = 1;
156269d5fd8fSJohnny Huang 	}
156369d5fd8fSJohnny Huang 	if (fail == 1)
1564a6af4a17SJohnny Huang 		return OTP_FAILURE;
1565a6af4a17SJohnny Huang 	else if (skip == 1)
1566a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
15677e22f42dSJohnny Huang 
1568eda10d61SJohnny Huang 	return OTP_SUCCESS;
156969d5fd8fSJohnny Huang }
157069d5fd8fSJohnny Huang 
15712a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
157269d5fd8fSJohnny Huang {
157369d5fd8fSJohnny Huang 	int i, j;
1574*de6b0cc4SJohnny Huang 	int remains;
157566f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
157669d5fd8fSJohnny Huang 
15772a856b9aSJohnny Huang 	if (start < 0 || start > 64)
15782a856b9aSJohnny Huang 		return OTP_USAGE;
15792a856b9aSJohnny Huang 
15802a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
15812a856b9aSJohnny Huang 		return OTP_USAGE;
15822a856b9aSJohnny Huang 
1583541eb887SJohnny Huang 	otp_strap_status(otpstrap);
158469d5fd8fSJohnny Huang 
1585*de6b0cc4SJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1586*de6b0cc4SJohnny Huang 		remains = 7;
158707baa4e8SJohnny Huang 		printf("BIT(hex)  Value  Option           Status\n");
1588*de6b0cc4SJohnny Huang 	} else {
1589*de6b0cc4SJohnny Huang 		remains = 6;
1590*de6b0cc4SJohnny Huang 		printf("BIT(hex)  Value  Option         Reg_Protect Status\n");
1591*de6b0cc4SJohnny Huang 	}
1592*de6b0cc4SJohnny Huang 	printf("______________________________________________________________________________\n");
1593737ed20bSJohnny Huang 
1594cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
159507baa4e8SJohnny Huang 		printf("0x%-8X", i);
1596737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1597*de6b0cc4SJohnny Huang 		for (j = 0; j < remains; j++)
1598737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1599737ed20bSJohnny Huang 		printf("   ");
1600*de6b0cc4SJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1601*de6b0cc4SJohnny Huang 			printf("%d           ", otpstrap[i].reg_protected);
1602*de6b0cc4SJohnny Huang 		}
160369d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1604737ed20bSJohnny Huang 			printf("protected and not writable");
160569d5fd8fSJohnny Huang 		} else {
1606737ed20bSJohnny Huang 			printf("not protected ");
160769d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1608737ed20bSJohnny Huang 				printf("and no remaining times to write.");
160969d5fd8fSJohnny Huang 			} else {
1610737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
161169d5fd8fSJohnny Huang 			}
161269d5fd8fSJohnny Huang 		}
1613737ed20bSJohnny Huang 		printf("\n");
161469d5fd8fSJohnny Huang 	}
16152a856b9aSJohnny Huang 
16162a856b9aSJohnny Huang 	return OTP_SUCCESS;
161769d5fd8fSJohnny Huang }
161869d5fd8fSJohnny Huang 
16198848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value)
16208848d5dcSJohnny Huang {
16218848d5dcSJohnny Huang 	struct otpstrap_status otpstrap[64];
16228848d5dcSJohnny Huang 	uint32_t prog_bit, prog_address;
16238848d5dcSJohnny Huang 	int offset;
16248848d5dcSJohnny Huang 	int i;
16258848d5dcSJohnny Huang 	int pass;
16268848d5dcSJohnny Huang 	int ret;
16278848d5dcSJohnny Huang 
16288848d5dcSJohnny Huang 
16298848d5dcSJohnny Huang 	otp_strap_status(otpstrap);
16308848d5dcSJohnny Huang 
16318848d5dcSJohnny Huang 	ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
16328848d5dcSJohnny Huang 
16338848d5dcSJohnny Huang 	if (ret != OTP_SUCCESS) {
16348848d5dcSJohnny Huang 		return ret;
16358848d5dcSJohnny Huang 	}
16368848d5dcSJohnny Huang 
16378848d5dcSJohnny Huang 	prog_address = 0x800;
16388848d5dcSJohnny Huang 	if (bit_offset < 32) {
16398848d5dcSJohnny Huang 		offset = bit_offset;
16408848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200;
16418848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2;
16428848d5dcSJohnny Huang 
16438848d5dcSJohnny Huang 	} else {
16448848d5dcSJohnny Huang 		offset = (bit_offset - 32);
16458848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200;
16468848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2;
16478848d5dcSJohnny Huang 	}
16488848d5dcSJohnny Huang 
16498848d5dcSJohnny Huang 	prog_bit = ~(0x1 << offset);
16508848d5dcSJohnny Huang 
16518848d5dcSJohnny Huang 	otp_soak(1);
16528848d5dcSJohnny Huang 	otp_prog(prog_address, prog_bit);
16538848d5dcSJohnny Huang 
16548848d5dcSJohnny Huang 	pass = 0;
16558848d5dcSJohnny Huang 	for (i = 0; i < RETRY; i++) {
16568848d5dcSJohnny Huang 		if (verify_bit(prog_address, offset, 1) != 0) {
16578848d5dcSJohnny Huang 			otp_soak(2);
16588848d5dcSJohnny Huang 			otp_prog(prog_address, prog_bit);
16598848d5dcSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
16608848d5dcSJohnny Huang 				otp_soak(1);
16618848d5dcSJohnny Huang 			} else {
16628848d5dcSJohnny Huang 				pass = 1;
16638848d5dcSJohnny Huang 				break;
16648848d5dcSJohnny Huang 			}
16658848d5dcSJohnny Huang 		} else {
16668848d5dcSJohnny Huang 			pass = 1;
16678848d5dcSJohnny Huang 			break;
16688848d5dcSJohnny Huang 		}
16698848d5dcSJohnny Huang 	}
1670*de6b0cc4SJohnny Huang 	otp_soak(0);
16718848d5dcSJohnny Huang 	if (!pass)
16728848d5dcSJohnny Huang 		return OTP_FAILURE;
16738848d5dcSJohnny Huang 
16748848d5dcSJohnny Huang 	return OTP_SUCCESS;
16758848d5dcSJohnny Huang }
16768848d5dcSJohnny Huang 
16775010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout)
167869d5fd8fSJohnny Huang {
167969d5fd8fSJohnny Huang 	int i, j;
16805010032bSJohnny Huang 	uint32_t *strap;
16815010032bSJohnny Huang 	uint32_t *strap_ignore;
16825010032bSJohnny Huang 	uint32_t *strap_pro;
16835010032bSJohnny Huang 	uint32_t *strap_reg_protect;
168469d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
1685eda10d61SJohnny Huang 	int bit, pbit, ibit, offset, rpbit;
168669d5fd8fSJohnny Huang 	int fail = 0;
16877e22f42dSJohnny Huang 	int pass = 0;
168866f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
168969d5fd8fSJohnny Huang 
16905010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
16915010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
16925010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
16935010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
16945010032bSJohnny Huang 
16957f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1696541eb887SJohnny Huang 	otp_strap_status(otpstrap);
169769d5fd8fSJohnny Huang 
16987f795e57SJohnny Huang 	printf("Check writable...\n");
16995010032bSJohnny Huang 	if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) {
17007f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
17017f795e57SJohnny Huang 		return OTP_FAILURE;
17027f795e57SJohnny Huang 	}
17037e22f42dSJohnny Huang 
170469d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
170569d5fd8fSJohnny Huang 		prog_address = 0x800;
170669d5fd8fSJohnny Huang 		if (i < 32) {
170769d5fd8fSJohnny Huang 			offset = i;
17085010032bSJohnny Huang 			bit = (strap[0] >> offset) & 0x1;
1709eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> offset) & 0x1;
17105010032bSJohnny Huang 			pbit = (strap_pro[0] >> offset) & 0x1;
171169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
171269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
171369d5fd8fSJohnny Huang 
171469d5fd8fSJohnny Huang 		} else {
171569d5fd8fSJohnny Huang 			offset = (i - 32);
17165010032bSJohnny Huang 			bit = (strap[1] >> offset) & 0x1;
1717eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> offset) & 0x1;
17185010032bSJohnny Huang 			pbit = (strap_pro[1] >> offset) & 0x1;
171969d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
172069d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
172169d5fd8fSJohnny Huang 		}
17225010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
17235010032bSJohnny Huang 			if (i < 32) {
17245010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
17255010032bSJohnny Huang 			} else {
17265010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
17275010032bSJohnny Huang 			}
17285010032bSJohnny Huang 		} else {
17295010032bSJohnny Huang 			rpbit = 0;
17305010032bSJohnny Huang 		}
173169d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
173269d5fd8fSJohnny Huang 
1733eda10d61SJohnny Huang 		if (ibit == 1) {
173469d5fd8fSJohnny Huang 			continue;
173569d5fd8fSJohnny Huang 		}
173669d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
173769d5fd8fSJohnny Huang 			continue;
173869d5fd8fSJohnny Huang 		}
173969d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
174069d5fd8fSJohnny Huang 			fail = 1;
174169d5fd8fSJohnny Huang 			continue;
174269d5fd8fSJohnny Huang 		}
174369d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
174469d5fd8fSJohnny Huang 			fail = 1;
174569d5fd8fSJohnny Huang 			continue;
174669d5fd8fSJohnny Huang 		}
17477e22f42dSJohnny Huang 
17487e22f42dSJohnny Huang 
1749de6fbf1cSJohnny Huang 		otp_soak(1);
17507e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
17517e22f42dSJohnny Huang 
17527e22f42dSJohnny Huang 		pass = 0;
175369d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1754de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
1755de6fbf1cSJohnny Huang 				otp_soak(2);
1756de6fbf1cSJohnny Huang 				otp_prog(prog_address, prog_bit);
1757de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1758de6fbf1cSJohnny Huang 					otp_soak(1);
1759de6fbf1cSJohnny Huang 				} else {
176069d5fd8fSJohnny Huang 					pass = 1;
176169d5fd8fSJohnny Huang 					break;
176269d5fd8fSJohnny Huang 				}
1763de6fbf1cSJohnny Huang 			} else {
1764de6fbf1cSJohnny Huang 				pass = 1;
1765de6fbf1cSJohnny Huang 				break;
17664b65a65dSJohnny Huang 			}
176769d5fd8fSJohnny Huang 		}
176869d5fd8fSJohnny Huang 		if (!pass)
17692a856b9aSJohnny Huang 			return OTP_FAILURE;
177069d5fd8fSJohnny Huang 
17715010032bSJohnny Huang 		if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
177269d5fd8fSJohnny Huang 			prog_address = 0x800;
177369d5fd8fSJohnny Huang 			if (i < 32)
17745010032bSJohnny Huang 				prog_address |= 0x608;
177569d5fd8fSJohnny Huang 			else
17765010032bSJohnny Huang 				prog_address |= 0x60a;
17777e22f42dSJohnny Huang 
1778de6fbf1cSJohnny Huang 			otp_soak(1);
17797e22f42dSJohnny Huang 			otp_prog(prog_address, prog_bit);
17807e22f42dSJohnny Huang 
17817e22f42dSJohnny Huang 			pass = 0;
178269d5fd8fSJohnny Huang 			for (j = 0; j < RETRY; j++) {
1783de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1784de6fbf1cSJohnny Huang 					otp_soak(2);
1785de6fbf1cSJohnny Huang 					otp_prog(prog_address, prog_bit);
1786de6fbf1cSJohnny Huang 					if (verify_bit(prog_address, offset, 1) != 0) {
1787de6fbf1cSJohnny Huang 						otp_soak(1);
1788de6fbf1cSJohnny Huang 					} else {
178969d5fd8fSJohnny Huang 						pass = 1;
179069d5fd8fSJohnny Huang 						break;
179169d5fd8fSJohnny Huang 					}
1792de6fbf1cSJohnny Huang 				} else {
1793de6fbf1cSJohnny Huang 					pass = 1;
1794de6fbf1cSJohnny Huang 					break;
179569d5fd8fSJohnny Huang 				}
179669d5fd8fSJohnny Huang 			}
179769d5fd8fSJohnny Huang 			if (!pass)
17982a856b9aSJohnny Huang 				return OTP_FAILURE;
17995010032bSJohnny Huang 		}
18005010032bSJohnny Huang 
18015010032bSJohnny Huang 		if (pbit != 0) {
18025010032bSJohnny Huang 			prog_address = 0x800;
18035010032bSJohnny Huang 			if (i < 32)
18045010032bSJohnny Huang 				prog_address |= 0x60c;
18055010032bSJohnny Huang 			else
18065010032bSJohnny Huang 				prog_address |= 0x60e;
18075010032bSJohnny Huang 
18085010032bSJohnny Huang 			otp_soak(1);
18095010032bSJohnny Huang 			otp_prog(prog_address, prog_bit);
18105010032bSJohnny Huang 
18115010032bSJohnny Huang 			pass = 0;
18125010032bSJohnny Huang 			for (j = 0; j < RETRY; j++) {
18135010032bSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
18145010032bSJohnny Huang 					otp_soak(2);
18155010032bSJohnny Huang 					otp_prog(prog_address, prog_bit);
18165010032bSJohnny Huang 					if (verify_bit(prog_address, offset, 1) != 0) {
18175010032bSJohnny Huang 						otp_soak(1);
18185010032bSJohnny Huang 					} else {
18195010032bSJohnny Huang 						pass = 1;
18205010032bSJohnny Huang 						break;
18215010032bSJohnny Huang 					}
18225010032bSJohnny Huang 				} else {
18235010032bSJohnny Huang 					pass = 1;
18245010032bSJohnny Huang 					break;
18255010032bSJohnny Huang 				}
18265010032bSJohnny Huang 			}
18275010032bSJohnny Huang 			if (!pass)
18285010032bSJohnny Huang 				return OTP_FAILURE;
18295010032bSJohnny Huang 		}
183069d5fd8fSJohnny Huang 
183169d5fd8fSJohnny Huang 	}
1832de6fbf1cSJohnny Huang 	otp_soak(0);
183369d5fd8fSJohnny Huang 	if (fail == 1)
18342a856b9aSJohnny Huang 		return OTP_FAILURE;
183569d5fd8fSJohnny Huang 	else
18362a856b9aSJohnny Huang 		return OTP_SUCCESS;
183769d5fd8fSJohnny Huang 
183869d5fd8fSJohnny Huang }
183969d5fd8fSJohnny Huang 
1840de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
1841cd1610b4SJohnny Huang {
1842cd1610b4SJohnny Huang 	int prog_bit;
1843cd1610b4SJohnny Huang 
1844cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1845cd1610b4SJohnny Huang 		if (value)
1846cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1847cd1610b4SJohnny Huang 		else
1848cd1610b4SJohnny Huang 			return;
1849cd1610b4SJohnny Huang 	} else {
1850cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1851cd1610b4SJohnny Huang 		if (!value)
1852cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1853cd1610b4SJohnny Huang 		else
1854cd1610b4SJohnny Huang 			return;
1855cd1610b4SJohnny Huang 	}
1856cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1857cd1610b4SJohnny Huang }
1858cd1610b4SJohnny Huang 
18595010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout)
18604c1c9b35SJohnny Huang {
186154552c69SJohnny Huang 	int i;
186254552c69SJohnny Huang 	int ret;
18635010032bSJohnny Huang 	int data_dw;
1864d90825e2SJohnny Huang 	uint32_t data[2048];
18655010032bSJohnny Huang 	uint32_t *buf;
18665010032bSJohnny Huang 	uint32_t *buf_ignore;
18674c1c9b35SJohnny Huang 
186854552c69SJohnny Huang 	uint32_t data_masked;
186954552c69SJohnny Huang 	uint32_t buf_masked;
18704c1c9b35SJohnny Huang 
18715010032bSJohnny Huang 	buf = (uint32_t *)image_layout->data;
18725010032bSJohnny Huang 	buf_ignore = (uint32_t *)image_layout->data_ignore;
18735010032bSJohnny Huang 
18745010032bSJohnny Huang 	data_dw = image_layout->data_length / 4;
18755010032bSJohnny Huang 
18764c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
18774c1c9b35SJohnny Huang 
18785010032bSJohnny Huang 	for (i = 0; i < data_dw - 2 ; i += 2) {
1879d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
18804c1c9b35SJohnny Huang 	}
1881d90825e2SJohnny Huang 
18824c1c9b35SJohnny Huang 	printf("Check writable...\n");
188354552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
18845010032bSJohnny Huang 	for (i = 0; i < data_dw - 2; i++) {
1885696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1886696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
188754552c69SJohnny Huang 		if (data_masked == buf_masked)
18884c1c9b35SJohnny Huang 			continue;
1889d90825e2SJohnny Huang 		if (i % 2 == 0) {
189054552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
18914c1c9b35SJohnny Huang 				continue;
18924c1c9b35SJohnny Huang 			} else {
18934c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1894d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
18954c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1896696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
18972a856b9aSJohnny Huang 				return OTP_FAILURE;
189869d5fd8fSJohnny Huang 			}
1899d90825e2SJohnny Huang 		} else {
190054552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1901d90825e2SJohnny Huang 				continue;
1902d90825e2SJohnny Huang 			} else {
1903d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1904d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1905d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1906696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
19072a856b9aSJohnny Huang 				return OTP_FAILURE;
1908d90825e2SJohnny Huang 			}
1909d90825e2SJohnny Huang 		}
1910d90825e2SJohnny Huang 	}
191169d5fd8fSJohnny Huang 
1912d90825e2SJohnny Huang 	printf("Start Programing...\n");
1913d90825e2SJohnny Huang 
191454552c69SJohnny Huang 	// programing ecc region first
191554552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
1916696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
191754552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
191854552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1919696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
192054552c69SJohnny Huang 			return ret;
1921d90825e2SJohnny Huang 		}
1922d90825e2SJohnny Huang 	}
1923d90825e2SJohnny Huang 
192454552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
1925696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
192654552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
192754552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1928696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
192954552c69SJohnny Huang 			return ret;
1930d90825e2SJohnny Huang 		}
1931de6fbf1cSJohnny Huang 	}
1932de6fbf1cSJohnny Huang 	otp_soak(0);
19332a856b9aSJohnny Huang 	return OTP_SUCCESS;
1934d90825e2SJohnny Huang 
1935d90825e2SJohnny Huang }
1936d90825e2SJohnny Huang 
1937696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf)
1938696656c6SJohnny Huang {
1939696656c6SJohnny Huang 	sha256_context ctx;
1940696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
1941696656c6SJohnny Huang 
1942696656c6SJohnny Huang 	sha256_starts(&ctx);
1943696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
1944696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
1945696656c6SJohnny Huang 
1946696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
1947696656c6SJohnny Huang 		return 0;
1948696656c6SJohnny Huang 	else
1949696656c6SJohnny Huang 		return -1;
1950696656c6SJohnny Huang 
1951696656c6SJohnny Huang }
1952696656c6SJohnny Huang 
1953*de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm)
195469d5fd8fSJohnny Huang {
195569d5fd8fSJohnny Huang 	int ret;
19569a4fe690SJohnny Huang 	int image_version = 0;
1957696656c6SJohnny Huang 	struct otp_header *otp_header;
1958696656c6SJohnny Huang 	struct otp_image_layout image_layout;
1959696656c6SJohnny Huang 	int image_size;
1960696656c6SJohnny Huang 	uint8_t *buf;
1961696656c6SJohnny Huang 	uint8_t *checksum;
196269d5fd8fSJohnny Huang 
1963696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
1964696656c6SJohnny Huang 	if (!otp_header) {
196569d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
19662a856b9aSJohnny Huang 		return OTP_FAILURE;
196769d5fd8fSJohnny Huang 	}
1968d90825e2SJohnny Huang 
1969696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
1970696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
1971696656c6SJohnny Huang 
1972696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
1973696656c6SJohnny Huang 
1974696656c6SJohnny Huang 	if (!buf) {
1975696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
1976696656c6SJohnny Huang 		return OTP_FAILURE;
1977696656c6SJohnny Huang 	}
1978696656c6SJohnny Huang 	otp_header = (struct otp_header *) buf;
1979696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
1980696656c6SJohnny Huang 
1981696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
1982696656c6SJohnny Huang 		puts("Image is invalid\n");
1983696656c6SJohnny Huang 		return OTP_FAILURE;
1984696656c6SJohnny Huang 	}
1985696656c6SJohnny Huang 
1986696656c6SJohnny Huang 
19875010032bSJohnny Huang 	image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
19885010032bSJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
19895010032bSJohnny Huang 	image_layout.data_ignore = image_layout.data + image_layout.data_length;
19905010032bSJohnny Huang 
19915010032bSJohnny Huang 	image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
1992696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
19935010032bSJohnny Huang 	image_layout.conf_ignore = image_layout.conf + image_layout.conf_length;
1994696656c6SJohnny Huang 
1995696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
1996696656c6SJohnny Huang 
1997696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
1998696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
19995010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
20005010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + image_layout.strap_length;
20015010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length;
2002696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
2003696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
20045010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
20055010032bSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
20065010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
20075010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
2008696656c6SJohnny Huang 	} else {
2009696656c6SJohnny Huang 		puts("Version is not supported\n");
2010696656c6SJohnny Huang 		return OTP_FAILURE;
2011696656c6SJohnny Huang 	}
2012696656c6SJohnny Huang 
20139a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
20149a4fe690SJohnny Huang 		puts("Version is not match\n");
20159a4fe690SJohnny Huang 		return OTP_FAILURE;
20169a4fe690SJohnny Huang 	}
20179a4fe690SJohnny Huang 
2018696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
2019696656c6SJohnny Huang 		puts("checksum is invalid\n");
2020696656c6SJohnny Huang 		return OTP_FAILURE;
2021d90825e2SJohnny Huang 	}
20227332532cSJohnny Huang 
202369d5fd8fSJohnny Huang 	if (!nconfirm) {
2024696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
20257f795e57SJohnny Huang 			printf("\nOTP data region :\n");
2026696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
202769d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
20282a856b9aSJohnny Huang 				return OTP_FAILURE;
202969d5fd8fSJohnny Huang 			}
203069d5fd8fSJohnny Huang 		}
2031696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
20327332532cSJohnny Huang 			printf("\nOTP strap region :\n");
20335010032bSJohnny Huang 			if (otp_print_strap_image(&image_layout) < 0) {
20347332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
20357332532cSJohnny Huang 				return OTP_FAILURE;
20367332532cSJohnny Huang 			}
20377332532cSJohnny Huang 		}
2038696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
20397332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
2040696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
20417332532cSJohnny Huang 				printf("OTP config error, please check.\n");
20427332532cSJohnny Huang 				return OTP_FAILURE;
20437332532cSJohnny Huang 			}
20447332532cSJohnny Huang 		}
20457332532cSJohnny Huang 
204669d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
204769d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
204869d5fd8fSJohnny Huang 			printf(" Aborting\n");
20492a856b9aSJohnny Huang 			return OTP_FAILURE;
205069d5fd8fSJohnny Huang 		}
205169d5fd8fSJohnny Huang 	}
20527332532cSJohnny Huang 
20535010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_DATA) {
20545010032bSJohnny Huang 		printf("programing data region ...\n");
20555010032bSJohnny Huang 		ret = otp_prog_data(&image_layout);
20565010032bSJohnny Huang 		if (ret != 0) {
20575010032bSJohnny Huang 			printf("Error\n");
20585010032bSJohnny Huang 			return ret;
20595010032bSJohnny Huang 		} else {
20605010032bSJohnny Huang 			printf("Done\n");
20615010032bSJohnny Huang 		}
20625010032bSJohnny Huang 	}
20635010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_STRAP) {
20645010032bSJohnny Huang 		printf("programing strap region ...\n");
20655010032bSJohnny Huang 		ret = otp_prog_strap(&image_layout);
20665010032bSJohnny Huang 		if (ret != 0) {
20675010032bSJohnny Huang 			printf("Error\n");
20685010032bSJohnny Huang 			return ret;
20695010032bSJohnny Huang 		} else {
20705010032bSJohnny Huang 			printf("Done\n");
20715010032bSJohnny Huang 		}
20725010032bSJohnny Huang 	}
20735010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_CONFIG) {
20745010032bSJohnny Huang 		printf("programing configuration region ...\n");
20755010032bSJohnny Huang 		ret = otp_prog_conf(&image_layout);
20765010032bSJohnny Huang 		if (ret != 0) {
20775010032bSJohnny Huang 			printf("Error\n");
20785010032bSJohnny Huang 			return ret;
20795010032bSJohnny Huang 		}
20805010032bSJohnny Huang 		printf("Done\n");
20815010032bSJohnny Huang 	}
2082cd1610b4SJohnny Huang 
20837332532cSJohnny Huang 	return OTP_SUCCESS;
20842a856b9aSJohnny Huang }
20852a856b9aSJohnny Huang 
20862a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
2087cd1610b4SJohnny Huang {
2088a6af4a17SJohnny Huang 	uint32_t read[2];
2089d90825e2SJohnny Huang 	uint32_t prog_address = 0;
209066f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
2091cd1610b4SJohnny Huang 	int otp_bit;
2092cd1610b4SJohnny Huang 	int i;
2093cd1610b4SJohnny Huang 	int pass;
2094a6af4a17SJohnny Huang 	int ret;
2095cd1610b4SJohnny Huang 
2096cd1610b4SJohnny Huang 	switch (mode) {
2097a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2098a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
2099cd1610b4SJohnny Huang 		prog_address = 0x800;
2100cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
2101cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
2102a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
2103cd1610b4SJohnny Huang 		if (otp_bit == value) {
2104a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
2105cd1610b4SJohnny Huang 			printf("No need to program\n");
21062a856b9aSJohnny Huang 			return OTP_SUCCESS;
2107cd1610b4SJohnny Huang 		}
2108cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
2109a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
2110cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
21112a856b9aSJohnny Huang 			return OTP_FAILURE;
2112cd1610b4SJohnny Huang 		}
2113a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
2114cd1610b4SJohnny Huang 		break;
2115a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2116cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
2117cd1610b4SJohnny Huang 
2118cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
2119a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
2120a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
2121643b9cfdSJohnny Huang 
2122643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
2123643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
2124643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
2125643b9cfdSJohnny Huang 				return OTP_FAILURE;
2126643b9cfdSJohnny Huang 			}
2127cd1610b4SJohnny Huang 		} else {
2128a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
2129a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
2130643b9cfdSJohnny Huang 
2131643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
2132643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
2133643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
2134643b9cfdSJohnny Huang 				return OTP_FAILURE;
2135643b9cfdSJohnny Huang 			}
2136cd1610b4SJohnny Huang 		}
2137cd1610b4SJohnny Huang 		if (otp_bit == value) {
2138a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
2139cd1610b4SJohnny Huang 			printf("No need to program\n");
21402a856b9aSJohnny Huang 			return OTP_SUCCESS;
2141cd1610b4SJohnny Huang 		}
2142643b9cfdSJohnny Huang 
2143a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
2144cd1610b4SJohnny Huang 		break;
2145a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
21468848d5dcSJohnny Huang 		otp_strap_status(otpstrap);
21478848d5dcSJohnny Huang 		otp_print_strap(bit_offset, 1);
21488848d5dcSJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
21498848d5dcSJohnny Huang 		if (ret == OTP_FAILURE)
21508848d5dcSJohnny Huang 			return OTP_FAILURE;
21518848d5dcSJohnny Huang 		else if (ret == OTP_PROG_SKIP)
21528848d5dcSJohnny Huang 			return OTP_SUCCESS;
2153a6af4a17SJohnny Huang 
2154cd1610b4SJohnny Huang 		break;
2155cd1610b4SJohnny Huang 	}
2156cd1610b4SJohnny Huang 
2157cd1610b4SJohnny Huang 	if (!nconfirm) {
2158cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2159cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
2160cd1610b4SJohnny Huang 			printf(" Aborting\n");
21612a856b9aSJohnny Huang 			return OTP_FAILURE;
2162cd1610b4SJohnny Huang 		}
2163cd1610b4SJohnny Huang 	}
2164cd1610b4SJohnny Huang 
2165cd1610b4SJohnny Huang 	switch (mode) {
2166a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
21678848d5dcSJohnny Huang 		return otp_prog_strap_bit(bit_offset, value);
2168a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2169a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2170de6fbf1cSJohnny Huang 		otp_soak(1);
2171de6fbf1cSJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset);
2172de6fbf1cSJohnny Huang 		pass = 0;
2173de6fbf1cSJohnny Huang 
2174cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
2175a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
2176de6fbf1cSJohnny Huang 				otp_soak(2);
2177de6fbf1cSJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset);
2178de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, bit_offset, value) != 0) {
2179de6fbf1cSJohnny Huang 					otp_soak(1);
2180cd1610b4SJohnny Huang 				} else {
2181de6fbf1cSJohnny Huang 					pass = 1;
2182de6fbf1cSJohnny Huang 					break;
2183de6fbf1cSJohnny Huang 				}
2184de6fbf1cSJohnny Huang 			} else {
2185de6fbf1cSJohnny Huang 				pass = 1;
2186cd1610b4SJohnny Huang 				break;
2187cd1610b4SJohnny Huang 			}
2188cd1610b4SJohnny Huang 		}
2189de6fbf1cSJohnny Huang 
2190de6fbf1cSJohnny Huang 		otp_soak(0);
2191de6fbf1cSJohnny Huang 		if (pass) {
21929009c25dSJohnny Huang 			printf("SUCCESS\n");
21932a856b9aSJohnny Huang 			return OTP_SUCCESS;
21949009c25dSJohnny Huang 		} else {
21959009c25dSJohnny Huang 			printf("OTP cannot be programed\n");
21969009c25dSJohnny Huang 			printf("FAILED\n");
21979009c25dSJohnny Huang 			return OTP_FAILURE;
21989009c25dSJohnny Huang 		}
2199cd1610b4SJohnny Huang 	}
2200cd1610b4SJohnny Huang 
22012a856b9aSJohnny Huang 	return OTP_USAGE;
2202cd1610b4SJohnny Huang }
2203cd1610b4SJohnny Huang 
22042a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
220569d5fd8fSJohnny Huang {
22062a856b9aSJohnny Huang 	uint32_t offset, count;
22072a856b9aSJohnny Huang 	int ret;
220869d5fd8fSJohnny Huang 
22092a856b9aSJohnny Huang 	if (argc == 4) {
22102a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
22112a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
22122a856b9aSJohnny Huang 	} else if (argc == 3) {
22132a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
22142a856b9aSJohnny Huang 		count = 1;
22152a856b9aSJohnny Huang 	} else {
221669d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
221769d5fd8fSJohnny Huang 	}
221869d5fd8fSJohnny Huang 
221969d5fd8fSJohnny Huang 
22202a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
22213d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
22222a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
22232a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
22243d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
22252a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
22262a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
22273d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
22282a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
22292a856b9aSJohnny Huang 	} else {
22302a856b9aSJohnny Huang 		return CMD_RET_USAGE;
223169d5fd8fSJohnny Huang 	}
223269d5fd8fSJohnny Huang 
22332a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
22342a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
22352a856b9aSJohnny Huang 	else
22362a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22372a856b9aSJohnny Huang 
22382a856b9aSJohnny Huang }
22392a856b9aSJohnny Huang 
22402a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
22412a856b9aSJohnny Huang {
22422a856b9aSJohnny Huang 	phys_addr_t addr;
22432a856b9aSJohnny Huang 	int ret;
22442a856b9aSJohnny Huang 
2245*de6b0cc4SJohnny Huang 	if (argc == 3) {
2246ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
22472a856b9aSJohnny Huang 			return CMD_RET_USAGE;
22482a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
22493d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2250*de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 1);
2251*de6b0cc4SJohnny Huang 	} else if (argc == 2) {
22522a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
22533d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2254*de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 0);
22552a856b9aSJohnny Huang 	} else {
22562a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22572a856b9aSJohnny Huang 	}
22582a856b9aSJohnny Huang 
22592a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
22602a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
22612a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
22622a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
22632a856b9aSJohnny Huang 	else
22642a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22652a856b9aSJohnny Huang }
22662a856b9aSJohnny Huang 
22672a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
22682a856b9aSJohnny Huang {
22692a856b9aSJohnny Huang 	int mode = 0;
22702a856b9aSJohnny Huang 	int nconfirm = 0;
22712a856b9aSJohnny Huang 	int otp_addr = 0;
22722a856b9aSJohnny Huang 	int bit_offset;
22732a856b9aSJohnny Huang 	int value;
22742a856b9aSJohnny Huang 	int ret;
22752a856b9aSJohnny Huang 
22762a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
22772a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22782a856b9aSJohnny Huang 
22792a856b9aSJohnny Huang 	/* Drop the pb cmd */
22802a856b9aSJohnny Huang 	argc--;
22812a856b9aSJohnny Huang 	argv++;
22822a856b9aSJohnny Huang 
22832a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2284a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
22852a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2286a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
22872a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
2288a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
2289cd1610b4SJohnny Huang 	else
22902a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22912a856b9aSJohnny Huang 
22922a856b9aSJohnny Huang 	/* Drop the region cmd */
22932a856b9aSJohnny Huang 	argc--;
22942a856b9aSJohnny Huang 	argv++;
22952a856b9aSJohnny Huang 
2296ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2297cd1610b4SJohnny Huang 		nconfirm = 1;
22982a856b9aSJohnny Huang 		/* Drop the force option */
22992a856b9aSJohnny Huang 		argc--;
23002a856b9aSJohnny Huang 		argv++;
23012a856b9aSJohnny Huang 	}
2302cd1610b4SJohnny Huang 
2303a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
23042a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
23052a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
23060808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
23072a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2308cd1610b4SJohnny Huang 	} else {
23092a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
23102a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
23112a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
23120808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
23132a856b9aSJohnny Huang 			return CMD_RET_USAGE;
23140808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
231578855207SJohnny Huang 			if (otp_addr >= 0x800)
23160808cc55SJohnny Huang 				return CMD_RET_USAGE;
23170808cc55SJohnny Huang 		} else {
231878855207SJohnny Huang 			if (otp_addr >= 0x20)
23190808cc55SJohnny Huang 				return CMD_RET_USAGE;
23200808cc55SJohnny Huang 		}
2321cd1610b4SJohnny Huang 	}
2322cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
23232a856b9aSJohnny Huang 		return CMD_RET_USAGE;
2324cd1610b4SJohnny Huang 
23253d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23262a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
23272a856b9aSJohnny Huang 
23282a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
23292a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
23302a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
23312a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
23322a856b9aSJohnny Huang 	else
23332a856b9aSJohnny Huang 		return CMD_RET_USAGE;
23342a856b9aSJohnny Huang }
23352a856b9aSJohnny Huang 
23362a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
23372a856b9aSJohnny Huang {
23382a856b9aSJohnny Huang 	phys_addr_t addr;
23392a856b9aSJohnny Huang 	int otp_addr = 0;
23402a856b9aSJohnny Huang 
23412a856b9aSJohnny Huang 	if (argc != 3)
23422a856b9aSJohnny Huang 		return CMD_RET_USAGE;
23432a856b9aSJohnny Huang 
23443d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23452a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
23462a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
23472a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
234869d5fd8fSJohnny Huang 		printf("Compare pass\n");
23492a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
235069d5fd8fSJohnny Huang 	} else {
235169d5fd8fSJohnny Huang 		printf("Compare fail\n");
23522a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
235369d5fd8fSJohnny Huang 	}
235469d5fd8fSJohnny Huang }
235569d5fd8fSJohnny Huang 
235666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
235766f2f8e5SJohnny Huang {
2358a8bd6d8cSJohnny Huang 	int view = 0;
23592d4b0742SJohnny Huang 	int input;
2360a8bd6d8cSJohnny Huang 
2361a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
236266f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
236366f2f8e5SJohnny Huang 
23642d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
236566f2f8e5SJohnny Huang 
23663d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23672d4b0742SJohnny Huang 		if (argc == 3) {
23682d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
23692d4b0742SJohnny Huang 			otp_print_conf_info(input);
23702d4b0742SJohnny Huang 		} else {
23712d4b0742SJohnny Huang 			otp_print_conf_info(-1);
23722d4b0742SJohnny Huang 		}
23732d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
23742d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
2375a8bd6d8cSJohnny Huang 			view = 1;
2376a8bd6d8cSJohnny Huang 			/* Drop the view option */
2377a8bd6d8cSJohnny Huang 			argc--;
2378a8bd6d8cSJohnny Huang 			argv++;
2379a8bd6d8cSJohnny Huang 		}
23803d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2381b458cd62SJohnny Huang 		otp_print_strap_info(view);
238266f2f8e5SJohnny Huang 	} else {
238366f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
238466f2f8e5SJohnny Huang 	}
23852d4b0742SJohnny Huang 
238666f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
238766f2f8e5SJohnny Huang }
238866f2f8e5SJohnny Huang 
2389737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2390737ed20bSJohnny Huang {
2391737ed20bSJohnny Huang 	int input;
2392737ed20bSJohnny Huang 	int bit_offset;
2393737ed20bSJohnny Huang 	int prog_address;
2394737ed20bSJohnny Huang 	int pass;
2395737ed20bSJohnny Huang 	int i;
2396737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2397737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2398737ed20bSJohnny Huang 
2399ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2400737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2401737ed20bSJohnny Huang 	} else {
2402737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2403737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2404737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2405737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2406737ed20bSJohnny Huang 			printf(" Aborting\n");
2407737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2408737ed20bSJohnny Huang 		}
2409737ed20bSJohnny Huang 	}
2410737ed20bSJohnny Huang 
2411737ed20bSJohnny Huang 	prog_address = 0x800;
2412737ed20bSJohnny Huang 	if (input < 32) {
2413737ed20bSJohnny Huang 		bit_offset = input;
2414737ed20bSJohnny Huang 		prog_address |= 0x60c;
2415737ed20bSJohnny Huang 	} else if (input < 64) {
2416737ed20bSJohnny Huang 		bit_offset = input - 32;
2417737ed20bSJohnny Huang 		prog_address |= 0x60e;
2418737ed20bSJohnny Huang 	} else {
2419737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2420737ed20bSJohnny Huang 	}
2421737ed20bSJohnny Huang 
2422737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2423737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2424737ed20bSJohnny Huang 	}
2425de6fbf1cSJohnny Huang 
2426de6fbf1cSJohnny Huang 	otp_soak(1);
2427de6fbf1cSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset);
2428de6fbf1cSJohnny Huang 	pass = 0;
2429de6fbf1cSJohnny Huang 
2430737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2431737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2432de6fbf1cSJohnny Huang 			otp_soak(2);
2433de6fbf1cSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset);
2434de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, bit_offset, 1) != 0) {
2435de6fbf1cSJohnny Huang 				otp_soak(1);
2436737ed20bSJohnny Huang 			} else {
2437de6fbf1cSJohnny Huang 				pass = 1;
2438de6fbf1cSJohnny Huang 				break;
2439de6fbf1cSJohnny Huang 			}
2440de6fbf1cSJohnny Huang 		} else {
2441de6fbf1cSJohnny Huang 			pass = 1;
2442737ed20bSJohnny Huang 			break;
2443737ed20bSJohnny Huang 		}
2444737ed20bSJohnny Huang 	}
2445de6fbf1cSJohnny Huang 	otp_soak(0);
2446de6fbf1cSJohnny Huang 	if (pass) {
2447737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2448737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2449737ed20bSJohnny Huang 	}
2450737ed20bSJohnny Huang 
2451737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2452737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2453737ed20bSJohnny Huang 
2454737ed20bSJohnny Huang }
24559a4fe690SJohnny Huang 
24562a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
24572a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2458a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
2459*de6b0cc4SJohnny Huang 	U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""),
24602a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2461737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
24622a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
24632a856b9aSJohnny Huang };
24642a856b9aSJohnny Huang 
24652a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
24662a856b9aSJohnny Huang {
24672a856b9aSJohnny Huang 	cmd_tbl_t *cp;
24682a856b9aSJohnny Huang 
24692a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
24702a856b9aSJohnny Huang 
2471737ed20bSJohnny Huang 	/* Drop the otp command */
24722a856b9aSJohnny Huang 	argc--;
24732a856b9aSJohnny Huang 	argv++;
24742a856b9aSJohnny Huang 
24752a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
24762a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24772a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
24782a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
24792a856b9aSJohnny Huang 
2480696656c6SJohnny Huang 	if (chip_version() == OTP_AST2600A0) {
2481696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
24829a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
24839a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
24849a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
24859a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
24869a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
24879a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
2488696656c6SJohnny Huang 	} else if (chip_version() == OTP_AST2600A1) {
2489696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
24903cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
24913cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
24923cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
24933cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
24949a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
24959a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
24969a4fe690SJohnny Huang 	}
24979a4fe690SJohnny Huang 
24982a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
249969d5fd8fSJohnny Huang }
250069d5fd8fSJohnny Huang 
250169d5fd8fSJohnny Huang U_BOOT_CMD(
250269d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
250369d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
25042a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
25052a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
25062d4b0742SJohnny Huang 	"otp info strap [v]\n"
25072d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2508*de6b0cc4SJohnny Huang 	"otp prog [o] <addr>\n"
2509ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2510ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2511ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
25122a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
251369d5fd8fSJohnny Huang );
2514