xref: /openbmc/u-boot/cmd/otp.c (revision 696656c6cb369a08334bafbc62c540e38e78c017)
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>
23*696656c6SJohnny 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 
63*696656c6SJohnny Huang #define OTP_MAGIC		"SOCOTP"
64*696656c6SJohnny Huang #define CHECKSUM_LEN		32
65*696656c6SJohnny Huang #define OTP_INC_DATA		(1 << 31)
66*696656c6SJohnny Huang #define OTP_INC_CONFIG		(1 << 30)
67*696656c6SJohnny Huang #define OTP_INC_STRAP		(1 << 29)
68*696656c6SJohnny Huang #define OTP_ECC_EN		(1 << 28)
69*696656c6SJohnny Huang #define OTP_REGION_SIZE(info)	((info >> 16) & 0xffff)
70*696656c6SJohnny Huang #define OTP_REGION_OFFSET(info)	(info & 0xffff)
71*696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info)	(info & 0xffff)
72*696656c6SJohnny Huang 
73*696656c6SJohnny Huang #define OTP_AST2600A0		0
74*696656c6SJohnny Huang #define OTP_AST2600A1		1
75*696656c6SJohnny Huang 
76*696656c6SJohnny Huang struct otp_header {
77*696656c6SJohnny Huang 	u8	otp_magic[8];
78*696656c6SJohnny Huang 	u8	otp_version[8];
79*696656c6SJohnny Huang 	u32	image_info;
80*696656c6SJohnny Huang 	u32	data_info;
81*696656c6SJohnny Huang 	u32	config_info;
82*696656c6SJohnny Huang 	u32	strap_info;
83*696656c6SJohnny Huang 	u32	checksum_offset;
84*696656c6SJohnny Huang } __attribute__((packed));
85*696656c6SJohnny 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;
9169d5fd8fSJohnny Huang 	int protected;
9269d5fd8fSJohnny Huang };
9369d5fd8fSJohnny Huang 
9466f2f8e5SJohnny Huang struct otpconf_parse {
9566f2f8e5SJohnny Huang 	int dw_offset;
9666f2f8e5SJohnny Huang 	int bit;
9766f2f8e5SJohnny Huang 	int length;
9866f2f8e5SJohnny Huang 	int value;
99*696656c6SJohnny Huang 	int ignore;
10066f2f8e5SJohnny Huang 	char status[80];
10166f2f8e5SJohnny Huang };
10266f2f8e5SJohnny Huang 
103a8bd6d8cSJohnny Huang struct otpstrap_info {
10479e42a59SJoel Stanley 	int8_t bit_offset;
10579e42a59SJoel Stanley 	int8_t length;
10679e42a59SJoel Stanley 	int8_t value;
10779e42a59SJoel Stanley 	char *information;
108a8bd6d8cSJohnny Huang };
109a8bd6d8cSJohnny Huang 
110a8bd6d8cSJohnny Huang struct otpconf_info {
11179e42a59SJoel Stanley 	int8_t dw_offset;
11279e42a59SJoel Stanley 	int8_t bit_offset;
11379e42a59SJoel Stanley 	int8_t length;
11479e42a59SJoel Stanley 	int8_t value;
11579e42a59SJoel Stanley 	char *information;
116a8bd6d8cSJohnny Huang };
117a8bd6d8cSJohnny Huang 
1189a4fe690SJohnny Huang struct otpkey_type {
1199a4fe690SJohnny Huang 	int value;
1209a4fe690SJohnny Huang 	int key_type;
1219a4fe690SJohnny Huang 	int need_id;
1229a4fe690SJohnny Huang 	char information[110];
1239a4fe690SJohnny Huang };
1249a4fe690SJohnny Huang 
1259a4fe690SJohnny Huang struct otp_info_cb {
1269a4fe690SJohnny Huang 	int version;
12779e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1289a4fe690SJohnny Huang 	int strap_info_len;
12979e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1309a4fe690SJohnny Huang 	int conf_info_len;
13179e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1329a4fe690SJohnny Huang 	int key_info_len;
1339a4fe690SJohnny Huang };
1349a4fe690SJohnny Huang 
135*696656c6SJohnny Huang struct otp_image_layout {
136*696656c6SJohnny Huang 	uint8_t *data;
137*696656c6SJohnny Huang 	uint8_t *data_ignore;
138*696656c6SJohnny Huang 	uint8_t *conf;
139*696656c6SJohnny Huang 	uint8_t *conf_ignore;
140*696656c6SJohnny Huang 	uint8_t *strap;
141*696656c6SJohnny Huang 	uint8_t *strap_reg_pro;
142*696656c6SJohnny Huang 	uint8_t *strap_pro;
143*696656c6SJohnny Huang 	uint8_t *strap_ignore;
144*696656c6SJohnny Huang };
145*696656c6SJohnny Huang 
1469a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1479a4fe690SJohnny Huang 
14879e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = {
14991448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
15091448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
15191448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
15291448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
15391448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
15491448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
15591448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
15691448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
157541eb887SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
15891448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
15991448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
16091448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
16191448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
16291448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
16391448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
16491448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
16591448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
16691448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
16791448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
16891448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
16991448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
17091448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
17191448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
17291448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
17391448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
17491448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
17591448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
17691448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
17791448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
17891448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
17991448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
18091448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
18191448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
18291448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
18391448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
18491448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
18591448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
18691448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
18791448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
18891448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
18991448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
19091448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
19191448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
19291448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
19391448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
19491448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
19591448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
19691448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
19791448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
19891448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
19991448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
20091448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
20191448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
20291448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
20391448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
20491448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
20591448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
20691448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
20791448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
20891448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
20991448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
21091448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
21191448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
21291448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
21391448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
21491448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
21591448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
21691448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
21791448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
21891448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
21991448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
22091448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
22191448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
22291448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
22391448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
22491448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
22591448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
22691448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
22791448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
22891448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
22991448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
23091448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
23191448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
23291448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
23391448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
23491448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
23591448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
23691448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
23791448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
23891448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
23991448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
24091448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
24191448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
24291448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
24391448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
24491448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
24591448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
24691448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
24791448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
24891448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
24991448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
25091448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
25191448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
25291448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
25391448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
25491448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
25591448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
25691448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
25791448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
25876d13988SJohnny Huang };
2599a4fe690SJohnny Huang 
26079e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = {
2613cb28812SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
2623cb28812SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
2633cb28812SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
2643cb28812SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
2653cb28812SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
2663cb28812SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
2673cb28812SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
2683cb28812SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
2693cb28812SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
2703cb28812SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
2713cb28812SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
2723cb28812SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
2733cb28812SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
2743cb28812SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
2753cb28812SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
2763cb28812SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
2773cb28812SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
2783cb28812SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
2793cb28812SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
2803cb28812SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
2813cb28812SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
2823cb28812SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
2833cb28812SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
2843cb28812SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
2853cb28812SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
2863cb28812SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
2873cb28812SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
2883cb28812SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
2893cb28812SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
2903cb28812SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
2913cb28812SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
2923cb28812SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
2933cb28812SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
2943cb28812SJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
2953cb28812SJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
2963cb28812SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
2973cb28812SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
2983cb28812SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
2993cb28812SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
3003cb28812SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
3013cb28812SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
3023cb28812SJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
3033cb28812SJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
3043cb28812SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
3053cb28812SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
3063cb28812SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
3073cb28812SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
3083cb28812SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
3093cb28812SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
3103cb28812SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
3113cb28812SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
3123cb28812SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
3133cb28812SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
3143cb28812SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
3153cb28812SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
3163cb28812SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
3173cb28812SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
3183cb28812SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
3193cb28812SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
3203cb28812SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
3213cb28812SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
3223cb28812SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
3233cb28812SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
3243cb28812SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
3253cb28812SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
3263cb28812SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
3273cb28812SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
3283cb28812SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
3293cb28812SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
3303cb28812SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
3313cb28812SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
3323cb28812SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
3333cb28812SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
3343cb28812SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
3353cb28812SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
3363cb28812SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
3373cb28812SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
3383cb28812SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
3393cb28812SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
3403cb28812SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
3413cb28812SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
3423cb28812SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
3433cb28812SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
3443cb28812SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
3453cb28812SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
3463cb28812SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
3473cb28812SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
3483cb28812SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
3493cb28812SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
3503cb28812SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
3513cb28812SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
3523cb28812SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
3533cb28812SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
3543cb28812SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
3553cb28812SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
3563cb28812SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
3573cb28812SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
3583cb28812SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
3593cb28812SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
3603cb28812SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
3613cb28812SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
3623cb28812SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
3633cb28812SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
3643cb28812SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
3653cb28812SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
3663cb28812SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
3673cb28812SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
3683cb28812SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
3693cb28812SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
3703cb28812SJohnny Huang };
3713cb28812SJohnny Huang 
37279e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = {
37391448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
37491448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
37591448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
37691448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
37791448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
37891448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
37991448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
38091448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
38191448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
38291448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
38391448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
38491448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
38591448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
38691448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
38791448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
38891448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
38991448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
390541eb887SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
39191448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
39291448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
39391448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
39491448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
39591448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
39691448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
39791448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
39891448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
39991448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
40091448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
40191448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
40291448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
40391448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
40491448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
40591448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
40691448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
40791448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
40891448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
40991448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
41091448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
41191448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
41291448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
41391448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
41491448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
41591448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
41691448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
4173cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
4183cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
4193cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
4203cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
4213cb28812SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
4223cb28812SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
4233cb28812SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
4243cb28812SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
4253cb28812SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
4263cb28812SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
4273cb28812SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
4283cb28812SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
4293cb28812SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
4303cb28812SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
4313cb28812SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
4323cb28812SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
4333cb28812SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
4343cb28812SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
4353cb28812SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
4363cb28812SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
4373cb28812SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
4383cb28812SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
4393cb28812SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
4403cb28812SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
4413cb28812SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
4423cb28812SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
4433cb28812SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
4443cb28812SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
4453cb28812SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
4463cb28812SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
4473cb28812SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
4483cb28812SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
4493cb28812SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
4503cb28812SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
4513cb28812SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
4523cb28812SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
4533cb28812SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
4543cb28812SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
4553cb28812SJohnny Huang };
4563cb28812SJohnny Huang 
45779e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = {
4583cb28812SJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
4593cb28812SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
4603cb28812SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
4613cb28812SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
4623cb28812SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
4633cb28812SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
4643cb28812SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
4653cb28812SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
4663cb28812SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
4673cb28812SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
4683cb28812SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
4693cb28812SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
4703cb28812SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
4713cb28812SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
4723cb28812SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
4733cb28812SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
4743cb28812SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
4753cb28812SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
4763cb28812SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
4773cb28812SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
4783cb28812SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
4793cb28812SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
4803cb28812SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
4813cb28812SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
4823cb28812SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
4833cb28812SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
484bb34a7bfSJohnny Huang 	{ 0, 14, 1,  0, "Disable Patch code" },
485bb34a7bfSJohnny Huang 	{ 0, 14, 1,  1, "Enable Patch code" },
486bb34a7bfSJohnny Huang 	{ 0, 15, 1,  OTP_REG_RESERVED, "" },
4873cb28812SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
4883cb28812SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
4893cb28812SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
4903cb28812SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
4913cb28812SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
4923cb28812SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
4933cb28812SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
4943cb28812SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
4953cb28812SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
4963cb28812SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
4973cb28812SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
4983cb28812SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
4993cb28812SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
5003cb28812SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
5013cb28812SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
5023cb28812SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
5033cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
5043cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
5053cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
5063cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
50791448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
50891448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
50991448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
51073f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
51173f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
51291448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
51391448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
51491448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
51591448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
51691448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
51791448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
51891448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
51991448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
52091448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
52191448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
52291448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
52391448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
52491448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
52591448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
52691448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
52791448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
52891448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
52991448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
53091448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
53191448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
53291448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
53391448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
53491448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
53591448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
53691448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
53791448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
53891448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
53991448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
540bb34a7bfSJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" },
541bb34a7bfSJohnny Huang 	{ 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" },
542bb34a7bfSJohnny Huang 	{ 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" }
543b458cd62SJohnny Huang };
5449a4fe690SJohnny Huang 
54579e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
5469a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
5479a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5489a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
5499a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5509a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
5519a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5529a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
5539a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5549a4fe690SJohnny Huang };
5559a4fe690SJohnny Huang 
55679e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
5579a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5589a4fe690SJohnny 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"},
5599a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5609a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5619a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5629a4fe690SJohnny Huang };
5639a4fe690SJohnny Huang 
5649a4fe690SJohnny Huang static uint32_t chip_version(void)
5659a4fe690SJohnny Huang {
5669a4fe690SJohnny Huang 	uint32_t rev_id;
5679a4fe690SJohnny Huang 
5689a4fe690SJohnny Huang 	rev_id = (readl(0x1e6e2004) >> 16) & 0xff ;
5699a4fe690SJohnny Huang 
5709a4fe690SJohnny Huang 	return rev_id;
5719a4fe690SJohnny Huang }
5729a4fe690SJohnny Huang 
5733d3688adSJohnny Huang static void wait_complete(void)
5743d3688adSJohnny Huang {
5753d3688adSJohnny Huang 	int reg;
5763d3688adSJohnny Huang 
5773d3688adSJohnny Huang 	do {
5783d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
5793d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
5803d3688adSJohnny Huang }
5813d3688adSJohnny Huang 
5822a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
58369d5fd8fSJohnny Huang {
5843d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
5853d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
5863d3688adSJohnny Huang 	wait_complete();
5873d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
5883d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
58969d5fd8fSJohnny Huang }
59069d5fd8fSJohnny Huang 
5912a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
59269d5fd8fSJohnny Huang {
59369d5fd8fSJohnny Huang 	int config_offset;
59469d5fd8fSJohnny Huang 
59569d5fd8fSJohnny Huang 	config_offset = 0x800;
59669d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
59769d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
59869d5fd8fSJohnny Huang 
5993d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
6003d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6013d3688adSJohnny Huang 	wait_complete();
6023d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
60369d5fd8fSJohnny Huang }
60469d5fd8fSJohnny Huang 
60569d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
60669d5fd8fSJohnny Huang {
60769d5fd8fSJohnny Huang 	int i;
60869d5fd8fSJohnny Huang 	uint32_t ret[1];
60969d5fd8fSJohnny Huang 
61069d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
6112a856b9aSJohnny Huang 		return OTP_USAGE;
61269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
61369d5fd8fSJohnny Huang 		otp_read_config(i, ret);
614a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
61569d5fd8fSJohnny Huang 	}
61669d5fd8fSJohnny Huang 	printf("\n");
6172a856b9aSJohnny Huang 	return OTP_SUCCESS;
61869d5fd8fSJohnny Huang }
61969d5fd8fSJohnny Huang 
62069d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
62169d5fd8fSJohnny Huang {
62269d5fd8fSJohnny Huang 	int i;
62369d5fd8fSJohnny Huang 	uint32_t ret[2];
62469d5fd8fSJohnny Huang 
62569d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
6262a856b9aSJohnny Huang 		return OTP_USAGE;
62769d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
62869d5fd8fSJohnny Huang 		otp_read_data(i, ret);
62969d5fd8fSJohnny Huang 		if (i % 4 == 0)
63069d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
63169d5fd8fSJohnny Huang 		else
63269d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
63369d5fd8fSJohnny Huang 
63469d5fd8fSJohnny Huang 	}
63569d5fd8fSJohnny Huang 	printf("\n");
6362a856b9aSJohnny Huang 	return OTP_SUCCESS;
63769d5fd8fSJohnny Huang }
63869d5fd8fSJohnny Huang 
63969d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
64069d5fd8fSJohnny Huang {
64169d5fd8fSJohnny Huang 	uint32_t ret;
64269d5fd8fSJohnny Huang 	uint32_t *buf;
64369d5fd8fSJohnny Huang 
64469d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
64569d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
64669d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
64769d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
64869d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
6493d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
6503d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
6513d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
6523d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
6533d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
6543d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
6553d3688adSJohnny Huang 	wait_complete();
6563d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
65769d5fd8fSJohnny Huang 	if (ret & 0x1)
65869d5fd8fSJohnny Huang 		return 0;
65969d5fd8fSJohnny Huang 	else
66069d5fd8fSJohnny Huang 		return -1;
66169d5fd8fSJohnny Huang }
66269d5fd8fSJohnny Huang 
66369d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
66469d5fd8fSJohnny Huang {
6653d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6663d3688adSJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
6673d3688adSJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
6683d3688adSJohnny Huang 	wait_complete();
66969d5fd8fSJohnny Huang }
67069d5fd8fSJohnny Huang 
67169d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
67269d5fd8fSJohnny Huang {
6733d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6743d3688adSJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
6753d3688adSJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
6763d3688adSJohnny Huang 	wait_complete();
67769d5fd8fSJohnny Huang }
67869d5fd8fSJohnny Huang 
679a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
68069d5fd8fSJohnny Huang {
68130a8c590SJohnny Huang 	uint32_t ret[2];
68269d5fd8fSJohnny Huang 
68330a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
6843d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
68530a8c590SJohnny Huang 	else
6863d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
68730a8c590SJohnny Huang 
6883d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6893d3688adSJohnny Huang 	wait_complete();
6903d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
6913d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
692a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
69330a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
69430a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
69569d5fd8fSJohnny Huang 			return 0;
69669d5fd8fSJohnny Huang 		else
69769d5fd8fSJohnny Huang 			return -1;
69830a8c590SJohnny Huang 	} else {
69930a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
70030a8c590SJohnny Huang 			return 0;
70130a8c590SJohnny Huang 		else
70230a8c590SJohnny Huang 			return -1;
70330a8c590SJohnny Huang 	}
70430a8c590SJohnny Huang 
70569d5fd8fSJohnny Huang }
70669d5fd8fSJohnny Huang 
707*696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size)
7084c1c9b35SJohnny Huang {
7094c1c9b35SJohnny Huang 	uint32_t ret[2];
7104c1c9b35SJohnny Huang 
7114c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
7124c1c9b35SJohnny Huang 
7134c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
7143d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
7154c1c9b35SJohnny Huang 	else
7163d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
7173d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
7183d3688adSJohnny Huang 	wait_complete();
7193d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
7203d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
7214c1c9b35SJohnny Huang 	if (size == 1) {
7224c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
7234c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
724*696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
7254c1c9b35SJohnny Huang 				compare[0] = 0;
7264c1c9b35SJohnny Huang 				return 0;
7274c1c9b35SJohnny Huang 			} else {
7284c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
7294c1c9b35SJohnny Huang 				return -1;
7304c1c9b35SJohnny Huang 			}
7314c1c9b35SJohnny Huang 
7324c1c9b35SJohnny Huang 		} else {
7334c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
734*696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
7354c1c9b35SJohnny Huang 				compare[0] = ~0;
7364c1c9b35SJohnny Huang 				return 0;
7374c1c9b35SJohnny Huang 			} else {
738d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
7394c1c9b35SJohnny Huang 				return -1;
7404c1c9b35SJohnny Huang 			}
7414c1c9b35SJohnny Huang 		}
7424c1c9b35SJohnny Huang 	} else if (size == 2) {
7434c1c9b35SJohnny Huang 		// otp_addr should be even
744*696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
7454c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7464c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7474c1c9b35SJohnny Huang 			compare[0] = 0;
7484c1c9b35SJohnny Huang 			compare[1] = ~0;
7494c1c9b35SJohnny Huang 			return 0;
7504c1c9b35SJohnny Huang 		} else {
7514c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7524c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7534c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
7544c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
7554c1c9b35SJohnny Huang 			return -1;
7564c1c9b35SJohnny Huang 		}
7574c1c9b35SJohnny Huang 	} else {
7584c1c9b35SJohnny Huang 		return -1;
7594c1c9b35SJohnny Huang 	}
7604c1c9b35SJohnny Huang }
7614c1c9b35SJohnny Huang 
7627e22f42dSJohnny Huang static void otp_soak(int soak)
763d90825e2SJohnny Huang {
764de6fbf1cSJohnny Huang 	switch (soak) {
765de6fbf1cSJohnny Huang 	case 0: //default
766de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x0); // Write MRA
767de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x0); // Write MRB
768de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x0); // Write MR
769de6fbf1cSJohnny Huang 		break;
770de6fbf1cSJohnny Huang 	case 1: //normal program
771de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
772de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
773de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
774de6fbf1cSJohnny Huang 		writel(0x04190760, OTP_TIMING);
775de6fbf1cSJohnny Huang 		break;
776de6fbf1cSJohnny Huang 	case 2: //soak program
777d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
778d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
779d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
780de6fbf1cSJohnny Huang 		writel(0x041930d4, OTP_TIMING);
781de6fbf1cSJohnny Huang 		break;
782d90825e2SJohnny Huang 	}
783de6fbf1cSJohnny Huang 
7843d3688adSJohnny Huang 	wait_complete();
785d90825e2SJohnny Huang }
786d90825e2SJohnny Huang 
787*696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address)
788d90825e2SJohnny Huang {
789d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
790d90825e2SJohnny Huang 
791d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
792*696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
793d90825e2SJohnny Huang 			continue;
794d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
795d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
796d90825e2SJohnny Huang 			if (bit_value)
797d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
798d90825e2SJohnny Huang 			else
799d90825e2SJohnny Huang 				continue;
800d90825e2SJohnny Huang 		} else {
801d90825e2SJohnny Huang 			prog_address |= 1 << 15;
802d90825e2SJohnny Huang 			if (bit_value)
803d90825e2SJohnny Huang 				continue;
804d90825e2SJohnny Huang 			else
805d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
806d90825e2SJohnny Huang 		}
807d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
808d90825e2SJohnny Huang 	}
809d90825e2SJohnny Huang }
810d90825e2SJohnny Huang 
81154552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
81254552c69SJohnny Huang {
81354552c69SJohnny Huang 	int pass;
81454552c69SJohnny Huang 	int i;
81554552c69SJohnny Huang 	uint32_t data0_masked;
81654552c69SJohnny Huang 	uint32_t data1_masked;
81754552c69SJohnny Huang 	uint32_t buf0_masked;
81854552c69SJohnny Huang 	uint32_t buf1_masked;
81954552c69SJohnny Huang 	uint32_t compare[2];
82054552c69SJohnny Huang 
82154552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
82254552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
82354552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
82454552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
82554552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
82654552c69SJohnny Huang 		return 0;
82754552c69SJohnny Huang 
82854552c69SJohnny Huang 	otp_soak(1);
82954552c69SJohnny Huang 	if (data0_masked != buf0_masked)
83054552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
83154552c69SJohnny Huang 	if (data1_masked != buf1_masked)
83254552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
83354552c69SJohnny Huang 
83454552c69SJohnny Huang 	pass = 0;
83554552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
83654552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
83754552c69SJohnny Huang 			otp_soak(2);
83854552c69SJohnny Huang 			if (compare[0] != 0) {
83954552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
84054552c69SJohnny Huang 			}
84154552c69SJohnny Huang 			if (compare[1] != ~0) {
84254552c69SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1);
84354552c69SJohnny Huang 			}
84454552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
84554552c69SJohnny Huang 				otp_soak(1);
84654552c69SJohnny Huang 			} else {
84754552c69SJohnny Huang 				pass = 1;
84854552c69SJohnny Huang 				break;
84954552c69SJohnny Huang 			}
85054552c69SJohnny Huang 		} else {
85154552c69SJohnny Huang 			pass = 1;
85254552c69SJohnny Huang 			break;
85354552c69SJohnny Huang 		}
85454552c69SJohnny Huang 	}
85554552c69SJohnny Huang 
85654552c69SJohnny Huang 	if (!pass) {
85754552c69SJohnny Huang 		otp_soak(0);
85854552c69SJohnny Huang 		return OTP_FAILURE;
85954552c69SJohnny Huang 	}
86054552c69SJohnny Huang 	return OTP_SUCCESS;
86154552c69SJohnny Huang }
86254552c69SJohnny Huang 
86376d13988SJohnny Huang 
864541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
86576d13988SJohnny Huang {
86676d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
86776d13988SJohnny Huang 	int i, j;
86876d13988SJohnny Huang 
86976d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
87076d13988SJohnny Huang 		otpstrap[j].value = 0;
87176d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
87276d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
87376d13988SJohnny Huang 		otpstrap[j].protected = 0;
87476d13988SJohnny Huang 	}
87576d13988SJohnny Huang 
87676d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
87776d13988SJohnny Huang 		int option = (i - 16) / 2;
87876d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
87976d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
88076d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
88176d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
88276d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
88376d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
88476d13988SJohnny Huang 			}
88576d13988SJohnny Huang 			if (bit_value == 1)
88676d13988SJohnny Huang 				otpstrap[j].remain_times --;
88776d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
88876d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
88976d13988SJohnny Huang 		}
89076d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
89176d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
89276d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
89376d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
89476d13988SJohnny Huang 			}
89576d13988SJohnny Huang 			if (bit_value == 1)
89676d13988SJohnny Huang 				otpstrap[j].remain_times --;
89776d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
89876d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
89976d13988SJohnny Huang 		}
90076d13988SJohnny Huang 	}
90176d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
90276d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
90376d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
90476d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
90576d13988SJohnny Huang 			otpstrap[j].protected = 1;
90676d13988SJohnny Huang 	}
90776d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
90876d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
90976d13988SJohnny Huang 			otpstrap[j].protected = 1;
91076d13988SJohnny Huang 	}
91176d13988SJohnny Huang }
91276d13988SJohnny Huang 
913*696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
91469d5fd8fSJohnny Huang {
91579e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
916*696656c6SJohnny Huang 	uint32_t *OTPCFG = (uint32_t *)image_layout->conf;
917*696656c6SJohnny Huang 	uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore;
918b458cd62SJohnny Huang 	uint32_t mask;
919b458cd62SJohnny Huang 	uint32_t dw_offset;
920b458cd62SJohnny Huang 	uint32_t bit_offset;
921b458cd62SJohnny Huang 	uint32_t otp_value;
922*696656c6SJohnny Huang 	uint32_t otp_ignore;
923b458cd62SJohnny Huang 	int fail = 0;
92473f11549SJohnny Huang 	char valid_bit[20];
92566f2f8e5SJohnny Huang 	int i;
92673f11549SJohnny Huang 	int j;
92766f2f8e5SJohnny Huang 
928737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
92966f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
9303cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
9313cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
9323cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
9333cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
934b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
935*696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
936b458cd62SJohnny Huang 
937*696656c6SJohnny Huang 		if (otp_ignore == mask) {
938b458cd62SJohnny Huang 			continue;
939*696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
940b458cd62SJohnny Huang 			fail = 1;
941b458cd62SJohnny Huang 		}
942b458cd62SJohnny Huang 
9433cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
9443cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
9453cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
9463cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
947b458cd62SJohnny Huang 			continue;
948b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
949b458cd62SJohnny Huang 
9503cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
9513cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
95266f2f8e5SJohnny Huang 		} else {
953b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9543cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
9553cb28812SJohnny Huang 			       conf_info[i].bit_offset);
95666f2f8e5SJohnny Huang 		}
957b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
958b458cd62SJohnny Huang 
959b458cd62SJohnny Huang 		if (fail) {
960*696656c6SJohnny Huang 			printf("Ignore mask error\n");
961b458cd62SJohnny Huang 		} else {
9623cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
963b458cd62SJohnny Huang 				printf("Reserved\n");
9643cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
9653cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
966b458cd62SJohnny Huang 				printf("\n");
9673cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
968b458cd62SJohnny Huang 				if (otp_value != 0) {
96973f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
97073f11549SJohnny Huang 						if (otp_value == (1 << j)) {
97173f11549SJohnny Huang 							valid_bit[j * 2] = '1';
972b458cd62SJohnny Huang 						} else {
97373f11549SJohnny Huang 							valid_bit[j * 2] = '0';
97473f11549SJohnny Huang 						}
97573f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
97673f11549SJohnny Huang 					}
97773f11549SJohnny Huang 					valid_bit[15] = 0;
97873f11549SJohnny Huang 				} else {
97973f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
980b458cd62SJohnny Huang 				}
9813cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
982b458cd62SJohnny Huang 				printf("\n");
983b458cd62SJohnny Huang 			} else {
9843cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
985b458cd62SJohnny Huang 			}
986b458cd62SJohnny Huang 		}
987b458cd62SJohnny Huang 	}
988b458cd62SJohnny Huang 
989b458cd62SJohnny Huang 	if (fail)
990b458cd62SJohnny Huang 		return OTP_FAILURE;
991b458cd62SJohnny Huang 
99266f2f8e5SJohnny Huang 	return OTP_SUCCESS;
99366f2f8e5SJohnny Huang }
99466f2f8e5SJohnny Huang 
9952d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
99666f2f8e5SJohnny Huang {
99779e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
998bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
999b458cd62SJohnny Huang 	uint32_t mask;
1000b458cd62SJohnny Huang 	uint32_t dw_offset;
1001b458cd62SJohnny Huang 	uint32_t bit_offset;
1002b458cd62SJohnny Huang 	uint32_t otp_value;
100373f11549SJohnny Huang 	char valid_bit[20];
100466f2f8e5SJohnny Huang 	int i;
100573f11549SJohnny Huang 	int j;
100666f2f8e5SJohnny Huang 
1007bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
100866f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
100966f2f8e5SJohnny Huang 
101066f2f8e5SJohnny Huang 
1011b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
1012b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
10133cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
10143cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
10152d4b0742SJohnny Huang 			continue;
10163cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
10173cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
10183cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
1019b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
1020b458cd62SJohnny Huang 
10213cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
10223cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
10233cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
10243cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
1025b458cd62SJohnny Huang 			continue;
1026b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
1027b458cd62SJohnny Huang 
10283cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
10293cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
1030b458cd62SJohnny Huang 		} else {
1031b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
10323cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
10333cb28812SJohnny Huang 			       conf_info[i].bit_offset);
1034b458cd62SJohnny Huang 		}
1035b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
1036b458cd62SJohnny Huang 
10373cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
1038b458cd62SJohnny Huang 			printf("Reserved\n");
10393cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
10403cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
1041b458cd62SJohnny Huang 			printf("\n");
10423cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1043b458cd62SJohnny Huang 			if (otp_value != 0) {
104473f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
104573f11549SJohnny Huang 					if (otp_value == (1 << j)) {
104673f11549SJohnny Huang 						valid_bit[j * 2] = '1';
1047b458cd62SJohnny Huang 					} else {
104873f11549SJohnny Huang 						valid_bit[j * 2] = '0';
104973f11549SJohnny Huang 					}
105073f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
105173f11549SJohnny Huang 				}
105273f11549SJohnny Huang 				valid_bit[15] = 0;
105373f11549SJohnny Huang 			} else {
105473f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1055b458cd62SJohnny Huang 			}
10563cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
1057b458cd62SJohnny Huang 			printf("\n");
1058b458cd62SJohnny Huang 		} else {
10593cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
1060b458cd62SJohnny Huang 		}
1061b458cd62SJohnny Huang 	}
1062b458cd62SJohnny Huang 	return OTP_SUCCESS;
106366f2f8e5SJohnny Huang }
106466f2f8e5SJohnny Huang 
1065*696656c6SJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout, int version)
106676d13988SJohnny Huang {
106779e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
1068*696656c6SJohnny Huang 	uint32_t *OTPSTRAP;
1069*696656c6SJohnny Huang 	uint32_t *OTPSTRAP_REG_PRO;
1070*696656c6SJohnny Huang 	uint32_t *OTPSTRAP_PRO;
1071*696656c6SJohnny Huang 	uint32_t *OTPSTRAP_IGNORE;
107276d13988SJohnny Huang 	int i;
1073a8bd6d8cSJohnny Huang 	int fail = 0;
1074a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
1075a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
1076a8bd6d8cSJohnny Huang 	uint32_t mask;
1077a8bd6d8cSJohnny Huang 	uint32_t otp_value;
1078*696656c6SJohnny Huang 	uint32_t otp_reg_protect;
1079a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
1080*696656c6SJohnny Huang 	uint32_t otp_ignore;
108176d13988SJohnny Huang 
1082*696656c6SJohnny Huang 	OTPSTRAP = (uint32_t *)image_layout->strap;
1083*696656c6SJohnny Huang 	OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro;
1084*696656c6SJohnny Huang 	OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore;
1085*696656c6SJohnny Huang 	if (version == OTP_AST2600A0) {
1086*696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
1087a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
1088a8bd6d8cSJohnny Huang 		printf("__________________________________________________________________________________________\n");
1089*696656c6SJohnny Huang 	} else {
1090*696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro;
1091*696656c6SJohnny Huang 		printf("BIT(hex)   Value       REG_Protect Protect     Description\n");
1092*696656c6SJohnny Huang 		printf("__________________________________________________________________________________________\n");
1093*696656c6SJohnny Huang 	}
1094b458cd62SJohnny Huang 
10953cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1096*696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
1097a8bd6d8cSJohnny Huang 			dw_offset = 1;
10983cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
1099a8bd6d8cSJohnny Huang 		} else {
1100a8bd6d8cSJohnny Huang 			dw_offset = 0;
11013cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
1102a8bd6d8cSJohnny Huang 		}
110376d13988SJohnny Huang 
11043cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
1105a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
1106a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
1107*696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
1108a8bd6d8cSJohnny Huang 
1109*696656c6SJohnny Huang 		if (version != OTP_AST2600A0)
1110*696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
1111*696656c6SJohnny Huang 
1112*696656c6SJohnny Huang 		if (otp_ignore == mask) {
1113a8bd6d8cSJohnny Huang 			continue;
1114*696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
1115a8bd6d8cSJohnny Huang 			fail = 1;
1116a8bd6d8cSJohnny Huang 		}
1117a8bd6d8cSJohnny Huang 
11183cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
11193cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1120a8bd6d8cSJohnny Huang 			continue;
1121a8bd6d8cSJohnny Huang 
11223cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
11233cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
1124a8bd6d8cSJohnny Huang 		} else {
1125b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
11263cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
11273cb28812SJohnny Huang 			       strap_info[i].bit_offset);
1128a8bd6d8cSJohnny Huang 		}
1129a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
1130*696656c6SJohnny Huang 		if (version != OTP_AST2600A0)
1131*696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
1132a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
1133a8bd6d8cSJohnny Huang 
1134a8bd6d8cSJohnny Huang 		if (fail) {
1135*696656c6SJohnny Huang 			printf("Ignore mask error\n");
1136a8bd6d8cSJohnny Huang 		} else {
11373cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
11383cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1139a8bd6d8cSJohnny Huang 			else
1140a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1141a8bd6d8cSJohnny Huang 		}
1142a8bd6d8cSJohnny Huang 	}
1143a8bd6d8cSJohnny Huang 
1144a8bd6d8cSJohnny Huang 	if (fail)
114576d13988SJohnny Huang 		return OTP_FAILURE;
114676d13988SJohnny Huang 
114776d13988SJohnny Huang 	return OTP_SUCCESS;
114876d13988SJohnny Huang }
114976d13988SJohnny Huang 
1150b458cd62SJohnny Huang static int otp_print_strap_info(int view)
115176d13988SJohnny Huang {
115279e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
115376d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
115407baa4e8SJohnny Huang 	int i, j;
1155b458cd62SJohnny Huang 	int fail = 0;
1156b458cd62SJohnny Huang 	uint32_t bit_offset;
1157b458cd62SJohnny Huang 	uint32_t length;
1158b458cd62SJohnny Huang 	uint32_t otp_value;
1159b458cd62SJohnny Huang 	uint32_t otp_protect;
116076d13988SJohnny Huang 
1161541eb887SJohnny Huang 	otp_strap_status(strap_status);
116276d13988SJohnny Huang 
1163b458cd62SJohnny Huang 	if (view) {
116407baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
116507baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
116607baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
116707baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
1168b458cd62SJohnny Huang 	} else {
1169b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
1170b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
117176d13988SJohnny Huang 	}
11723cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1173b458cd62SJohnny Huang 		otp_value = 0;
11743cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
11753cb28812SJohnny Huang 		length = strap_info[i].length;
1176b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
1177c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
1178c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
1179b458cd62SJohnny Huang 		}
11803cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
11813cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1182b458cd62SJohnny Huang 			continue;
1183b458cd62SJohnny Huang 		if (view) {
1184b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
11853cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
1186b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
118707baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
1188b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
11893cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
1190b458cd62SJohnny Huang 					printf(" Reserved\n");
1191b458cd62SJohnny Huang 					continue;
1192b458cd62SJohnny Huang 				}
1193b458cd62SJohnny Huang 				if (length == 1) {
11943cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
1195b458cd62SJohnny Huang 					continue;
119676d13988SJohnny Huang 				}
119776d13988SJohnny Huang 
1198b458cd62SJohnny Huang 				if (j == 0)
11993cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
1200b458cd62SJohnny Huang 				else if (j == length - 1)
1201b458cd62SJohnny Huang 					printf("\\ \"\n");
1202b458cd62SJohnny Huang 				else
1203b458cd62SJohnny Huang 					printf("| \"\n");
120476d13988SJohnny Huang 			}
1205b458cd62SJohnny Huang 		} else {
1206c947ef08SJohnny Huang 			if (length == 1) {
12073cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
1208b458cd62SJohnny Huang 			} else {
1209b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1210b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1211b458cd62SJohnny Huang 			}
1212b458cd62SJohnny Huang 
1213b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1214b458cd62SJohnny Huang 
12153cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
12163cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1217b458cd62SJohnny Huang 			else
1218b458cd62SJohnny Huang 				printf("Reserved\n");
1219b458cd62SJohnny Huang 		}
1220b458cd62SJohnny Huang 	}
1221b458cd62SJohnny Huang 
1222b458cd62SJohnny Huang 	if (fail)
1223b458cd62SJohnny Huang 		return OTP_FAILURE;
1224b458cd62SJohnny Huang 
1225b458cd62SJohnny Huang 	return OTP_SUCCESS;
1226b458cd62SJohnny Huang }
1227b458cd62SJohnny Huang 
1228*696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len)
122969d5fd8fSJohnny Huang {
123069d5fd8fSJohnny Huang 	int i;
123169d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
123269d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
123369d5fd8fSJohnny Huang 		if (i % 16 == 0) {
123469d5fd8fSJohnny Huang 			printf("%04X: ", i);
123569d5fd8fSJohnny Huang 		}
123669d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
123769d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
123869d5fd8fSJohnny Huang 			printf("\n");
123969d5fd8fSJohnny Huang 		}
124069d5fd8fSJohnny Huang 	}
124169d5fd8fSJohnny Huang }
124269d5fd8fSJohnny Huang 
1243*696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
124469d5fd8fSJohnny Huang {
124569d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
124679e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
12479a4fe690SJohnny Huang 	struct otpkey_type key_info;
1248*696656c6SJohnny Huang 	uint32_t *buf;
1249*696656c6SJohnny Huang 	uint8_t *byte_buf;
12509d998018SJohnny Huang 	char empty = 1;
125169d5fd8fSJohnny Huang 	int i = 0, len = 0;
12529a4fe690SJohnny Huang 	int j;
125354552c69SJohnny Huang 
1254*696656c6SJohnny Huang 	byte_buf = image_layout->data;
1255*696656c6SJohnny Huang 	buf = (uint32_t *)byte_buf;
12569d998018SJohnny Huang 
12579d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
12589d998018SJohnny Huang 		if (buf[i] != 0) {
12599d998018SJohnny Huang 			empty = 0;
12609d998018SJohnny Huang 		}
12619d998018SJohnny Huang 	}
12629d998018SJohnny Huang 	if (empty)
12639d998018SJohnny Huang 		return 0;
12649d998018SJohnny Huang 
12659d998018SJohnny Huang 	i = 0;
126669d5fd8fSJohnny Huang 	while (1) {
126769d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
126869d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
126969d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
127069d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
127169d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
127269d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
12739a4fe690SJohnny Huang 
12749a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
12759a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
12769a4fe690SJohnny Huang 				key_info = key_info_array[j];
12779a4fe690SJohnny Huang 				break;
12789a4fe690SJohnny Huang 			}
12799a4fe690SJohnny Huang 		}
12809a4fe690SJohnny Huang 
12817f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
128269d5fd8fSJohnny Huang 		printf("Key Type: ");
12839a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
12849a4fe690SJohnny Huang 
12859a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
128669d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
128769d5fd8fSJohnny Huang 			switch (key_length) {
128869d5fd8fSJohnny Huang 			case 0:
128969d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
129069d5fd8fSJohnny Huang 				break;
129169d5fd8fSJohnny Huang 			case 1:
129269d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
129369d5fd8fSJohnny Huang 				break;
129469d5fd8fSJohnny Huang 			case 2:
129569d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
129669d5fd8fSJohnny Huang 				break;
129769d5fd8fSJohnny Huang 			case 3:
129869d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
129969d5fd8fSJohnny Huang 				break;
130069d5fd8fSJohnny Huang 			}
13019a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
130269d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
130369d5fd8fSJohnny Huang 			switch (key_length) {
130469d5fd8fSJohnny Huang 			case 0:
130569d5fd8fSJohnny Huang 				printf("RSA1024\n");
130669d5fd8fSJohnny Huang 				len = 0x100;
130769d5fd8fSJohnny Huang 				break;
130869d5fd8fSJohnny Huang 			case 1:
130969d5fd8fSJohnny Huang 				printf("RSA2048\n");
131069d5fd8fSJohnny Huang 				len = 0x200;
131169d5fd8fSJohnny Huang 				break;
131269d5fd8fSJohnny Huang 			case 2:
131369d5fd8fSJohnny Huang 				printf("RSA3072\n");
131469d5fd8fSJohnny Huang 				len = 0x300;
131569d5fd8fSJohnny Huang 				break;
131669d5fd8fSJohnny Huang 			case 3:
131769d5fd8fSJohnny Huang 				printf("RSA4096\n");
131869d5fd8fSJohnny Huang 				len = 0x400;
131969d5fd8fSJohnny Huang 				break;
132069d5fd8fSJohnny Huang 			}
132169d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
132269d5fd8fSJohnny Huang 		}
13239a4fe690SJohnny Huang 		if (key_info.need_id)
132469d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
132569d5fd8fSJohnny Huang 		printf("Key Value:\n");
13269a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
132769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
13289a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
13299a4fe690SJohnny Huang 			printf("AES Key:\n");
13309a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
13319a4fe690SJohnny Huang 			if (info_cb.version == 0) {
13329a4fe690SJohnny Huang 				printf("AES IV:\n");
13339a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
13349a4fe690SJohnny Huang 			}
13359a4fe690SJohnny Huang 
13369a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
13379a4fe690SJohnny Huang 			if (info_cb.version == 0) {
133869d5fd8fSJohnny Huang 				printf("AES Key:\n");
133969d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
134069d5fd8fSJohnny Huang 				printf("AES IV:\n");
134169d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
13429a4fe690SJohnny Huang 			} else if (info_cb.version == 1) {
13439a4fe690SJohnny Huang 				printf("AES Key 1:\n");
13449a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
13459a4fe690SJohnny Huang 				printf("AES Key 2:\n");
13469a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
13479a4fe690SJohnny Huang 			}
134869d5fd8fSJohnny Huang 
13499a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
135069d5fd8fSJohnny Huang 			printf("RSA mod:\n");
135169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
135269d5fd8fSJohnny Huang 			printf("RSA exp:\n");
135369d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
135469d5fd8fSJohnny Huang 		}
135569d5fd8fSJohnny Huang 		if (last)
135669d5fd8fSJohnny Huang 			break;
135769d5fd8fSJohnny Huang 		i++;
135869d5fd8fSJohnny Huang 	}
135969d5fd8fSJohnny Huang 	return 0;
136069d5fd8fSJohnny Huang }
136169d5fd8fSJohnny Huang 
1362a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
136369d5fd8fSJohnny Huang {
1364a6d0d645SJohnny Huang 	int i, k;
1365d90825e2SJohnny Huang 	int pass = 0;
1366a6d0d645SJohnny Huang 	uint32_t prog_address;
1367bb34a7bfSJohnny Huang 	uint32_t data[16];
1368a6d0d645SJohnny Huang 	uint32_t compare[2];
1369*696656c6SJohnny Huang 	uint32_t *buf_ignore = &buf[16];
1370d90825e2SJohnny Huang 	uint32_t data_masked;
1371d90825e2SJohnny Huang 	uint32_t buf_masked;
137269d5fd8fSJohnny Huang 
1373a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1374a6d0d645SJohnny Huang 
1375bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
137669d5fd8fSJohnny Huang 		prog_address = 0x800;
1377a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1378a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1379a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1380a6d0d645SJohnny Huang 	}
1381a6d0d645SJohnny Huang 
1382a6d0d645SJohnny Huang 	printf("Check writable...\n");
1383bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
1384*696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1385*696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
1386d90825e2SJohnny Huang 		if (data_masked == buf_masked)
138769d5fd8fSJohnny Huang 			continue;
1388d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1389a6d0d645SJohnny Huang 			continue;
1390a6d0d645SJohnny Huang 		} else {
1391a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1392a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1393a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1394*696656c6SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_ignore[i]);
13952a856b9aSJohnny Huang 			return OTP_FAILURE;
1396a6d0d645SJohnny Huang 		}
1397a6d0d645SJohnny Huang 	}
1398a6d0d645SJohnny Huang 
1399a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1400d90825e2SJohnny Huang 	otp_soak(0);
1401bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
1402*696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1403*696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
1404a6d0d645SJohnny Huang 		prog_address = 0x800;
1405a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1406a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1407bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1408bb34a7bfSJohnny Huang 			pass = 1;
1409a6d0d645SJohnny Huang 			continue;
1410bb34a7bfSJohnny Huang 		}
1411de6fbf1cSJohnny Huang 
1412a6d0d645SJohnny Huang 
1413de6fbf1cSJohnny Huang 		otp_soak(1);
1414*696656c6SJohnny Huang 		otp_prog_dw(buf[i], buf_ignore[i], prog_address);
1415a6d0d645SJohnny Huang 
141669d5fd8fSJohnny Huang 		pass = 0;
141769d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1418*696656c6SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_ignore[i], compare, 1) != 0) {
1419de6fbf1cSJohnny Huang 				otp_soak(2);
1420a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1421*696656c6SJohnny Huang 				if (verify_dw(prog_address, &buf[i], &buf_ignore[i], compare, 1) != 0) {
1422de6fbf1cSJohnny Huang 					otp_soak(1);
1423de6fbf1cSJohnny Huang 				} else {
1424de6fbf1cSJohnny Huang 					pass = 1;
1425de6fbf1cSJohnny Huang 					break;
1426de6fbf1cSJohnny Huang 				}
1427a6d0d645SJohnny Huang 			} else {
142869d5fd8fSJohnny Huang 				pass = 1;
142969d5fd8fSJohnny Huang 				break;
143069d5fd8fSJohnny Huang 			}
143169d5fd8fSJohnny Huang 		}
1432bb34a7bfSJohnny Huang 		if (pass == 0) {
1433bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
1434*696656c6SJohnny Huang 			       i, data[i], buf[i], buf_ignore[i]);
1435bb34a7bfSJohnny Huang 			break;
1436bb34a7bfSJohnny Huang 		}
1437a6d0d645SJohnny Huang 	}
1438a6d0d645SJohnny Huang 
1439de6fbf1cSJohnny Huang 	otp_soak(0);
144069d5fd8fSJohnny Huang 	if (!pass)
14412a856b9aSJohnny Huang 		return OTP_FAILURE;
1442a6d0d645SJohnny Huang 
14432a856b9aSJohnny Huang 	return OTP_SUCCESS;
1444d90825e2SJohnny Huang 
144569d5fd8fSJohnny Huang }
144669d5fd8fSJohnny Huang 
144769d5fd8fSJohnny Huang 
144876d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
144969d5fd8fSJohnny Huang {
145069d5fd8fSJohnny Huang 	int i;
1451*696656c6SJohnny Huang 	uint32_t *strap_ignore = buf + 2;
145269d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
145369d5fd8fSJohnny Huang 	int bit, pbit, kbit;
145469d5fd8fSJohnny Huang 	int fail = 0;
1455a6af4a17SJohnny Huang 	int skip = -1;
145666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
145769d5fd8fSJohnny Huang 
1458541eb887SJohnny Huang 	otp_strap_status(otpstrap);
145969d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
146069d5fd8fSJohnny Huang 		if (i < 32) {
146169d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
1462*696656c6SJohnny Huang 			kbit = (strap_ignore[0] >> i) & 0x1;
146369d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
146469d5fd8fSJohnny Huang 		} else {
146569d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
1466*696656c6SJohnny Huang 			kbit = (strap_ignore[1] >> (i - 32)) & 0x1;
146769d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
146869d5fd8fSJohnny Huang 		}
146969d5fd8fSJohnny Huang 
147069d5fd8fSJohnny Huang 		if (kbit == 1) {
147169d5fd8fSJohnny Huang 			continue;
147269d5fd8fSJohnny Huang 		} else {
1473a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
147469d5fd8fSJohnny Huang 		}
147569d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
147669d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1477a6af4a17SJohnny Huang 			if (skip == -1)
1478a6af4a17SJohnny Huang 				skip = 1;
147969d5fd8fSJohnny Huang 			continue;
1480a6af4a17SJohnny Huang 		} else {
1481a6af4a17SJohnny Huang 			skip = 0;
148269d5fd8fSJohnny Huang 		}
148369d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
148469d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
148569d5fd8fSJohnny Huang 			fail = 1;
148669d5fd8fSJohnny Huang 			continue;
148769d5fd8fSJohnny Huang 		}
148869d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1489a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
149069d5fd8fSJohnny Huang 			fail = 1;
149169d5fd8fSJohnny Huang 			continue;
149269d5fd8fSJohnny Huang 		}
149369d5fd8fSJohnny Huang 		if (pbit == 1) {
149469d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
149569d5fd8fSJohnny Huang 		}
1496a6af4a17SJohnny Huang 		printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1);
149769d5fd8fSJohnny Huang 	}
149869d5fd8fSJohnny Huang 	if (fail == 1)
1499a6af4a17SJohnny Huang 		return OTP_FAILURE;
1500a6af4a17SJohnny Huang 	else if (skip == 1)
1501a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
15027e22f42dSJohnny Huang 
15037e22f42dSJohnny Huang 	return 0;
150469d5fd8fSJohnny Huang }
150569d5fd8fSJohnny Huang 
15062a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
150769d5fd8fSJohnny Huang {
150869d5fd8fSJohnny Huang 	int i, j;
150966f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
151069d5fd8fSJohnny Huang 
15112a856b9aSJohnny Huang 	if (start < 0 || start > 64)
15122a856b9aSJohnny Huang 		return OTP_USAGE;
15132a856b9aSJohnny Huang 
15142a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
15152a856b9aSJohnny Huang 		return OTP_USAGE;
15162a856b9aSJohnny Huang 
1517541eb887SJohnny Huang 	otp_strap_status(otpstrap);
151869d5fd8fSJohnny Huang 
151907baa4e8SJohnny Huang 	printf("BIT(hex)  Value  Option           Status\n");
1520a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1521737ed20bSJohnny Huang 
1522cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
152307baa4e8SJohnny Huang 		printf("0x%-8X", i);
1524737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1525737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1526737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1527737ed20bSJohnny Huang 		printf("   ");
152869d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1529737ed20bSJohnny Huang 			printf("protected and not writable");
153069d5fd8fSJohnny Huang 		} else {
1531737ed20bSJohnny Huang 			printf("not protected ");
153269d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1533737ed20bSJohnny Huang 				printf("and no remaining times to write.");
153469d5fd8fSJohnny Huang 			} else {
1535737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
153669d5fd8fSJohnny Huang 			}
153769d5fd8fSJohnny Huang 		}
1538737ed20bSJohnny Huang 		printf("\n");
153969d5fd8fSJohnny Huang 	}
15402a856b9aSJohnny Huang 
15412a856b9aSJohnny Huang 	return OTP_SUCCESS;
154269d5fd8fSJohnny Huang }
154369d5fd8fSJohnny Huang 
154469d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
154569d5fd8fSJohnny Huang {
154669d5fd8fSJohnny Huang 	int i, j;
1547*696656c6SJohnny Huang 	uint32_t *strap_ignore = buf + 2;
154869d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
154969d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
155069d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
155169d5fd8fSJohnny Huang 	int fail = 0;
15527e22f42dSJohnny Huang 	int pass = 0;
155366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
155469d5fd8fSJohnny Huang 
15557f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1556541eb887SJohnny Huang 	otp_strap_status(otpstrap);
155769d5fd8fSJohnny Huang 
15587f795e57SJohnny Huang 	printf("Check writable...\n");
15597f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
15607f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
15617f795e57SJohnny Huang 		return OTP_FAILURE;
15627f795e57SJohnny Huang 	}
15637e22f42dSJohnny Huang 
156469d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
156569d5fd8fSJohnny Huang 		prog_address = 0x800;
156669d5fd8fSJohnny Huang 		if (i < 32) {
156769d5fd8fSJohnny Huang 			offset = i;
156869d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
1569*696656c6SJohnny Huang 			kbit = (strap_ignore[0] >> offset) & 0x1;
157069d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
157169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
157269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
157369d5fd8fSJohnny Huang 
157469d5fd8fSJohnny Huang 		} else {
157569d5fd8fSJohnny Huang 			offset = (i - 32);
157669d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
1577*696656c6SJohnny Huang 			kbit = (strap_ignore[1] >> offset) & 0x1;
157869d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
157969d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
158069d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
158169d5fd8fSJohnny Huang 		}
158269d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
158369d5fd8fSJohnny Huang 
158469d5fd8fSJohnny Huang 		if (kbit == 1) {
158569d5fd8fSJohnny Huang 			continue;
158669d5fd8fSJohnny Huang 		}
158769d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
158869d5fd8fSJohnny Huang 			continue;
158969d5fd8fSJohnny Huang 		}
159069d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
159169d5fd8fSJohnny Huang 			fail = 1;
159269d5fd8fSJohnny Huang 			continue;
159369d5fd8fSJohnny Huang 		}
159469d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
159569d5fd8fSJohnny Huang 			fail = 1;
159669d5fd8fSJohnny Huang 			continue;
159769d5fd8fSJohnny Huang 		}
15987e22f42dSJohnny Huang 
15997e22f42dSJohnny Huang 
1600de6fbf1cSJohnny Huang 		otp_soak(1);
16017e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
16027e22f42dSJohnny Huang 
16037e22f42dSJohnny Huang 		pass = 0;
160469d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1605de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
1606de6fbf1cSJohnny Huang 				otp_soak(2);
1607de6fbf1cSJohnny Huang 				otp_prog(prog_address, prog_bit);
1608de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1609de6fbf1cSJohnny Huang 					otp_soak(1);
1610de6fbf1cSJohnny Huang 				} else {
161169d5fd8fSJohnny Huang 					pass = 1;
161269d5fd8fSJohnny Huang 					break;
161369d5fd8fSJohnny Huang 				}
1614de6fbf1cSJohnny Huang 			} else {
1615de6fbf1cSJohnny Huang 				pass = 1;
1616de6fbf1cSJohnny Huang 				break;
16174b65a65dSJohnny Huang 			}
161869d5fd8fSJohnny Huang 		}
161969d5fd8fSJohnny Huang 		if (!pass)
16202a856b9aSJohnny Huang 			return OTP_FAILURE;
162169d5fd8fSJohnny Huang 
162269d5fd8fSJohnny Huang 		if (pbit == 0)
162369d5fd8fSJohnny Huang 			continue;
162469d5fd8fSJohnny Huang 		prog_address = 0x800;
162569d5fd8fSJohnny Huang 		if (i < 32)
162669d5fd8fSJohnny Huang 			prog_address |= 0x60c;
162769d5fd8fSJohnny Huang 		else
162869d5fd8fSJohnny Huang 			prog_address |= 0x60e;
162969d5fd8fSJohnny Huang 
16307e22f42dSJohnny Huang 
1631de6fbf1cSJohnny Huang 		otp_soak(1);
16327e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
16337e22f42dSJohnny Huang 
16347e22f42dSJohnny Huang 		pass = 0;
163569d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1636de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
1637de6fbf1cSJohnny Huang 				otp_soak(2);
1638de6fbf1cSJohnny Huang 				otp_prog(prog_address, prog_bit);
1639de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1640de6fbf1cSJohnny Huang 					otp_soak(1);
1641de6fbf1cSJohnny Huang 				} else {
164269d5fd8fSJohnny Huang 					pass = 1;
164369d5fd8fSJohnny Huang 					break;
164469d5fd8fSJohnny Huang 				}
1645de6fbf1cSJohnny Huang 			} else {
1646de6fbf1cSJohnny Huang 				pass = 1;
1647de6fbf1cSJohnny Huang 				break;
164869d5fd8fSJohnny Huang 			}
164969d5fd8fSJohnny Huang 		}
165069d5fd8fSJohnny Huang 		if (!pass)
16512a856b9aSJohnny Huang 			return OTP_FAILURE;
165269d5fd8fSJohnny Huang 
165369d5fd8fSJohnny Huang 	}
1654de6fbf1cSJohnny Huang 	otp_soak(0);
165569d5fd8fSJohnny Huang 	if (fail == 1)
16562a856b9aSJohnny Huang 		return OTP_FAILURE;
165769d5fd8fSJohnny Huang 	else
16582a856b9aSJohnny Huang 		return OTP_SUCCESS;
165969d5fd8fSJohnny Huang 
166069d5fd8fSJohnny Huang }
166169d5fd8fSJohnny Huang 
1662de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
1663cd1610b4SJohnny Huang {
1664cd1610b4SJohnny Huang 	int prog_bit;
1665cd1610b4SJohnny Huang 
1666cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1667cd1610b4SJohnny Huang 		if (value)
1668cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1669cd1610b4SJohnny Huang 		else
1670cd1610b4SJohnny Huang 			return;
1671cd1610b4SJohnny Huang 	} else {
1672cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1673cd1610b4SJohnny Huang 		if (!value)
1674cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1675cd1610b4SJohnny Huang 		else
1676cd1610b4SJohnny Huang 			return;
1677cd1610b4SJohnny Huang 	}
1678cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1679cd1610b4SJohnny Huang }
1680cd1610b4SJohnny Huang 
1681d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
16824c1c9b35SJohnny Huang {
168354552c69SJohnny Huang 	int i;
168454552c69SJohnny Huang 	int ret;
1685d90825e2SJohnny Huang 	uint32_t data[2048];
1686*696656c6SJohnny Huang 	uint32_t *buf_ignore = &buf[2048];
16874c1c9b35SJohnny Huang 
168854552c69SJohnny Huang 	uint32_t data_masked;
168954552c69SJohnny Huang 	uint32_t buf_masked;
16904c1c9b35SJohnny Huang 
16914c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
16924c1c9b35SJohnny Huang 
1693d6cdf762SJohnny Huang 	for (i = 0; i < 2046 ; i += 2) {
1694d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
16954c1c9b35SJohnny Huang 	}
1696d90825e2SJohnny Huang 
16974c1c9b35SJohnny Huang 	printf("Check writable...\n");
169854552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
1699d6cdf762SJohnny Huang 	for (i = 0; i < 2046; i++) {
1700*696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
1701*696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
170254552c69SJohnny Huang 		if (data_masked == buf_masked)
17034c1c9b35SJohnny Huang 			continue;
1704d90825e2SJohnny Huang 		if (i % 2 == 0) {
170554552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
17064c1c9b35SJohnny Huang 				continue;
17074c1c9b35SJohnny Huang 			} else {
17084c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1709d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
17104c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1711*696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
17122a856b9aSJohnny Huang 				return OTP_FAILURE;
171369d5fd8fSJohnny Huang 			}
1714d90825e2SJohnny Huang 		} else {
171554552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1716d90825e2SJohnny Huang 				continue;
1717d90825e2SJohnny Huang 			} else {
1718d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1719d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1720d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1721*696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
17222a856b9aSJohnny Huang 				return OTP_FAILURE;
1723d90825e2SJohnny Huang 			}
1724d90825e2SJohnny Huang 		}
1725d90825e2SJohnny Huang 	}
172669d5fd8fSJohnny Huang 
1727d90825e2SJohnny Huang 	printf("Start Programing...\n");
1728d90825e2SJohnny Huang 
172954552c69SJohnny Huang 	// programing ecc region first
173054552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
1731*696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
173254552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
173354552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1734*696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
173554552c69SJohnny Huang 			return ret;
1736d90825e2SJohnny Huang 		}
1737d90825e2SJohnny Huang 	}
1738d90825e2SJohnny Huang 
173954552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
1740*696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
174154552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
174254552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
1743*696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
174454552c69SJohnny Huang 			return ret;
1745d90825e2SJohnny Huang 		}
1746de6fbf1cSJohnny Huang 	}
1747de6fbf1cSJohnny Huang 	otp_soak(0);
17482a856b9aSJohnny Huang 	return OTP_SUCCESS;
1749d90825e2SJohnny Huang 
1750d90825e2SJohnny Huang }
1751d90825e2SJohnny Huang 
1752*696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf)
1753*696656c6SJohnny Huang {
1754*696656c6SJohnny Huang 	sha256_context ctx;
1755*696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
1756*696656c6SJohnny Huang 
1757*696656c6SJohnny Huang 	sha256_starts(&ctx);
1758*696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
1759*696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
1760*696656c6SJohnny Huang 
1761*696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
1762*696656c6SJohnny Huang 		return 0;
1763*696656c6SJohnny Huang 	else
1764*696656c6SJohnny Huang 		return -1;
1765*696656c6SJohnny Huang 
1766*696656c6SJohnny Huang }
1767*696656c6SJohnny Huang 
1768d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
176969d5fd8fSJohnny Huang {
177069d5fd8fSJohnny Huang 	int ret;
17719a4fe690SJohnny Huang 	int image_version = 0;
1772*696656c6SJohnny Huang 	struct otp_header *otp_header;
1773*696656c6SJohnny Huang 	struct otp_image_layout image_layout;
1774*696656c6SJohnny Huang 	int image_size;
1775*696656c6SJohnny Huang 	int data_region_size;
1776*696656c6SJohnny Huang 	int config_region_size;
1777*696656c6SJohnny Huang 	int strap_region_size;
1778*696656c6SJohnny Huang 	uint8_t *buf;
1779*696656c6SJohnny Huang 	uint8_t *checksum;
178069d5fd8fSJohnny Huang 
1781*696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
1782*696656c6SJohnny Huang 	if (!otp_header) {
178369d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
17842a856b9aSJohnny Huang 		return OTP_FAILURE;
178569d5fd8fSJohnny Huang 	}
1786d90825e2SJohnny Huang 
1787*696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
1788*696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
1789*696656c6SJohnny Huang 
1790*696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
1791*696656c6SJohnny Huang 
1792*696656c6SJohnny Huang 	if (!buf) {
1793*696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
1794*696656c6SJohnny Huang 		return OTP_FAILURE;
1795*696656c6SJohnny Huang 	}
1796*696656c6SJohnny Huang 	otp_header = (struct otp_header *) buf;
1797*696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
1798*696656c6SJohnny Huang 
1799*696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
1800*696656c6SJohnny Huang 		puts("Image is invalid\n");
1801*696656c6SJohnny Huang 		return OTP_FAILURE;
1802*696656c6SJohnny Huang 	}
1803*696656c6SJohnny Huang 
1804*696656c6SJohnny Huang 	data_region_size = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
1805*696656c6SJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
1806*696656c6SJohnny Huang 	image_layout.data_ignore = image_layout.data + data_region_size;
1807*696656c6SJohnny Huang 
1808*696656c6SJohnny Huang 	config_region_size = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
1809*696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
1810*696656c6SJohnny Huang 	image_layout.conf_ignore = image_layout.conf + config_region_size;
1811*696656c6SJohnny Huang 
1812*696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
1813*696656c6SJohnny Huang 
1814*696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
1815*696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
1816*696656c6SJohnny Huang 		strap_region_size = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
1817*696656c6SJohnny Huang 		image_layout.strap_pro = image_layout.strap + strap_region_size;
1818*696656c6SJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * strap_region_size;
1819*696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
1820*696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
1821*696656c6SJohnny Huang 		strap_region_size = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
1822*696656c6SJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + strap_region_size;
1823*696656c6SJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * strap_region_size;
1824*696656c6SJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * strap_region_size;
1825*696656c6SJohnny Huang 	} else {
1826*696656c6SJohnny Huang 		puts("Version is not supported\n");
1827*696656c6SJohnny Huang 		return OTP_FAILURE;
1828*696656c6SJohnny Huang 	}
1829*696656c6SJohnny Huang 
18309a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
18319a4fe690SJohnny Huang 		puts("Version is not match\n");
18329a4fe690SJohnny Huang 		return OTP_FAILURE;
18339a4fe690SJohnny Huang 	}
18349a4fe690SJohnny Huang 
1835*696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
1836*696656c6SJohnny Huang 		puts("checksum is invalid\n");
1837*696656c6SJohnny Huang 		return OTP_FAILURE;
1838d90825e2SJohnny Huang 	}
18397332532cSJohnny Huang 
184069d5fd8fSJohnny Huang 	if (!nconfirm) {
1841*696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
18427f795e57SJohnny Huang 			printf("\nOTP data region :\n");
1843*696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
184469d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
18452a856b9aSJohnny Huang 				return OTP_FAILURE;
184669d5fd8fSJohnny Huang 			}
184769d5fd8fSJohnny Huang 		}
1848*696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
18497332532cSJohnny Huang 			printf("\nOTP strap region :\n");
1850*696656c6SJohnny Huang 			if (otp_print_strap_image(&image_layout, image_version) < 0) {
18517332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
18527332532cSJohnny Huang 				return OTP_FAILURE;
18537332532cSJohnny Huang 			}
18547332532cSJohnny Huang 		}
1855*696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
18567332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
1857*696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
18587332532cSJohnny Huang 				printf("OTP config error, please check.\n");
18597332532cSJohnny Huang 				return OTP_FAILURE;
18607332532cSJohnny Huang 			}
18617332532cSJohnny Huang 		}
18627332532cSJohnny Huang 
186369d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
186469d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
186569d5fd8fSJohnny Huang 			printf(" Aborting\n");
18662a856b9aSJohnny Huang 			return OTP_FAILURE;
186769d5fd8fSJohnny Huang 		}
186869d5fd8fSJohnny Huang 	}
18697332532cSJohnny Huang 
1870*696656c6SJohnny Huang 	// if (otp_header->image_info & OTP_INC_DATA) {
1871*696656c6SJohnny Huang 	// 	printf("programing data region ...\n");
1872*696656c6SJohnny Huang 	// 	ret = otp_prog_data(data_region);
1873*696656c6SJohnny Huang 	// 	if (ret != 0) {
1874*696656c6SJohnny Huang 	// 		printf("Error\n");
1875*696656c6SJohnny Huang 	// 		return ret;
1876*696656c6SJohnny Huang 	// 	} else {
1877*696656c6SJohnny Huang 	// 		printf("Done\n");
1878*696656c6SJohnny Huang 	// 	}
1879*696656c6SJohnny Huang 	// }
1880*696656c6SJohnny Huang 	// if (mode & OTP_REGION_STRAP) {
1881*696656c6SJohnny Huang 	// 	printf("programing strap region ...\n");
1882*696656c6SJohnny Huang 	// 	ret = otp_prog_strap(strap_region);
1883*696656c6SJohnny Huang 	// 	if (ret != 0) {
1884*696656c6SJohnny Huang 	// 		printf("Error\n");
1885*696656c6SJohnny Huang 	// 		return ret;
1886*696656c6SJohnny Huang 	// 	} else {
1887*696656c6SJohnny Huang 	// 		printf("Done\n");
1888*696656c6SJohnny Huang 	// 	}
1889*696656c6SJohnny Huang 	// }
1890*696656c6SJohnny Huang 	// if (mode & OTP_REGION_CONF) {
1891*696656c6SJohnny Huang 	// 	printf("programing configuration region ...\n");
1892*696656c6SJohnny Huang 	// 	ret = otp_prog_conf(conf_region);
1893*696656c6SJohnny Huang 	// 	if (ret != 0) {
1894*696656c6SJohnny Huang 	// 		printf("Error\n");
1895*696656c6SJohnny Huang 	// 		return ret;
1896*696656c6SJohnny Huang 	// 	}
1897*696656c6SJohnny Huang 	// 	printf("Done\n");
1898*696656c6SJohnny Huang 	// }
1899cd1610b4SJohnny Huang 
19007332532cSJohnny Huang 	return OTP_SUCCESS;
19012a856b9aSJohnny Huang }
19022a856b9aSJohnny Huang 
19032a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1904cd1610b4SJohnny Huang {
1905a6af4a17SJohnny Huang 	uint32_t read[2];
1906cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1907d90825e2SJohnny Huang 	uint32_t prog_address = 0;
190866f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1909cd1610b4SJohnny Huang 	int otp_bit;
1910cd1610b4SJohnny Huang 	int i;
1911cd1610b4SJohnny Huang 	int pass;
1912a6af4a17SJohnny Huang 	int ret;
1913cd1610b4SJohnny Huang 
1914cd1610b4SJohnny Huang 	switch (mode) {
1915a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1916a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1917cd1610b4SJohnny Huang 		prog_address = 0x800;
1918cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1919cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1920a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1921cd1610b4SJohnny Huang 		if (otp_bit == value) {
1922a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1923cd1610b4SJohnny Huang 			printf("No need to program\n");
19242a856b9aSJohnny Huang 			return OTP_SUCCESS;
1925cd1610b4SJohnny Huang 		}
1926cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1927a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1928cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
19292a856b9aSJohnny Huang 			return OTP_FAILURE;
1930cd1610b4SJohnny Huang 		}
1931a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1932cd1610b4SJohnny Huang 		break;
1933a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1934cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1935cd1610b4SJohnny Huang 
1936cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1937a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1938a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1939643b9cfdSJohnny Huang 
1940643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1941643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1942643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1943643b9cfdSJohnny Huang 				return OTP_FAILURE;
1944643b9cfdSJohnny Huang 			}
1945cd1610b4SJohnny Huang 		} else {
1946a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1947a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1948643b9cfdSJohnny Huang 
1949643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1950643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1951643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1952643b9cfdSJohnny Huang 				return OTP_FAILURE;
1953643b9cfdSJohnny Huang 			}
1954cd1610b4SJohnny Huang 		}
1955cd1610b4SJohnny Huang 		if (otp_bit == value) {
1956a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1957cd1610b4SJohnny Huang 			printf("No need to program\n");
19582a856b9aSJohnny Huang 			return OTP_SUCCESS;
1959cd1610b4SJohnny Huang 		}
1960643b9cfdSJohnny Huang 
1961a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1962cd1610b4SJohnny Huang 		break;
1963a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1964541eb887SJohnny Huang 		otp_strap_status(otpstrap);
1965cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1966cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1967cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
19683d1cbeb0SJohnny Huang 			strap_buf[1] = 0;
1969cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1970cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
19713d1cbeb0SJohnny Huang 			strap_buf[4] = 0;
1972cd1610b4SJohnny Huang 			strap_buf[5] = 0;
1973cd1610b4SJohnny Huang 		} else {
19743d1cbeb0SJohnny Huang 			strap_buf[0] = 0;
1975cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1976cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1977cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1978cd1610b4SJohnny Huang 			strap_buf[4] = 0;
19793d1cbeb0SJohnny Huang 			strap_buf[5] = 0;
1980cd1610b4SJohnny Huang 		}
198176d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1982a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
19832a856b9aSJohnny Huang 			return OTP_FAILURE;
1984a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1985a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1986a6af4a17SJohnny Huang 
1987cd1610b4SJohnny Huang 		break;
1988cd1610b4SJohnny Huang 	}
1989cd1610b4SJohnny Huang 
1990cd1610b4SJohnny Huang 	if (!nconfirm) {
1991cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1992cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1993cd1610b4SJohnny Huang 			printf(" Aborting\n");
19942a856b9aSJohnny Huang 			return OTP_FAILURE;
1995cd1610b4SJohnny Huang 		}
1996cd1610b4SJohnny Huang 	}
1997cd1610b4SJohnny Huang 
1998cd1610b4SJohnny Huang 	switch (mode) {
1999a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
2000cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
2001a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2002a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2003de6fbf1cSJohnny Huang 		otp_soak(1);
2004de6fbf1cSJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset);
2005de6fbf1cSJohnny Huang 		pass = 0;
2006de6fbf1cSJohnny Huang 
2007cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
2008a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
2009de6fbf1cSJohnny Huang 				otp_soak(2);
2010de6fbf1cSJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset);
2011de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, bit_offset, value) != 0) {
2012de6fbf1cSJohnny Huang 					otp_soak(1);
2013cd1610b4SJohnny Huang 				} else {
2014de6fbf1cSJohnny Huang 					pass = 1;
2015de6fbf1cSJohnny Huang 					break;
2016de6fbf1cSJohnny Huang 				}
2017de6fbf1cSJohnny Huang 			} else {
2018de6fbf1cSJohnny Huang 				pass = 1;
2019cd1610b4SJohnny Huang 				break;
2020cd1610b4SJohnny Huang 			}
2021cd1610b4SJohnny Huang 		}
2022de6fbf1cSJohnny Huang 
2023de6fbf1cSJohnny Huang 		otp_soak(0);
2024de6fbf1cSJohnny Huang 		if (pass) {
20259009c25dSJohnny Huang 			printf("SUCCESS\n");
20262a856b9aSJohnny Huang 			return OTP_SUCCESS;
20279009c25dSJohnny Huang 		} else {
20289009c25dSJohnny Huang 			printf("OTP cannot be programed\n");
20299009c25dSJohnny Huang 			printf("FAILED\n");
20309009c25dSJohnny Huang 			return OTP_FAILURE;
20319009c25dSJohnny Huang 		}
2032cd1610b4SJohnny Huang 	}
2033cd1610b4SJohnny Huang 
20342a856b9aSJohnny Huang 	return OTP_USAGE;
2035cd1610b4SJohnny Huang }
2036cd1610b4SJohnny Huang 
20372a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
203869d5fd8fSJohnny Huang {
20392a856b9aSJohnny Huang 	uint32_t offset, count;
20402a856b9aSJohnny Huang 	int ret;
204169d5fd8fSJohnny Huang 
20422a856b9aSJohnny Huang 	if (argc == 4) {
20432a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
20442a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
20452a856b9aSJohnny Huang 	} else if (argc == 3) {
20462a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
20472a856b9aSJohnny Huang 		count = 1;
20482a856b9aSJohnny Huang 	} else {
204969d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
205069d5fd8fSJohnny Huang 	}
205169d5fd8fSJohnny Huang 
205269d5fd8fSJohnny Huang 
20532a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
20543d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20552a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
20562a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
20573d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20582a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
20592a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
20603d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20612a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
20622a856b9aSJohnny Huang 	} else {
20632a856b9aSJohnny Huang 		return CMD_RET_USAGE;
206469d5fd8fSJohnny Huang 	}
206569d5fd8fSJohnny Huang 
20662a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
20672a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20682a856b9aSJohnny Huang 	else
20692a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20702a856b9aSJohnny Huang 
20712a856b9aSJohnny Huang }
20722a856b9aSJohnny Huang 
20732a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20742a856b9aSJohnny Huang {
20752a856b9aSJohnny Huang 	phys_addr_t addr;
20762a856b9aSJohnny Huang 	uint32_t byte_size;
20772a856b9aSJohnny Huang 	int ret;
20782a856b9aSJohnny Huang 
20792a856b9aSJohnny Huang 	if (argc == 4) {
2080ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
20812a856b9aSJohnny Huang 			return CMD_RET_USAGE;
20822a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
20832a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
20843d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20852a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
20862a856b9aSJohnny Huang 	} else if (argc == 3) {
20872a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
20882a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
20893d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20902a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
20912a856b9aSJohnny Huang 	} else {
20922a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20932a856b9aSJohnny Huang 	}
20942a856b9aSJohnny Huang 
20952a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
20962a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20972a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
20982a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
20992a856b9aSJohnny Huang 	else
21002a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21012a856b9aSJohnny Huang }
21022a856b9aSJohnny Huang 
21032a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21042a856b9aSJohnny Huang {
21052a856b9aSJohnny Huang 	int mode = 0;
21062a856b9aSJohnny Huang 	int nconfirm = 0;
21072a856b9aSJohnny Huang 	int otp_addr = 0;
21082a856b9aSJohnny Huang 	int bit_offset;
21092a856b9aSJohnny Huang 	int value;
21102a856b9aSJohnny Huang 	int ret;
21112a856b9aSJohnny Huang 
21122a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
21132a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21142a856b9aSJohnny Huang 
21152a856b9aSJohnny Huang 	/* Drop the pb cmd */
21162a856b9aSJohnny Huang 	argc--;
21172a856b9aSJohnny Huang 	argv++;
21182a856b9aSJohnny Huang 
21192a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2120a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
21212a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2122a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
21232a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
2124a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
2125cd1610b4SJohnny Huang 	else
21262a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21272a856b9aSJohnny Huang 
21282a856b9aSJohnny Huang 	/* Drop the region cmd */
21292a856b9aSJohnny Huang 	argc--;
21302a856b9aSJohnny Huang 	argv++;
21312a856b9aSJohnny Huang 
2132ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2133cd1610b4SJohnny Huang 		nconfirm = 1;
21342a856b9aSJohnny Huang 		/* Drop the force option */
21352a856b9aSJohnny Huang 		argc--;
21362a856b9aSJohnny Huang 		argv++;
21372a856b9aSJohnny Huang 	}
2138cd1610b4SJohnny Huang 
2139a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
21402a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
21412a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
21420808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
21432a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2144cd1610b4SJohnny Huang 	} else {
21452a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
21462a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
21472a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
21480808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
21492a856b9aSJohnny Huang 			return CMD_RET_USAGE;
21500808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
215178855207SJohnny Huang 			if (otp_addr >= 0x800)
21520808cc55SJohnny Huang 				return CMD_RET_USAGE;
21530808cc55SJohnny Huang 		} else {
215478855207SJohnny Huang 			if (otp_addr >= 0x20)
21550808cc55SJohnny Huang 				return CMD_RET_USAGE;
21560808cc55SJohnny Huang 		}
2157cd1610b4SJohnny Huang 	}
2158cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
21592a856b9aSJohnny Huang 		return CMD_RET_USAGE;
2160cd1610b4SJohnny Huang 
21613d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
21622a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
21632a856b9aSJohnny Huang 
21642a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
21652a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
21662a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
21672a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
21682a856b9aSJohnny Huang 	else
21692a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21702a856b9aSJohnny Huang }
21712a856b9aSJohnny Huang 
21722a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21732a856b9aSJohnny Huang {
21742a856b9aSJohnny Huang 	phys_addr_t addr;
21752a856b9aSJohnny Huang 	int otp_addr = 0;
21762a856b9aSJohnny Huang 
21772a856b9aSJohnny Huang 	if (argc != 3)
21782a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21792a856b9aSJohnny Huang 
21803d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
21812a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
21822a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
21832a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
218469d5fd8fSJohnny Huang 		printf("Compare pass\n");
21852a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
218669d5fd8fSJohnny Huang 	} else {
218769d5fd8fSJohnny Huang 		printf("Compare fail\n");
21882a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
218969d5fd8fSJohnny Huang 	}
219069d5fd8fSJohnny Huang }
219169d5fd8fSJohnny Huang 
219266f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
219366f2f8e5SJohnny Huang {
2194a8bd6d8cSJohnny Huang 	int view = 0;
21952d4b0742SJohnny Huang 	int input;
2196a8bd6d8cSJohnny Huang 
2197a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
219866f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
219966f2f8e5SJohnny Huang 
22002d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
220166f2f8e5SJohnny Huang 
22023d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
22032d4b0742SJohnny Huang 		if (argc == 3) {
22042d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
22052d4b0742SJohnny Huang 			otp_print_conf_info(input);
22062d4b0742SJohnny Huang 		} else {
22072d4b0742SJohnny Huang 			otp_print_conf_info(-1);
22082d4b0742SJohnny Huang 		}
22092d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
22102d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
2211a8bd6d8cSJohnny Huang 			view = 1;
2212a8bd6d8cSJohnny Huang 			/* Drop the view option */
2213a8bd6d8cSJohnny Huang 			argc--;
2214a8bd6d8cSJohnny Huang 			argv++;
2215a8bd6d8cSJohnny Huang 		}
22163d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2217b458cd62SJohnny Huang 		otp_print_strap_info(view);
221866f2f8e5SJohnny Huang 	} else {
221966f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
222066f2f8e5SJohnny Huang 	}
22212d4b0742SJohnny Huang 
222266f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
222366f2f8e5SJohnny Huang }
222466f2f8e5SJohnny Huang 
2225737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2226737ed20bSJohnny Huang {
2227737ed20bSJohnny Huang 	int input;
2228737ed20bSJohnny Huang 	int bit_offset;
2229737ed20bSJohnny Huang 	int prog_address;
2230737ed20bSJohnny Huang 	int pass;
2231737ed20bSJohnny Huang 	int i;
2232737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2233737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2234737ed20bSJohnny Huang 
2235ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2236737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2237737ed20bSJohnny Huang 	} else {
2238737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2239737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2240737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2241737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2242737ed20bSJohnny Huang 			printf(" Aborting\n");
2243737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2244737ed20bSJohnny Huang 		}
2245737ed20bSJohnny Huang 	}
2246737ed20bSJohnny Huang 
2247737ed20bSJohnny Huang 	prog_address = 0x800;
2248737ed20bSJohnny Huang 	if (input < 32) {
2249737ed20bSJohnny Huang 		bit_offset = input;
2250737ed20bSJohnny Huang 		prog_address |= 0x60c;
2251737ed20bSJohnny Huang 	} else if (input < 64) {
2252737ed20bSJohnny Huang 		bit_offset = input - 32;
2253737ed20bSJohnny Huang 		prog_address |= 0x60e;
2254737ed20bSJohnny Huang 	} else {
2255737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2256737ed20bSJohnny Huang 	}
2257737ed20bSJohnny Huang 
2258737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2259737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2260737ed20bSJohnny Huang 	}
2261de6fbf1cSJohnny Huang 
2262de6fbf1cSJohnny Huang 	otp_soak(1);
2263de6fbf1cSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset);
2264de6fbf1cSJohnny Huang 	pass = 0;
2265de6fbf1cSJohnny Huang 
2266737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2267737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2268de6fbf1cSJohnny Huang 			otp_soak(2);
2269de6fbf1cSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset);
2270de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, bit_offset, 1) != 0) {
2271de6fbf1cSJohnny Huang 				otp_soak(1);
2272737ed20bSJohnny Huang 			} else {
2273de6fbf1cSJohnny Huang 				pass = 1;
2274de6fbf1cSJohnny Huang 				break;
2275de6fbf1cSJohnny Huang 			}
2276de6fbf1cSJohnny Huang 		} else {
2277de6fbf1cSJohnny Huang 			pass = 1;
2278737ed20bSJohnny Huang 			break;
2279737ed20bSJohnny Huang 		}
2280737ed20bSJohnny Huang 	}
2281de6fbf1cSJohnny Huang 	otp_soak(0);
2282de6fbf1cSJohnny Huang 	if (pass) {
2283737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2284737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2285737ed20bSJohnny Huang 	}
2286737ed20bSJohnny Huang 
2287737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2288737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2289737ed20bSJohnny Huang 
2290737ed20bSJohnny Huang }
22919a4fe690SJohnny Huang 
22922a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
22932a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2294a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
22952a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
22962a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2297737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
22982a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
22992a856b9aSJohnny Huang };
23002a856b9aSJohnny Huang 
23012a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
23022a856b9aSJohnny Huang {
23032a856b9aSJohnny Huang 	cmd_tbl_t *cp;
23042a856b9aSJohnny Huang 
23052a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
23062a856b9aSJohnny Huang 
2307737ed20bSJohnny Huang 	/* Drop the otp command */
23082a856b9aSJohnny Huang 	argc--;
23092a856b9aSJohnny Huang 	argv++;
23102a856b9aSJohnny Huang 
23112a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
23122a856b9aSJohnny Huang 		return CMD_RET_USAGE;
23132a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
23142a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
23152a856b9aSJohnny Huang 
2316*696656c6SJohnny Huang 	if (chip_version() == OTP_AST2600A0) {
2317*696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
23189a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
23199a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
23209a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
23219a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
23229a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
23239a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
2324*696656c6SJohnny Huang 	} else if (chip_version() == OTP_AST2600A1) {
2325*696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
23263cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
23273cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
23283cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
23293cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
23309a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
23319a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
23329a4fe690SJohnny Huang 	}
23339a4fe690SJohnny Huang 
23342a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
233569d5fd8fSJohnny Huang }
233669d5fd8fSJohnny Huang 
233769d5fd8fSJohnny Huang U_BOOT_CMD(
233869d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
233969d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
23402a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
23412a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
23422d4b0742SJohnny Huang 	"otp info strap [v]\n"
23432d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2344ed071a2bSJohnny Huang 	"otp prog [o] <addr> <byte_size>\n"
2345ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2346ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2347ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
23482a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
234969d5fd8fSJohnny Huang );
2350