xref: /openbmc/u-boot/cmd/otp.c (revision bb34a7bfccc0f486d8f729bdf2fdcb1cffa59b4f)
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>
2369d5fd8fSJohnny Huang 
2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR;
2569d5fd8fSJohnny Huang 
2669d5fd8fSJohnny Huang #define OTP_PASSWD			0x349fe38a
2769d5fd8fSJohnny Huang #define RETRY				3
287332532cSJohnny Huang #define OTP_REGION_STRAP		BIT(0)
297332532cSJohnny Huang #define OTP_REGION_CONF			BIT(1)
307332532cSJohnny Huang #define OTP_REGION_DATA			BIT(2)
3169d5fd8fSJohnny Huang 
322a856b9aSJohnny Huang #define OTP_USAGE			-1
332a856b9aSJohnny Huang #define OTP_FAILURE			-2
342a856b9aSJohnny Huang #define OTP_SUCCESS			0
352a856b9aSJohnny Huang 
36a6af4a17SJohnny Huang #define OTP_PROG_SKIP			1
37a6af4a17SJohnny Huang 
389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA		1
399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES		2
409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT		3
419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC		4
429a4fe690SJohnny Huang 
439a4fe690SJohnny Huang 
44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
45b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4776d13988SJohnny Huang 
484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
494c1c9b35SJohnny Huang #define PBWIDTH 60
504c1c9b35SJohnny Huang 
513d3688adSJohnny Huang #define OTP_BASE		0x1e6f2000
523d3688adSJohnny Huang #define OTP_PROTECT_KEY		OTP_BASE
533d3688adSJohnny Huang #define OTP_COMMAND		OTP_BASE + 0x4
543d3688adSJohnny Huang #define OTP_TIMING		OTP_BASE + 0x8
553d3688adSJohnny Huang #define OTP_ADDR		OTP_BASE + 0x10
563d3688adSJohnny Huang #define OTP_STATUS		OTP_BASE + 0x14
573d3688adSJohnny Huang #define OTP_COMPARE_1		OTP_BASE + 0x20
583d3688adSJohnny Huang #define OTP_COMPARE_2		OTP_BASE + 0x24
593d3688adSJohnny Huang #define OTP_COMPARE_3		OTP_BASE + 0x28
603d3688adSJohnny Huang #define OTP_COMPARE_4		OTP_BASE + 0x2c
613d3688adSJohnny Huang 
6266f2f8e5SJohnny Huang struct otpstrap_status {
6369d5fd8fSJohnny Huang 	int value;
6469d5fd8fSJohnny Huang 	int option_array[7];
6569d5fd8fSJohnny Huang 	int remain_times;
6669d5fd8fSJohnny Huang 	int writeable_option;
6769d5fd8fSJohnny Huang 	int protected;
6869d5fd8fSJohnny Huang };
6969d5fd8fSJohnny Huang 
7066f2f8e5SJohnny Huang struct otpconf_parse {
7166f2f8e5SJohnny Huang 	int dw_offset;
7266f2f8e5SJohnny Huang 	int bit;
7366f2f8e5SJohnny Huang 	int length;
7466f2f8e5SJohnny Huang 	int value;
7566f2f8e5SJohnny Huang 	int keep;
7666f2f8e5SJohnny Huang 	char status[80];
7766f2f8e5SJohnny Huang };
7866f2f8e5SJohnny Huang 
79a8bd6d8cSJohnny Huang struct otpstrap_info {
8079e42a59SJoel Stanley 	int8_t bit_offset;
8179e42a59SJoel Stanley 	int8_t length;
8279e42a59SJoel Stanley 	int8_t value;
8379e42a59SJoel Stanley 	char *information;
84a8bd6d8cSJohnny Huang };
85a8bd6d8cSJohnny Huang 
86a8bd6d8cSJohnny Huang struct otpconf_info {
8779e42a59SJoel Stanley 	int8_t dw_offset;
8879e42a59SJoel Stanley 	int8_t bit_offset;
8979e42a59SJoel Stanley 	int8_t length;
9079e42a59SJoel Stanley 	int8_t value;
9179e42a59SJoel Stanley 	char *information;
92a8bd6d8cSJohnny Huang };
93a8bd6d8cSJohnny Huang 
949a4fe690SJohnny Huang struct otpkey_type {
959a4fe690SJohnny Huang 	int value;
969a4fe690SJohnny Huang 	int key_type;
979a4fe690SJohnny Huang 	int need_id;
989a4fe690SJohnny Huang 	char information[110];
999a4fe690SJohnny Huang };
1009a4fe690SJohnny Huang 
1019a4fe690SJohnny Huang struct otp_info_cb {
1029a4fe690SJohnny Huang 	int version;
10379e42a59SJoel Stanley 	const struct otpstrap_info *strap_info;
1049a4fe690SJohnny Huang 	int strap_info_len;
10579e42a59SJoel Stanley 	const struct otpconf_info *conf_info;
1069a4fe690SJohnny Huang 	int conf_info_len;
10779e42a59SJoel Stanley 	const struct otpkey_type *key_info;
1089a4fe690SJohnny Huang 	int key_info_len;
1099a4fe690SJohnny Huang };
1109a4fe690SJohnny Huang 
1119a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1129a4fe690SJohnny Huang 
11379e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = {
11491448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
11591448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
11691448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
11791448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
11891448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
11991448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
12091448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
12191448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
122541eb887SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
12391448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
12491448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
12591448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
12691448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
12791448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
12891448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
12991448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
13091448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
13191448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
13291448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
13391448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
13491448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
13591448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
13691448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
13791448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
13891448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
13991448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
14091448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
14191448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
14291448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
14391448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
14491448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
14591448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
14691448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
14791448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
14891448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
14991448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
15091448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
15191448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
15291448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
15391448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
15491448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
15591448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
15691448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
15791448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
15891448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
15991448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
16091448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
16191448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
16291448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
16391448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
16491448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
16591448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
16691448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
16791448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
16891448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
16991448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
17091448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
17191448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
17291448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
17391448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
17491448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
17591448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
17691448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
17791448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
17891448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
17991448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
18091448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
18191448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
18291448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
18391448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
18491448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
18591448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
18691448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
18791448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
18891448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
18991448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
19091448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
19191448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
19291448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
19391448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
19491448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
19591448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
19691448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
19791448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
19891448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
19991448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
20091448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
20191448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
20291448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
20391448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
20491448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
20591448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
20691448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
20791448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
20891448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
20991448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
21091448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
21191448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
21291448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
21391448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
21491448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
21591448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
21691448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
21791448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
21891448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
21991448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
22091448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
22191448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
22291448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
22376d13988SJohnny Huang };
2249a4fe690SJohnny Huang 
22579e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = {
2263cb28812SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
2273cb28812SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
2283cb28812SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
2293cb28812SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
2303cb28812SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
2313cb28812SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
2323cb28812SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
2333cb28812SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
2343cb28812SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
2353cb28812SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
2363cb28812SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
2373cb28812SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
2383cb28812SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
2393cb28812SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
2403cb28812SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
2413cb28812SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
2423cb28812SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
2433cb28812SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
2443cb28812SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
2453cb28812SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
2463cb28812SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
2473cb28812SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
2483cb28812SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
2493cb28812SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
2503cb28812SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
2513cb28812SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
2523cb28812SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
2533cb28812SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
2543cb28812SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
2553cb28812SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
2563cb28812SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
2573cb28812SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
2583cb28812SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
2593cb28812SJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
2603cb28812SJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
2613cb28812SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
2623cb28812SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
2633cb28812SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
2643cb28812SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
2653cb28812SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
2663cb28812SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
2673cb28812SJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
2683cb28812SJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
2693cb28812SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
2703cb28812SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
2713cb28812SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
2723cb28812SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
2733cb28812SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
2743cb28812SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
2753cb28812SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
2763cb28812SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
2773cb28812SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
2783cb28812SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
2793cb28812SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
2803cb28812SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
2813cb28812SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
2823cb28812SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
2833cb28812SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
2843cb28812SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
2853cb28812SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
2863cb28812SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
2873cb28812SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
2883cb28812SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
2893cb28812SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
2903cb28812SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
2913cb28812SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
2923cb28812SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
2933cb28812SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
2943cb28812SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
2953cb28812SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
2963cb28812SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
2973cb28812SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
2983cb28812SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
2993cb28812SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
3003cb28812SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
3013cb28812SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
3023cb28812SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
3033cb28812SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
3043cb28812SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
3053cb28812SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
3063cb28812SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
3073cb28812SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
3083cb28812SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
3093cb28812SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
3103cb28812SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
3113cb28812SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
3123cb28812SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
3133cb28812SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
3143cb28812SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
3153cb28812SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
3163cb28812SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
3173cb28812SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
3183cb28812SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
3193cb28812SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
3203cb28812SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
3213cb28812SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
3223cb28812SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
3233cb28812SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
3243cb28812SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
3253cb28812SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
3263cb28812SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
3273cb28812SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
3283cb28812SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
3293cb28812SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
3303cb28812SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
3313cb28812SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
3323cb28812SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
3333cb28812SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
3343cb28812SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
3353cb28812SJohnny Huang };
3363cb28812SJohnny Huang 
33779e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = {
33891448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
33991448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
34091448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
34191448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
34291448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
34391448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
34491448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
34591448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
34691448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
34791448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
34891448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
34991448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
35091448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
35191448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
35291448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
35391448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
35491448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
355541eb887SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
35691448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
35791448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
35891448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
35991448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
36091448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
36191448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
36291448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
36391448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
36491448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
36591448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
36691448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
36791448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
36891448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
36991448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
37091448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
37191448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
37291448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
37391448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
37491448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
37591448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
37691448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
37791448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
37891448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
37991448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
38091448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
38191448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
3823cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
3833cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
3843cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
3853cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
3863cb28812SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
3873cb28812SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
3883cb28812SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
3893cb28812SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
3903cb28812SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
3913cb28812SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
3923cb28812SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
3933cb28812SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
3943cb28812SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
3953cb28812SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
3963cb28812SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
3973cb28812SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
3983cb28812SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
3993cb28812SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
4003cb28812SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
4013cb28812SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
4023cb28812SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
4033cb28812SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
4043cb28812SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
4053cb28812SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
4063cb28812SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
4073cb28812SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
4083cb28812SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
4093cb28812SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
4103cb28812SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
4113cb28812SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
4123cb28812SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
4133cb28812SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
4143cb28812SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
4153cb28812SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
4163cb28812SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
4173cb28812SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
4183cb28812SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
4193cb28812SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
4203cb28812SJohnny Huang };
4213cb28812SJohnny Huang 
42279e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = {
4233cb28812SJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
4243cb28812SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
4253cb28812SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
4263cb28812SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
4273cb28812SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
4283cb28812SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
4293cb28812SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
4303cb28812SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
4313cb28812SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
4323cb28812SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
4333cb28812SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
4343cb28812SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
4353cb28812SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
4363cb28812SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
4373cb28812SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
4383cb28812SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
4393cb28812SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
4403cb28812SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
4413cb28812SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
4423cb28812SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
4433cb28812SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
4443cb28812SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
4453cb28812SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
4463cb28812SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
4473cb28812SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
4483cb28812SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
449*bb34a7bfSJohnny Huang 	{ 0, 14, 1,  0, "Disable Patch code" },
450*bb34a7bfSJohnny Huang 	{ 0, 14, 1,  1, "Enable Patch code" },
451*bb34a7bfSJohnny Huang 	{ 0, 15, 1,  OTP_REG_RESERVED, "" },
4523cb28812SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
4533cb28812SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
4543cb28812SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
4553cb28812SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
4563cb28812SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
4573cb28812SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
4583cb28812SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
4593cb28812SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
4603cb28812SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
4613cb28812SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
4623cb28812SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
4633cb28812SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
4643cb28812SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
4653cb28812SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
4663cb28812SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
4673cb28812SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
4683cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
4693cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
4703cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
4713cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
47291448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
47391448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
47491448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
47573f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
47673f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
47791448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
47891448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
47991448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
48091448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
48191448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
48291448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
48391448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
48491448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
48591448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
48691448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
48791448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
48891448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
48991448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
49091448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
49191448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
49291448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
49391448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
49491448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
49591448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
49691448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
49791448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
49891448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
49991448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
50091448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
50191448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
50291448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
50391448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
50491448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
505*bb34a7bfSJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" },
506*bb34a7bfSJohnny Huang 	{ 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" },
507*bb34a7bfSJohnny Huang 	{ 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" }
508b458cd62SJohnny Huang };
5099a4fe690SJohnny Huang 
51079e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = {
5119a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
5129a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5139a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
5149a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5159a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
5169a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5179a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
5189a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5199a4fe690SJohnny Huang };
5209a4fe690SJohnny Huang 
52179e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = {
5229a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5239a4fe690SJohnny 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"},
5249a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5259a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5269a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5279a4fe690SJohnny Huang };
5289a4fe690SJohnny Huang 
5299a4fe690SJohnny Huang static uint32_t chip_version(void)
5309a4fe690SJohnny Huang {
5319a4fe690SJohnny Huang 	uint32_t rev_id;
5329a4fe690SJohnny Huang 
5339a4fe690SJohnny Huang 	rev_id = (readl(0x1e6e2004) >> 16) & 0xff ;
5349a4fe690SJohnny Huang 
5359a4fe690SJohnny Huang 	return rev_id;
5369a4fe690SJohnny Huang }
5379a4fe690SJohnny Huang 
5383d3688adSJohnny Huang static void wait_complete(void)
5393d3688adSJohnny Huang {
5403d3688adSJohnny Huang 	int reg;
5413d3688adSJohnny Huang 
5423d3688adSJohnny Huang 	do {
5433d3688adSJohnny Huang 		reg = readl(OTP_STATUS);
5443d3688adSJohnny Huang 	} while ((reg & 0x6) != 0x6);
5453d3688adSJohnny Huang }
5463d3688adSJohnny Huang 
5472a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
54869d5fd8fSJohnny Huang {
5493d3688adSJohnny Huang 	writel(offset, OTP_ADDR); //Read address
5503d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
5513d3688adSJohnny Huang 	wait_complete();
5523d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
5533d3688adSJohnny Huang 	data[1] = readl(OTP_COMPARE_2);
55469d5fd8fSJohnny Huang }
55569d5fd8fSJohnny Huang 
5562a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
55769d5fd8fSJohnny Huang {
55869d5fd8fSJohnny Huang 	int config_offset;
55969d5fd8fSJohnny Huang 
56069d5fd8fSJohnny Huang 	config_offset = 0x800;
56169d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
56269d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
56369d5fd8fSJohnny Huang 
5643d3688adSJohnny Huang 	writel(config_offset, OTP_ADDR);  //Read address
5653d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
5663d3688adSJohnny Huang 	wait_complete();
5673d3688adSJohnny Huang 	data[0] = readl(OTP_COMPARE_1);
56869d5fd8fSJohnny Huang }
56969d5fd8fSJohnny Huang 
57069d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
57169d5fd8fSJohnny Huang {
57269d5fd8fSJohnny Huang 	int i;
57369d5fd8fSJohnny Huang 	uint32_t ret[1];
57469d5fd8fSJohnny Huang 
57569d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
5762a856b9aSJohnny Huang 		return OTP_USAGE;
57769d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
57869d5fd8fSJohnny Huang 		otp_read_config(i, ret);
579a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
58069d5fd8fSJohnny Huang 	}
58169d5fd8fSJohnny Huang 	printf("\n");
5822a856b9aSJohnny Huang 	return OTP_SUCCESS;
58369d5fd8fSJohnny Huang }
58469d5fd8fSJohnny Huang 
58569d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
58669d5fd8fSJohnny Huang {
58769d5fd8fSJohnny Huang 	int i;
58869d5fd8fSJohnny Huang 	uint32_t ret[2];
58969d5fd8fSJohnny Huang 
59069d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
5912a856b9aSJohnny Huang 		return OTP_USAGE;
59269d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
59369d5fd8fSJohnny Huang 		otp_read_data(i, ret);
59469d5fd8fSJohnny Huang 		if (i % 4 == 0)
59569d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
59669d5fd8fSJohnny Huang 		else
59769d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
59869d5fd8fSJohnny Huang 
59969d5fd8fSJohnny Huang 	}
60069d5fd8fSJohnny Huang 	printf("\n");
6012a856b9aSJohnny Huang 	return OTP_SUCCESS;
60269d5fd8fSJohnny Huang }
60369d5fd8fSJohnny Huang 
60469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
60569d5fd8fSJohnny Huang {
60669d5fd8fSJohnny Huang 	uint32_t ret;
60769d5fd8fSJohnny Huang 	uint32_t *buf;
60869d5fd8fSJohnny Huang 
60969d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
61069d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
61169d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
61269d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
61369d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
6143d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //Compare address
6153d3688adSJohnny Huang 	writel(buf[0], OTP_COMPARE_1); //Compare data 1
6163d3688adSJohnny Huang 	writel(buf[1], OTP_COMPARE_2); //Compare data 2
6173d3688adSJohnny Huang 	writel(buf[2], OTP_COMPARE_3); //Compare data 3
6183d3688adSJohnny Huang 	writel(buf[3], OTP_COMPARE_4); //Compare data 4
6193d3688adSJohnny Huang 	writel(0x23b1e363, OTP_COMMAND); //Compare command
6203d3688adSJohnny Huang 	wait_complete();
6213d3688adSJohnny Huang 	ret = readl(OTP_STATUS); //Compare command
62269d5fd8fSJohnny Huang 	if (ret & 0x1)
62369d5fd8fSJohnny Huang 		return 0;
62469d5fd8fSJohnny Huang 	else
62569d5fd8fSJohnny Huang 		return -1;
62669d5fd8fSJohnny Huang }
62769d5fd8fSJohnny Huang 
62869d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
62969d5fd8fSJohnny Huang {
6303d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6313d3688adSJohnny Huang 	writel(data, OTP_COMPARE_1); //write data
6323d3688adSJohnny Huang 	writel(0x23b1e362, OTP_COMMAND); //write command
6333d3688adSJohnny Huang 	wait_complete();
63469d5fd8fSJohnny Huang }
63569d5fd8fSJohnny Huang 
63669d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
63769d5fd8fSJohnny Huang {
6383d3688adSJohnny Huang 	writel(otp_addr, OTP_ADDR); //write address
6393d3688adSJohnny Huang 	writel(prog_bit, OTP_COMPARE_1); //write data
6403d3688adSJohnny Huang 	writel(0x23b1e364, OTP_COMMAND); //write command
6413d3688adSJohnny Huang 	wait_complete();
64269d5fd8fSJohnny Huang }
64369d5fd8fSJohnny Huang 
644a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
64569d5fd8fSJohnny Huang {
64630a8c590SJohnny Huang 	uint32_t ret[2];
64769d5fd8fSJohnny Huang 
64830a8c590SJohnny Huang 	if (otp_addr % 2 == 0)
6493d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
65030a8c590SJohnny Huang 	else
6513d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
65230a8c590SJohnny Huang 
6533d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6543d3688adSJohnny Huang 	wait_complete();
6553d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
6563d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
657a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
65830a8c590SJohnny Huang 	if (otp_addr % 2 == 0) {
65930a8c590SJohnny Huang 		if (((ret[0] >> bit_offset) & 1) == value)
66069d5fd8fSJohnny Huang 			return 0;
66169d5fd8fSJohnny Huang 		else
66269d5fd8fSJohnny Huang 			return -1;
66330a8c590SJohnny Huang 	} else {
66430a8c590SJohnny Huang 		if (((ret[1] >> bit_offset) & 1) == value)
66530a8c590SJohnny Huang 			return 0;
66630a8c590SJohnny Huang 		else
66730a8c590SJohnny Huang 			return -1;
66830a8c590SJohnny Huang 	}
66930a8c590SJohnny Huang 
67069d5fd8fSJohnny Huang }
67169d5fd8fSJohnny Huang 
672d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
6734c1c9b35SJohnny Huang {
6744c1c9b35SJohnny Huang 	uint32_t ret[2];
6754c1c9b35SJohnny Huang 
6764c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
6774c1c9b35SJohnny Huang 
6784c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
6793d3688adSJohnny Huang 		writel(otp_addr, OTP_ADDR); //Read address
6804c1c9b35SJohnny Huang 	else
6813d3688adSJohnny Huang 		writel(otp_addr - 1, OTP_ADDR); //Read address
6823d3688adSJohnny Huang 	writel(0x23b1e361, OTP_COMMAND); //trigger read
6833d3688adSJohnny Huang 	wait_complete();
6843d3688adSJohnny Huang 	ret[0] = readl(OTP_COMPARE_1);
6853d3688adSJohnny Huang 	ret[1] = readl(OTP_COMPARE_2);
6864c1c9b35SJohnny Huang 	if (size == 1) {
6874c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
6884c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
689d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
6904c1c9b35SJohnny Huang 				compare[0] = 0;
6914c1c9b35SJohnny Huang 				return 0;
6924c1c9b35SJohnny Huang 			} else {
6934c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
6944c1c9b35SJohnny Huang 				return -1;
6954c1c9b35SJohnny Huang 			}
6964c1c9b35SJohnny Huang 
6974c1c9b35SJohnny Huang 		} else {
6984c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
699d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
7004c1c9b35SJohnny Huang 				compare[0] = ~0;
7014c1c9b35SJohnny Huang 				return 0;
7024c1c9b35SJohnny Huang 			} else {
703d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
7044c1c9b35SJohnny Huang 				return -1;
7054c1c9b35SJohnny Huang 			}
7064c1c9b35SJohnny Huang 		}
7074c1c9b35SJohnny Huang 	} else if (size == 2) {
7084c1c9b35SJohnny Huang 		// otp_addr should be even
709d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
7104c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7114c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7124c1c9b35SJohnny Huang 			compare[0] = 0;
7134c1c9b35SJohnny Huang 			compare[1] = ~0;
7144c1c9b35SJohnny Huang 			return 0;
7154c1c9b35SJohnny Huang 		} else {
7164c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
7174c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
7184c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
7194c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
7204c1c9b35SJohnny Huang 			return -1;
7214c1c9b35SJohnny Huang 		}
7224c1c9b35SJohnny Huang 	} else {
7234c1c9b35SJohnny Huang 		return -1;
7244c1c9b35SJohnny Huang 	}
7254c1c9b35SJohnny Huang }
7264c1c9b35SJohnny Huang 
7277e22f42dSJohnny Huang static void otp_soak(int soak)
728d90825e2SJohnny Huang {
729de6fbf1cSJohnny Huang 	switch (soak) {
730de6fbf1cSJohnny Huang 	case 0: //default
731de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x0); // Write MRA
732de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x0); // Write MRB
733de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x0); // Write MR
734de6fbf1cSJohnny Huang 		break;
735de6fbf1cSJohnny Huang 	case 1: //normal program
736de6fbf1cSJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
737de6fbf1cSJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
738de6fbf1cSJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
739de6fbf1cSJohnny Huang 		writel(0x04190760, OTP_TIMING);
740de6fbf1cSJohnny Huang 		break;
741de6fbf1cSJohnny Huang 	case 2: //soak program
742d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
743d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
744d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
745de6fbf1cSJohnny Huang 		writel(0x041930d4, OTP_TIMING);
746de6fbf1cSJohnny Huang 		break;
747d90825e2SJohnny Huang 	}
748de6fbf1cSJohnny Huang 
7493d3688adSJohnny Huang 	wait_complete();
750d90825e2SJohnny Huang }
751d90825e2SJohnny Huang 
752d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
753d90825e2SJohnny Huang {
754d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
755d90825e2SJohnny Huang 
756d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
757d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
758d90825e2SJohnny Huang 			continue;
759d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
760d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
761d90825e2SJohnny Huang 			if (bit_value)
762d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
763d90825e2SJohnny Huang 			else
764d90825e2SJohnny Huang 				continue;
765d90825e2SJohnny Huang 		} else {
766d90825e2SJohnny Huang 			prog_address |= 1 << 15;
767d90825e2SJohnny Huang 			if (bit_value)
768d90825e2SJohnny Huang 				continue;
769d90825e2SJohnny Huang 			else
770d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
771d90825e2SJohnny Huang 		}
772d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
773d90825e2SJohnny Huang 	}
774d90825e2SJohnny Huang }
775d90825e2SJohnny Huang 
77654552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address)
77754552c69SJohnny Huang {
77854552c69SJohnny Huang 	int pass;
77954552c69SJohnny Huang 	int i;
78054552c69SJohnny Huang 	uint32_t data0_masked;
78154552c69SJohnny Huang 	uint32_t data1_masked;
78254552c69SJohnny Huang 	uint32_t buf0_masked;
78354552c69SJohnny Huang 	uint32_t buf1_masked;
78454552c69SJohnny Huang 	uint32_t compare[2];
78554552c69SJohnny Huang 
78654552c69SJohnny Huang 	data0_masked = data[0]  & ~ignore_mask[0];
78754552c69SJohnny Huang 	buf0_masked  = buf[0] & ~ignore_mask[0];
78854552c69SJohnny Huang 	data1_masked = data[1]  & ~ignore_mask[1];
78954552c69SJohnny Huang 	buf1_masked  = buf[1] & ~ignore_mask[1];
79054552c69SJohnny Huang 	if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked))
79154552c69SJohnny Huang 		return 0;
79254552c69SJohnny Huang 
79354552c69SJohnny Huang 	otp_soak(1);
79454552c69SJohnny Huang 	if (data0_masked != buf0_masked)
79554552c69SJohnny Huang 		otp_prog_dw(buf[0], ignore_mask[0], prog_address);
79654552c69SJohnny Huang 	if (data1_masked != buf1_masked)
79754552c69SJohnny Huang 		otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1);
79854552c69SJohnny Huang 
79954552c69SJohnny Huang 	pass = 0;
80054552c69SJohnny Huang 	for (i = 0; i < RETRY; i++) {
80154552c69SJohnny Huang 		if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
80254552c69SJohnny Huang 			otp_soak(2);
80354552c69SJohnny Huang 			if (compare[0] != 0) {
80454552c69SJohnny Huang 				otp_prog_dw(compare[0], ignore_mask[0], prog_address);
80554552c69SJohnny Huang 			}
80654552c69SJohnny Huang 			if (compare[1] != ~0) {
80754552c69SJohnny Huang 				otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1);
80854552c69SJohnny Huang 			}
80954552c69SJohnny Huang 			if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) {
81054552c69SJohnny Huang 				otp_soak(1);
81154552c69SJohnny Huang 			} else {
81254552c69SJohnny Huang 				pass = 1;
81354552c69SJohnny Huang 				break;
81454552c69SJohnny Huang 			}
81554552c69SJohnny Huang 		} else {
81654552c69SJohnny Huang 			pass = 1;
81754552c69SJohnny Huang 			break;
81854552c69SJohnny Huang 		}
81954552c69SJohnny Huang 	}
82054552c69SJohnny Huang 
82154552c69SJohnny Huang 	if (!pass) {
82254552c69SJohnny Huang 		otp_soak(0);
82354552c69SJohnny Huang 		return OTP_FAILURE;
82454552c69SJohnny Huang 	}
82554552c69SJohnny Huang 	return OTP_SUCCESS;
82654552c69SJohnny Huang }
82754552c69SJohnny Huang 
82876d13988SJohnny Huang 
829541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
83076d13988SJohnny Huang {
83176d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
83276d13988SJohnny Huang 	int i, j;
83376d13988SJohnny Huang 
83476d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
83576d13988SJohnny Huang 		otpstrap[j].value = 0;
83676d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
83776d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
83876d13988SJohnny Huang 		otpstrap[j].protected = 0;
83976d13988SJohnny Huang 	}
84076d13988SJohnny Huang 
84176d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
84276d13988SJohnny Huang 		int option = (i - 16) / 2;
84376d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
84476d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
84576d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
84676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
84776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
84876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
84976d13988SJohnny Huang 			}
85076d13988SJohnny Huang 			if (bit_value == 1)
85176d13988SJohnny Huang 				otpstrap[j].remain_times --;
85276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
85376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
85476d13988SJohnny Huang 		}
85576d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
85676d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
85776d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
85876d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
85976d13988SJohnny Huang 			}
86076d13988SJohnny Huang 			if (bit_value == 1)
86176d13988SJohnny Huang 				otpstrap[j].remain_times --;
86276d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
86376d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
86476d13988SJohnny Huang 		}
86576d13988SJohnny Huang 	}
86676d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
86776d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
86876d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
86976d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
87076d13988SJohnny Huang 			otpstrap[j].protected = 1;
87176d13988SJohnny Huang 	}
87276d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
87376d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
87476d13988SJohnny Huang 			otpstrap[j].protected = 1;
87576d13988SJohnny Huang 	}
87676d13988SJohnny Huang }
87776d13988SJohnny Huang 
878b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG)
87969d5fd8fSJohnny Huang {
88079e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
881*bb34a7bfSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[16];
882b458cd62SJohnny Huang 	uint32_t mask;
883b458cd62SJohnny Huang 	uint32_t dw_offset;
884b458cd62SJohnny Huang 	uint32_t bit_offset;
885b458cd62SJohnny Huang 	uint32_t otp_value;
886b458cd62SJohnny Huang 	uint32_t otp_keep;
887b458cd62SJohnny Huang 	int fail = 0;
88873f11549SJohnny Huang 	char valid_bit[20];
88966f2f8e5SJohnny Huang 	int i;
89073f11549SJohnny Huang 	int j;
89166f2f8e5SJohnny Huang 
892737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
89366f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
8943cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
8953cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
8963cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
8973cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
898b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
899b458cd62SJohnny Huang 		otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask;
900b458cd62SJohnny Huang 
901b458cd62SJohnny Huang 		if (otp_keep == mask) {
902b458cd62SJohnny Huang 			continue;
903b458cd62SJohnny Huang 		} else if (otp_keep != 0) {
904b458cd62SJohnny Huang 			fail = 1;
905b458cd62SJohnny Huang 		}
906b458cd62SJohnny Huang 
9073cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
9083cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
9093cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
9103cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
911b458cd62SJohnny Huang 			continue;
912b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
913b458cd62SJohnny Huang 
9143cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
9153cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
91666f2f8e5SJohnny Huang 		} else {
917b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9183cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
9193cb28812SJohnny Huang 			       conf_info[i].bit_offset);
92066f2f8e5SJohnny Huang 		}
921b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
922b458cd62SJohnny Huang 
923b458cd62SJohnny Huang 		if (fail) {
924b458cd62SJohnny Huang 			printf("Keep mask error\n");
925b458cd62SJohnny Huang 		} else {
9263cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
927b458cd62SJohnny Huang 				printf("Reserved\n");
9283cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
9293cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
930b458cd62SJohnny Huang 				printf("\n");
9313cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
932b458cd62SJohnny Huang 				if (otp_value != 0) {
93373f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
93473f11549SJohnny Huang 						if (otp_value == (1 << j)) {
93573f11549SJohnny Huang 							valid_bit[j * 2] = '1';
936b458cd62SJohnny Huang 						} else {
93773f11549SJohnny Huang 							valid_bit[j * 2] = '0';
93873f11549SJohnny Huang 						}
93973f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
94073f11549SJohnny Huang 					}
94173f11549SJohnny Huang 					valid_bit[15] = 0;
94273f11549SJohnny Huang 				} else {
94373f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
944b458cd62SJohnny Huang 				}
9453cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
946b458cd62SJohnny Huang 				printf("\n");
947b458cd62SJohnny Huang 			} else {
9483cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
949b458cd62SJohnny Huang 			}
950b458cd62SJohnny Huang 		}
951b458cd62SJohnny Huang 	}
952b458cd62SJohnny Huang 
953b458cd62SJohnny Huang 	if (fail)
954b458cd62SJohnny Huang 		return OTP_FAILURE;
955b458cd62SJohnny Huang 
95666f2f8e5SJohnny Huang 	return OTP_SUCCESS;
95766f2f8e5SJohnny Huang }
95866f2f8e5SJohnny Huang 
9592d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
96066f2f8e5SJohnny Huang {
96179e42a59SJoel Stanley 	const struct otpconf_info *conf_info = info_cb.conf_info;
962*bb34a7bfSJohnny Huang 	uint32_t OTPCFG[16];
963b458cd62SJohnny Huang 	uint32_t mask;
964b458cd62SJohnny Huang 	uint32_t dw_offset;
965b458cd62SJohnny Huang 	uint32_t bit_offset;
966b458cd62SJohnny Huang 	uint32_t otp_value;
96773f11549SJohnny Huang 	char valid_bit[20];
96866f2f8e5SJohnny Huang 	int i;
96973f11549SJohnny Huang 	int j;
97066f2f8e5SJohnny Huang 
971*bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++)
97266f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
97366f2f8e5SJohnny Huang 
97466f2f8e5SJohnny Huang 
975b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
976b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
9773cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
9783cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
9792d4b0742SJohnny Huang 			continue;
9803cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
9813cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
9823cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
983b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
984b458cd62SJohnny Huang 
9853cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
9863cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
9873cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
9883cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
989b458cd62SJohnny Huang 			continue;
990b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
991b458cd62SJohnny Huang 
9923cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
9933cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
994b458cd62SJohnny Huang 		} else {
995b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9963cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
9973cb28812SJohnny Huang 			       conf_info[i].bit_offset);
998b458cd62SJohnny Huang 		}
999b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
1000b458cd62SJohnny Huang 
10013cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
1002b458cd62SJohnny Huang 			printf("Reserved\n");
10033cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
10043cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
1005b458cd62SJohnny Huang 			printf("\n");
10063cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
1007b458cd62SJohnny Huang 			if (otp_value != 0) {
100873f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
100973f11549SJohnny Huang 					if (otp_value == (1 << j)) {
101073f11549SJohnny Huang 						valid_bit[j * 2] = '1';
1011b458cd62SJohnny Huang 					} else {
101273f11549SJohnny Huang 						valid_bit[j * 2] = '0';
101373f11549SJohnny Huang 					}
101473f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
101573f11549SJohnny Huang 				}
101673f11549SJohnny Huang 				valid_bit[15] = 0;
101773f11549SJohnny Huang 			} else {
101873f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
1019b458cd62SJohnny Huang 			}
10203cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
1021b458cd62SJohnny Huang 			printf("\n");
1022b458cd62SJohnny Huang 		} else {
10233cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
1024b458cd62SJohnny Huang 		}
1025b458cd62SJohnny Huang 	}
1026b458cd62SJohnny Huang 	return OTP_SUCCESS;
102766f2f8e5SJohnny Huang }
102866f2f8e5SJohnny Huang 
1029b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP)
103076d13988SJohnny Huang {
103179e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
1032a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
1033a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
103476d13988SJohnny Huang 	int i;
1035a8bd6d8cSJohnny Huang 	int fail = 0;
1036a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
1037a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
1038a8bd6d8cSJohnny Huang 	uint32_t mask;
1039a8bd6d8cSJohnny Huang 	uint32_t otp_value;
1040a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
1041a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
104276d13988SJohnny Huang 
1043a8bd6d8cSJohnny Huang 	printf("BIT(hex)   Value       Protect     Description\n");
1044a8bd6d8cSJohnny Huang 	printf("__________________________________________________________________________________________\n");
1045b458cd62SJohnny Huang 
10463cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
10473cb28812SJohnny Huang 		if (strap_info[i].bit_offset > 32) {
1048a8bd6d8cSJohnny Huang 			dw_offset = 1;
10493cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
1050a8bd6d8cSJohnny Huang 		} else {
1051a8bd6d8cSJohnny Huang 			dw_offset = 0;
10523cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
1053a8bd6d8cSJohnny Huang 		}
105476d13988SJohnny Huang 
10553cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
1056a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
1057a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
1058a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
1059a8bd6d8cSJohnny Huang 
1060a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
1061a8bd6d8cSJohnny Huang 			continue;
1062a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
1063a8bd6d8cSJohnny Huang 			fail = 1;
1064a8bd6d8cSJohnny Huang 		}
1065a8bd6d8cSJohnny Huang 
10663cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
10673cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1068a8bd6d8cSJohnny Huang 			continue;
1069a8bd6d8cSJohnny Huang 
10703cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
10713cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
1072a8bd6d8cSJohnny Huang 		} else {
1073b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
10743cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
10753cb28812SJohnny Huang 			       strap_info[i].bit_offset);
1076a8bd6d8cSJohnny Huang 		}
1077a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
1078a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
1079a8bd6d8cSJohnny Huang 
1080a8bd6d8cSJohnny Huang 		if (fail) {
1081a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
1082a8bd6d8cSJohnny Huang 		} else {
10833cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
10843cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1085a8bd6d8cSJohnny Huang 			else
1086a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1087a8bd6d8cSJohnny Huang 		}
1088a8bd6d8cSJohnny Huang 	}
1089a8bd6d8cSJohnny Huang 
1090a8bd6d8cSJohnny Huang 	if (fail)
109176d13988SJohnny Huang 		return OTP_FAILURE;
109276d13988SJohnny Huang 
109376d13988SJohnny Huang 	return OTP_SUCCESS;
109476d13988SJohnny Huang }
109576d13988SJohnny Huang 
1096b458cd62SJohnny Huang static int otp_print_strap_info(int view)
109776d13988SJohnny Huang {
109879e42a59SJoel Stanley 	const struct otpstrap_info *strap_info = info_cb.strap_info;
109976d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
110007baa4e8SJohnny Huang 	int i, j;
1101b458cd62SJohnny Huang 	int fail = 0;
1102b458cd62SJohnny Huang 	uint32_t bit_offset;
1103b458cd62SJohnny Huang 	uint32_t length;
1104b458cd62SJohnny Huang 	uint32_t otp_value;
1105b458cd62SJohnny Huang 	uint32_t otp_protect;
110676d13988SJohnny Huang 
1107541eb887SJohnny Huang 	otp_strap_status(strap_status);
110876d13988SJohnny Huang 
1109b458cd62SJohnny Huang 	if (view) {
111007baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
111107baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
111207baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
111307baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
1114b458cd62SJohnny Huang 	} else {
1115b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
1116b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
111776d13988SJohnny Huang 	}
11183cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1119b458cd62SJohnny Huang 		otp_value = 0;
11203cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
11213cb28812SJohnny Huang 		length = strap_info[i].length;
1122b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
1123c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
1124c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
1125b458cd62SJohnny Huang 		}
11263cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
11273cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1128b458cd62SJohnny Huang 			continue;
1129b458cd62SJohnny Huang 		if (view) {
1130b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
11313cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
1132b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
113307baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
1134b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
11353cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
1136b458cd62SJohnny Huang 					printf(" Reserved\n");
1137b458cd62SJohnny Huang 					continue;
1138b458cd62SJohnny Huang 				}
1139b458cd62SJohnny Huang 				if (length == 1) {
11403cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
1141b458cd62SJohnny Huang 					continue;
114276d13988SJohnny Huang 				}
114376d13988SJohnny Huang 
1144b458cd62SJohnny Huang 				if (j == 0)
11453cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
1146b458cd62SJohnny Huang 				else if (j == length - 1)
1147b458cd62SJohnny Huang 					printf("\\ \"\n");
1148b458cd62SJohnny Huang 				else
1149b458cd62SJohnny Huang 					printf("| \"\n");
115076d13988SJohnny Huang 			}
1151b458cd62SJohnny Huang 		} else {
1152c947ef08SJohnny Huang 			if (length == 1) {
11533cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
1154b458cd62SJohnny Huang 			} else {
1155b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1156b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1157b458cd62SJohnny Huang 			}
1158b458cd62SJohnny Huang 
1159b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1160b458cd62SJohnny Huang 
11613cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
11623cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1163b458cd62SJohnny Huang 			else
1164b458cd62SJohnny Huang 				printf("Reserved\n");
1165b458cd62SJohnny Huang 		}
1166b458cd62SJohnny Huang 	}
1167b458cd62SJohnny Huang 
1168b458cd62SJohnny Huang 	if (fail)
1169b458cd62SJohnny Huang 		return OTP_FAILURE;
1170b458cd62SJohnny Huang 
1171b458cd62SJohnny Huang 	return OTP_SUCCESS;
1172b458cd62SJohnny Huang }
1173b458cd62SJohnny Huang 
117469d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
117569d5fd8fSJohnny Huang {
117669d5fd8fSJohnny Huang 	int i;
117769d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
117869d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
117969d5fd8fSJohnny Huang 		if (i % 16 == 0) {
118069d5fd8fSJohnny Huang 			printf("%04X: ", i);
118169d5fd8fSJohnny Huang 		}
118269d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
118369d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
118469d5fd8fSJohnny Huang 			printf("\n");
118569d5fd8fSJohnny Huang 		}
118669d5fd8fSJohnny Huang 	}
118769d5fd8fSJohnny Huang }
118869d5fd8fSJohnny Huang 
11897f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
119069d5fd8fSJohnny Huang {
119169d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
119279e42a59SJoel Stanley 	const struct otpkey_type *key_info_array = info_cb.key_info;
11939a4fe690SJohnny Huang 	struct otpkey_type key_info;
119469d5fd8fSJohnny Huang 	char *byte_buf;
11959d998018SJohnny Huang 	char empty = 1;
119669d5fd8fSJohnny Huang 	int i = 0, len = 0;
11979a4fe690SJohnny Huang 	int j;
119854552c69SJohnny Huang 
119969d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
12009d998018SJohnny Huang 
12019d998018SJohnny Huang 	for (i = 0; i < 16; i++) {
12029d998018SJohnny Huang 		if (buf[i] != 0) {
12039d998018SJohnny Huang 			empty = 0;
12049d998018SJohnny Huang 		}
12059d998018SJohnny Huang 	}
12069d998018SJohnny Huang 	if (empty)
12079d998018SJohnny Huang 		return 0;
12089d998018SJohnny Huang 
12099d998018SJohnny Huang 	i = 0;
121069d5fd8fSJohnny Huang 	while (1) {
121169d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
121269d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
121369d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
121469d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
121569d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
121669d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
12179a4fe690SJohnny Huang 
12189a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
12199a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
12209a4fe690SJohnny Huang 				key_info = key_info_array[j];
12219a4fe690SJohnny Huang 				break;
12229a4fe690SJohnny Huang 			}
12239a4fe690SJohnny Huang 		}
12249a4fe690SJohnny Huang 
12257f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
122669d5fd8fSJohnny Huang 		printf("Key Type: ");
12279a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
12289a4fe690SJohnny Huang 
12299a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
123069d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
123169d5fd8fSJohnny Huang 			switch (key_length) {
123269d5fd8fSJohnny Huang 			case 0:
123369d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
123469d5fd8fSJohnny Huang 				break;
123569d5fd8fSJohnny Huang 			case 1:
123669d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
123769d5fd8fSJohnny Huang 				break;
123869d5fd8fSJohnny Huang 			case 2:
123969d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
124069d5fd8fSJohnny Huang 				break;
124169d5fd8fSJohnny Huang 			case 3:
124269d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
124369d5fd8fSJohnny Huang 				break;
124469d5fd8fSJohnny Huang 			}
12459a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
124669d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
124769d5fd8fSJohnny Huang 			switch (key_length) {
124869d5fd8fSJohnny Huang 			case 0:
124969d5fd8fSJohnny Huang 				printf("RSA1024\n");
125069d5fd8fSJohnny Huang 				len = 0x100;
125169d5fd8fSJohnny Huang 				break;
125269d5fd8fSJohnny Huang 			case 1:
125369d5fd8fSJohnny Huang 				printf("RSA2048\n");
125469d5fd8fSJohnny Huang 				len = 0x200;
125569d5fd8fSJohnny Huang 				break;
125669d5fd8fSJohnny Huang 			case 2:
125769d5fd8fSJohnny Huang 				printf("RSA3072\n");
125869d5fd8fSJohnny Huang 				len = 0x300;
125969d5fd8fSJohnny Huang 				break;
126069d5fd8fSJohnny Huang 			case 3:
126169d5fd8fSJohnny Huang 				printf("RSA4096\n");
126269d5fd8fSJohnny Huang 				len = 0x400;
126369d5fd8fSJohnny Huang 				break;
126469d5fd8fSJohnny Huang 			}
126569d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
126669d5fd8fSJohnny Huang 		}
12679a4fe690SJohnny Huang 		if (key_info.need_id)
126869d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
126969d5fd8fSJohnny Huang 		printf("Key Value:\n");
12709a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
127169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
12729a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
12739a4fe690SJohnny Huang 			printf("AES Key:\n");
12749a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
12759a4fe690SJohnny Huang 			if (info_cb.version == 0) {
12769a4fe690SJohnny Huang 				printf("AES IV:\n");
12779a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
12789a4fe690SJohnny Huang 			}
12799a4fe690SJohnny Huang 
12809a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
12819a4fe690SJohnny Huang 			if (info_cb.version == 0) {
128269d5fd8fSJohnny Huang 				printf("AES Key:\n");
128369d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
128469d5fd8fSJohnny Huang 				printf("AES IV:\n");
128569d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
12869a4fe690SJohnny Huang 			} else if (info_cb.version == 1) {
12879a4fe690SJohnny Huang 				printf("AES Key 1:\n");
12889a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
12899a4fe690SJohnny Huang 				printf("AES Key 2:\n");
12909a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
12919a4fe690SJohnny Huang 			}
129269d5fd8fSJohnny Huang 
12939a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
129469d5fd8fSJohnny Huang 			printf("RSA mod:\n");
129569d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
129669d5fd8fSJohnny Huang 			printf("RSA exp:\n");
129769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
129869d5fd8fSJohnny Huang 		}
129969d5fd8fSJohnny Huang 		if (last)
130069d5fd8fSJohnny Huang 			break;
130169d5fd8fSJohnny Huang 		i++;
130269d5fd8fSJohnny Huang 	}
130369d5fd8fSJohnny Huang 	return 0;
130469d5fd8fSJohnny Huang }
130569d5fd8fSJohnny Huang 
1306a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
130769d5fd8fSJohnny Huang {
1308a6d0d645SJohnny Huang 	int i, k;
1309d90825e2SJohnny Huang 	int pass = 0;
1310a6d0d645SJohnny Huang 	uint32_t prog_address;
1311*bb34a7bfSJohnny Huang 	uint32_t data[16];
1312a6d0d645SJohnny Huang 	uint32_t compare[2];
1313*bb34a7bfSJohnny Huang 	uint32_t *buf_keep = &buf[16];
1314d90825e2SJohnny Huang 	uint32_t data_masked;
1315d90825e2SJohnny Huang 	uint32_t buf_masked;
131669d5fd8fSJohnny Huang 
1317a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1318a6d0d645SJohnny Huang 
1319*bb34a7bfSJohnny Huang 	for (i = 0; i < 16 ; i ++) {
132069d5fd8fSJohnny Huang 		prog_address = 0x800;
1321a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1322a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1323a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1324a6d0d645SJohnny Huang 	}
1325a6d0d645SJohnny Huang 
1326a6d0d645SJohnny Huang 	printf("Check writable...\n");
1327*bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
1328d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1329d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1330d90825e2SJohnny Huang 		if (data_masked == buf_masked)
133169d5fd8fSJohnny Huang 			continue;
1332d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1333a6d0d645SJohnny Huang 			continue;
1334a6d0d645SJohnny Huang 		} else {
1335a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1336a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1337a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1338a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
13392a856b9aSJohnny Huang 			return OTP_FAILURE;
1340a6d0d645SJohnny Huang 		}
1341a6d0d645SJohnny Huang 	}
1342a6d0d645SJohnny Huang 
1343a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1344d90825e2SJohnny Huang 	otp_soak(0);
1345*bb34a7bfSJohnny Huang 	for (i = 0; i < 16; i++) {
1346d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1347d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1348a6d0d645SJohnny Huang 		prog_address = 0x800;
1349a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1350a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1351*bb34a7bfSJohnny Huang 		if (data_masked == buf_masked) {
1352*bb34a7bfSJohnny Huang 			pass = 1;
1353a6d0d645SJohnny Huang 			continue;
1354*bb34a7bfSJohnny Huang 		}
1355de6fbf1cSJohnny Huang 
1356a6d0d645SJohnny Huang 
1357de6fbf1cSJohnny Huang 		otp_soak(1);
1358d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1359a6d0d645SJohnny Huang 
136069d5fd8fSJohnny Huang 		pass = 0;
136169d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1362d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1363de6fbf1cSJohnny Huang 				otp_soak(2);
1364a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1365de6fbf1cSJohnny Huang 				if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1366de6fbf1cSJohnny Huang 					otp_soak(1);
1367de6fbf1cSJohnny Huang 				} else {
1368de6fbf1cSJohnny Huang 					pass = 1;
1369de6fbf1cSJohnny Huang 					break;
1370de6fbf1cSJohnny Huang 				}
1371a6d0d645SJohnny Huang 			} else {
137269d5fd8fSJohnny Huang 				pass = 1;
137369d5fd8fSJohnny Huang 				break;
137469d5fd8fSJohnny Huang 			}
137569d5fd8fSJohnny Huang 		}
1376*bb34a7bfSJohnny Huang 		if (pass == 0) {
1377*bb34a7bfSJohnny Huang 			printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n",
1378*bb34a7bfSJohnny Huang 			       i, data[i], buf[i], buf_keep[i]);
1379*bb34a7bfSJohnny Huang 			break;
1380*bb34a7bfSJohnny Huang 		}
1381a6d0d645SJohnny Huang 	}
1382a6d0d645SJohnny Huang 
1383de6fbf1cSJohnny Huang 	otp_soak(0);
138469d5fd8fSJohnny Huang 	if (!pass)
13852a856b9aSJohnny Huang 		return OTP_FAILURE;
1386a6d0d645SJohnny Huang 
13872a856b9aSJohnny Huang 	return OTP_SUCCESS;
1388d90825e2SJohnny Huang 
138969d5fd8fSJohnny Huang }
139069d5fd8fSJohnny Huang 
139169d5fd8fSJohnny Huang 
139276d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
139369d5fd8fSJohnny Huang {
139469d5fd8fSJohnny Huang 	int i;
139569d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
139669d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
139769d5fd8fSJohnny Huang 	int bit, pbit, kbit;
139869d5fd8fSJohnny Huang 	int fail = 0;
1399a6af4a17SJohnny Huang 	int skip = -1;
140066f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
140169d5fd8fSJohnny Huang 
1402541eb887SJohnny Huang 	otp_strap_status(otpstrap);
140369d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
140469d5fd8fSJohnny Huang 		if (i < 32) {
140569d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
140669d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
140769d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
140869d5fd8fSJohnny Huang 		} else {
140969d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
141069d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
141169d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
141269d5fd8fSJohnny Huang 		}
141369d5fd8fSJohnny Huang 
141469d5fd8fSJohnny Huang 		if (kbit == 1) {
141569d5fd8fSJohnny Huang 			continue;
141669d5fd8fSJohnny Huang 		} else {
1417a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
141869d5fd8fSJohnny Huang 		}
141969d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
142069d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1421a6af4a17SJohnny Huang 			if (skip == -1)
1422a6af4a17SJohnny Huang 				skip = 1;
142369d5fd8fSJohnny Huang 			continue;
1424a6af4a17SJohnny Huang 		} else {
1425a6af4a17SJohnny Huang 			skip = 0;
142669d5fd8fSJohnny Huang 		}
142769d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
142869d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
142969d5fd8fSJohnny Huang 			fail = 1;
143069d5fd8fSJohnny Huang 			continue;
143169d5fd8fSJohnny Huang 		}
143269d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1433a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
143469d5fd8fSJohnny Huang 			fail = 1;
143569d5fd8fSJohnny Huang 			continue;
143669d5fd8fSJohnny Huang 		}
143769d5fd8fSJohnny Huang 		if (pbit == 1) {
143869d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
143969d5fd8fSJohnny Huang 		}
1440a6af4a17SJohnny Huang 		printf("    Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1);
144169d5fd8fSJohnny Huang 	}
144269d5fd8fSJohnny Huang 	if (fail == 1)
1443a6af4a17SJohnny Huang 		return OTP_FAILURE;
1444a6af4a17SJohnny Huang 	else if (skip == 1)
1445a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
14467e22f42dSJohnny Huang 
14477e22f42dSJohnny Huang 	return 0;
144869d5fd8fSJohnny Huang }
144969d5fd8fSJohnny Huang 
14502a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
145169d5fd8fSJohnny Huang {
145269d5fd8fSJohnny Huang 	int i, j;
145366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
145469d5fd8fSJohnny Huang 
14552a856b9aSJohnny Huang 	if (start < 0 || start > 64)
14562a856b9aSJohnny Huang 		return OTP_USAGE;
14572a856b9aSJohnny Huang 
14582a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
14592a856b9aSJohnny Huang 		return OTP_USAGE;
14602a856b9aSJohnny Huang 
1461541eb887SJohnny Huang 	otp_strap_status(otpstrap);
146269d5fd8fSJohnny Huang 
146307baa4e8SJohnny Huang 	printf("BIT(hex)  Value  Option           Status\n");
1464a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1465737ed20bSJohnny Huang 
1466cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
146707baa4e8SJohnny Huang 		printf("0x%-8X", i);
1468737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1469737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1470737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1471737ed20bSJohnny Huang 		printf("   ");
147269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1473737ed20bSJohnny Huang 			printf("protected and not writable");
147469d5fd8fSJohnny Huang 		} else {
1475737ed20bSJohnny Huang 			printf("not protected ");
147669d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1477737ed20bSJohnny Huang 				printf("and no remaining times to write.");
147869d5fd8fSJohnny Huang 			} else {
1479737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
148069d5fd8fSJohnny Huang 			}
148169d5fd8fSJohnny Huang 		}
1482737ed20bSJohnny Huang 		printf("\n");
148369d5fd8fSJohnny Huang 	}
14842a856b9aSJohnny Huang 
14852a856b9aSJohnny Huang 	return OTP_SUCCESS;
148669d5fd8fSJohnny Huang }
148769d5fd8fSJohnny Huang 
148869d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
148969d5fd8fSJohnny Huang {
149069d5fd8fSJohnny Huang 	int i, j;
149169d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
149269d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
149369d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
149469d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
149569d5fd8fSJohnny Huang 	int fail = 0;
14967e22f42dSJohnny Huang 	int pass = 0;
149766f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
149869d5fd8fSJohnny Huang 
14997f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1500541eb887SJohnny Huang 	otp_strap_status(otpstrap);
150169d5fd8fSJohnny Huang 
15027f795e57SJohnny Huang 	printf("Check writable...\n");
15037f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
15047f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
15057f795e57SJohnny Huang 		return OTP_FAILURE;
15067f795e57SJohnny Huang 	}
15077e22f42dSJohnny Huang 
150869d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
150969d5fd8fSJohnny Huang 		prog_address = 0x800;
151069d5fd8fSJohnny Huang 		if (i < 32) {
151169d5fd8fSJohnny Huang 			offset = i;
151269d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
151369d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
151469d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
151569d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
151669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
151769d5fd8fSJohnny Huang 
151869d5fd8fSJohnny Huang 		} else {
151969d5fd8fSJohnny Huang 			offset = (i - 32);
152069d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
152169d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
152269d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
152369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
152469d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
152569d5fd8fSJohnny Huang 		}
152669d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
152769d5fd8fSJohnny Huang 
152869d5fd8fSJohnny Huang 		if (kbit == 1) {
152969d5fd8fSJohnny Huang 			continue;
153069d5fd8fSJohnny Huang 		}
153169d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
153269d5fd8fSJohnny Huang 			continue;
153369d5fd8fSJohnny Huang 		}
153469d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
153569d5fd8fSJohnny Huang 			fail = 1;
153669d5fd8fSJohnny Huang 			continue;
153769d5fd8fSJohnny Huang 		}
153869d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
153969d5fd8fSJohnny Huang 			fail = 1;
154069d5fd8fSJohnny Huang 			continue;
154169d5fd8fSJohnny Huang 		}
15427e22f42dSJohnny Huang 
15437e22f42dSJohnny Huang 
1544de6fbf1cSJohnny Huang 		otp_soak(1);
15457e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
15467e22f42dSJohnny Huang 
15477e22f42dSJohnny Huang 		pass = 0;
154869d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1549de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
1550de6fbf1cSJohnny Huang 				otp_soak(2);
1551de6fbf1cSJohnny Huang 				otp_prog(prog_address, prog_bit);
1552de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1553de6fbf1cSJohnny Huang 					otp_soak(1);
1554de6fbf1cSJohnny Huang 				} else {
155569d5fd8fSJohnny Huang 					pass = 1;
155669d5fd8fSJohnny Huang 					break;
155769d5fd8fSJohnny Huang 				}
1558de6fbf1cSJohnny Huang 			} else {
1559de6fbf1cSJohnny Huang 				pass = 1;
1560de6fbf1cSJohnny Huang 				break;
15614b65a65dSJohnny Huang 			}
156269d5fd8fSJohnny Huang 		}
156369d5fd8fSJohnny Huang 		if (!pass)
15642a856b9aSJohnny Huang 			return OTP_FAILURE;
156569d5fd8fSJohnny Huang 
156669d5fd8fSJohnny Huang 		if (pbit == 0)
156769d5fd8fSJohnny Huang 			continue;
156869d5fd8fSJohnny Huang 		prog_address = 0x800;
156969d5fd8fSJohnny Huang 		if (i < 32)
157069d5fd8fSJohnny Huang 			prog_address |= 0x60c;
157169d5fd8fSJohnny Huang 		else
157269d5fd8fSJohnny Huang 			prog_address |= 0x60e;
157369d5fd8fSJohnny Huang 
15747e22f42dSJohnny Huang 
1575de6fbf1cSJohnny Huang 		otp_soak(1);
15767e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
15777e22f42dSJohnny Huang 
15787e22f42dSJohnny Huang 		pass = 0;
157969d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1580de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, offset, 1) != 0) {
1581de6fbf1cSJohnny Huang 				otp_soak(2);
1582de6fbf1cSJohnny Huang 				otp_prog(prog_address, prog_bit);
1583de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, offset, 1) != 0) {
1584de6fbf1cSJohnny Huang 					otp_soak(1);
1585de6fbf1cSJohnny Huang 				} else {
158669d5fd8fSJohnny Huang 					pass = 1;
158769d5fd8fSJohnny Huang 					break;
158869d5fd8fSJohnny Huang 				}
1589de6fbf1cSJohnny Huang 			} else {
1590de6fbf1cSJohnny Huang 				pass = 1;
1591de6fbf1cSJohnny Huang 				break;
159269d5fd8fSJohnny Huang 			}
159369d5fd8fSJohnny Huang 		}
159469d5fd8fSJohnny Huang 		if (!pass)
15952a856b9aSJohnny Huang 			return OTP_FAILURE;
159669d5fd8fSJohnny Huang 
159769d5fd8fSJohnny Huang 	}
1598de6fbf1cSJohnny Huang 	otp_soak(0);
159969d5fd8fSJohnny Huang 	if (fail == 1)
16002a856b9aSJohnny Huang 		return OTP_FAILURE;
160169d5fd8fSJohnny Huang 	else
16022a856b9aSJohnny Huang 		return OTP_SUCCESS;
160369d5fd8fSJohnny Huang 
160469d5fd8fSJohnny Huang }
160569d5fd8fSJohnny Huang 
1606de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset)
1607cd1610b4SJohnny Huang {
1608cd1610b4SJohnny Huang 	int prog_bit;
1609cd1610b4SJohnny Huang 
1610cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1611cd1610b4SJohnny Huang 		if (value)
1612cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1613cd1610b4SJohnny Huang 		else
1614cd1610b4SJohnny Huang 			return;
1615cd1610b4SJohnny Huang 	} else {
1616cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1617cd1610b4SJohnny Huang 		if (!value)
1618cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1619cd1610b4SJohnny Huang 		else
1620cd1610b4SJohnny Huang 			return;
1621cd1610b4SJohnny Huang 	}
1622cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1623cd1610b4SJohnny Huang }
1624cd1610b4SJohnny Huang 
1625d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
16264c1c9b35SJohnny Huang {
162754552c69SJohnny Huang 	int i;
162854552c69SJohnny Huang 	int ret;
1629d90825e2SJohnny Huang 	uint32_t data[2048];
1630d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
16314c1c9b35SJohnny Huang 
163254552c69SJohnny Huang 	uint32_t data_masked;
163354552c69SJohnny Huang 	uint32_t buf_masked;
16344c1c9b35SJohnny Huang 
16354c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
16364c1c9b35SJohnny Huang 
1637d6cdf762SJohnny Huang 	for (i = 0; i < 2046 ; i += 2) {
1638d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
16394c1c9b35SJohnny Huang 	}
1640d90825e2SJohnny Huang 
16414c1c9b35SJohnny Huang 
16424c1c9b35SJohnny Huang 	printf("Check writable...\n");
164354552c69SJohnny Huang 	// ignore last two dw, the last two dw is used for slt otp write check.
1644d6cdf762SJohnny Huang 	for (i = 0; i < 2046; i++) {
164554552c69SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
164654552c69SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
164754552c69SJohnny Huang 		if (data_masked == buf_masked)
16484c1c9b35SJohnny Huang 			continue;
1649d90825e2SJohnny Huang 		if (i % 2 == 0) {
165054552c69SJohnny Huang 			if ((data_masked | buf_masked) == buf_masked) {
16514c1c9b35SJohnny Huang 				continue;
16524c1c9b35SJohnny Huang 			} else {
16534c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1654d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
16554c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1656d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
16572a856b9aSJohnny Huang 				return OTP_FAILURE;
165869d5fd8fSJohnny Huang 			}
1659d90825e2SJohnny Huang 		} else {
166054552c69SJohnny Huang 			if ((data_masked & buf_masked) == buf_masked) {
1661d90825e2SJohnny Huang 				continue;
1662d90825e2SJohnny Huang 			} else {
1663d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1664d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1665d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1666d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
16672a856b9aSJohnny Huang 				return OTP_FAILURE;
1668d90825e2SJohnny Huang 			}
1669d90825e2SJohnny Huang 		}
1670d90825e2SJohnny Huang 	}
167169d5fd8fSJohnny Huang 
1672d90825e2SJohnny Huang 	printf("Start Programing...\n");
1673d90825e2SJohnny Huang 
167454552c69SJohnny Huang 	// programing ecc region first
167554552c69SJohnny Huang 	for (i = 1792; i < 2046; i += 2) {
167654552c69SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i);
167754552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
167854552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
167954552c69SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]);
168054552c69SJohnny Huang 			return ret;
1681d90825e2SJohnny Huang 		}
1682d90825e2SJohnny Huang 	}
1683d90825e2SJohnny Huang 
168454552c69SJohnny Huang 	for (i = 0; i < 1792; i += 2) {
168554552c69SJohnny Huang 		ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i);
168654552c69SJohnny Huang 		if (ret != OTP_SUCCESS) {
168754552c69SJohnny Huang 			printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n",
168854552c69SJohnny Huang 			       i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]);
168954552c69SJohnny Huang 			return ret;
1690d90825e2SJohnny Huang 		}
1691de6fbf1cSJohnny Huang 	}
1692de6fbf1cSJohnny Huang 	otp_soak(0);
16932a856b9aSJohnny Huang 	return OTP_SUCCESS;
1694d90825e2SJohnny Huang 
1695d90825e2SJohnny Huang }
1696d90825e2SJohnny Huang 
1697d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
169869d5fd8fSJohnny Huang {
169969d5fd8fSJohnny Huang 	int ret;
17007332532cSJohnny Huang 	int mode = 0;
17019a4fe690SJohnny Huang 	int image_version = 0;
170269d5fd8fSJohnny Huang 	uint32_t *buf;
1703d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1704d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1705d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
170669d5fd8fSJohnny Huang 
1707d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
170869d5fd8fSJohnny Huang 	if (!buf) {
170969d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
17102a856b9aSJohnny Huang 		return OTP_FAILURE;
171169d5fd8fSJohnny Huang 	}
1712d90825e2SJohnny Huang 
17139a4fe690SJohnny Huang 	image_version = buf[0] & 0x3;
17149a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
17159a4fe690SJohnny Huang 		puts("Version is not match\n");
17169a4fe690SJohnny Huang 		return OTP_FAILURE;
17179a4fe690SJohnny Huang 	}
17189a4fe690SJohnny Huang 
1719d90825e2SJohnny Huang 	if (buf[0] & BIT(29)) {
17207332532cSJohnny Huang 		mode |= OTP_REGION_DATA;
1721*bb34a7bfSJohnny Huang 		data_region = &buf[44];
1722d90825e2SJohnny Huang 	}
1723d90825e2SJohnny Huang 	if (buf[0] & BIT(30)) {
17247332532cSJohnny Huang 		mode |= OTP_REGION_CONF;
17257332532cSJohnny Huang 		conf_region = &buf[12];
1726d90825e2SJohnny Huang 	}
1727d90825e2SJohnny Huang 	if (buf[0] & BIT(31)) {
17287332532cSJohnny Huang 		mode |= OTP_REGION_STRAP;
17297332532cSJohnny Huang 		strap_region = &buf[4];
1730d90825e2SJohnny Huang 	}
17317332532cSJohnny Huang 
173269d5fd8fSJohnny Huang 	if (!nconfirm) {
17337332532cSJohnny Huang 		if (mode & OTP_REGION_DATA) {
17347f795e57SJohnny Huang 			printf("\nOTP data region :\n");
17357f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
173669d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
17372a856b9aSJohnny Huang 				return OTP_FAILURE;
173869d5fd8fSJohnny Huang 			}
173969d5fd8fSJohnny Huang 		}
17407332532cSJohnny Huang 		if (mode & OTP_REGION_STRAP) {
17417332532cSJohnny Huang 			printf("\nOTP strap region :\n");
17427332532cSJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
17437332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
17447332532cSJohnny Huang 				return OTP_FAILURE;
17457332532cSJohnny Huang 			}
17467332532cSJohnny Huang 		}
17477332532cSJohnny Huang 		if (mode & OTP_REGION_CONF) {
17487332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
17497332532cSJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
17507332532cSJohnny Huang 				printf("OTP config error, please check.\n");
17517332532cSJohnny Huang 				return OTP_FAILURE;
17527332532cSJohnny Huang 			}
17537332532cSJohnny Huang 		}
17547332532cSJohnny Huang 
175569d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
175669d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
175769d5fd8fSJohnny Huang 			printf(" Aborting\n");
17582a856b9aSJohnny Huang 			return OTP_FAILURE;
175969d5fd8fSJohnny Huang 		}
176069d5fd8fSJohnny Huang 	}
17617332532cSJohnny Huang 
17627332532cSJohnny Huang 	if (mode & OTP_REGION_DATA) {
17637332532cSJohnny Huang 		printf("programing data region ...\n");
1764d90825e2SJohnny Huang 		ret = otp_prog_data(data_region);
17652a856b9aSJohnny Huang 		if (ret != 0) {
176669d5fd8fSJohnny Huang 			printf("Error\n");
176769d5fd8fSJohnny Huang 			return ret;
176869d5fd8fSJohnny Huang 		} else {
176969d5fd8fSJohnny Huang 			printf("Done\n");
177069d5fd8fSJohnny Huang 		}
17717332532cSJohnny Huang 	}
17727332532cSJohnny Huang 	if (mode & OTP_REGION_STRAP) {
17737332532cSJohnny Huang 		printf("programing strap region ...\n");
1774d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
17752a856b9aSJohnny Huang 		if (ret != 0) {
177669d5fd8fSJohnny Huang 			printf("Error\n");
177769d5fd8fSJohnny Huang 			return ret;
177869d5fd8fSJohnny Huang 		} else {
177969d5fd8fSJohnny Huang 			printf("Done\n");
178069d5fd8fSJohnny Huang 		}
17817332532cSJohnny Huang 	}
17827332532cSJohnny Huang 	if (mode & OTP_REGION_CONF) {
17837332532cSJohnny Huang 		printf("programing configuration region ...\n");
1784d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
17852a856b9aSJohnny Huang 		if (ret != 0) {
178669d5fd8fSJohnny Huang 			printf("Error\n");
178769d5fd8fSJohnny Huang 			return ret;
178869d5fd8fSJohnny Huang 		}
178969d5fd8fSJohnny Huang 		printf("Done\n");
179069d5fd8fSJohnny Huang 	}
1791cd1610b4SJohnny Huang 
17927332532cSJohnny Huang 	return OTP_SUCCESS;
17932a856b9aSJohnny Huang }
17942a856b9aSJohnny Huang 
17952a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1796cd1610b4SJohnny Huang {
1797a6af4a17SJohnny Huang 	uint32_t read[2];
1798cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1799d90825e2SJohnny Huang 	uint32_t prog_address = 0;
180066f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1801cd1610b4SJohnny Huang 	int otp_bit;
1802cd1610b4SJohnny Huang 	int i;
1803cd1610b4SJohnny Huang 	int pass;
1804a6af4a17SJohnny Huang 	int ret;
1805cd1610b4SJohnny Huang 
1806cd1610b4SJohnny Huang 	switch (mode) {
1807a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1808a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1809cd1610b4SJohnny Huang 		prog_address = 0x800;
1810cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1811cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1812a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1813cd1610b4SJohnny Huang 		if (otp_bit == value) {
1814a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1815cd1610b4SJohnny Huang 			printf("No need to program\n");
18162a856b9aSJohnny Huang 			return OTP_SUCCESS;
1817cd1610b4SJohnny Huang 		}
1818cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1819a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1820cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
18212a856b9aSJohnny Huang 			return OTP_FAILURE;
1822cd1610b4SJohnny Huang 		}
1823a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1824cd1610b4SJohnny Huang 		break;
1825a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1826cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1827cd1610b4SJohnny Huang 
1828cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1829a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1830a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1831643b9cfdSJohnny Huang 
1832643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1833643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1834643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1835643b9cfdSJohnny Huang 				return OTP_FAILURE;
1836643b9cfdSJohnny Huang 			}
1837cd1610b4SJohnny Huang 		} else {
1838a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1839a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1840643b9cfdSJohnny Huang 
1841643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1842643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1843643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1844643b9cfdSJohnny Huang 				return OTP_FAILURE;
1845643b9cfdSJohnny Huang 			}
1846cd1610b4SJohnny Huang 		}
1847cd1610b4SJohnny Huang 		if (otp_bit == value) {
1848a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1849cd1610b4SJohnny Huang 			printf("No need to program\n");
18502a856b9aSJohnny Huang 			return OTP_SUCCESS;
1851cd1610b4SJohnny Huang 		}
1852643b9cfdSJohnny Huang 
1853a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1854cd1610b4SJohnny Huang 		break;
1855a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1856541eb887SJohnny Huang 		otp_strap_status(otpstrap);
1857cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1858cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1859cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
18603d1cbeb0SJohnny Huang 			strap_buf[1] = 0;
1861cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1862cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
18633d1cbeb0SJohnny Huang 			strap_buf[4] = 0;
1864cd1610b4SJohnny Huang 			strap_buf[5] = 0;
1865cd1610b4SJohnny Huang 		} else {
18663d1cbeb0SJohnny Huang 			strap_buf[0] = 0;
1867cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1868cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1869cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1870cd1610b4SJohnny Huang 			strap_buf[4] = 0;
18713d1cbeb0SJohnny Huang 			strap_buf[5] = 0;
1872cd1610b4SJohnny Huang 		}
187376d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1874a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
18752a856b9aSJohnny Huang 			return OTP_FAILURE;
1876a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1877a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1878a6af4a17SJohnny Huang 
1879cd1610b4SJohnny Huang 		break;
1880cd1610b4SJohnny Huang 	}
1881cd1610b4SJohnny Huang 
1882cd1610b4SJohnny Huang 	if (!nconfirm) {
1883cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1884cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1885cd1610b4SJohnny Huang 			printf(" Aborting\n");
18862a856b9aSJohnny Huang 			return OTP_FAILURE;
1887cd1610b4SJohnny Huang 		}
1888cd1610b4SJohnny Huang 	}
1889cd1610b4SJohnny Huang 
1890cd1610b4SJohnny Huang 	switch (mode) {
1891a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1892cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
1893a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1894a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1895de6fbf1cSJohnny Huang 		otp_soak(1);
1896de6fbf1cSJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset);
1897de6fbf1cSJohnny Huang 		pass = 0;
1898de6fbf1cSJohnny Huang 
1899cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
1900a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
1901de6fbf1cSJohnny Huang 				otp_soak(2);
1902de6fbf1cSJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset);
1903de6fbf1cSJohnny Huang 				if (verify_bit(prog_address, bit_offset, value) != 0) {
1904de6fbf1cSJohnny Huang 					otp_soak(1);
1905cd1610b4SJohnny Huang 				} else {
1906de6fbf1cSJohnny Huang 					pass = 1;
1907de6fbf1cSJohnny Huang 					break;
1908de6fbf1cSJohnny Huang 				}
1909de6fbf1cSJohnny Huang 			} else {
1910de6fbf1cSJohnny Huang 				pass = 1;
1911cd1610b4SJohnny Huang 				break;
1912cd1610b4SJohnny Huang 			}
1913cd1610b4SJohnny Huang 		}
1914de6fbf1cSJohnny Huang 
1915de6fbf1cSJohnny Huang 		otp_soak(0);
1916de6fbf1cSJohnny Huang 		if (pass) {
19179009c25dSJohnny Huang 			printf("SUCCESS\n");
19182a856b9aSJohnny Huang 			return OTP_SUCCESS;
19199009c25dSJohnny Huang 		} else {
19209009c25dSJohnny Huang 			printf("OTP cannot be programed\n");
19219009c25dSJohnny Huang 			printf("FAILED\n");
19229009c25dSJohnny Huang 			return OTP_FAILURE;
19239009c25dSJohnny Huang 		}
1924cd1610b4SJohnny Huang 	}
1925cd1610b4SJohnny Huang 
19262a856b9aSJohnny Huang 	return OTP_USAGE;
1927cd1610b4SJohnny Huang }
1928cd1610b4SJohnny Huang 
19292a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
193069d5fd8fSJohnny Huang {
19312a856b9aSJohnny Huang 	uint32_t offset, count;
19322a856b9aSJohnny Huang 	int ret;
193369d5fd8fSJohnny Huang 
19342a856b9aSJohnny Huang 	if (argc == 4) {
19352a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
19362a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
19372a856b9aSJohnny Huang 	} else if (argc == 3) {
19382a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
19392a856b9aSJohnny Huang 		count = 1;
19402a856b9aSJohnny Huang 	} else {
194169d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
194269d5fd8fSJohnny Huang 	}
194369d5fd8fSJohnny Huang 
194469d5fd8fSJohnny Huang 
19452a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
19463d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19472a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
19482a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
19493d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19502a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
19512a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
19523d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19532a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
19542a856b9aSJohnny Huang 	} else {
19552a856b9aSJohnny Huang 		return CMD_RET_USAGE;
195669d5fd8fSJohnny Huang 	}
195769d5fd8fSJohnny Huang 
19582a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19592a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19602a856b9aSJohnny Huang 	else
19612a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19622a856b9aSJohnny Huang 
19632a856b9aSJohnny Huang }
19642a856b9aSJohnny Huang 
19652a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19662a856b9aSJohnny Huang {
19672a856b9aSJohnny Huang 	phys_addr_t addr;
19682a856b9aSJohnny Huang 	uint32_t byte_size;
19692a856b9aSJohnny Huang 	int ret;
19702a856b9aSJohnny Huang 
19712a856b9aSJohnny Huang 	if (argc == 4) {
1972ed071a2bSJohnny Huang 		if (strcmp(argv[1], "o"))
19732a856b9aSJohnny Huang 			return CMD_RET_USAGE;
19742a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
19752a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
19763d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19772a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
19782a856b9aSJohnny Huang 	} else if (argc == 3) {
19792a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
19802a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
19813d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
19822a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
19832a856b9aSJohnny Huang 	} else {
19842a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19852a856b9aSJohnny Huang 	}
19862a856b9aSJohnny Huang 
19872a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19882a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19892a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
19902a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19912a856b9aSJohnny Huang 	else
19922a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19932a856b9aSJohnny Huang }
19942a856b9aSJohnny Huang 
19952a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19962a856b9aSJohnny Huang {
19972a856b9aSJohnny Huang 	int mode = 0;
19982a856b9aSJohnny Huang 	int nconfirm = 0;
19992a856b9aSJohnny Huang 	int otp_addr = 0;
20002a856b9aSJohnny Huang 	int bit_offset;
20012a856b9aSJohnny Huang 	int value;
20022a856b9aSJohnny Huang 	int ret;
20032a856b9aSJohnny Huang 
20042a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
20052a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20062a856b9aSJohnny Huang 
20072a856b9aSJohnny Huang 	/* Drop the pb cmd */
20082a856b9aSJohnny Huang 	argc--;
20092a856b9aSJohnny Huang 	argv++;
20102a856b9aSJohnny Huang 
20112a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
2012a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
20132a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
2014a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
20152a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
2016a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
2017cd1610b4SJohnny Huang 	else
20182a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20192a856b9aSJohnny Huang 
20202a856b9aSJohnny Huang 	/* Drop the region cmd */
20212a856b9aSJohnny Huang 	argc--;
20222a856b9aSJohnny Huang 	argv++;
20232a856b9aSJohnny Huang 
2024ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2025cd1610b4SJohnny Huang 		nconfirm = 1;
20262a856b9aSJohnny Huang 		/* Drop the force option */
20272a856b9aSJohnny Huang 		argc--;
20282a856b9aSJohnny Huang 		argv++;
20292a856b9aSJohnny Huang 	}
2030cd1610b4SJohnny Huang 
2031a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
20322a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
20332a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
20340808cc55SJohnny Huang 		if (bit_offset >= 64 || (value != 0 && value != 1))
20352a856b9aSJohnny Huang 			return CMD_RET_USAGE;
2036cd1610b4SJohnny Huang 	} else {
20372a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
20382a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
20392a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
20400808cc55SJohnny Huang 		if (bit_offset >= 32 || (value != 0 && value != 1))
20412a856b9aSJohnny Huang 			return CMD_RET_USAGE;
20420808cc55SJohnny Huang 		if (mode == OTP_REGION_DATA) {
204378855207SJohnny Huang 			if (otp_addr >= 0x800)
20440808cc55SJohnny Huang 				return CMD_RET_USAGE;
20450808cc55SJohnny Huang 		} else {
204678855207SJohnny Huang 			if (otp_addr >= 0x20)
20470808cc55SJohnny Huang 				return CMD_RET_USAGE;
20480808cc55SJohnny Huang 		}
2049cd1610b4SJohnny Huang 	}
2050cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
20512a856b9aSJohnny Huang 		return CMD_RET_USAGE;
2052cd1610b4SJohnny Huang 
20533d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20542a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
20552a856b9aSJohnny Huang 
20562a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
20572a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
20582a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
20592a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
20602a856b9aSJohnny Huang 	else
20612a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20622a856b9aSJohnny Huang }
20632a856b9aSJohnny Huang 
20642a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
20652a856b9aSJohnny Huang {
20662a856b9aSJohnny Huang 	phys_addr_t addr;
20672a856b9aSJohnny Huang 	int otp_addr = 0;
20682a856b9aSJohnny Huang 
20692a856b9aSJohnny Huang 	if (argc != 3)
20702a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20712a856b9aSJohnny Huang 
20723d3688adSJohnny Huang 	writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20732a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
20742a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
20752a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
207669d5fd8fSJohnny Huang 		printf("Compare pass\n");
20772a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
207869d5fd8fSJohnny Huang 	} else {
207969d5fd8fSJohnny Huang 		printf("Compare fail\n");
20802a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
208169d5fd8fSJohnny Huang 	}
208269d5fd8fSJohnny Huang }
208369d5fd8fSJohnny Huang 
208466f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
208566f2f8e5SJohnny Huang {
2086a8bd6d8cSJohnny Huang 	int view = 0;
20872d4b0742SJohnny Huang 	int input;
2088a8bd6d8cSJohnny Huang 
2089a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
209066f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
209166f2f8e5SJohnny Huang 
20922d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
209366f2f8e5SJohnny Huang 
20943d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
20952d4b0742SJohnny Huang 		if (argc == 3) {
20962d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
20972d4b0742SJohnny Huang 			otp_print_conf_info(input);
20982d4b0742SJohnny Huang 		} else {
20992d4b0742SJohnny Huang 			otp_print_conf_info(-1);
21002d4b0742SJohnny Huang 		}
21012d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
21022d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
2103a8bd6d8cSJohnny Huang 			view = 1;
2104a8bd6d8cSJohnny Huang 			/* Drop the view option */
2105a8bd6d8cSJohnny Huang 			argc--;
2106a8bd6d8cSJohnny Huang 			argv++;
2107a8bd6d8cSJohnny Huang 		}
21083d3688adSJohnny Huang 		writel(OTP_PASSWD, OTP_PROTECT_KEY); //password
2109b458cd62SJohnny Huang 		otp_print_strap_info(view);
211066f2f8e5SJohnny Huang 	} else {
211166f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
211266f2f8e5SJohnny Huang 	}
21132d4b0742SJohnny Huang 
211466f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
211566f2f8e5SJohnny Huang }
211666f2f8e5SJohnny Huang 
2117737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2118737ed20bSJohnny Huang {
2119737ed20bSJohnny Huang 	int input;
2120737ed20bSJohnny Huang 	int bit_offset;
2121737ed20bSJohnny Huang 	int prog_address;
2122737ed20bSJohnny Huang 	int pass;
2123737ed20bSJohnny Huang 	int i;
2124737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2125737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2126737ed20bSJohnny Huang 
2127ed071a2bSJohnny Huang 	if (!strcmp(argv[0], "o")) {
2128737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2129737ed20bSJohnny Huang 	} else {
2130737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2131737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2132737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2133737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2134737ed20bSJohnny Huang 			printf(" Aborting\n");
2135737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2136737ed20bSJohnny Huang 		}
2137737ed20bSJohnny Huang 	}
2138737ed20bSJohnny Huang 
2139737ed20bSJohnny Huang 	prog_address = 0x800;
2140737ed20bSJohnny Huang 	if (input < 32) {
2141737ed20bSJohnny Huang 		bit_offset = input;
2142737ed20bSJohnny Huang 		prog_address |= 0x60c;
2143737ed20bSJohnny Huang 	} else if (input < 64) {
2144737ed20bSJohnny Huang 		bit_offset = input - 32;
2145737ed20bSJohnny Huang 		prog_address |= 0x60e;
2146737ed20bSJohnny Huang 	} else {
2147737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2148737ed20bSJohnny Huang 	}
2149737ed20bSJohnny Huang 
2150737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2151737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2152737ed20bSJohnny Huang 	}
2153de6fbf1cSJohnny Huang 
2154de6fbf1cSJohnny Huang 	otp_soak(1);
2155de6fbf1cSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset);
2156de6fbf1cSJohnny Huang 	pass = 0;
2157de6fbf1cSJohnny Huang 
2158737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2159737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2160de6fbf1cSJohnny Huang 			otp_soak(2);
2161de6fbf1cSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset);
2162de6fbf1cSJohnny Huang 			if (verify_bit(prog_address, bit_offset, 1) != 0) {
2163de6fbf1cSJohnny Huang 				otp_soak(1);
2164737ed20bSJohnny Huang 			} else {
2165de6fbf1cSJohnny Huang 				pass = 1;
2166de6fbf1cSJohnny Huang 				break;
2167de6fbf1cSJohnny Huang 			}
2168de6fbf1cSJohnny Huang 		} else {
2169de6fbf1cSJohnny Huang 			pass = 1;
2170737ed20bSJohnny Huang 			break;
2171737ed20bSJohnny Huang 		}
2172737ed20bSJohnny Huang 	}
2173de6fbf1cSJohnny Huang 	otp_soak(0);
2174de6fbf1cSJohnny Huang 	if (pass) {
2175737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2176737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2177737ed20bSJohnny Huang 	}
2178737ed20bSJohnny Huang 
2179737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2180737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2181737ed20bSJohnny Huang 
2182737ed20bSJohnny Huang }
21839a4fe690SJohnny Huang 
21842a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
21852a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2186a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
21872a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
21882a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2189737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
21902a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
21912a856b9aSJohnny Huang };
21922a856b9aSJohnny Huang 
21932a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21942a856b9aSJohnny Huang {
21952a856b9aSJohnny Huang 	cmd_tbl_t *cp;
21962a856b9aSJohnny Huang 
21972a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
21982a856b9aSJohnny Huang 
2199737ed20bSJohnny Huang 	/* Drop the otp command */
22002a856b9aSJohnny Huang 	argc--;
22012a856b9aSJohnny Huang 	argv++;
22022a856b9aSJohnny Huang 
22032a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
22042a856b9aSJohnny Huang 		return CMD_RET_USAGE;
22052a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
22062a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
22072a856b9aSJohnny Huang 
22089a4fe690SJohnny Huang 	if (chip_version() == 0) {
22099a4fe690SJohnny Huang 		info_cb.version = 0;
22109a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
22119a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
22129a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
22139a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
22149a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
22159a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
22169a4fe690SJohnny Huang 	} else if (chip_version() == 1) {
22179a4fe690SJohnny Huang 		info_cb.version = 1;
22183cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
22193cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
22203cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
22213cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
22229a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
22239a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
22249a4fe690SJohnny Huang 	}
22259a4fe690SJohnny Huang 
22262a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
222769d5fd8fSJohnny Huang }
222869d5fd8fSJohnny Huang 
222969d5fd8fSJohnny Huang U_BOOT_CMD(
223069d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
223169d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
22322a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
22332a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
22342d4b0742SJohnny Huang 	"otp info strap [v]\n"
22352d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2236ed071a2bSJohnny Huang 	"otp prog [o] <addr> <byte_size>\n"
2237ed071a2bSJohnny Huang 	"otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n"
2238ed071a2bSJohnny Huang 	"otp pb strap [o] <bit_offset> <value>\n"
2239ed071a2bSJohnny Huang 	"otp protect [o] <bit_offset>\n"
22402a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
224169d5fd8fSJohnny Huang );
2242