xref: /openbmc/u-boot/cmd/otp.c (revision 5fdde29ffbfc171d0fa53bc089ef6578e5e0b0be)
169d5fd8fSJohnny Huang /*
269d5fd8fSJohnny Huang  *  This program is distributed in the hope that it will be useful,
369d5fd8fSJohnny Huang  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
469d5fd8fSJohnny Huang  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
569d5fd8fSJohnny Huang  *  GNU General Public License for more details.
669d5fd8fSJohnny Huang  *
769d5fd8fSJohnny Huang  *  You should have received a copy of the GNU General Public License
869d5fd8fSJohnny Huang  *  along with this program; if not, write to the Free Software
969d5fd8fSJohnny Huang  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1069d5fd8fSJohnny Huang  */
114c1c9b35SJohnny Huang #include <stdlib.h>
1269d5fd8fSJohnny Huang #include <common.h>
1369d5fd8fSJohnny Huang #include <console.h>
1469d5fd8fSJohnny Huang #include <bootretry.h>
1569d5fd8fSJohnny Huang #include <cli.h>
1669d5fd8fSJohnny Huang #include <command.h>
1769d5fd8fSJohnny Huang #include <console.h>
184c1c9b35SJohnny Huang #include <malloc.h>
1969d5fd8fSJohnny Huang #include <inttypes.h>
2069d5fd8fSJohnny Huang #include <mapmem.h>
2169d5fd8fSJohnny Huang #include <asm/io.h>
2269d5fd8fSJohnny Huang #include <linux/compiler.h>
23696656c6SJohnny Huang #include <u-boot/sha256.h>
2469d5fd8fSJohnny Huang 
2569d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2669d5fd8fSJohnny Huang 
2769d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
2869d5fd8fSJohnny Huang #define RETRY				3
297332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
307332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
317332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
3269d5fd8fSJohnny Huang 
332a856b9aSJohnny Huang #define OTP_USAGE			-1
342a856b9aSJohnny Huang #define OTP_FAILURE			-2
352a856b9aSJohnny Huang #define OTP_SUCCESS			0
362a856b9aSJohnny Huang 
37a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
38a6af4a17SJohnny Huang 
399a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA		1
409a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES		2
419a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT		3
429a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC		4
439a4fe690SJohnny Huang 
449a4fe690SJohnny Huang 
45a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
46b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
47b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4876d13988SJohnny Huang 
494c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
504c1c9b35SJohnny Huang #define PBWIDTH 60
514c1c9b35SJohnny Huang 
523d3688adSJohnny Huang #define OTP_BASE		0x1e6f2000
533d3688adSJohnny Huang #define OTP_PROTECT_KEY		OTP_BASE
543d3688adSJohnny Huang #define OTP_COMMAND		OTP_BASE + 0x4
553d3688adSJohnny Huang #define OTP_TIMING		OTP_BASE + 0x8
563d3688adSJohnny Huang #define OTP_ADDR		OTP_BASE + 0x10
573d3688adSJohnny Huang #define OTP_STATUS		OTP_BASE + 0x14
583d3688adSJohnny Huang #define OTP_COMPARE_1		OTP_BASE + 0x20
593d3688adSJohnny Huang #define OTP_COMPARE_2		OTP_BASE + 0x24
603d3688adSJohnny Huang #define OTP_COMPARE_3		OTP_BASE + 0x28
613d3688adSJohnny Huang #define OTP_COMPARE_4		OTP_BASE + 0x2c
623d3688adSJohnny Huang 
63696656c6SJohnny Huang #define OTP_MAGIC		"SOCOTP"
64696656c6SJohnny Huang #define CHECKSUM_LEN		32
65696656c6SJohnny Huang #define OTP_INC_DATA		(1 << 31)
66696656c6SJohnny Huang #define OTP_INC_CONFIG		(1 << 30)
67696656c6SJohnny Huang #define OTP_INC_STRAP		(1 << 29)
68696656c6SJohnny Huang #define OTP_ECC_EN		(1 << 28)
69696656c6SJohnny Huang #define OTP_REGION_SIZE(info)	((info >> 16) & 0xffff)
70696656c6SJohnny Huang #define OTP_REGION_OFFSET(info)	(info & 0xffff)
71696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info)	(info & 0xffff)
72696656c6SJohnny Huang 
73696656c6SJohnny Huang #define OTP_AST2600A0		0
74696656c6SJohnny Huang #define OTP_AST2600A1		1
75*5fdde29fSJohnny Huang #define OTP_AST2600A2		7 // fpga
76696656c6SJohnny Huang 
77696656c6SJohnny Huang struct otp_header {
78696656c6SJohnny Huang 	u8	otp_magic[8];
79696656c6SJohnny Huang 	u8	otp_version[8];
80696656c6SJohnny Huang 	u32	image_info;
81696656c6SJohnny Huang 	u32	data_info;
82696656c6SJohnny Huang 	u32	config_info;
83696656c6SJohnny Huang 	u32	strap_info;
84696656c6SJohnny Huang 	u32	checksum_offset;
85696656c6SJohnny Huang } __attribute__((packed));
86696656c6SJohnny Huang 
8766f2f8e5SJohnny Huang struct otpstrap_status {
8869d5fd8fSJohnny Huang 	int value;
8969d5fd8fSJohnny Huang 	int option_array[7];
9069d5fd8fSJohnny Huang 	int remain_times;
9169d5fd8fSJohnny Huang 	int writeable_option;
925010032bSJohnny Huang 	int reg_protected;
9369d5fd8fSJohnny Huang 	int protected;
9469d5fd8fSJohnny Huang };
9569d5fd8fSJohnny Huang 
9666f2f8e5SJohnny Huang struct otpconf_parse {
9766f2f8e5SJohnny Huang 	int dw_offset;
9866f2f8e5SJohnny Huang 	int bit;
9966f2f8e5SJohnny Huang 	int length;
10066f2f8e5SJohnny Huang 	int value;
101696656c6SJohnny Huang 	int ignore;
10266f2f8e5SJohnny Huang 	char status[80];
10366f2f8e5SJohnny Huang };
10466f2f8e5SJohnny Huang 
105a8bd6d8cSJohnny Huang struct otpstrap_info {
10679e42a59SJoel Stanley 	int8_t bit_offset;
10779e42a59SJoel Stanley 	int8_t length;
10879e42a59SJoel Stanley 	int8_t value;
10979e42a59SJoel Stanley 	char *information;
110a8bd6d8cSJohnny Huang };
111a8bd6d8cSJohnny Huang 
112a8bd6d8cSJohnny Huang struct otpconf_info {
11379e42a59SJoel Stanley 	int8_t dw_offset;
11479e42a59SJoel Stanley 	int8_t bit_offset;
11579e42a59SJoel Stanley 	int8_t length;
11679e42a59SJoel Stanley 	int8_t value;
11779e42a59SJoel Stanley 	char *information;
118a8bd6d8cSJohnny Huang };
119a8bd6d8cSJohnny Huang 
1209a4fe690SJohnny Huang struct otpkey_type {
1219a4fe690SJohnny Huang 	int value;
1229a4fe690SJohnny Huang 	int key_type;
1239a4fe690SJohnny Huang 	int need_id;
1249a4fe690SJohnny Huang 	char information[110];
1259a4fe690SJohnny Huang };
1269a4fe690SJohnny Huang 
1279a4fe690SJohnny Huang struct otp_info_cb {
1289a4fe690SJohnny Huang 	int version;
12979e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1309a4fe690SJohnny Huang 	int strap_info_len;
13179e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1329a4fe690SJohnny Huang 	int conf_info_len;
13379e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1349a4fe690SJohnny Huang 	int key_info_len;
1355010032bSJohnny Huang 
1369a4fe690SJohnny Huang };
1379a4fe690SJohnny Huang 
138696656c6SJohnny Huang struct otp_image_layout {
1395010032bSJohnny Huang 	int data_length;
1405010032bSJohnny Huang 	int conf_length;
1415010032bSJohnny Huang 	int strap_length;
142696656c6SJohnny Huang 	uint8_t *data;
143696656c6SJohnny Huang 	uint8_t *data_ignore;
144696656c6SJohnny Huang 	uint8_t *conf;
145696656c6SJohnny Huang 	uint8_t *conf_ignore;
146696656c6SJohnny Huang 	uint8_t *strap;
147696656c6SJohnny Huang 	uint8_t *strap_reg_pro;
148696656c6SJohnny Huang 	uint8_t *strap_pro;
149696656c6SJohnny Huang 	uint8_t *strap_ignore;
150696656c6SJohnny Huang };
151696656c6SJohnny Huang 
1529a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1539a4fe690SJohnny Huang 
15479e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = {
15591448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
15691448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
15791448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
15891448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
15991448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
16091448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
16191448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
16291448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
163541eb887SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
16491448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
16591448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
16691448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
16791448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
16891448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
16991448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
17091448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
17191448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
17291448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
17391448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
17491448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
17591448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
17691448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
17791448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
17891448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
17991448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
18091448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
18191448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
18291448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
18391448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
18491448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
18591448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
18691448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
18791448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
18891448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
18991448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
19091448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
19191448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
19291448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
19391448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
19491448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
19591448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
19691448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
19791448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
19891448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
19991448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
20091448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
20191448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
20291448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
20391448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
20491448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
20591448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
20691448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
20791448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
20891448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
20991448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
21091448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
21191448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
21291448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
21391448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
21491448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
21591448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
21691448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
21791448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
21891448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
21991448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
22091448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
22191448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
22291448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
22391448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
22491448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
22591448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
22691448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
22791448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
22891448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
22991448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
23091448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
23191448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
23291448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
23391448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
23491448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
23591448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
23691448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
23791448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
23891448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
23991448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
24091448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
24191448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
24291448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
24391448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
24491448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
24591448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
24691448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
24791448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
24891448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
24991448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
25091448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
25191448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
25291448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
25391448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
25491448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
25591448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
25691448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
25791448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
25891448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
25991448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
26091448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
26191448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
26291448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
26391448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
26476d13988SJohnny Huang };
2659a4fe690SJohnny Huang 
26679e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = {
2673cb28812SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
2683cb28812SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
2693cb28812SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
2703cb28812SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
2713cb28812SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
2723cb28812SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
2733cb28812SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
2743cb28812SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
2753cb28812SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
2763cb28812SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
2773cb28812SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
2783cb28812SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
2793cb28812SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
2803cb28812SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
281e1a7245eSJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1.2GHz" },
282e1a7245eSJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 1.6MHz" },
2833cb28812SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
284e1a7245eSJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.6GHz" },
285e1a7245eSJohnny Huang 	{ 7, 3, 4, "CPU Frequency : 800MHz" },
286e1a7245eSJohnny Huang 	{ 7, 3, 5, "CPU Frequency : 800MHz" },
287e1a7245eSJohnny Huang 	{ 7, 3, 6, "CPU Frequency : 800MHz" },
288e1a7245eSJohnny Huang 	{ 7, 3, 7, "CPU Frequency : 800MHz" },
2893cb28812SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
2903cb28812SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
2913cb28812SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
2923cb28812SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
2933cb28812SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
2943cb28812SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
2953cb28812SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
2963cb28812SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
2973cb28812SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
2983cb28812SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
2993cb28812SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
3003cb28812SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
3013cb28812SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
3023cb28812SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
3033cb28812SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
3043cb28812SJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
3053cb28812SJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
3063cb28812SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
3073cb28812SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
3083cb28812SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
3093cb28812SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
3103cb28812SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
3113cb28812SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
3123cb28812SJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
3133cb28812SJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
3143cb28812SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
3153cb28812SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
3163cb28812SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
3173cb28812SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
3183cb28812SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
3193cb28812SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
3203cb28812SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
3213cb28812SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
3223cb28812SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
3233cb28812SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
3243cb28812SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
3253cb28812SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
3263cb28812SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
3273cb28812SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
3283cb28812SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
3293cb28812SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
3303cb28812SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
3313cb28812SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
3323cb28812SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
3333cb28812SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
3343cb28812SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
3353cb28812SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
3363cb28812SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
3373cb28812SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
3383cb28812SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
3393cb28812SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
3403cb28812SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
3413cb28812SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
3423cb28812SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
3433cb28812SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
3443cb28812SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
3453cb28812SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
3463cb28812SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
3473cb28812SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
3483cb28812SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
3493cb28812SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
3503cb28812SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
3513cb28812SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
3523cb28812SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
3533cb28812SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
3543cb28812SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
3553cb28812SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
3563cb28812SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
3573cb28812SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
3583cb28812SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
3593cb28812SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
3603cb28812SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
3613cb28812SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
3623cb28812SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
3633cb28812SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
3643cb28812SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
3653cb28812SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
3663cb28812SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
3673cb28812SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
3683cb28812SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
3693cb28812SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
3703cb28812SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
3713cb28812SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
3723cb28812SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
3733cb28812SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
3743cb28812SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
3753cb28812SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
3763cb28812SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
3773cb28812SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
3783cb28812SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
3793cb28812SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
3803cb28812SJohnny Huang };
3813cb28812SJohnny Huang 
382*5fdde29fSJohnny Huang static const struct otpstrap_info a2_strap_info[] = {
383*5fdde29fSJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
384*5fdde29fSJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
385*5fdde29fSJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
386*5fdde29fSJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
387*5fdde29fSJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
388*5fdde29fSJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
389*5fdde29fSJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
390*5fdde29fSJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
391*5fdde29fSJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
392*5fdde29fSJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
393*5fdde29fSJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
394*5fdde29fSJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
395*5fdde29fSJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
396*5fdde29fSJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
397*5fdde29fSJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1.2GHz" },
398*5fdde29fSJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 1.6MHz" },
399*5fdde29fSJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
400*5fdde29fSJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.6GHz" },
401*5fdde29fSJohnny Huang 	{ 7, 3, 4, "CPU Frequency : 800MHz" },
402*5fdde29fSJohnny Huang 	{ 7, 3, 5, "CPU Frequency : 800MHz" },
403*5fdde29fSJohnny Huang 	{ 7, 3, 6, "CPU Frequency : 800MHz" },
404*5fdde29fSJohnny Huang 	{ 7, 3, 7, "CPU Frequency : 800MHz" },
405*5fdde29fSJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
406*5fdde29fSJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
407*5fdde29fSJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
408*5fdde29fSJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
409*5fdde29fSJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
410*5fdde29fSJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
411*5fdde29fSJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
412*5fdde29fSJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
413*5fdde29fSJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
414*5fdde29fSJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
415*5fdde29fSJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
416*5fdde29fSJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
417*5fdde29fSJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
418*5fdde29fSJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
419*5fdde29fSJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
420*5fdde29fSJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
421*5fdde29fSJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
422*5fdde29fSJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
423*5fdde29fSJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
424*5fdde29fSJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
425*5fdde29fSJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
426*5fdde29fSJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
427*5fdde29fSJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
428*5fdde29fSJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
429*5fdde29fSJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
430*5fdde29fSJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
431*5fdde29fSJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
432*5fdde29fSJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
433*5fdde29fSJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
434*5fdde29fSJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
435*5fdde29fSJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
436*5fdde29fSJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
437*5fdde29fSJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
438*5fdde29fSJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
439*5fdde29fSJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
440*5fdde29fSJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
441*5fdde29fSJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
442*5fdde29fSJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
443*5fdde29fSJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
444*5fdde29fSJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
445*5fdde29fSJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
446*5fdde29fSJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
447*5fdde29fSJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
448*5fdde29fSJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
449*5fdde29fSJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
450*5fdde29fSJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
451*5fdde29fSJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
452*5fdde29fSJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
453*5fdde29fSJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
454*5fdde29fSJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
455*5fdde29fSJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
456*5fdde29fSJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
457*5fdde29fSJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
458*5fdde29fSJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
459*5fdde29fSJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
460*5fdde29fSJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
461*5fdde29fSJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
462*5fdde29fSJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
463*5fdde29fSJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
464*5fdde29fSJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
465*5fdde29fSJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
466*5fdde29fSJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
467*5fdde29fSJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
468*5fdde29fSJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
469*5fdde29fSJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
470*5fdde29fSJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
471*5fdde29fSJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
472*5fdde29fSJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
473*5fdde29fSJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
474*5fdde29fSJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
475*5fdde29fSJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
476*5fdde29fSJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
477*5fdde29fSJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
478*5fdde29fSJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
479*5fdde29fSJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
480*5fdde29fSJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
481*5fdde29fSJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
482*5fdde29fSJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
483*5fdde29fSJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
484*5fdde29fSJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
485*5fdde29fSJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
486*5fdde29fSJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
487*5fdde29fSJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
488*5fdde29fSJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
489*5fdde29fSJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
490*5fdde29fSJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
491*5fdde29fSJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
492*5fdde29fSJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
493*5fdde29fSJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
494*5fdde29fSJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
495*5fdde29fSJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
496*5fdde29fSJohnny Huang };
497*5fdde29fSJohnny Huang 
49879e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = {
49991448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
50091448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
50191448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
50291448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
50391448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
50491448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
50591448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
50691448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
50791448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
50891448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
50991448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
51091448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
51191448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
51291448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
51391448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
51491448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
51591448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
516541eb887SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
51791448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
51891448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
51991448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
52091448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
52191448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
52291448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
52391448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
52491448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
52591448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
52691448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
52791448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
52891448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
52991448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
53091448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
53191448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
53291448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
53391448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
53491448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
53591448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
53691448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
53791448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
53891448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
53991448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
54091448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
54191448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
54291448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
5433cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
5443cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
5453cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
5463cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
5473cb28812SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
5483cb28812SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
5493cb28812SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
5503cb28812SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
5513cb28812SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
5523cb28812SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
5533cb28812SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
5543cb28812SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
5553cb28812SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
5563cb28812SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
5573cb28812SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
5583cb28812SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
5593cb28812SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
5603cb28812SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
5613cb28812SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
5623cb28812SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
5633cb28812SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
5643cb28812SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
5653cb28812SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
5663cb28812SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
5673cb28812SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
5683cb28812SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
5693cb28812SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
5703cb28812SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
5713cb28812SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
5723cb28812SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
5733cb28812SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
5743cb28812SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
5753cb28812SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
5763cb28812SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
5773cb28812SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
5783cb28812SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
5793cb28812SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
5803cb28812SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
5813cb28812SJohnny Huang };
5823cb28812SJohnny Huang 
58379e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = {
5843cb28812SJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
5853cb28812SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
5863cb28812SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
5873cb28812SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
5883cb28812SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
5893cb28812SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
5903cb28812SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
5913cb28812SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
5923cb28812SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
5933cb28812SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
5943cb28812SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
5953cb28812SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
5963cb28812SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
5973cb28812SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
5983cb28812SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
5993cb28812SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
6003cb28812SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
6013cb28812SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
6023cb28812SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
6033cb28812SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
6043cb28812SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
6053cb28812SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
6063cb28812SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
6073cb28812SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
6083cb28812SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
6093cb28812SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
610bb34a7bfSJohnny Huang 	{ 0, 14, 1,  0, "Disable Patch code" },
611bb34a7bfSJohnny Huang 	{ 0, 14, 1,  1, "Enable Patch code" },
612bb34a7bfSJohnny Huang 	{ 0, 15, 1,  OTP_REG_RESERVED, "" },
6133cb28812SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
6143cb28812SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
6153cb28812SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
6163cb28812SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
6173cb28812SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
6183cb28812SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
6193cb28812SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
6203cb28812SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
6213cb28812SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
6223cb28812SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
6233cb28812SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
6243cb28812SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
6253cb28812SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
6263cb28812SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
6273cb28812SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
6283cb28812SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
6293cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
6303cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
6313cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
6323cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
63391448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
63491448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
63591448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
63673f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
63773f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
63891448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
63991448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
64091448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
64191448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
64291448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
64391448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
64491448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
64591448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
64691448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
64791448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
64891448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
64991448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
65091448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
65191448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
65291448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
65391448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
65491448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
65591448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
65691448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
65791448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
65891448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
65991448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
66091448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
66191448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
66291448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
66391448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
66491448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
66591448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
666bb34a7bfSJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" },
667bb34a7bfSJohnny Huang 	{ 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" },
668bb34a7bfSJohnny Huang 	{ 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" }
669b458cd62SJohnny Huang };
6709a4fe690SJohnny Huang 
671*5fdde29fSJohnny Huang static const struct otpconf_info a2_conf_info[] = {
672*5fdde29fSJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
673*5fdde29fSJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
674*5fdde29fSJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
675*5fdde29fSJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
676*5fdde29fSJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
677*5fdde29fSJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
678*5fdde29fSJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
679*5fdde29fSJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
680*5fdde29fSJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
681*5fdde29fSJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
682*5fdde29fSJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
683*5fdde29fSJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
684*5fdde29fSJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
685*5fdde29fSJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
686*5fdde29fSJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
687*5fdde29fSJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
688*5fdde29fSJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
689*5fdde29fSJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
690*5fdde29fSJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
691*5fdde29fSJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
692*5fdde29fSJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
693*5fdde29fSJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
694*5fdde29fSJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
695*5fdde29fSJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
696*5fdde29fSJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
697*5fdde29fSJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
698*5fdde29fSJohnny Huang 	{ 0, 14, 1,  0, "Disable Patch code" },
699*5fdde29fSJohnny Huang 	{ 0, 14, 1,  1, "Enable Patch code" },
700*5fdde29fSJohnny Huang 	{ 0, 15, 1,  OTP_REG_RESERVED, "" },
701*5fdde29fSJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
702*5fdde29fSJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
703*5fdde29fSJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
704*5fdde29fSJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
705*5fdde29fSJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
706*5fdde29fSJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
707*5fdde29fSJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
708*5fdde29fSJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
709*5fdde29fSJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
710*5fdde29fSJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
711*5fdde29fSJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
712*5fdde29fSJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
713*5fdde29fSJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
714*5fdde29fSJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
715*5fdde29fSJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
716*5fdde29fSJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
717*5fdde29fSJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
718*5fdde29fSJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
719*5fdde29fSJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
720*5fdde29fSJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
721*5fdde29fSJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
722*5fdde29fSJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
723*5fdde29fSJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
724*5fdde29fSJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
725*5fdde29fSJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
726*5fdde29fSJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
727*5fdde29fSJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
728*5fdde29fSJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
729*5fdde29fSJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
730*5fdde29fSJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
731*5fdde29fSJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
732*5fdde29fSJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
733*5fdde29fSJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
734*5fdde29fSJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
735*5fdde29fSJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
736*5fdde29fSJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
737*5fdde29fSJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
738*5fdde29fSJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
739*5fdde29fSJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
740*5fdde29fSJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
741*5fdde29fSJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
742*5fdde29fSJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
743*5fdde29fSJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
744*5fdde29fSJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
745*5fdde29fSJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
746*5fdde29fSJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
747*5fdde29fSJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
748*5fdde29fSJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
749*5fdde29fSJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
750*5fdde29fSJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
751*5fdde29fSJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
752*5fdde29fSJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
753*5fdde29fSJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
754*5fdde29fSJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" },
755*5fdde29fSJohnny Huang 	{ 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" },
756*5fdde29fSJohnny Huang 	{ 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" }
757*5fdde29fSJohnny Huang };
758*5fdde29fSJohnny Huang 
75979e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
7609a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
7619a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
7629a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
7639a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
7649a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
7659a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
7669a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
7679a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
7689a4fe690SJohnny Huang };
7699a4fe690SJohnny Huang 
77079e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
7719a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
7729a4fe690SJohnny 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"},
7739a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
7749a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
7759a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
7769a4fe690SJohnny Huang };
7779a4fe690SJohnny Huang 
778*5fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = {
779*5fdde29fSJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
780*5fdde29fSJohnny 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"},
781*5fdde29fSJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
782*5fdde29fSJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
783*5fdde29fSJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
784*5fdde29fSJohnny Huang };
785*5fdde29fSJohnny Huang 
7869a4fe690SJohnny Huang static uint32_t chip_version(void)
7879a4fe690SJohnny Huang {
7889a4fe690SJohnny Huang 	uint32_t rev_id;
7899a4fe690SJohnny Huang 
790*5fdde29fSJohnny Huang 	rev_id = readl(0x1e6e2014);
7919a4fe690SJohnny Huang 
792*5fdde29fSJohnny Huang 	if ((rev_id >> 24) & 0xf != 0x5)
793*5fdde29fSJohnny Huang 		return -1;
794*5fdde29fSJohnny Huang 
795*5fdde29fSJohnny Huang 	return (rev_id >> 16) & 0xf;
7969a4fe690SJohnny Huang }
7979a4fe690SJohnny Huang 
7983d3688adSJohnny Huang static void wait_complete(void)
7993d3688adSJohnny Huang {
8003d3688adSJohnny Huang 	int reg;
8013d3688adSJohnny Huang 
8023d3688adSJohnny Huang 	do {
8033d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
8043d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
8053d3688adSJohnny Huang }
8063d3688adSJohnny Huang 
8072a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
80869d5fd8fSJohnny Huang {
8093d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
8103d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
8113d3688adSJohnny Huang 	wait_complete();
8123d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
8133d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
81469d5fd8fSJohnny Huang }
81569d5fd8fSJohnny Huang 
8162a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
81769d5fd8fSJohnny Huang {
81869d5fd8fSJohnny Huang 	int config_offset;
81969d5fd8fSJohnny Huang 
82069d5fd8fSJohnny Huang 	config_offset = 0x800;
82169d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
82269d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
82369d5fd8fSJohnny Huang 
8243d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
8253d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
8263d3688adSJohnny Huang 	wait_complete();
8273d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
82869d5fd8fSJohnny Huang }
82969d5fd8fSJohnny Huang 
83069d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
83169d5fd8fSJohnny Huang {
83269d5fd8fSJohnny Huang 	int i;
83369d5fd8fSJohnny Huang 	uint32_t ret[1];
83469d5fd8fSJohnny Huang 
83569d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
8362a856b9aSJohnny Huang 		return OTP_USAGE;
83769d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
83869d5fd8fSJohnny Huang 		otp_read_config(i, ret);
839a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
84069d5fd8fSJohnny Huang 	}
84169d5fd8fSJohnny Huang 	printf("\n");
8422a856b9aSJohnny Huang 	return OTP_SUCCESS;
84369d5fd8fSJohnny Huang }
84469d5fd8fSJohnny Huang 
84569d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
84669d5fd8fSJohnny Huang {
84769d5fd8fSJohnny Huang 	int i;
84869d5fd8fSJohnny Huang 	uint32_t ret[2];
84969d5fd8fSJohnny Huang 
85069d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
8512a856b9aSJohnny Huang 		return OTP_USAGE;
85269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
85369d5fd8fSJohnny Huang 		otp_read_data(i, ret);
85469d5fd8fSJohnny Huang 		if (i % 4 == 0)
85569d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
85669d5fd8fSJohnny Huang 		else
85769d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
85869d5fd8fSJohnny Huang 
85969d5fd8fSJohnny Huang 	}
86069d5fd8fSJohnny Huang 	printf("\n");
8612a856b9aSJohnny Huang 	return OTP_SUCCESS;
86269d5fd8fSJohnny Huang }
86369d5fd8fSJohnny Huang 
86469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
86569d5fd8fSJohnny Huang {
86669d5fd8fSJohnny Huang 	uint32_t ret;
86769d5fd8fSJohnny Huang 	uint32_t *buf;
86869d5fd8fSJohnny Huang 
86969d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
87069d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
87169d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
87269d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
87369d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
8743d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
8753d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
8763d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
8773d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
8783d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
8793d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
8803d3688adSJohnny Huang 	wait_complete();
8813d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
88269d5fd8fSJohnny Huang 	if (ret & 0x1)
88369d5fd8fSJohnny Huang 		return 0;
88469d5fd8fSJohnny Huang 	else
88569d5fd8fSJohnny Huang 		return -1;
88669d5fd8fSJohnny Huang }
88769d5fd8fSJohnny Huang 
88869d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
88969d5fd8fSJohnny Huang {
8903d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
8913d3688adSJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
8923d3688adSJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
8933d3688adSJohnny Huang 	wait_complete();
89469d5fd8fSJohnny Huang }
89569d5fd8fSJohnny Huang 
896a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
89769d5fd8fSJohnny Huang {
89830a8c590SJohnny Huang 	uint32_t ret[2];
89969d5fd8fSJohnny Huang 
90030a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
9013d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
90230a8c590SJohnny Huang 	else
9033d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
90430a8c590SJohnny Huang 
9053d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
9063d3688adSJohnny Huang 	wait_complete();
9073d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
9083d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
90983655e91SJohnny Huang 
91030a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
91130a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
91269d5fd8fSJohnny Huang 			return 0;
91369d5fd8fSJohnny Huang 		else
91469d5fd8fSJohnny Huang 			return -1;
91530a8c590SJohnny Huang 	} else {
91630a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
91730a8c590SJohnny Huang 			return 0;
91830a8c590SJohnny Huang 		else
91930a8c590SJohnny Huang 			return -1;
92030a8c590SJohnny Huang 	}
92130a8c590SJohnny Huang 
92269d5fd8fSJohnny Huang }
92369d5fd8fSJohnny Huang 
924696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size)
9254c1c9b35SJohnny Huang {
9264c1c9b35SJohnny Huang 	uint32_t ret[2];
9274c1c9b35SJohnny Huang 
9284c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
9294c1c9b35SJohnny Huang 
9304c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
9313d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
9324c1c9b35SJohnny Huang 	else
9333d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
9343d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
9353d3688adSJohnny Huang 	wait_complete();
9363d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
9373d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
9384c1c9b35SJohnny Huang 	if (size == 1) {
9394c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
9404c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
941696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) {
9424c1c9b35SJohnny Huang 				compare[0] = 0;
9434c1c9b35SJohnny Huang 				return 0;
9444c1c9b35SJohnny Huang 			} else {
9454c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
9464c1c9b35SJohnny Huang 				return -1;
9474c1c9b35SJohnny Huang 			}
9484c1c9b35SJohnny Huang 
9494c1c9b35SJohnny Huang 		} else {
9504c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
951696656c6SJohnny Huang 			if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) {
9524c1c9b35SJohnny Huang 				compare[0] = ~0;
9534c1c9b35SJohnny Huang 				return 0;
9544c1c9b35SJohnny Huang 			} else {
955d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
9564c1c9b35SJohnny Huang 				return -1;
9574c1c9b35SJohnny Huang 			}
9584c1c9b35SJohnny Huang 		}
9594c1c9b35SJohnny Huang 	} else if (size == 2) {
9604c1c9b35SJohnny Huang 		// otp_addr should be even
961696656c6SJohnny Huang 		if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) {
9624c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
9634c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
9644c1c9b35SJohnny Huang 			compare[0] = 0;
9654c1c9b35SJohnny Huang 			compare[1] = ~0;
9664c1c9b35SJohnny Huang 			return 0;
9674c1c9b35SJohnny Huang 		} else {
9684c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
9694c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
9704c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
9714c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
9724c1c9b35SJohnny Huang 			return -1;
9734c1c9b35SJohnny Huang 		}
9744c1c9b35SJohnny Huang 	} else {
9754c1c9b35SJohnny Huang 		return -1;
9764c1c9b35SJohnny Huang 	}
9774c1c9b35SJohnny Huang }
9784c1c9b35SJohnny Huang 
9797e22f42dSJohnny Huang static void otp_soak(int soak)
980d90825e2SJohnny Huang {
981de6fbf1cSJohnny Huang 	switch (soak) {
982de6fbf1cSJohnny Huang 	case 0: //default
983de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x0); // Write MRA
984de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x0); // Write MRB
985de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x0); // Write MR
986de6fbf1cSJohnny Huang 		break;
987de6fbf1cSJohnny Huang 	case 1: //normal program
988de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
989de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
990de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
991de6fbf1cSJohnny Huang 		writel(0x04190760, OTP_TIMING);
992de6fbf1cSJohnny Huang 		break;
993de6fbf1cSJohnny Huang 	case 2: //soak program
994d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
995d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
996d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
997de6fbf1cSJohnny Huang 		writel(0x041930d4, OTP_TIMING);
998de6fbf1cSJohnny Huang 		break;
999d90825e2SJohnny Huang 	}
1000de6fbf1cSJohnny Huang 
10013d3688adSJohnny Huang 	wait_complete();
1002d90825e2SJohnny Huang }
1003d90825e2SJohnny Huang 
100483655e91SJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
100583655e91SJohnny Huang {
100683655e91SJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
100783655e91SJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
100883655e91SJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
100983655e91SJohnny Huang 	wait_complete();
101083655e91SJohnny Huang }
101183655e91SJohnny Huang 
101283655e91SJohnny Huang static void _otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
101383655e91SJohnny Huang {
101483655e91SJohnny Huang 	int prog_bit;
101583655e91SJohnny Huang 
101683655e91SJohnny Huang 	if (prog_address % 2 == 0) {
101783655e91SJohnny Huang 		if (value)
101883655e91SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
101983655e91SJohnny Huang 		else
102083655e91SJohnny Huang 			return;
102183655e91SJohnny Huang 	} else {
102283655e91SJohnny Huang 		prog_address |= 1 << 15;
102383655e91SJohnny Huang 		if (!value)
102483655e91SJohnny Huang 			prog_bit = 0x1 << bit_offset;
102583655e91SJohnny Huang 		else
102683655e91SJohnny Huang 			return;
102783655e91SJohnny Huang 	}
102883655e91SJohnny Huang 	otp_prog(prog_address, prog_bit);
102983655e91SJohnny Huang }
103083655e91SJohnny Huang 
103183655e91SJohnny Huang static int otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
103283655e91SJohnny Huang {
103383655e91SJohnny Huang 	int pass;
103483655e91SJohnny Huang 	int i;
103583655e91SJohnny Huang 
103683655e91SJohnny Huang 	otp_soak(1);
103783655e91SJohnny Huang 	_otp_prog_bit(value, prog_address, bit_offset);
103883655e91SJohnny Huang 	pass = 0;
103983655e91SJohnny Huang 
104083655e91SJohnny Huang 	for (i = 0; i < RETRY; i++) {
104183655e91SJohnny Huang 		if (verify_bit(prog_address, bit_offset, value) != 0) {
104283655e91SJohnny Huang 			otp_soak(2);
104383655e91SJohnny Huang 			_otp_prog_bit(value, prog_address, bit_offset);
104483655e91SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
104583655e91SJohnny Huang 				otp_soak(1);
104683655e91SJohnny Huang 			} else {
104783655e91SJohnny Huang 				pass = 1;
104883655e91SJohnny Huang 				break;
104983655e91SJohnny Huang 			}
105083655e91SJohnny Huang 		} else {
105183655e91SJohnny Huang 			pass = 1;
105283655e91SJohnny Huang 			break;
105383655e91SJohnny Huang 		}
105483655e91SJohnny Huang 	}
105583655e91SJohnny Huang 
105683655e91SJohnny Huang 	return pass;
105783655e91SJohnny Huang }
105883655e91SJohnny Huang 
1059696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address)
1060d90825e2SJohnny Huang {
1061d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
1062d90825e2SJohnny Huang 
1063d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
1064696656c6SJohnny Huang 		if ((ignore >> j) & 0x1)
1065d90825e2SJohnny Huang 			continue;
1066d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
1067d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
1068d90825e2SJohnny Huang 			if (bit_value)
1069d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
1070d90825e2SJohnny Huang 			else
1071d90825e2SJohnny Huang 				continue;
1072d90825e2SJohnny Huang 		} else {
1073d90825e2SJohnny Huang 			prog_address |= 1 << 15;
1074d90825e2SJohnny Huang 			if (bit_value)
1075d90825e2SJohnny Huang 				continue;
1076d90825e2SJohnny Huang 			else
1077d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
1078d90825e2SJohnny Huang 		}
1079d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
1080d90825e2SJohnny Huang 	}
1081d90825e2SJohnny Huang }
1082d90825e2SJohnny Huang 
108354552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
108454552c69SJohnny Huang {
108554552c69SJohnny Huang 	int pass;
108654552c69SJohnny Huang 	int i;
108754552c69SJohnny Huang 	uint32_t data0_masked;
108854552c69SJohnny Huang 	uint32_t data1_masked;
108954552c69SJohnny Huang 	uint32_t buf0_masked;
109054552c69SJohnny Huang 	uint32_t buf1_masked;
109154552c69SJohnny Huang 	uint32_t compare[2];
109254552c69SJohnny Huang 
109354552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
109454552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
109554552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
109654552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
109754552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
109854552c69SJohnny Huang 		return 0;
109954552c69SJohnny Huang 
110054552c69SJohnny Huang 	otp_soak(1);
110154552c69SJohnny Huang 	if (data0_masked != buf0_masked)
110254552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
110354552c69SJohnny Huang 	if (data1_masked != buf1_masked)
110454552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
110554552c69SJohnny Huang 
110654552c69SJohnny Huang 	pass = 0;
110754552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
110854552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
110954552c69SJohnny Huang 			otp_soak(2);
111054552c69SJohnny Huang 			if (compare[0] != 0) {
111154552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
111254552c69SJohnny Huang 			}
111354552c69SJohnny Huang 			if (compare[1] != ~0) {
111454552c69SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1);
111554552c69SJohnny Huang 			}
111654552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
111754552c69SJohnny Huang 				otp_soak(1);
111854552c69SJohnny Huang 			} else {
111954552c69SJohnny Huang 				pass = 1;
112054552c69SJohnny Huang 				break;
112154552c69SJohnny Huang 			}
112254552c69SJohnny Huang 		} else {
112354552c69SJohnny Huang 			pass = 1;
112454552c69SJohnny Huang 			break;
112554552c69SJohnny Huang 		}
112654552c69SJohnny Huang 	}
112754552c69SJohnny Huang 
112854552c69SJohnny Huang 	if (!pass) {
112954552c69SJohnny Huang 		otp_soak(0);
113054552c69SJohnny Huang 		return OTP_FAILURE;
113154552c69SJohnny Huang 	}
113254552c69SJohnny Huang 	return OTP_SUCCESS;
113354552c69SJohnny Huang }
113454552c69SJohnny Huang 
1135541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
113676d13988SJohnny Huang {
113776d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
11385010032bSJohnny Huang 	int strap_end;
113976d13988SJohnny Huang 	int i, j;
114076d13988SJohnny Huang 
11415010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
114276d13988SJohnny Huang 		for (j = 0; j < 64; j++) {
114376d13988SJohnny Huang 			otpstrap[j].value = 0;
114476d13988SJohnny Huang 			otpstrap[j].remain_times = 7;
114576d13988SJohnny Huang 			otpstrap[j].writeable_option = -1;
114676d13988SJohnny Huang 			otpstrap[j].protected = 0;
114776d13988SJohnny Huang 		}
11485010032bSJohnny Huang 		strap_end = 30;
11495010032bSJohnny Huang 	} else {
11505010032bSJohnny Huang 		for (j = 0; j < 64; j++) {
11515010032bSJohnny Huang 			otpstrap[j].value = 0;
11525010032bSJohnny Huang 			otpstrap[j].remain_times = 6;
11535010032bSJohnny Huang 			otpstrap[j].writeable_option = -1;
11545010032bSJohnny Huang 			otpstrap[j].reg_protected = 0;
11555010032bSJohnny Huang 			otpstrap[j].protected = 0;
11565010032bSJohnny Huang 		}
11575010032bSJohnny Huang 		strap_end = 28;
11585010032bSJohnny Huang 	}
115976d13988SJohnny Huang 
11605010032bSJohnny Huang 	for (i = 16; i < strap_end; i += 2) {
116176d13988SJohnny Huang 		int option = (i - 16) / 2;
116276d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
116376d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
116476d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
116576d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
116676d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
116776d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
116876d13988SJohnny Huang 			}
116976d13988SJohnny Huang 			if (bit_value == 1)
117076d13988SJohnny Huang 				otpstrap[j].remain_times --;
117176d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
117276d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
117376d13988SJohnny Huang 		}
117476d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
117576d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
117676d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
117776d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
117876d13988SJohnny Huang 			}
117976d13988SJohnny Huang 			if (bit_value == 1)
118076d13988SJohnny Huang 				otpstrap[j].remain_times --;
118176d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
118276d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
118376d13988SJohnny Huang 		}
118476d13988SJohnny Huang 	}
11855010032bSJohnny Huang 
11865010032bSJohnny Huang 	if (info_cb.version != OTP_AST2600A0) {
11875010032bSJohnny Huang 		otp_read_config(28, &OTPSTRAP_RAW[0]);
11885010032bSJohnny Huang 		otp_read_config(29, &OTPSTRAP_RAW[1]);
11895010032bSJohnny Huang 		for (j = 0; j < 32; j++) {
11905010032bSJohnny Huang 			if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
11915010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
11925010032bSJohnny Huang 		}
11935010032bSJohnny Huang 		for (j = 32; j < 64; j++) {
11945010032bSJohnny Huang 			if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
11955010032bSJohnny Huang 				otpstrap[j].reg_protected = 1;
11965010032bSJohnny Huang 		}
11975010032bSJohnny Huang 
11985010032bSJohnny Huang 	}
11995010032bSJohnny Huang 
120076d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
120176d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
120276d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
120376d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
120476d13988SJohnny Huang 			otpstrap[j].protected = 1;
120576d13988SJohnny Huang 	}
120676d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
120776d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
120876d13988SJohnny Huang 			otpstrap[j].protected = 1;
120976d13988SJohnny Huang 	}
121076d13988SJohnny Huang }
121176d13988SJohnny Huang 
1212696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout)
121369d5fd8fSJohnny Huang {
121479e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
1215696656c6SJohnny Huang 	uint32_t *OTPCFG = (uint32_t *)image_layout->conf;
1216696656c6SJohnny Huang 	uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore;
1217b458cd62SJohnny Huang 	uint32_t mask;
1218b458cd62SJohnny Huang 	uint32_t dw_offset;
1219b458cd62SJohnny Huang 	uint32_t bit_offset;
1220b458cd62SJohnny Huang 	uint32_t otp_value;
1221696656c6SJohnny Huang 	uint32_t otp_ignore;
1222b458cd62SJohnny Huang 	int fail = 0;
122373f11549SJohnny Huang 	char valid_bit[20];
122466f2f8e5SJohnny Huang 	int i;
122573f11549SJohnny Huang 	int j;
122666f2f8e5SJohnny Huang 
1227737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
122866f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
12293cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
12303cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
12313cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
12323cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
1233b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
1234696656c6SJohnny Huang 		otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask;
1235b458cd62SJohnny Huang 
1236696656c6SJohnny Huang 		if (otp_ignore == mask) {
1237b458cd62SJohnny Huang 			continue;
1238696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
1239b458cd62SJohnny Huang 			fail = 1;
1240b458cd62SJohnny Huang 		}
1241b458cd62SJohnny Huang 
12423cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
12433cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
12443cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
12453cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
1246b458cd62SJohnny Huang 			continue;
1247b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
1248b458cd62SJohnny Huang 
12493cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
12503cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
125166f2f8e5SJohnny Huang 		} else {
1252b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
12533cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
12543cb28812SJohnny Huang 			       conf_info[i].bit_offset);
125566f2f8e5SJohnny Huang 		}
1256b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
1257b458cd62SJohnny Huang 
1258b458cd62SJohnny Huang 		if (fail) {
1259696656c6SJohnny Huang 			printf("Ignore mask error\n");
1260b458cd62SJohnny Huang 		} else {
12613cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
1262b458cd62SJohnny Huang 				printf("Reserved\n");
12633cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
12643cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
1265b458cd62SJohnny Huang 				printf("\n");
12663cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1267b458cd62SJohnny Huang 				if (otp_value != 0) {
126873f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
126973f11549SJohnny Huang 						if (otp_value == (1 << j)) {
127073f11549SJohnny Huang 							valid_bit[j * 2] = '1';
1271b458cd62SJohnny Huang 						} else {
127273f11549SJohnny Huang 							valid_bit[j * 2] = '0';
127373f11549SJohnny Huang 						}
127473f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
127573f11549SJohnny Huang 					}
127673f11549SJohnny Huang 					valid_bit[15] = 0;
127773f11549SJohnny Huang 				} else {
127873f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1279b458cd62SJohnny Huang 				}
12803cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
1281b458cd62SJohnny Huang 				printf("\n");
1282b458cd62SJohnny Huang 			} else {
12833cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
1284b458cd62SJohnny Huang 			}
1285b458cd62SJohnny Huang 		}
1286b458cd62SJohnny Huang 	}
1287b458cd62SJohnny Huang 
1288b458cd62SJohnny Huang 	if (fail)
1289b458cd62SJohnny Huang 		return OTP_FAILURE;
1290b458cd62SJohnny Huang 
129166f2f8e5SJohnny Huang 	return OTP_SUCCESS;
129266f2f8e5SJohnny Huang }
129366f2f8e5SJohnny Huang 
12942d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
129566f2f8e5SJohnny Huang {
129679e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
1297bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
1298b458cd62SJohnny Huang 	uint32_t mask;
1299b458cd62SJohnny Huang 	uint32_t dw_offset;
1300b458cd62SJohnny Huang 	uint32_t bit_offset;
1301b458cd62SJohnny Huang 	uint32_t otp_value;
130273f11549SJohnny Huang 	char valid_bit[20];
130366f2f8e5SJohnny Huang 	int i;
130473f11549SJohnny Huang 	int j;
130566f2f8e5SJohnny Huang 
1306bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
130766f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
130866f2f8e5SJohnny Huang 
130966f2f8e5SJohnny Huang 
1310b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
1311b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
13123cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
13133cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
13142d4b0742SJohnny Huang 			continue;
13153cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
13163cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
13173cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
1318b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
1319b458cd62SJohnny Huang 
13203cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
13213cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
13223cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
13233cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
1324b458cd62SJohnny Huang 			continue;
1325b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
1326b458cd62SJohnny Huang 
13273cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
13283cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
1329b458cd62SJohnny Huang 		} else {
1330b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
13313cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
13323cb28812SJohnny Huang 			       conf_info[i].bit_offset);
1333b458cd62SJohnny Huang 		}
1334b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
1335b458cd62SJohnny Huang 
13363cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
1337b458cd62SJohnny Huang 			printf("Reserved\n");
13383cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
13393cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
1340b458cd62SJohnny Huang 			printf("\n");
13413cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1342b458cd62SJohnny Huang 			if (otp_value != 0) {
134373f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
134473f11549SJohnny Huang 					if (otp_value == (1 << j)) {
134573f11549SJohnny Huang 						valid_bit[j * 2] = '1';
1346b458cd62SJohnny Huang 					} else {
134773f11549SJohnny Huang 						valid_bit[j * 2] = '0';
134873f11549SJohnny Huang 					}
134973f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
135073f11549SJohnny Huang 				}
135173f11549SJohnny Huang 				valid_bit[15] = 0;
135273f11549SJohnny Huang 			} else {
135373f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1354b458cd62SJohnny Huang 			}
13553cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
1356b458cd62SJohnny Huang 			printf("\n");
1357b458cd62SJohnny Huang 		} else {
13583cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
1359b458cd62SJohnny Huang 		}
1360b458cd62SJohnny Huang 	}
1361b458cd62SJohnny Huang 	return OTP_SUCCESS;
136266f2f8e5SJohnny Huang }
136366f2f8e5SJohnny Huang 
13645010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout)
136576d13988SJohnny Huang {
136679e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
1367696656c6SJohnny Huang 	uint32_t *OTPSTRAP;
1368696656c6SJohnny Huang 	uint32_t *OTPSTRAP_REG_PRO;
1369696656c6SJohnny Huang 	uint32_t *OTPSTRAP_PRO;
1370696656c6SJohnny Huang 	uint32_t *OTPSTRAP_IGNORE;
137176d13988SJohnny Huang 	int i;
1372a8bd6d8cSJohnny Huang 	int fail = 0;
1373a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
1374a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
1375a8bd6d8cSJohnny Huang 	uint32_t mask;
1376a8bd6d8cSJohnny Huang 	uint32_t otp_value;
1377696656c6SJohnny Huang 	uint32_t otp_reg_protect;
1378a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
1379696656c6SJohnny Huang 	uint32_t otp_ignore;
138076d13988SJohnny Huang 
1381696656c6SJohnny Huang 	OTPSTRAP = (uint32_t *)image_layout->strap;
1382696656c6SJohnny Huang 	OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro;
1383696656c6SJohnny Huang 	OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore;
13845010032bSJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1385696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = NULL;
1386a8bd6d8cSJohnny Huang 		printf("BIT(hex)   Value       Protect     Description\n");
1387696656c6SJohnny Huang 	} else {
1388696656c6SJohnny Huang 		OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro;
1389de6b0cc4SJohnny Huang 		printf("BIT(hex)   Value       Reg_Protect Protect     Description\n");
1390696656c6SJohnny Huang 	}
1391de6b0cc4SJohnny Huang 	printf("__________________________________________________________________________________________\n");
1392b458cd62SJohnny Huang 
13933cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1394696656c6SJohnny Huang 		if (strap_info[i].bit_offset > 31) {
1395a8bd6d8cSJohnny Huang 			dw_offset = 1;
13963cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
1397a8bd6d8cSJohnny Huang 		} else {
1398a8bd6d8cSJohnny Huang 			dw_offset = 0;
13993cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
1400a8bd6d8cSJohnny Huang 		}
140176d13988SJohnny Huang 
14023cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
1403a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
1404a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
1405696656c6SJohnny Huang 		otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask;
1406a8bd6d8cSJohnny Huang 
14075010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
1408696656c6SJohnny Huang 			otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask;
14095010032bSJohnny Huang 		else
14105010032bSJohnny Huang 			otp_reg_protect = 0;
1411696656c6SJohnny Huang 
1412696656c6SJohnny Huang 		if (otp_ignore == mask) {
1413a8bd6d8cSJohnny Huang 			continue;
1414696656c6SJohnny Huang 		} else if (otp_ignore != 0) {
1415a8bd6d8cSJohnny Huang 			fail = 1;
1416a8bd6d8cSJohnny Huang 		}
1417a8bd6d8cSJohnny Huang 
14183cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
14193cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1420a8bd6d8cSJohnny Huang 			continue;
1421a8bd6d8cSJohnny Huang 
14223cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
14233cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
1424a8bd6d8cSJohnny Huang 		} else {
1425b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
14263cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
14273cb28812SJohnny Huang 			       strap_info[i].bit_offset);
1428a8bd6d8cSJohnny Huang 		}
1429a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
14305010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0)
1431696656c6SJohnny Huang 			printf("0x%-10x", otp_reg_protect);
1432a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
1433a8bd6d8cSJohnny Huang 
1434a8bd6d8cSJohnny Huang 		if (fail) {
1435696656c6SJohnny Huang 			printf("Ignore mask error\n");
1436a8bd6d8cSJohnny Huang 		} else {
14373cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
14383cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1439a8bd6d8cSJohnny Huang 			else
1440a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1441a8bd6d8cSJohnny Huang 		}
1442a8bd6d8cSJohnny Huang 	}
1443a8bd6d8cSJohnny Huang 
1444a8bd6d8cSJohnny Huang 	if (fail)
144576d13988SJohnny Huang 		return OTP_FAILURE;
144676d13988SJohnny Huang 
144776d13988SJohnny Huang 	return OTP_SUCCESS;
144876d13988SJohnny Huang }
144976d13988SJohnny Huang 
1450b458cd62SJohnny Huang static int otp_print_strap_info(int view)
145176d13988SJohnny Huang {
145279e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
145376d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
145407baa4e8SJohnny Huang 	int i, j;
1455b458cd62SJohnny Huang 	int fail = 0;
1456b458cd62SJohnny Huang 	uint32_t bit_offset;
1457b458cd62SJohnny Huang 	uint32_t length;
1458b458cd62SJohnny Huang 	uint32_t otp_value;
1459b458cd62SJohnny Huang 	uint32_t otp_protect;
146076d13988SJohnny Huang 
1461541eb887SJohnny Huang 	otp_strap_status(strap_status);
146276d13988SJohnny Huang 
1463b458cd62SJohnny Huang 	if (view) {
146483655e91SJohnny Huang 		if (info_cb.version == OTP_AST2600A0)
146507baa4e8SJohnny Huang 			printf("BIT(hex) Value  Remains  Protect   Description\n");
146683655e91SJohnny Huang 		else
146783655e91SJohnny Huang 			printf("BIT(hex) Value  Remains  Reg_Protect Protect   Description\n");
146807baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
1469b458cd62SJohnny Huang 	} else {
1470b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
1471b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
147276d13988SJohnny Huang 	}
14733cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1474b458cd62SJohnny Huang 		otp_value = 0;
14753cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
14763cb28812SJohnny Huang 		length = strap_info[i].length;
1477b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
1478c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
1479c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
1480b458cd62SJohnny Huang 		}
14813cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
14823cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1483b458cd62SJohnny Huang 			continue;
1484b458cd62SJohnny Huang 		if (view) {
1485b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
14863cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
1487b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
148807baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
148983655e91SJohnny Huang 				if (info_cb.version != OTP_AST2600A0)
1490e1a7245eSJohnny Huang 					printf("0x%-10X", strap_status[bit_offset + j].reg_protected);
1491e1a7245eSJohnny Huang 				printf("0x%-7X", strap_status[bit_offset + j].protected);
14923cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
1493b458cd62SJohnny Huang 					printf(" Reserved\n");
1494b458cd62SJohnny Huang 					continue;
1495b458cd62SJohnny Huang 				}
1496b458cd62SJohnny Huang 				if (length == 1) {
14973cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
1498b458cd62SJohnny Huang 					continue;
149976d13988SJohnny Huang 				}
150076d13988SJohnny Huang 
1501b458cd62SJohnny Huang 				if (j == 0)
15023cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
1503b458cd62SJohnny Huang 				else if (j == length - 1)
1504b458cd62SJohnny Huang 					printf("\\ \"\n");
1505b458cd62SJohnny Huang 				else
1506b458cd62SJohnny Huang 					printf("| \"\n");
150776d13988SJohnny Huang 			}
1508b458cd62SJohnny Huang 		} else {
1509c947ef08SJohnny Huang 			if (length == 1) {
15103cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
1511b458cd62SJohnny Huang 			} else {
1512b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1513b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1514b458cd62SJohnny Huang 			}
1515b458cd62SJohnny Huang 
1516b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1517b458cd62SJohnny Huang 
15183cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
15193cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1520b458cd62SJohnny Huang 			else
1521b458cd62SJohnny Huang 				printf("Reserved\n");
1522b458cd62SJohnny Huang 		}
1523b458cd62SJohnny Huang 	}
1524b458cd62SJohnny Huang 
1525b458cd62SJohnny Huang 	if (fail)
1526b458cd62SJohnny Huang 		return OTP_FAILURE;
1527b458cd62SJohnny Huang 
1528b458cd62SJohnny Huang 	return OTP_SUCCESS;
1529b458cd62SJohnny Huang }
1530b458cd62SJohnny Huang 
1531696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len)
153269d5fd8fSJohnny Huang {
153369d5fd8fSJohnny Huang 	int i;
153469d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
153569d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
153669d5fd8fSJohnny Huang 		if (i % 16 == 0) {
153769d5fd8fSJohnny Huang 			printf("%04X: ", i);
153869d5fd8fSJohnny Huang 		}
153969d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
154069d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
154169d5fd8fSJohnny Huang 			printf("\n");
154269d5fd8fSJohnny Huang 		}
154369d5fd8fSJohnny Huang 	}
154469d5fd8fSJohnny Huang }
154569d5fd8fSJohnny Huang 
1546696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout)
154769d5fd8fSJohnny Huang {
154869d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
154979e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
15509a4fe690SJohnny Huang 	struct otpkey_type key_info;
1551696656c6SJohnny Huang 	uint32_t *buf;
1552696656c6SJohnny Huang 	uint8_t *byte_buf;
15539d998018SJohnny Huang 	char empty = 1;
155469d5fd8fSJohnny Huang 	int i = 0, len = 0;
15559a4fe690SJohnny Huang 	int j;
155654552c69SJohnny Huang 
1557696656c6SJohnny Huang 	byte_buf = image_layout->data;
1558696656c6SJohnny Huang 	buf = (uint32_t *)byte_buf;
15599d998018SJohnny Huang 
15609d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
15619d998018SJohnny Huang 		if (buf[i] != 0) {
15629d998018SJohnny Huang 			empty = 0;
15639d998018SJohnny Huang 		}
15649d998018SJohnny Huang 	}
15659d998018SJohnny Huang 	if (empty)
15669d998018SJohnny Huang 		return 0;
15679d998018SJohnny Huang 
15689d998018SJohnny Huang 	i = 0;
156969d5fd8fSJohnny Huang 	while (1) {
157069d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
157169d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
157269d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
157369d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
157469d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
157569d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
15769a4fe690SJohnny Huang 
15779a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
15789a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
15799a4fe690SJohnny Huang 				key_info = key_info_array[j];
15809a4fe690SJohnny Huang 				break;
15819a4fe690SJohnny Huang 			}
15829a4fe690SJohnny Huang 		}
15839a4fe690SJohnny Huang 
15847f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
158569d5fd8fSJohnny Huang 		printf("Key Type: ");
15869a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
15879a4fe690SJohnny Huang 
15889a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
158969d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
159069d5fd8fSJohnny Huang 			switch (key_length) {
159169d5fd8fSJohnny Huang 			case 0:
159269d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
159369d5fd8fSJohnny Huang 				break;
159469d5fd8fSJohnny Huang 			case 1:
159569d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
159669d5fd8fSJohnny Huang 				break;
159769d5fd8fSJohnny Huang 			case 2:
159869d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
159969d5fd8fSJohnny Huang 				break;
160069d5fd8fSJohnny Huang 			case 3:
160169d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
160269d5fd8fSJohnny Huang 				break;
160369d5fd8fSJohnny Huang 			}
16049a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
160569d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
160669d5fd8fSJohnny Huang 			switch (key_length) {
160769d5fd8fSJohnny Huang 			case 0:
160869d5fd8fSJohnny Huang 				printf("RSA1024\n");
160969d5fd8fSJohnny Huang 				len = 0x100;
161069d5fd8fSJohnny Huang 				break;
161169d5fd8fSJohnny Huang 			case 1:
161269d5fd8fSJohnny Huang 				printf("RSA2048\n");
161369d5fd8fSJohnny Huang 				len = 0x200;
161469d5fd8fSJohnny Huang 				break;
161569d5fd8fSJohnny Huang 			case 2:
161669d5fd8fSJohnny Huang 				printf("RSA3072\n");
161769d5fd8fSJohnny Huang 				len = 0x300;
161869d5fd8fSJohnny Huang 				break;
161969d5fd8fSJohnny Huang 			case 3:
162069d5fd8fSJohnny Huang 				printf("RSA4096\n");
162169d5fd8fSJohnny Huang 				len = 0x400;
162269d5fd8fSJohnny Huang 				break;
162369d5fd8fSJohnny Huang 			}
162469d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
162569d5fd8fSJohnny Huang 		}
16269a4fe690SJohnny Huang 		if (key_info.need_id)
162769d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
162869d5fd8fSJohnny Huang 		printf("Key Value:\n");
16299a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
163069d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
16319a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
16329a4fe690SJohnny Huang 			printf("AES Key:\n");
16339a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
1634*5fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
16359a4fe690SJohnny Huang 				printf("AES IV:\n");
16369a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
16379a4fe690SJohnny Huang 			}
16389a4fe690SJohnny Huang 
16399a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
1640*5fdde29fSJohnny Huang 			if (info_cb.version == OTP_AST2600A0) {
164169d5fd8fSJohnny Huang 				printf("AES Key:\n");
164269d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
164369d5fd8fSJohnny Huang 				printf("AES IV:\n");
164469d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
1645*5fdde29fSJohnny Huang 			} else {
16469a4fe690SJohnny Huang 				printf("AES Key 1:\n");
16479a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
16489a4fe690SJohnny Huang 				printf("AES Key 2:\n");
16499a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
16509a4fe690SJohnny Huang 			}
165169d5fd8fSJohnny Huang 
16529a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
165369d5fd8fSJohnny Huang 			printf("RSA mod:\n");
165469d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
165569d5fd8fSJohnny Huang 			printf("RSA exp:\n");
165669d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
165769d5fd8fSJohnny Huang 		}
165869d5fd8fSJohnny Huang 		if (last)
165969d5fd8fSJohnny Huang 			break;
166069d5fd8fSJohnny Huang 		i++;
166169d5fd8fSJohnny Huang 	}
166269d5fd8fSJohnny Huang 	return 0;
166369d5fd8fSJohnny Huang }
166469d5fd8fSJohnny Huang 
16655010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout)
166669d5fd8fSJohnny Huang {
1667a6d0d645SJohnny Huang 	int i, k;
1668d90825e2SJohnny Huang 	int pass = 0;
1669a6d0d645SJohnny Huang 	uint32_t prog_address;
1670bb34a7bfSJohnny Huang 	uint32_t data[16];
1671a6d0d645SJohnny Huang 	uint32_t compare[2];
16725010032bSJohnny Huang 	uint32_t *conf = (uint32_t *)image_layout->conf;
16735010032bSJohnny Huang 	uint32_t *conf_ignore = (uint32_t *)image_layout->conf_ignore;
1674d90825e2SJohnny Huang 	uint32_t data_masked;
1675d90825e2SJohnny Huang 	uint32_t buf_masked;
167669d5fd8fSJohnny Huang 
1677a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1678a6d0d645SJohnny Huang 
1679bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
168069d5fd8fSJohnny Huang 		prog_address = 0x800;
1681a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1682a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1683a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1684a6d0d645SJohnny Huang 	}
1685a6d0d645SJohnny Huang 
1686a6d0d645SJohnny Huang 	printf("Check writable...\n");
1687bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
16885010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
16895010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1690d90825e2SJohnny Huang 		if (data_masked == buf_masked)
169169d5fd8fSJohnny Huang 			continue;
1692d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1693a6d0d645SJohnny Huang 			continue;
1694a6d0d645SJohnny Huang 		} else {
1695a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1696a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
16975010032bSJohnny Huang 			printf("Input [%X] = %x\n", i, conf[i]);
16985010032bSJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~conf_ignore[i]);
16992a856b9aSJohnny Huang 			return OTP_FAILURE;
1700a6d0d645SJohnny Huang 		}
1701a6d0d645SJohnny Huang 	}
1702a6d0d645SJohnny Huang 
1703a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1704d90825e2SJohnny Huang 	otp_soak(0);
1705bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
17065010032bSJohnny Huang 		data_masked = data[i]  & ~conf_ignore[i];
17075010032bSJohnny Huang 		buf_masked  = conf[i] & ~conf_ignore[i];
1708a6d0d645SJohnny Huang 		prog_address = 0x800;
1709a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1710a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1711bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1712bb34a7bfSJohnny Huang 			pass = 1;
1713a6d0d645SJohnny Huang 			continue;
1714bb34a7bfSJohnny Huang 		}
1715de6fbf1cSJohnny Huang 
1716a6d0d645SJohnny Huang 
1717de6fbf1cSJohnny Huang 		otp_soak(1);
17185010032bSJohnny Huang 		otp_prog_dw(conf[i], conf_ignore[i], prog_address);
1719a6d0d645SJohnny Huang 
172069d5fd8fSJohnny Huang 		pass = 0;
172169d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
17225010032bSJohnny Huang 			if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1723de6fbf1cSJohnny Huang 				otp_soak(2);
1724a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
17255010032bSJohnny Huang 				if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) {
1726de6fbf1cSJohnny Huang 					otp_soak(1);
1727de6fbf1cSJohnny Huang 				} else {
1728de6fbf1cSJohnny Huang 					pass = 1;
1729de6fbf1cSJohnny Huang 					break;
1730de6fbf1cSJohnny Huang 				}
1731a6d0d645SJohnny Huang 			} else {
173269d5fd8fSJohnny Huang 				pass = 1;
173369d5fd8fSJohnny Huang 				break;
173469d5fd8fSJohnny Huang 			}
173569d5fd8fSJohnny Huang 		}
1736bb34a7bfSJohnny Huang 		if (pass == 0) {
1737bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
17385010032bSJohnny Huang 			       i, data[i], conf[i], conf_ignore[i]);
1739bb34a7bfSJohnny Huang 			break;
1740bb34a7bfSJohnny Huang 		}
1741a6d0d645SJohnny Huang 	}
1742a6d0d645SJohnny Huang 
1743de6fbf1cSJohnny Huang 	otp_soak(0);
174469d5fd8fSJohnny Huang 	if (!pass)
17452a856b9aSJohnny Huang 		return OTP_FAILURE;
1746a6d0d645SJohnny Huang 
17472a856b9aSJohnny Huang 	return OTP_SUCCESS;
1748d90825e2SJohnny Huang 
174969d5fd8fSJohnny Huang }
175069d5fd8fSJohnny Huang 
1751eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit)
1752eda10d61SJohnny Huang {
1753eda10d61SJohnny Huang 	if (ibit == 1) {
1754eda10d61SJohnny Huang 		return OTP_SUCCESS;
1755eda10d61SJohnny Huang 	} else {
1756eda10d61SJohnny Huang 		printf("OTPSTRAP[%X]:\n", offset);
1757eda10d61SJohnny Huang 	}
1758eda10d61SJohnny Huang 	if (bit == otpstrap->value) {
1759eda10d61SJohnny Huang 		printf("    The value is same as before, skip it.\n");
1760eda10d61SJohnny Huang 		return OTP_PROG_SKIP;
1761eda10d61SJohnny Huang 	}
1762eda10d61SJohnny Huang 	if (otpstrap->protected == 1) {
1763eda10d61SJohnny Huang 		printf("    This bit is protected and is not writable\n");
1764eda10d61SJohnny Huang 		return OTP_FAILURE;
1765eda10d61SJohnny Huang 	}
1766eda10d61SJohnny Huang 	if (otpstrap->remain_times == 0) {
1767eda10d61SJohnny Huang 		printf("    This bit is no remaining times to write.\n");
1768eda10d61SJohnny Huang 		return OTP_FAILURE;
1769eda10d61SJohnny Huang 	}
1770eda10d61SJohnny Huang 	if (pbit == 1) {
1771eda10d61SJohnny Huang 		printf("    This bit will be protected and become non-writable.\n");
1772eda10d61SJohnny Huang 	}
1773eda10d61SJohnny Huang 	if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
1774eda10d61SJohnny Huang 		printf("    The relative register will be protected.\n");
1775eda10d61SJohnny Huang 	}
1776eda10d61SJohnny Huang 	printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", offset, otpstrap->writeable_option + 1, otpstrap->value, otpstrap->value ^ 1);
1777eda10d61SJohnny Huang 	return OTP_SUCCESS;
1778eda10d61SJohnny Huang }
1779eda10d61SJohnny Huang 
17805010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout)
178169d5fd8fSJohnny Huang {
178269d5fd8fSJohnny Huang 	int i;
17835010032bSJohnny Huang 	uint32_t *strap;
17845010032bSJohnny Huang 	uint32_t *strap_ignore;
17855010032bSJohnny Huang 	uint32_t *strap_reg_protect;
17865010032bSJohnny Huang 	uint32_t *strap_pro;
1787eda10d61SJohnny Huang 	int bit, pbit, ibit, rpbit;
178869d5fd8fSJohnny Huang 	int fail = 0;
1789a6af4a17SJohnny Huang 	int skip = -1;
1790eda10d61SJohnny Huang 	int ret;
179166f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
179269d5fd8fSJohnny Huang 
17935010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
17945010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
17955010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
17965010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
17975010032bSJohnny Huang 
1798541eb887SJohnny Huang 	otp_strap_status(otpstrap);
179969d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
180069d5fd8fSJohnny Huang 		if (i < 32) {
18015010032bSJohnny Huang 			bit = (strap[0] >> i) & 0x1;
1802eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> i) & 0x1;
18035010032bSJohnny Huang 			pbit = (strap_pro[0] >> i) & 0x1;
180469d5fd8fSJohnny Huang 		} else {
18055010032bSJohnny Huang 			bit = (strap[1] >> (i - 32)) & 0x1;
1806eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> (i - 32)) & 0x1;
18075010032bSJohnny Huang 			pbit = (strap_pro[1] >> (i - 32)) & 0x1;
18085010032bSJohnny Huang 		}
18095010032bSJohnny Huang 
18105010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
18115010032bSJohnny Huang 			if (i < 32) {
18125010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
18135010032bSJohnny Huang 			} else {
18145010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
18155010032bSJohnny Huang 			}
18165010032bSJohnny Huang 		} else {
18175010032bSJohnny Huang 			rpbit = 0;
181869d5fd8fSJohnny Huang 		}
1819eda10d61SJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit);
1820eda10d61SJohnny Huang 		if (ret == OTP_PROG_SKIP) {
1821a6af4a17SJohnny Huang 			if (skip == -1)
1822a6af4a17SJohnny Huang 				skip = 1;
182369d5fd8fSJohnny Huang 			continue;
1824a6af4a17SJohnny Huang 		} else {
1825eda10d61SJohnny Huang 			skip = 1;
182669d5fd8fSJohnny Huang 		}
1827eda10d61SJohnny Huang 
1828eda10d61SJohnny Huang 		if (ret == OTP_FAILURE)
182969d5fd8fSJohnny Huang 			fail = 1;
183069d5fd8fSJohnny Huang 	}
183169d5fd8fSJohnny Huang 	if (fail == 1)
1832a6af4a17SJohnny Huang 		return OTP_FAILURE;
1833a6af4a17SJohnny Huang 	else if (skip == 1)
1834a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
18357e22f42dSJohnny Huang 
1836eda10d61SJohnny Huang 	return OTP_SUCCESS;
183769d5fd8fSJohnny Huang }
183869d5fd8fSJohnny Huang 
18392a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
184069d5fd8fSJohnny Huang {
184169d5fd8fSJohnny Huang 	int i, j;
1842de6b0cc4SJohnny Huang 	int remains;
184366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
184469d5fd8fSJohnny Huang 
18452a856b9aSJohnny Huang 	if (start < 0 || start > 64)
18462a856b9aSJohnny Huang 		return OTP_USAGE;
18472a856b9aSJohnny Huang 
18482a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
18492a856b9aSJohnny Huang 		return OTP_USAGE;
18502a856b9aSJohnny Huang 
1851541eb887SJohnny Huang 	otp_strap_status(otpstrap);
185269d5fd8fSJohnny Huang 
1853de6b0cc4SJohnny Huang 	if (info_cb.version == OTP_AST2600A0) {
1854de6b0cc4SJohnny Huang 		remains = 7;
185507baa4e8SJohnny Huang 		printf("BIT(hex)  Value  Option           Status\n");
1856de6b0cc4SJohnny Huang 	} else {
1857de6b0cc4SJohnny Huang 		remains = 6;
1858de6b0cc4SJohnny Huang 		printf("BIT(hex)  Value  Option         Reg_Protect Status\n");
1859de6b0cc4SJohnny Huang 	}
1860de6b0cc4SJohnny Huang 	printf("______________________________________________________________________________\n");
1861737ed20bSJohnny Huang 
1862cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
186307baa4e8SJohnny Huang 		printf("0x%-8X", i);
1864737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1865de6b0cc4SJohnny Huang 		for (j = 0; j < remains; j++)
1866737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1867737ed20bSJohnny Huang 		printf("   ");
1868de6b0cc4SJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
1869de6b0cc4SJohnny Huang 			printf("%d           ", otpstrap[i].reg_protected);
1870de6b0cc4SJohnny Huang 		}
187169d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1872737ed20bSJohnny Huang 			printf("protected and not writable");
187369d5fd8fSJohnny Huang 		} else {
1874737ed20bSJohnny Huang 			printf("not protected ");
187569d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1876737ed20bSJohnny Huang 				printf("and no remaining times to write.");
187769d5fd8fSJohnny Huang 			} else {
1878737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
187969d5fd8fSJohnny Huang 			}
188069d5fd8fSJohnny Huang 		}
1881737ed20bSJohnny Huang 		printf("\n");
188269d5fd8fSJohnny Huang 	}
18832a856b9aSJohnny Huang 
18842a856b9aSJohnny Huang 	return OTP_SUCCESS;
188569d5fd8fSJohnny Huang }
188669d5fd8fSJohnny Huang 
18878848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value)
18888848d5dcSJohnny Huang {
18898848d5dcSJohnny Huang 	struct otpstrap_status otpstrap[64];
189083655e91SJohnny Huang 	uint32_t prog_address;
18918848d5dcSJohnny Huang 	int offset;
18928848d5dcSJohnny Huang 	int ret;
18938848d5dcSJohnny Huang 
18948848d5dcSJohnny Huang 
18958848d5dcSJohnny Huang 	otp_strap_status(otpstrap);
18968848d5dcSJohnny Huang 
18978848d5dcSJohnny Huang 	ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
18988848d5dcSJohnny Huang 
18998848d5dcSJohnny Huang 	if (ret != OTP_SUCCESS) {
19008848d5dcSJohnny Huang 		return ret;
19018848d5dcSJohnny Huang 	}
19028848d5dcSJohnny Huang 
19038848d5dcSJohnny Huang 	prog_address = 0x800;
19048848d5dcSJohnny Huang 	if (bit_offset < 32) {
19058848d5dcSJohnny Huang 		offset = bit_offset;
19068848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200;
19078848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2;
19088848d5dcSJohnny Huang 
19098848d5dcSJohnny Huang 	} else {
19108848d5dcSJohnny Huang 		offset = (bit_offset - 32);
19118848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200;
19128848d5dcSJohnny Huang 		prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2;
19138848d5dcSJohnny Huang 	}
19148848d5dcSJohnny Huang 
19158848d5dcSJohnny Huang 
191683655e91SJohnny Huang 	return otp_prog_bit(1, prog_address, offset);
19178848d5dcSJohnny Huang }
19188848d5dcSJohnny Huang 
19195010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout)
192069d5fd8fSJohnny Huang {
19215010032bSJohnny Huang 	uint32_t *strap;
19225010032bSJohnny Huang 	uint32_t *strap_ignore;
19235010032bSJohnny Huang 	uint32_t *strap_pro;
19245010032bSJohnny Huang 	uint32_t *strap_reg_protect;
192583655e91SJohnny Huang 	uint32_t prog_address;
192683655e91SJohnny Huang 	int i;
1927eda10d61SJohnny Huang 	int bit, pbit, ibit, offset, rpbit;
192869d5fd8fSJohnny Huang 	int fail = 0;
192983655e91SJohnny Huang 	int ret;
193066f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
193169d5fd8fSJohnny Huang 
19325010032bSJohnny Huang 	strap = (uint32_t *)image_layout->strap;
19335010032bSJohnny Huang 	strap_pro = (uint32_t *)image_layout->strap_pro;
19345010032bSJohnny Huang 	strap_ignore = (uint32_t *)image_layout->strap_ignore;
19355010032bSJohnny Huang 	strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro;
19365010032bSJohnny Huang 
19377f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1938541eb887SJohnny Huang 	otp_strap_status(otpstrap);
193969d5fd8fSJohnny Huang 
19407f795e57SJohnny Huang 	printf("Check writable...\n");
19415010032bSJohnny Huang 	if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) {
19427f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
19437f795e57SJohnny Huang 		return OTP_FAILURE;
19447f795e57SJohnny Huang 	}
19457e22f42dSJohnny Huang 
194669d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
194769d5fd8fSJohnny Huang 		prog_address = 0x800;
194869d5fd8fSJohnny Huang 		if (i < 32) {
194969d5fd8fSJohnny Huang 			offset = i;
19505010032bSJohnny Huang 			bit = (strap[0] >> offset) & 0x1;
1951eda10d61SJohnny Huang 			ibit = (strap_ignore[0] >> offset) & 0x1;
19525010032bSJohnny Huang 			pbit = (strap_pro[0] >> offset) & 0x1;
195369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
195469d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
195569d5fd8fSJohnny Huang 
195669d5fd8fSJohnny Huang 		} else {
195769d5fd8fSJohnny Huang 			offset = (i - 32);
19585010032bSJohnny Huang 			bit = (strap[1] >> offset) & 0x1;
1959eda10d61SJohnny Huang 			ibit = (strap_ignore[1] >> offset) & 0x1;
19605010032bSJohnny Huang 			pbit = (strap_pro[1] >> offset) & 0x1;
196169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
196269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
196369d5fd8fSJohnny Huang 		}
19645010032bSJohnny Huang 		if (info_cb.version != OTP_AST2600A0) {
19655010032bSJohnny Huang 			if (i < 32) {
19665010032bSJohnny Huang 				rpbit = (strap_reg_protect[0] >> i) & 0x1;
19675010032bSJohnny Huang 			} else {
19685010032bSJohnny Huang 				rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1;
19695010032bSJohnny Huang 			}
19705010032bSJohnny Huang 		} else {
19715010032bSJohnny Huang 			rpbit = 0;
19725010032bSJohnny Huang 		}
197369d5fd8fSJohnny Huang 
1974eda10d61SJohnny Huang 		if (ibit == 1) {
197569d5fd8fSJohnny Huang 			continue;
197669d5fd8fSJohnny Huang 		}
197769d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
197869d5fd8fSJohnny Huang 			continue;
197969d5fd8fSJohnny Huang 		}
198069d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
198169d5fd8fSJohnny Huang 			fail = 1;
198269d5fd8fSJohnny Huang 			continue;
198369d5fd8fSJohnny Huang 		}
198469d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
198569d5fd8fSJohnny Huang 			fail = 1;
198669d5fd8fSJohnny Huang 			continue;
198769d5fd8fSJohnny Huang 		}
19887e22f42dSJohnny Huang 
198983655e91SJohnny Huang 		ret = otp_prog_bit(1, prog_address, offset);
199083655e91SJohnny Huang 		if (!ret)
19912a856b9aSJohnny Huang 			return OTP_FAILURE;
199269d5fd8fSJohnny Huang 
19935010032bSJohnny Huang 		if (rpbit == 1 && info_cb.version != OTP_AST2600A0) {
199469d5fd8fSJohnny Huang 			prog_address = 0x800;
199569d5fd8fSJohnny Huang 			if (i < 32)
19965010032bSJohnny Huang 				prog_address |= 0x608;
199769d5fd8fSJohnny Huang 			else
19985010032bSJohnny Huang 				prog_address |= 0x60a;
19997e22f42dSJohnny Huang 
200083655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
200183655e91SJohnny Huang 			if (!ret)
20022a856b9aSJohnny Huang 				return OTP_FAILURE;
20035010032bSJohnny Huang 		}
20045010032bSJohnny Huang 
20055010032bSJohnny Huang 		if (pbit != 0) {
20065010032bSJohnny Huang 			prog_address = 0x800;
20075010032bSJohnny Huang 			if (i < 32)
20085010032bSJohnny Huang 				prog_address |= 0x60c;
20095010032bSJohnny Huang 			else
20105010032bSJohnny Huang 				prog_address |= 0x60e;
20115010032bSJohnny Huang 
201283655e91SJohnny Huang 			ret = otp_prog_bit(1, prog_address, offset);
201383655e91SJohnny Huang 			if (!ret)
20145010032bSJohnny Huang 				return OTP_FAILURE;
20155010032bSJohnny Huang 		}
201669d5fd8fSJohnny Huang 
201769d5fd8fSJohnny Huang 	}
2018de6fbf1cSJohnny Huang 	otp_soak(0);
201969d5fd8fSJohnny Huang 	if (fail == 1)
20202a856b9aSJohnny Huang 		return OTP_FAILURE;
202169d5fd8fSJohnny Huang 	else
20222a856b9aSJohnny Huang 		return OTP_SUCCESS;
202369d5fd8fSJohnny Huang 
202469d5fd8fSJohnny Huang }
202569d5fd8fSJohnny Huang 
20265010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout)
20274c1c9b35SJohnny Huang {
202854552c69SJohnny Huang 	int i;
202954552c69SJohnny Huang 	int ret;
20305010032bSJohnny Huang 	int data_dw;
2031d90825e2SJohnny Huang 	uint32_t data[2048];
20325010032bSJohnny Huang 	uint32_t *buf;
20335010032bSJohnny Huang 	uint32_t *buf_ignore;
20344c1c9b35SJohnny Huang 
203554552c69SJohnny Huang 	uint32_t data_masked;
203654552c69SJohnny Huang 	uint32_t buf_masked;
20374c1c9b35SJohnny Huang 
20385010032bSJohnny Huang 	buf = (uint32_t *)image_layout->data;
20395010032bSJohnny Huang 	buf_ignore = (uint32_t *)image_layout->data_ignore;
20405010032bSJohnny Huang 
20415010032bSJohnny Huang 	data_dw = image_layout->data_length / 4;
20425010032bSJohnny Huang 
20434c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
20444c1c9b35SJohnny Huang 
20455010032bSJohnny Huang 	for (i = 0; i < data_dw - 2 ; i += 2) {
2046d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
20474c1c9b35SJohnny Huang 	}
2048d90825e2SJohnny Huang 
20494c1c9b35SJohnny Huang 	printf("Check writable...\n");
205054552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
20515010032bSJohnny Huang 	for (i = 0; i < data_dw - 2; i++) {
2052696656c6SJohnny Huang 		data_masked = data[i]  & ~buf_ignore[i];
2053696656c6SJohnny Huang 		buf_masked  = buf[i] & ~buf_ignore[i];
205454552c69SJohnny Huang 		if (data_masked == buf_masked)
20554c1c9b35SJohnny Huang 			continue;
2056d90825e2SJohnny Huang 		if (i % 2 == 0) {
205754552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
20584c1c9b35SJohnny Huang 				continue;
20594c1c9b35SJohnny Huang 			} else {
20604c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
2061d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
20624c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
2063696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
20642a856b9aSJohnny Huang 				return OTP_FAILURE;
206569d5fd8fSJohnny Huang 			}
2066d90825e2SJohnny Huang 		} else {
206754552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
2068d90825e2SJohnny Huang 				continue;
2069d90825e2SJohnny Huang 			} else {
2070d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
2071d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
2072d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
2073696656c6SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_ignore[i]);
20742a856b9aSJohnny Huang 				return OTP_FAILURE;
2075d90825e2SJohnny Huang 			}
2076d90825e2SJohnny Huang 		}
2077d90825e2SJohnny Huang 	}
207869d5fd8fSJohnny Huang 
2079d90825e2SJohnny Huang 	printf("Start Programing...\n");
2080d90825e2SJohnny Huang 
208154552c69SJohnny Huang 	// programing ecc region first
208254552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
2083696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
208454552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
208554552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
2086696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
208754552c69SJohnny Huang 			return ret;
2088d90825e2SJohnny Huang 		}
2089d90825e2SJohnny Huang 	}
2090d90825e2SJohnny Huang 
209154552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
2092696656c6SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i);
209354552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
209454552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
2095696656c6SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]);
209654552c69SJohnny Huang 			return ret;
2097d90825e2SJohnny Huang 		}
2098de6fbf1cSJohnny Huang 	}
2099de6fbf1cSJohnny Huang 	otp_soak(0);
21002a856b9aSJohnny Huang 	return OTP_SUCCESS;
2101d90825e2SJohnny Huang 
2102d90825e2SJohnny Huang }
2103d90825e2SJohnny Huang 
2104696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf)
2105696656c6SJohnny Huang {
2106696656c6SJohnny Huang 	sha256_context ctx;
2107696656c6SJohnny Huang 	u8 digest_ret[CHECKSUM_LEN];
2108696656c6SJohnny Huang 
2109696656c6SJohnny Huang 	sha256_starts(&ctx);
2110696656c6SJohnny Huang 	sha256_update(&ctx, src_buf, length);
2111696656c6SJohnny Huang 	sha256_finish(&ctx, digest_ret);
2112696656c6SJohnny Huang 
2113696656c6SJohnny Huang 	if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN))
2114696656c6SJohnny Huang 		return 0;
2115696656c6SJohnny Huang 	else
2116696656c6SJohnny Huang 		return -1;
2117696656c6SJohnny Huang 
2118696656c6SJohnny Huang }
2119696656c6SJohnny Huang 
2120de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm)
212169d5fd8fSJohnny Huang {
212269d5fd8fSJohnny Huang 	int ret;
21239a4fe690SJohnny Huang 	int image_version = 0;
2124696656c6SJohnny Huang 	struct otp_header *otp_header;
2125696656c6SJohnny Huang 	struct otp_image_layout image_layout;
2126696656c6SJohnny Huang 	int image_size;
2127696656c6SJohnny Huang 	uint8_t *buf;
2128696656c6SJohnny Huang 	uint8_t *checksum;
212969d5fd8fSJohnny Huang 
2130696656c6SJohnny Huang 	otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK);
2131696656c6SJohnny Huang 	if (!otp_header) {
213269d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
21332a856b9aSJohnny Huang 		return OTP_FAILURE;
213469d5fd8fSJohnny Huang 	}
2135d90825e2SJohnny Huang 
2136696656c6SJohnny Huang 	image_size = OTP_IMAGE_SIZE(otp_header->image_info);
2137696656c6SJohnny Huang 	unmap_physmem(otp_header, MAP_WRBACK);
2138696656c6SJohnny Huang 
2139696656c6SJohnny Huang 	buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK);
2140696656c6SJohnny Huang 
2141696656c6SJohnny Huang 	if (!buf) {
2142696656c6SJohnny Huang 		puts("Failed to map physical memory\n");
2143696656c6SJohnny Huang 		return OTP_FAILURE;
2144696656c6SJohnny Huang 	}
2145696656c6SJohnny Huang 	otp_header = (struct otp_header *) buf;
2146696656c6SJohnny Huang 	checksum = buf + otp_header->checksum_offset;
2147696656c6SJohnny Huang 
2148696656c6SJohnny Huang 	if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) {
2149696656c6SJohnny Huang 		puts("Image is invalid\n");
2150696656c6SJohnny Huang 		return OTP_FAILURE;
2151696656c6SJohnny Huang 	}
2152696656c6SJohnny Huang 
2153696656c6SJohnny Huang 
21545010032bSJohnny Huang 	image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2);
21555010032bSJohnny Huang 	image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info);
21565010032bSJohnny Huang 	image_layout.data_ignore = image_layout.data + image_layout.data_length;
21575010032bSJohnny Huang 
21585010032bSJohnny Huang 	image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2);
2159696656c6SJohnny Huang 	image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info);
21605010032bSJohnny Huang 	image_layout.conf_ignore = image_layout.conf + image_layout.conf_length;
2161696656c6SJohnny Huang 
2162696656c6SJohnny Huang 	image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info);
2163696656c6SJohnny Huang 
2164696656c6SJohnny Huang 	if (!strcmp("A0", (char *)otp_header->otp_version)) {
2165696656c6SJohnny Huang 		image_version = OTP_AST2600A0;
21665010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3);
21675010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + image_layout.strap_length;
21685010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length;
2169696656c6SJohnny Huang 	} else if (!strcmp("A1", (char *)otp_header->otp_version)) {
2170696656c6SJohnny Huang 		image_version = OTP_AST2600A1;
21715010032bSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
21725010032bSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
21735010032bSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
21745010032bSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
2175*5fdde29fSJohnny Huang 	} else if (!strcmp("A2", (char *)otp_header->otp_version)) {
2176*5fdde29fSJohnny Huang 		image_version = OTP_AST2600A2;
2177*5fdde29fSJohnny Huang 		image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4);
2178*5fdde29fSJohnny Huang 		image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length;
2179*5fdde29fSJohnny Huang 		image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length;
2180*5fdde29fSJohnny Huang 		image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length;
2181696656c6SJohnny Huang 	} else {
2182696656c6SJohnny Huang 		puts("Version is not supported\n");
2183696656c6SJohnny Huang 		return OTP_FAILURE;
2184696656c6SJohnny Huang 	}
2185696656c6SJohnny Huang 
21869a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
21879a4fe690SJohnny Huang 		puts("Version is not match\n");
21889a4fe690SJohnny Huang 		return OTP_FAILURE;
21899a4fe690SJohnny Huang 	}
21909a4fe690SJohnny Huang 
2191696656c6SJohnny Huang 	if (otp_image_verify(buf, image_size, checksum)) {
2192696656c6SJohnny Huang 		puts("checksum is invalid\n");
2193696656c6SJohnny Huang 		return OTP_FAILURE;
2194d90825e2SJohnny Huang 	}
21957332532cSJohnny Huang 
219669d5fd8fSJohnny Huang 	if (!nconfirm) {
2197696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_DATA) {
21987f795e57SJohnny Huang 			printf("\nOTP data region :\n");
2199696656c6SJohnny Huang 			if (otp_print_data_info(&image_layout) < 0) {
220069d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
22012a856b9aSJohnny Huang 				return OTP_FAILURE;
220269d5fd8fSJohnny Huang 			}
220369d5fd8fSJohnny Huang 		}
2204696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_STRAP) {
22057332532cSJohnny Huang 			printf("\nOTP strap region :\n");
22065010032bSJohnny Huang 			if (otp_print_strap_image(&image_layout) < 0) {
22077332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
22087332532cSJohnny Huang 				return OTP_FAILURE;
22097332532cSJohnny Huang 			}
22107332532cSJohnny Huang 		}
2211696656c6SJohnny Huang 		if (otp_header->image_info & OTP_INC_CONFIG) {
22127332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
2213696656c6SJohnny Huang 			if (otp_print_conf_image(&image_layout) < 0) {
22147332532cSJohnny Huang 				printf("OTP config error, please check.\n");
22157332532cSJohnny Huang 				return OTP_FAILURE;
22167332532cSJohnny Huang 			}
22177332532cSJohnny Huang 		}
22187332532cSJohnny Huang 
221969d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
222069d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
222169d5fd8fSJohnny Huang 			printf(" Aborting\n");
22222a856b9aSJohnny Huang 			return OTP_FAILURE;
222369d5fd8fSJohnny Huang 		}
222469d5fd8fSJohnny Huang 	}
22257332532cSJohnny Huang 
22265010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_DATA) {
22275010032bSJohnny Huang 		printf("programing data region ...\n");
22285010032bSJohnny Huang 		ret = otp_prog_data(&image_layout);
22295010032bSJohnny Huang 		if (ret != 0) {
22305010032bSJohnny Huang 			printf("Error\n");
22315010032bSJohnny Huang 			return ret;
22325010032bSJohnny Huang 		} else {
22335010032bSJohnny Huang 			printf("Done\n");
22345010032bSJohnny Huang 		}
22355010032bSJohnny Huang 	}
22365010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_STRAP) {
22375010032bSJohnny Huang 		printf("programing strap region ...\n");
22385010032bSJohnny Huang 		ret = otp_prog_strap(&image_layout);
22395010032bSJohnny Huang 		if (ret != 0) {
22405010032bSJohnny Huang 			printf("Error\n");
22415010032bSJohnny Huang 			return ret;
22425010032bSJohnny Huang 		} else {
22435010032bSJohnny Huang 			printf("Done\n");
22445010032bSJohnny Huang 		}
22455010032bSJohnny Huang 	}
22465010032bSJohnny Huang 	if (otp_header->image_info & OTP_INC_CONFIG) {
22475010032bSJohnny Huang 		printf("programing configuration region ...\n");
22485010032bSJohnny Huang 		ret = otp_prog_conf(&image_layout);
22495010032bSJohnny Huang 		if (ret != 0) {
22505010032bSJohnny Huang 			printf("Error\n");
22515010032bSJohnny Huang 			return ret;
22525010032bSJohnny Huang 		}
22535010032bSJohnny Huang 		printf("Done\n");
22545010032bSJohnny Huang 	}
2255cd1610b4SJohnny Huang 
22567332532cSJohnny Huang 	return OTP_SUCCESS;
22572a856b9aSJohnny Huang }
22582a856b9aSJohnny Huang 
22592a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
2260cd1610b4SJohnny Huang {
2261a6af4a17SJohnny Huang 	uint32_t read[2];
2262d90825e2SJohnny Huang 	uint32_t prog_address = 0;
226366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
2264cd1610b4SJohnny Huang 	int otp_bit;
226583655e91SJohnny Huang 	int ret = 0;
2266cd1610b4SJohnny Huang 
2267cd1610b4SJohnny Huang 	switch (mode) {
2268a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2269a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
2270cd1610b4SJohnny Huang 		prog_address = 0x800;
2271cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
2272cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
2273a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
2274cd1610b4SJohnny Huang 		if (otp_bit == value) {
2275a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
2276cd1610b4SJohnny Huang 			printf("No need to program\n");
22772a856b9aSJohnny Huang 			return OTP_SUCCESS;
2278cd1610b4SJohnny Huang 		}
2279cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
2280a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
2281cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
22822a856b9aSJohnny Huang 			return OTP_FAILURE;
2283cd1610b4SJohnny Huang 		}
2284a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
2285cd1610b4SJohnny Huang 		break;
2286a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
2287cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
2288cd1610b4SJohnny Huang 
2289cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
2290a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
2291a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
2292643b9cfdSJohnny Huang 
2293643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
2294643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
2295643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
2296643b9cfdSJohnny Huang 				return OTP_FAILURE;
2297643b9cfdSJohnny Huang 			}
2298cd1610b4SJohnny Huang 		} else {
2299a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
2300a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
2301643b9cfdSJohnny Huang 
2302643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
2303643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
2304643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
2305643b9cfdSJohnny Huang 				return OTP_FAILURE;
2306643b9cfdSJohnny Huang 			}
2307cd1610b4SJohnny Huang 		}
2308cd1610b4SJohnny Huang 		if (otp_bit == value) {
2309a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
2310cd1610b4SJohnny Huang 			printf("No need to program\n");
23112a856b9aSJohnny Huang 			return OTP_SUCCESS;
2312cd1610b4SJohnny Huang 		}
2313643b9cfdSJohnny Huang 
2314a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
2315cd1610b4SJohnny Huang 		break;
2316a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
23178848d5dcSJohnny Huang 		otp_strap_status(otpstrap);
23188848d5dcSJohnny Huang 		otp_print_strap(bit_offset, 1);
23198848d5dcSJohnny Huang 		ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0);
23208848d5dcSJohnny Huang 		if (ret == OTP_FAILURE)
23218848d5dcSJohnny Huang 			return OTP_FAILURE;
23228848d5dcSJohnny Huang 		else if (ret == OTP_PROG_SKIP)
23238848d5dcSJohnny Huang 			return OTP_SUCCESS;
2324a6af4a17SJohnny Huang 
2325cd1610b4SJohnny Huang 		break;
2326cd1610b4SJohnny Huang 	}
2327cd1610b4SJohnny Huang 
2328cd1610b4SJohnny Huang 	if (!nconfirm) {
2329cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2330cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
2331cd1610b4SJohnny Huang 			printf(" Aborting\n");
23322a856b9aSJohnny Huang 			return OTP_FAILURE;
2333cd1610b4SJohnny Huang 		}
2334cd1610b4SJohnny Huang 	}
2335cd1610b4SJohnny Huang 
2336cd1610b4SJohnny Huang 	switch (mode) {
2337a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
233883655e91SJohnny Huang 		ret =  otp_prog_strap_bit(bit_offset, value);
233983655e91SJohnny Huang 		break;
2340a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
2341a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
234283655e91SJohnny Huang 		ret = otp_prog_bit(value, prog_address, bit_offset);
2343de6fbf1cSJohnny Huang 		break;
2344de6fbf1cSJohnny Huang 	}
2345de6fbf1cSJohnny Huang 	otp_soak(0);
234683655e91SJohnny Huang 	if (ret) {
23479009c25dSJohnny Huang 		printf("SUCCESS\n");
23482a856b9aSJohnny Huang 		return OTP_SUCCESS;
23499009c25dSJohnny Huang 	} else {
23509009c25dSJohnny Huang 		printf("OTP cannot be programed\n");
23519009c25dSJohnny Huang 		printf("FAILED\n");
23529009c25dSJohnny Huang 		return OTP_FAILURE;
23539009c25dSJohnny Huang 	}
2354cd1610b4SJohnny Huang 
23552a856b9aSJohnny Huang 	return OTP_USAGE;
2356cd1610b4SJohnny Huang }
2357cd1610b4SJohnny Huang 
23582a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
235969d5fd8fSJohnny Huang {
23602a856b9aSJohnny Huang 	uint32_t offset, count;
23612a856b9aSJohnny Huang 	int ret;
236269d5fd8fSJohnny Huang 
23632a856b9aSJohnny Huang 	if (argc == 4) {
23642a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
23652a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
23662a856b9aSJohnny Huang 	} else if (argc == 3) {
23672a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
23682a856b9aSJohnny Huang 		count = 1;
23692a856b9aSJohnny Huang 	} else {
237069d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
237169d5fd8fSJohnny Huang 	}
237269d5fd8fSJohnny Huang 
237369d5fd8fSJohnny Huang 
23742a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
23753d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23762a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
23772a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
23783d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23792a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
23802a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
23813d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
23822a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
23832a856b9aSJohnny Huang 	} else {
23842a856b9aSJohnny Huang 		return CMD_RET_USAGE;
238569d5fd8fSJohnny Huang 	}
238669d5fd8fSJohnny Huang 
23872a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
23882a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
23892a856b9aSJohnny Huang 	else
23902a856b9aSJohnny Huang 		return CMD_RET_USAGE;
23912a856b9aSJohnny Huang 
23922a856b9aSJohnny Huang }
23932a856b9aSJohnny Huang 
23942a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
23952a856b9aSJohnny Huang {
23962a856b9aSJohnny Huang 	phys_addr_t addr;
23972a856b9aSJohnny Huang 	int ret;
23982a856b9aSJohnny Huang 
2399de6b0cc4SJohnny Huang 	if (argc == 3) {
2400ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
24012a856b9aSJohnny Huang 			return CMD_RET_USAGE;
24022a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
24033d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2404de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 1);
2405de6b0cc4SJohnny Huang 	} else if (argc == 2) {
24062a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
24073d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2408de6b0cc4SJohnny Huang 		ret = do_otp_prog(addr, 0);
24092a856b9aSJohnny Huang 	} else {
24102a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24112a856b9aSJohnny Huang 	}
24122a856b9aSJohnny Huang 
24132a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
24142a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
24152a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
24162a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
24172a856b9aSJohnny Huang 	else
24182a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24192a856b9aSJohnny Huang }
24202a856b9aSJohnny Huang 
24212a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
24222a856b9aSJohnny Huang {
24232a856b9aSJohnny Huang 	int mode = 0;
24242a856b9aSJohnny Huang 	int nconfirm = 0;
24252a856b9aSJohnny Huang 	int otp_addr = 0;
24262a856b9aSJohnny Huang 	int bit_offset;
24272a856b9aSJohnny Huang 	int value;
24282a856b9aSJohnny Huang 	int ret;
24292a856b9aSJohnny Huang 
24302a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
24312a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24322a856b9aSJohnny Huang 
24332a856b9aSJohnny Huang 	/* Drop the pb cmd */
24342a856b9aSJohnny Huang 	argc--;
24352a856b9aSJohnny Huang 	argv++;
24362a856b9aSJohnny Huang 
24372a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2438a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
24392a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2440a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
24412a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
2442a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
2443cd1610b4SJohnny Huang 	else
24442a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24452a856b9aSJohnny Huang 
24462a856b9aSJohnny Huang 	/* Drop the region cmd */
24472a856b9aSJohnny Huang 	argc--;
24482a856b9aSJohnny Huang 	argv++;
24492a856b9aSJohnny Huang 
2450ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2451cd1610b4SJohnny Huang 		nconfirm = 1;
24522a856b9aSJohnny Huang 		/* Drop the force option */
24532a856b9aSJohnny Huang 		argc--;
24542a856b9aSJohnny Huang 		argv++;
24552a856b9aSJohnny Huang 	}
2456cd1610b4SJohnny Huang 
2457a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
24582a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
24592a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
24600808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
24612a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2462cd1610b4SJohnny Huang 	} else {
24632a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
24642a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
24652a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
24660808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
24672a856b9aSJohnny Huang 			return CMD_RET_USAGE;
24680808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
246978855207SJohnny Huang 			if (otp_addr >= 0x800)
24700808cc55SJohnny Huang 				return CMD_RET_USAGE;
24710808cc55SJohnny Huang 		} else {
247278855207SJohnny Huang 			if (otp_addr >= 0x20)
24730808cc55SJohnny Huang 				return CMD_RET_USAGE;
24740808cc55SJohnny Huang 		}
2475cd1610b4SJohnny Huang 	}
2476cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
24772a856b9aSJohnny Huang 		return CMD_RET_USAGE;
2478cd1610b4SJohnny Huang 
24793d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
24802a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
24812a856b9aSJohnny Huang 
24822a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
24832a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
24842a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
24852a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
24862a856b9aSJohnny Huang 	else
24872a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24882a856b9aSJohnny Huang }
24892a856b9aSJohnny Huang 
24902a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
24912a856b9aSJohnny Huang {
24922a856b9aSJohnny Huang 	phys_addr_t addr;
24932a856b9aSJohnny Huang 	int otp_addr = 0;
24942a856b9aSJohnny Huang 
24952a856b9aSJohnny Huang 	if (argc != 3)
24962a856b9aSJohnny Huang 		return CMD_RET_USAGE;
24972a856b9aSJohnny Huang 
24983d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
24992a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
25002a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
25012a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
250269d5fd8fSJohnny Huang 		printf("Compare pass\n");
25032a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
250469d5fd8fSJohnny Huang 	} else {
250569d5fd8fSJohnny Huang 		printf("Compare fail\n");
25062a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
250769d5fd8fSJohnny Huang 	}
250869d5fd8fSJohnny Huang }
250969d5fd8fSJohnny Huang 
251066f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
251166f2f8e5SJohnny Huang {
2512a8bd6d8cSJohnny Huang 	int view = 0;
25132d4b0742SJohnny Huang 	int input;
2514a8bd6d8cSJohnny Huang 
2515a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
251666f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
251766f2f8e5SJohnny Huang 
25182d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
251966f2f8e5SJohnny Huang 
25203d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
25212d4b0742SJohnny Huang 		if (argc == 3) {
25222d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
25232d4b0742SJohnny Huang 			otp_print_conf_info(input);
25242d4b0742SJohnny Huang 		} else {
25252d4b0742SJohnny Huang 			otp_print_conf_info(-1);
25262d4b0742SJohnny Huang 		}
25272d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
25282d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
2529a8bd6d8cSJohnny Huang 			view = 1;
2530a8bd6d8cSJohnny Huang 			/* Drop the view option */
2531a8bd6d8cSJohnny Huang 			argc--;
2532a8bd6d8cSJohnny Huang 			argv++;
2533a8bd6d8cSJohnny Huang 		}
25343d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2535b458cd62SJohnny Huang 		otp_print_strap_info(view);
253666f2f8e5SJohnny Huang 	} else {
253766f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
253866f2f8e5SJohnny Huang 	}
25392d4b0742SJohnny Huang 
254066f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
254166f2f8e5SJohnny Huang }
254266f2f8e5SJohnny Huang 
2543737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2544737ed20bSJohnny Huang {
2545737ed20bSJohnny Huang 	int input;
2546737ed20bSJohnny Huang 	int bit_offset;
2547737ed20bSJohnny Huang 	int prog_address;
254883655e91SJohnny Huang 	int ret;
2549737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2550737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2551737ed20bSJohnny Huang 
2552ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2553737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2554737ed20bSJohnny Huang 	} else {
2555737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2556737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2557737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2558737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2559737ed20bSJohnny Huang 			printf(" Aborting\n");
2560737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2561737ed20bSJohnny Huang 		}
2562737ed20bSJohnny Huang 	}
2563737ed20bSJohnny Huang 
2564737ed20bSJohnny Huang 	prog_address = 0x800;
2565737ed20bSJohnny Huang 	if (input < 32) {
2566737ed20bSJohnny Huang 		bit_offset = input;
2567737ed20bSJohnny Huang 		prog_address |= 0x60c;
2568737ed20bSJohnny Huang 	} else if (input < 64) {
2569737ed20bSJohnny Huang 		bit_offset = input - 32;
2570737ed20bSJohnny Huang 		prog_address |= 0x60e;
2571737ed20bSJohnny Huang 	} else {
2572737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2573737ed20bSJohnny Huang 	}
2574737ed20bSJohnny Huang 
2575737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2576737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2577737ed20bSJohnny Huang 	}
2578de6fbf1cSJohnny Huang 
257983655e91SJohnny Huang 	ret = otp_prog_bit(1, prog_address, bit_offset);
2580de6fbf1cSJohnny Huang 	otp_soak(0);
258183655e91SJohnny Huang 
258283655e91SJohnny Huang 	if (ret) {
2583737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2584737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2585737ed20bSJohnny Huang 	}
2586737ed20bSJohnny Huang 
2587737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2588737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2589737ed20bSJohnny Huang 
2590737ed20bSJohnny Huang }
25919a4fe690SJohnny Huang 
25922a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
25932a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2594a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
2595de6b0cc4SJohnny Huang 	U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""),
25962a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2597737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
25982a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
25992a856b9aSJohnny Huang };
26002a856b9aSJohnny Huang 
26012a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
26022a856b9aSJohnny Huang {
26032a856b9aSJohnny Huang 	cmd_tbl_t *cp;
26042a856b9aSJohnny Huang 
26052a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
26062a856b9aSJohnny Huang 
2607737ed20bSJohnny Huang 	/* Drop the otp command */
26082a856b9aSJohnny Huang 	argc--;
26092a856b9aSJohnny Huang 	argv++;
26102a856b9aSJohnny Huang 
26112a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
26122a856b9aSJohnny Huang 		return CMD_RET_USAGE;
26132a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
26142a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
26152a856b9aSJohnny Huang 
2616696656c6SJohnny Huang 	if (chip_version() == OTP_AST2600A0) {
2617696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A0;
26189a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
26199a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
26209a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
26219a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
26229a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
26239a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
2624696656c6SJohnny Huang 	} else if (chip_version() == OTP_AST2600A1) {
2625696656c6SJohnny Huang 		info_cb.version = OTP_AST2600A1;
26263cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
26273cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
26283cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
26293cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
26309a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
26319a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
2632*5fdde29fSJohnny Huang 	} else if (chip_version() == OTP_AST2600A2) {
2633*5fdde29fSJohnny Huang 		info_cb.version = OTP_AST2600A2;
2634*5fdde29fSJohnny Huang 		info_cb.conf_info = a2_conf_info;
2635*5fdde29fSJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info);
2636*5fdde29fSJohnny Huang 		info_cb.strap_info = a2_strap_info;
2637*5fdde29fSJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info);
2638*5fdde29fSJohnny Huang 		info_cb.key_info = a2_key_type;
2639*5fdde29fSJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a2_key_type);
26409a4fe690SJohnny Huang 	}
26419a4fe690SJohnny Huang 
26422a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
264369d5fd8fSJohnny Huang }
264469d5fd8fSJohnny Huang 
264569d5fd8fSJohnny Huang U_BOOT_CMD(
264669d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
264769d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
26482a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
26492a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
26502d4b0742SJohnny Huang 	"otp info strap [v]\n"
26512d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2652de6b0cc4SJohnny Huang 	"otp prog [o] <addr>\n"
2653ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2654ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2655ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
26562a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
265769d5fd8fSJohnny Huang );
2658