xref: /openbmc/u-boot/cmd/otp.c (revision 643b9cfdf73cf333ff85f007b199b8e899a9864b)
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 
5166f2f8e5SJohnny Huang struct otpstrap_status {
5269d5fd8fSJohnny Huang 	int value;
5369d5fd8fSJohnny Huang 	int option_array[7];
5469d5fd8fSJohnny Huang 	int remain_times;
5569d5fd8fSJohnny Huang 	int writeable_option;
5669d5fd8fSJohnny Huang 	int protected;
5769d5fd8fSJohnny Huang };
5869d5fd8fSJohnny Huang 
5966f2f8e5SJohnny Huang struct otpconf_parse {
6066f2f8e5SJohnny Huang 	int dw_offset;
6166f2f8e5SJohnny Huang 	int bit;
6266f2f8e5SJohnny Huang 	int length;
6366f2f8e5SJohnny Huang 	int value;
6466f2f8e5SJohnny Huang 	int keep;
6566f2f8e5SJohnny Huang 	char status[80];
6666f2f8e5SJohnny Huang };
6766f2f8e5SJohnny Huang 
68a8bd6d8cSJohnny Huang struct otpstrap_info {
69a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
70a8bd6d8cSJohnny Huang 	uint32_t length;
7176d13988SJohnny Huang 	int value;
72a8bd6d8cSJohnny Huang 	char information[80];
73a8bd6d8cSJohnny Huang };
74a8bd6d8cSJohnny Huang 
75a8bd6d8cSJohnny Huang struct otpconf_info {
76a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
77a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
78a8bd6d8cSJohnny Huang 	uint32_t length;
79a8bd6d8cSJohnny Huang 	int value;
80a8bd6d8cSJohnny Huang 	char information[80];
81a8bd6d8cSJohnny Huang };
82a8bd6d8cSJohnny Huang 
839a4fe690SJohnny Huang struct otpkey_type {
849a4fe690SJohnny Huang 	int value;
859a4fe690SJohnny Huang 	int key_type;
869a4fe690SJohnny Huang 	int need_id;
879a4fe690SJohnny Huang 	char information[110];
889a4fe690SJohnny Huang };
899a4fe690SJohnny Huang 
909a4fe690SJohnny Huang struct otp_info_cb {
919a4fe690SJohnny Huang 	int version;
929a4fe690SJohnny Huang 	struct otpstrap_info *strap_info;
939a4fe690SJohnny Huang 	int strap_info_len;
949a4fe690SJohnny Huang 	struct otpconf_info *conf_info;
959a4fe690SJohnny Huang 	int conf_info_len;
969a4fe690SJohnny Huang 	struct otpkey_type *key_info;
979a4fe690SJohnny Huang 	int key_info_len;
989a4fe690SJohnny Huang };
999a4fe690SJohnny Huang 
100a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...)
101a8bd6d8cSJohnny Huang {
102a8bd6d8cSJohnny Huang 	int val = numerator * 100 / denominator;
103a8bd6d8cSJohnny Huang 	int lpad = numerator * PBWIDTH / denominator;
104a8bd6d8cSJohnny Huang 	int rpad = PBWIDTH - lpad;
105a8bd6d8cSJohnny Huang 	char buffer[256];
106a8bd6d8cSJohnny Huang 	va_list aptr;
107a8bd6d8cSJohnny Huang 
108a8bd6d8cSJohnny Huang 	va_start(aptr, format);
109a8bd6d8cSJohnny Huang 	vsprintf(buffer, format, aptr);
110a8bd6d8cSJohnny Huang 	va_end(aptr);
111a8bd6d8cSJohnny Huang 
112a8bd6d8cSJohnny Huang 	printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer);
113a8bd6d8cSJohnny Huang 	if (numerator == denominator)
114a8bd6d8cSJohnny Huang 		printf("\n");
115a8bd6d8cSJohnny Huang }
116a8bd6d8cSJohnny Huang 
1179a4fe690SJohnny Huang static struct otp_info_cb info_cb;
1189a4fe690SJohnny Huang 
119a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = {
12091448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
12191448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
12291448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
12391448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
12491448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
12591448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
12691448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
12791448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
128541eb887SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
12991448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
13091448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
13191448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
13291448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
13391448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
13491448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
13591448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
13691448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
13791448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
13891448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
13991448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
14091448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
14191448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
14291448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
14391448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
14491448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
14591448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
14691448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
14791448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
14891448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
14991448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
15091448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
15191448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
15291448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
15391448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
15491448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
15591448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
15691448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
15791448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
15891448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
15991448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
16091448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
16191448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
16291448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
16391448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
16491448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
16591448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
16691448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
16791448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
16891448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
16991448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
17091448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
17191448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
17291448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
17391448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
17491448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
17591448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
17691448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
17791448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
17891448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
17991448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
18091448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
18191448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
18291448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
18391448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
18491448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
18591448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
18691448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
18791448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
18891448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
18991448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
19091448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
19191448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
19291448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
19391448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
19491448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
19591448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
19691448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
19791448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
19891448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
19991448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
20091448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
20191448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
20291448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
20391448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
20491448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
20591448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
20691448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
20791448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
20891448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
20991448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
21091448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
21191448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
21291448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
21391448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
21491448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
21591448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
21691448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
21791448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
21891448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
21991448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
22091448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
22191448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
22291448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
22391448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
22491448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
22591448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
22691448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
22791448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
22891448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
22976d13988SJohnny Huang };
2309a4fe690SJohnny Huang 
2313cb28812SJohnny Huang struct otpstrap_info a1_strap_info[] = {
2323cb28812SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
2333cb28812SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
2343cb28812SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
2353cb28812SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
2363cb28812SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
2373cb28812SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
2383cb28812SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
2393cb28812SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
2403cb28812SJohnny Huang 	{ 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" },
2413cb28812SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
2423cb28812SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
2433cb28812SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
2443cb28812SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
2453cb28812SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
2463cb28812SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
2473cb28812SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
2483cb28812SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
2493cb28812SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
2503cb28812SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
2513cb28812SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
2523cb28812SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
2533cb28812SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
2543cb28812SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
2553cb28812SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
2563cb28812SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
2573cb28812SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
2583cb28812SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
2593cb28812SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
2603cb28812SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
2613cb28812SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
2623cb28812SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
2633cb28812SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
2643cb28812SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
2653cb28812SJohnny Huang 	{ 20, 1, 0, "Disable Pcie EHCI device" },
2663cb28812SJohnny Huang 	{ 20, 1, 1, "Enable Pcie EHCI device" },
2673cb28812SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
2683cb28812SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
2693cb28812SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
2703cb28812SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
2713cb28812SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
2723cb28812SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
2733cb28812SJohnny Huang 	{ 24, 1, 0, "Enable watchdog to reset full chip" },
2743cb28812SJohnny Huang 	{ 24, 1, 1, "Disable watchdog to reset full chip" },
2753cb28812SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
2763cb28812SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
2773cb28812SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
2783cb28812SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
2793cb28812SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
2803cb28812SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
2813cb28812SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
2823cb28812SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
2833cb28812SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
2843cb28812SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
2853cb28812SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
2863cb28812SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
2873cb28812SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
2883cb28812SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
2893cb28812SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
2903cb28812SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
2913cb28812SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
2923cb28812SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
2933cb28812SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
2943cb28812SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
2953cb28812SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
2963cb28812SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
2973cb28812SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
2983cb28812SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
2993cb28812SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
3003cb28812SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
3013cb28812SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
3023cb28812SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
3033cb28812SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
3043cb28812SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
3053cb28812SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
3063cb28812SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
3073cb28812SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
3083cb28812SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
3093cb28812SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
3103cb28812SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
3113cb28812SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
3123cb28812SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
3133cb28812SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
3143cb28812SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
3153cb28812SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
3163cb28812SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
3173cb28812SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
3183cb28812SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
3193cb28812SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
3203cb28812SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
3213cb28812SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
3223cb28812SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
3233cb28812SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
3243cb28812SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
3253cb28812SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
3263cb28812SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
3273cb28812SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
3283cb28812SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
3293cb28812SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
3303cb28812SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
3313cb28812SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
3323cb28812SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
3333cb28812SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
3343cb28812SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
3353cb28812SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
3363cb28812SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
3373cb28812SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
3383cb28812SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
3393cb28812SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
3403cb28812SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
3413cb28812SJohnny Huang };
3423cb28812SJohnny Huang 
343b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = {
34491448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
34591448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
34691448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
34791448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
34891448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
34991448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
35091448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
35191448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
35291448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
35391448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
35491448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
35591448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
35691448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
35791448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
35891448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
35991448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
36091448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
361541eb887SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
36291448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
36391448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
36491448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
36591448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
36691448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
36791448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
36891448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
36991448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
37091448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
37191448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
37291448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
37391448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
37491448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
37591448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
37691448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
37791448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
37891448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
37991448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
38091448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
38191448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
38291448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
38391448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
38491448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
38591448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
38691448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
38791448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
3883cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
3893cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
3903cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
3913cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
3923cb28812SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
3933cb28812SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
3943cb28812SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
3953cb28812SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
3963cb28812SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
3973cb28812SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
3983cb28812SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
3993cb28812SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
4003cb28812SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
4013cb28812SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
4023cb28812SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
4033cb28812SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
4043cb28812SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
4053cb28812SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
4063cb28812SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
4073cb28812SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
4083cb28812SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
4093cb28812SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
4103cb28812SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
4113cb28812SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
4123cb28812SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
4133cb28812SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
4143cb28812SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
4153cb28812SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
4163cb28812SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
4173cb28812SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
4183cb28812SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
4193cb28812SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
4203cb28812SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
4213cb28812SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
4223cb28812SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
4233cb28812SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
4243cb28812SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
4253cb28812SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
4263cb28812SJohnny Huang };
4273cb28812SJohnny Huang 
4283cb28812SJohnny Huang struct otpconf_info a1_conf_info[] = {
4293cb28812SJohnny Huang 	{ 0, 0,  1,  OTP_REG_RESERVED, "" },
4303cb28812SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
4313cb28812SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
4323cb28812SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
4333cb28812SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
4343cb28812SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
4353cb28812SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
4363cb28812SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
4373cb28812SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
4383cb28812SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
4393cb28812SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
4403cb28812SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
4413cb28812SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
4423cb28812SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: GCM" },
4433cb28812SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
4443cb28812SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
4453cb28812SJohnny Huang 	{ 0, 8,  2,  1, "Differential mode" },
4463cb28812SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
4473cb28812SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
4483cb28812SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
4493cb28812SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
4503cb28812SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
4513cb28812SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
4523cb28812SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
4533cb28812SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
4543cb28812SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
4553cb28812SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
4563cb28812SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
4573cb28812SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
4583cb28812SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
4593cb28812SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
4603cb28812SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
4613cb28812SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
4623cb28812SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
4633cb28812SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
4643cb28812SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
4653cb28812SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
4663cb28812SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
4673cb28812SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
4683cb28812SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
4693cb28812SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
4703cb28812SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
4713cb28812SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
4723cb28812SJohnny Huang 	{ 0, 30, 1,  0, "Data region redundancy repair disable" },
4733cb28812SJohnny Huang 	{ 0, 30, 1,  1, "Data region redundancy repair enable" },
4743cb28812SJohnny Huang 	{ 0, 31, 1,  0, "OTP memory lock disable" },
4753cb28812SJohnny Huang 	{ 0, 31, 1,  1, "OTP memory lock enable" },
47691448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
47791448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
47891448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
47973f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
48073f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
48191448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
48291448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
48391448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
48491448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
48591448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
48691448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
48791448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
48891448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
48991448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
49091448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
49191448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
49291448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
49391448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
49491448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
49591448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
49691448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
49791448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
49891448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
49991448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
50091448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
50191448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
50291448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
50391448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
50491448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
50591448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
50691448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
50791448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
50891448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
50991448c03SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
510b458cd62SJohnny Huang };
5119a4fe690SJohnny Huang 
5129a4fe690SJohnny Huang struct otpkey_type a0_key_type[] = {
5139a4fe690SJohnny Huang 	{0, OTP_KEY_TYPE_AES,   0, "AES-256 as OEM platform key for image encryption/decryption"},
5149a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5159a4fe690SJohnny Huang 	{4, OTP_KEY_TYPE_HMAC,  1, "HMAC as encrypted OEM HMAC keys in Mode 1"},
5169a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5179a4fe690SJohnny Huang 	{9, OTP_KEY_TYPE_RSA,   0, "RSA-public as SOC public key"},
5189a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5199a4fe690SJohnny Huang 	{13, OTP_KEY_TYPE_RSA,  0, "RSA-private as SOC private key"},
5209a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5219a4fe690SJohnny Huang };
5229a4fe690SJohnny Huang 
5239a4fe690SJohnny Huang struct otpkey_type a1_key_type[] = {
5249a4fe690SJohnny Huang 	{1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"},
5259a4fe690SJohnny 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"},
5269a4fe690SJohnny Huang 	{8, OTP_KEY_TYPE_RSA,   1, "RSA-public as OEM DSS public keys in Mode 2"},
5279a4fe690SJohnny Huang 	{10, OTP_KEY_TYPE_RSA,  0, "RSA-public as AES key decryption key"},
5289a4fe690SJohnny Huang 	{14, OTP_KEY_TYPE_RSA,  0, "RSA-private as AES key decryption key"},
5299a4fe690SJohnny Huang };
5309a4fe690SJohnny Huang 
5319a4fe690SJohnny Huang static uint32_t chip_version(void)
5329a4fe690SJohnny Huang {
5339a4fe690SJohnny Huang 	uint32_t rev_id;
5349a4fe690SJohnny Huang 
5359a4fe690SJohnny Huang 	rev_id = (readl(0x1e6e2004) >> 16) & 0xff ;
5369a4fe690SJohnny Huang 
5379a4fe690SJohnny Huang 	return rev_id;
5389a4fe690SJohnny Huang }
5399a4fe690SJohnny Huang 
5402a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
54169d5fd8fSJohnny Huang {
54269d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
54369d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
54469d5fd8fSJohnny Huang 	udelay(2);
54569d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
54669d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
54769d5fd8fSJohnny Huang }
54869d5fd8fSJohnny Huang 
5492a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
55069d5fd8fSJohnny Huang {
55169d5fd8fSJohnny Huang 	int config_offset;
55269d5fd8fSJohnny Huang 
55369d5fd8fSJohnny Huang 	config_offset = 0x800;
55469d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
55569d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
55669d5fd8fSJohnny Huang 
55769d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
55869d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
55969d5fd8fSJohnny Huang 	udelay(2);
56069d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
56169d5fd8fSJohnny Huang }
56269d5fd8fSJohnny Huang 
56369d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
56469d5fd8fSJohnny Huang {
56569d5fd8fSJohnny Huang 	int i;
56669d5fd8fSJohnny Huang 	uint32_t ret[1];
56769d5fd8fSJohnny Huang 
56869d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
5692a856b9aSJohnny Huang 		return OTP_USAGE;
57069d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
57169d5fd8fSJohnny Huang 		otp_read_config(i, ret);
572a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
57369d5fd8fSJohnny Huang 	}
57469d5fd8fSJohnny Huang 	printf("\n");
5752a856b9aSJohnny Huang 	return OTP_SUCCESS;
57669d5fd8fSJohnny Huang }
57769d5fd8fSJohnny Huang 
57869d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
57969d5fd8fSJohnny Huang {
58069d5fd8fSJohnny Huang 	int i;
58169d5fd8fSJohnny Huang 	uint32_t ret[2];
58269d5fd8fSJohnny Huang 
58369d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
5842a856b9aSJohnny Huang 		return OTP_USAGE;
58569d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
58669d5fd8fSJohnny Huang 		otp_read_data(i, ret);
58769d5fd8fSJohnny Huang 		if (i % 4 == 0)
58869d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
58969d5fd8fSJohnny Huang 		else
59069d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
59169d5fd8fSJohnny Huang 
59269d5fd8fSJohnny Huang 	}
59369d5fd8fSJohnny Huang 	printf("\n");
5942a856b9aSJohnny Huang 	return OTP_SUCCESS;
59569d5fd8fSJohnny Huang }
59669d5fd8fSJohnny Huang 
59769d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
59869d5fd8fSJohnny Huang {
59969d5fd8fSJohnny Huang 	uint32_t ret;
60069d5fd8fSJohnny Huang 	uint32_t *buf;
60169d5fd8fSJohnny Huang 
60269d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
60369d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
60469d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
60569d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
60669d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
60769d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
60869d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
60969d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
61069d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
61169d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
61269d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
61369d5fd8fSJohnny Huang 	udelay(10);
61469d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
61569d5fd8fSJohnny Huang 	if (ret & 0x1)
61669d5fd8fSJohnny Huang 		return 0;
61769d5fd8fSJohnny Huang 	else
61869d5fd8fSJohnny Huang 		return -1;
61969d5fd8fSJohnny Huang }
62069d5fd8fSJohnny Huang 
62169d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
62269d5fd8fSJohnny Huang {
62369d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
62469d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
62569d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
62669d5fd8fSJohnny Huang 	udelay(100);
62769d5fd8fSJohnny Huang }
62869d5fd8fSJohnny Huang 
62969d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
63069d5fd8fSJohnny Huang {
63169d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
63269d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
63369d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
63469d5fd8fSJohnny Huang 	udelay(85);
63569d5fd8fSJohnny Huang }
63669d5fd8fSJohnny Huang 
637a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
63869d5fd8fSJohnny Huang {
63969d5fd8fSJohnny Huang 	int ret;
64069d5fd8fSJohnny Huang 
64169d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
64269d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
64369d5fd8fSJohnny Huang 	udelay(2);
64469d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
645a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
64669d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
64769d5fd8fSJohnny Huang 		return 0;
64869d5fd8fSJohnny Huang 	else
64969d5fd8fSJohnny Huang 		return -1;
65069d5fd8fSJohnny Huang }
65169d5fd8fSJohnny Huang 
652d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
6534c1c9b35SJohnny Huang {
6544c1c9b35SJohnny Huang 	uint32_t ret[2];
6554c1c9b35SJohnny Huang 
6564c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
6574c1c9b35SJohnny Huang 
6584c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
6594c1c9b35SJohnny Huang 		writel(otp_addr, 0x1e6f2010); //Read address
6604c1c9b35SJohnny Huang 	else
6614c1c9b35SJohnny Huang 		writel(otp_addr - 1, 0x1e6f2010); //Read address
6624c1c9b35SJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
6634c1c9b35SJohnny Huang 	udelay(2);
6644c1c9b35SJohnny Huang 	ret[0] = readl(0x1e6f2020);
6654c1c9b35SJohnny Huang 	ret[1] = readl(0x1e6f2024);
6664c1c9b35SJohnny Huang 	if (size == 1) {
6674c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
6684c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
669d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
6704c1c9b35SJohnny Huang 				compare[0] = 0;
6714c1c9b35SJohnny Huang 				return 0;
6724c1c9b35SJohnny Huang 			} else {
6734c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
6744c1c9b35SJohnny Huang 				return -1;
6754c1c9b35SJohnny Huang 			}
6764c1c9b35SJohnny Huang 
6774c1c9b35SJohnny Huang 		} else {
6784c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
679d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
6804c1c9b35SJohnny Huang 				compare[0] = ~0;
6814c1c9b35SJohnny Huang 				return 0;
6824c1c9b35SJohnny Huang 			} else {
683d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
6844c1c9b35SJohnny Huang 				return -1;
6854c1c9b35SJohnny Huang 			}
6864c1c9b35SJohnny Huang 		}
6874c1c9b35SJohnny Huang 	} else if (size == 2) {
6884c1c9b35SJohnny Huang 		// otp_addr should be even
689d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
6904c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
6914c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
6924c1c9b35SJohnny Huang 			compare[0] = 0;
6934c1c9b35SJohnny Huang 			compare[1] = ~0;
6944c1c9b35SJohnny Huang 			return 0;
6954c1c9b35SJohnny Huang 		} else {
6964c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
6974c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
6984c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
6994c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
7004c1c9b35SJohnny Huang 			return -1;
7014c1c9b35SJohnny Huang 		}
7024c1c9b35SJohnny Huang 	} else {
7034c1c9b35SJohnny Huang 		return -1;
7044c1c9b35SJohnny Huang 	}
7054c1c9b35SJohnny Huang }
7064c1c9b35SJohnny Huang 
7077e22f42dSJohnny Huang static void otp_soak(int soak)
708d90825e2SJohnny Huang {
709d90825e2SJohnny Huang 	if (soak) {
710d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
711d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
712d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
713d90825e2SJohnny Huang 		writel(0x041930d4, 0x1e602008); //soak program
714d90825e2SJohnny Huang 	} else {
715d90825e2SJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
716d90825e2SJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
717d90825e2SJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
718d90825e2SJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
719d90825e2SJohnny Huang 	}
720d90825e2SJohnny Huang }
721d90825e2SJohnny Huang 
722d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
723d90825e2SJohnny Huang {
724d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
725d90825e2SJohnny Huang 
726d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
727d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
728d90825e2SJohnny Huang 			continue;
729d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
730d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
731d90825e2SJohnny Huang 			if (bit_value)
732d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
733d90825e2SJohnny Huang 			else
734d90825e2SJohnny Huang 				continue;
735d90825e2SJohnny Huang 		} else {
736d90825e2SJohnny Huang 			prog_address |= 1 << 15;
737d90825e2SJohnny Huang 			if (bit_value)
738d90825e2SJohnny Huang 				continue;
739d90825e2SJohnny Huang 			else
740d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
741d90825e2SJohnny Huang 		}
742d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
743d90825e2SJohnny Huang 	}
744d90825e2SJohnny Huang }
745d90825e2SJohnny Huang 
74676d13988SJohnny Huang 
747541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap)
74876d13988SJohnny Huang {
74976d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
75076d13988SJohnny Huang 	int i, j;
75176d13988SJohnny Huang 
75276d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
75376d13988SJohnny Huang 		otpstrap[j].value = 0;
75476d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
75576d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
75676d13988SJohnny Huang 		otpstrap[j].protected = 0;
75776d13988SJohnny Huang 	}
75876d13988SJohnny Huang 
75976d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
76076d13988SJohnny Huang 		int option = (i - 16) / 2;
76176d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
76276d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
76376d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
76476d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
76576d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
76676d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
76776d13988SJohnny Huang 			}
76876d13988SJohnny Huang 			if (bit_value == 1)
76976d13988SJohnny Huang 				otpstrap[j].remain_times --;
77076d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
77176d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
77276d13988SJohnny Huang 		}
77376d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
77476d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
77576d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
77676d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
77776d13988SJohnny Huang 			}
77876d13988SJohnny Huang 			if (bit_value == 1)
77976d13988SJohnny Huang 				otpstrap[j].remain_times --;
78076d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
78176d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
78276d13988SJohnny Huang 		}
78376d13988SJohnny Huang 	}
78476d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
78576d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
78676d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
78776d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
78876d13988SJohnny Huang 			otpstrap[j].protected = 1;
78976d13988SJohnny Huang 	}
79076d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
79176d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
79276d13988SJohnny Huang 			otpstrap[j].protected = 1;
79376d13988SJohnny Huang 	}
79476d13988SJohnny Huang }
79576d13988SJohnny Huang 
796b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG)
79769d5fd8fSJohnny Huang {
7983cb28812SJohnny Huang 	struct otpconf_info *conf_info = info_cb.conf_info;
799442839bbSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[12];
800b458cd62SJohnny Huang 	uint32_t mask;
801b458cd62SJohnny Huang 	uint32_t dw_offset;
802b458cd62SJohnny Huang 	uint32_t bit_offset;
803b458cd62SJohnny Huang 	uint32_t otp_value;
804b458cd62SJohnny Huang 	uint32_t otp_keep;
805b458cd62SJohnny Huang 	int fail = 0;
80673f11549SJohnny Huang 	char valid_bit[20];
80766f2f8e5SJohnny Huang 	int i;
80873f11549SJohnny Huang 	int j;
80966f2f8e5SJohnny Huang 
810737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
81166f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
8123cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
8133cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
8143cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
8153cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
816b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
817b458cd62SJohnny Huang 		otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask;
818b458cd62SJohnny Huang 
819b458cd62SJohnny Huang 		if (otp_keep == mask) {
820b458cd62SJohnny Huang 			continue;
821b458cd62SJohnny Huang 		} else if (otp_keep != 0) {
822b458cd62SJohnny Huang 			fail = 1;
823b458cd62SJohnny Huang 		}
824b458cd62SJohnny Huang 
8253cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
8263cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
8273cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
8283cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
829b458cd62SJohnny Huang 			continue;
830b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
831b458cd62SJohnny Huang 
8323cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
8333cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
83466f2f8e5SJohnny Huang 		} else {
835b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
8363cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
8373cb28812SJohnny Huang 			       conf_info[i].bit_offset);
83866f2f8e5SJohnny Huang 		}
839b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
840b458cd62SJohnny Huang 
841b458cd62SJohnny Huang 		if (fail) {
842b458cd62SJohnny Huang 			printf("Keep mask error\n");
843b458cd62SJohnny Huang 		} else {
8443cb28812SJohnny Huang 			if (conf_info[i].value == OTP_REG_RESERVED) {
845b458cd62SJohnny Huang 				printf("Reserved\n");
8463cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALUE) {
8473cb28812SJohnny Huang 				printf(conf_info[i].information, otp_value);
848b458cd62SJohnny Huang 				printf("\n");
8493cb28812SJohnny Huang 			} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
850b458cd62SJohnny Huang 				if (otp_value != 0) {
85173f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
85273f11549SJohnny Huang 						if (otp_value == (1 << j)) {
85373f11549SJohnny Huang 							valid_bit[j * 2] = '1';
854b458cd62SJohnny Huang 						} else {
85573f11549SJohnny Huang 							valid_bit[j * 2] = '0';
85673f11549SJohnny Huang 						}
85773f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
85873f11549SJohnny Huang 					}
85973f11549SJohnny Huang 					valid_bit[15] = 0;
86073f11549SJohnny Huang 				} else {
86173f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
862b458cd62SJohnny Huang 				}
8633cb28812SJohnny Huang 				printf(conf_info[i].information, valid_bit);
864b458cd62SJohnny Huang 				printf("\n");
865b458cd62SJohnny Huang 			} else {
8663cb28812SJohnny Huang 				printf("%s\n", conf_info[i].information);
867b458cd62SJohnny Huang 			}
868b458cd62SJohnny Huang 		}
869b458cd62SJohnny Huang 	}
870b458cd62SJohnny Huang 
871b458cd62SJohnny Huang 	if (fail)
872b458cd62SJohnny Huang 		return OTP_FAILURE;
873b458cd62SJohnny Huang 
87466f2f8e5SJohnny Huang 	return OTP_SUCCESS;
87566f2f8e5SJohnny Huang }
87666f2f8e5SJohnny Huang 
8772d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
87866f2f8e5SJohnny Huang {
8793cb28812SJohnny Huang 	struct otpconf_info *conf_info = info_cb.conf_info;
880b458cd62SJohnny Huang 	uint32_t OTPCFG[12];
881b458cd62SJohnny Huang 	uint32_t mask;
882b458cd62SJohnny Huang 	uint32_t dw_offset;
883b458cd62SJohnny Huang 	uint32_t bit_offset;
884b458cd62SJohnny Huang 	uint32_t otp_value;
88573f11549SJohnny Huang 	char valid_bit[20];
88666f2f8e5SJohnny Huang 	int i;
88773f11549SJohnny Huang 	int j;
88866f2f8e5SJohnny Huang 
88966f2f8e5SJohnny Huang 	for (i = 0; i < 12; i++)
89066f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
89166f2f8e5SJohnny Huang 
89266f2f8e5SJohnny Huang 
893b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
894b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
8953cb28812SJohnny Huang 	for (i = 0; i < info_cb.conf_info_len; i++) {
8963cb28812SJohnny Huang 		if (input_offset != -1 && input_offset != conf_info[i].dw_offset)
8972d4b0742SJohnny Huang 			continue;
8983cb28812SJohnny Huang 		dw_offset = conf_info[i].dw_offset;
8993cb28812SJohnny Huang 		bit_offset = conf_info[i].bit_offset;
9003cb28812SJohnny Huang 		mask = BIT(conf_info[i].length) - 1;
901b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
902b458cd62SJohnny Huang 
9033cb28812SJohnny Huang 		if ((otp_value != conf_info[i].value) &&
9043cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_RESERVED &&
9053cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALUE &&
9063cb28812SJohnny Huang 		    conf_info[i].value != OTP_REG_VALID_BIT)
907b458cd62SJohnny Huang 			continue;
908b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
909b458cd62SJohnny Huang 
9103cb28812SJohnny Huang 		if (conf_info[i].length == 1) {
9113cb28812SJohnny Huang 			printf("0x%-9X", conf_info[i].bit_offset);
912b458cd62SJohnny Huang 		} else {
913b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9143cb28812SJohnny Huang 			       conf_info[i].bit_offset + conf_info[i].length - 1,
9153cb28812SJohnny Huang 			       conf_info[i].bit_offset);
916b458cd62SJohnny Huang 		}
917b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
918b458cd62SJohnny Huang 
9193cb28812SJohnny Huang 		if (conf_info[i].value == OTP_REG_RESERVED) {
920b458cd62SJohnny Huang 			printf("Reserved\n");
9213cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALUE) {
9223cb28812SJohnny Huang 			printf(conf_info[i].information, otp_value);
923b458cd62SJohnny Huang 			printf("\n");
9243cb28812SJohnny Huang 		} else if (conf_info[i].value == OTP_REG_VALID_BIT) {
925b458cd62SJohnny Huang 			if (otp_value != 0) {
92673f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
92773f11549SJohnny Huang 					if (otp_value == (1 << j)) {
92873f11549SJohnny Huang 						valid_bit[j * 2] = '1';
929b458cd62SJohnny Huang 					} else {
93073f11549SJohnny Huang 						valid_bit[j * 2] = '0';
93173f11549SJohnny Huang 					}
93273f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
93373f11549SJohnny Huang 				}
93473f11549SJohnny Huang 				valid_bit[15] = 0;
93573f11549SJohnny Huang 			} else {
93673f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
937b458cd62SJohnny Huang 			}
9383cb28812SJohnny Huang 			printf(conf_info[i].information, valid_bit);
939b458cd62SJohnny Huang 			printf("\n");
940b458cd62SJohnny Huang 		} else {
9413cb28812SJohnny Huang 			printf("%s\n", conf_info[i].information);
942b458cd62SJohnny Huang 		}
943b458cd62SJohnny Huang 	}
944b458cd62SJohnny Huang 	return OTP_SUCCESS;
94566f2f8e5SJohnny Huang }
94666f2f8e5SJohnny Huang 
947b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP)
94876d13988SJohnny Huang {
9493cb28812SJohnny Huang 	struct otpstrap_info *strap_info = info_cb.strap_info;
950a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
951a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
95276d13988SJohnny Huang 	int i;
953a8bd6d8cSJohnny Huang 	int fail = 0;
954a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
955a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
956a8bd6d8cSJohnny Huang 	uint32_t mask;
957a8bd6d8cSJohnny Huang 	uint32_t otp_value;
958a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
959a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
96076d13988SJohnny Huang 
961a8bd6d8cSJohnny Huang 	printf("BIT(hex)   Value       Protect     Description\n");
962a8bd6d8cSJohnny Huang 	printf("__________________________________________________________________________________________\n");
963b458cd62SJohnny Huang 
9643cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
9653cb28812SJohnny Huang 		if (strap_info[i].bit_offset > 32) {
966a8bd6d8cSJohnny Huang 			dw_offset = 1;
9673cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset - 32;
968a8bd6d8cSJohnny Huang 		} else {
969a8bd6d8cSJohnny Huang 			dw_offset = 0;
9703cb28812SJohnny Huang 			bit_offset = strap_info[i].bit_offset;
971a8bd6d8cSJohnny Huang 		}
97276d13988SJohnny Huang 
9733cb28812SJohnny Huang 		mask = BIT(strap_info[i].length) - 1;
974a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
975a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
976a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
977a8bd6d8cSJohnny Huang 
978a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
979a8bd6d8cSJohnny Huang 			continue;
980a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
981a8bd6d8cSJohnny Huang 			fail = 1;
982a8bd6d8cSJohnny Huang 		}
983a8bd6d8cSJohnny Huang 
9843cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
9853cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
986a8bd6d8cSJohnny Huang 			continue;
987a8bd6d8cSJohnny Huang 
9883cb28812SJohnny Huang 		if (strap_info[i].length == 1) {
9893cb28812SJohnny Huang 			printf("0x%-9X", strap_info[i].bit_offset);
990a8bd6d8cSJohnny Huang 		} else {
991b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
9923cb28812SJohnny Huang 			       strap_info[i].bit_offset + strap_info[i].length - 1,
9933cb28812SJohnny Huang 			       strap_info[i].bit_offset);
994a8bd6d8cSJohnny Huang 		}
995a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
996a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
997a8bd6d8cSJohnny Huang 
998a8bd6d8cSJohnny Huang 		if (fail) {
999a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
1000a8bd6d8cSJohnny Huang 		} else {
10013cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
10023cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1003a8bd6d8cSJohnny Huang 			else
1004a8bd6d8cSJohnny Huang 				printf("Reserved\n");
1005a8bd6d8cSJohnny Huang 		}
1006a8bd6d8cSJohnny Huang 	}
1007a8bd6d8cSJohnny Huang 
1008a8bd6d8cSJohnny Huang 	if (fail)
100976d13988SJohnny Huang 		return OTP_FAILURE;
101076d13988SJohnny Huang 
101176d13988SJohnny Huang 	return OTP_SUCCESS;
101276d13988SJohnny Huang }
101376d13988SJohnny Huang 
1014b458cd62SJohnny Huang static int otp_print_strap_info(int view)
101576d13988SJohnny Huang {
10163cb28812SJohnny Huang 	struct otpstrap_info *strap_info = info_cb.strap_info;
101776d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
101807baa4e8SJohnny Huang 	int i, j;
1019b458cd62SJohnny Huang 	int fail = 0;
1020b458cd62SJohnny Huang 	uint32_t bit_offset;
1021b458cd62SJohnny Huang 	uint32_t length;
1022b458cd62SJohnny Huang 	uint32_t otp_value;
1023b458cd62SJohnny Huang 	uint32_t otp_protect;
102476d13988SJohnny Huang 
1025541eb887SJohnny Huang 	otp_strap_status(strap_status);
102676d13988SJohnny Huang 
1027b458cd62SJohnny Huang 	if (view) {
102807baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
102907baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
103007baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
103107baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
1032b458cd62SJohnny Huang 	} else {
1033b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
1034b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
103576d13988SJohnny Huang 	}
10363cb28812SJohnny Huang 	for (i = 0; i < info_cb.strap_info_len; i++) {
1037b458cd62SJohnny Huang 		otp_value = 0;
10383cb28812SJohnny Huang 		bit_offset = strap_info[i].bit_offset;
10393cb28812SJohnny Huang 		length = strap_info[i].length;
1040b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
1041c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
1042c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
1043b458cd62SJohnny Huang 		}
10443cb28812SJohnny Huang 		if ((otp_value != strap_info[i].value) &&
10453cb28812SJohnny Huang 		    strap_info[i].value != OTP_REG_RESERVED)
1046b458cd62SJohnny Huang 			continue;
1047b458cd62SJohnny Huang 		if (view) {
1048b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
10493cb28812SJohnny Huang 				printf("0x%-7X", strap_info[i].bit_offset + j);
1050b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
105107baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
1052b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
10533cb28812SJohnny Huang 				if (strap_info[i].value == OTP_REG_RESERVED) {
1054b458cd62SJohnny Huang 					printf(" Reserved\n");
1055b458cd62SJohnny Huang 					continue;
1056b458cd62SJohnny Huang 				}
1057b458cd62SJohnny Huang 				if (length == 1) {
10583cb28812SJohnny Huang 					printf(" %s\n", strap_info[i].information);
1059b458cd62SJohnny Huang 					continue;
106076d13988SJohnny Huang 				}
106176d13988SJohnny Huang 
1062b458cd62SJohnny Huang 				if (j == 0)
10633cb28812SJohnny Huang 					printf("/%s\n", strap_info[i].information);
1064b458cd62SJohnny Huang 				else if (j == length - 1)
1065b458cd62SJohnny Huang 					printf("\\ \"\n");
1066b458cd62SJohnny Huang 				else
1067b458cd62SJohnny Huang 					printf("| \"\n");
106876d13988SJohnny Huang 			}
1069b458cd62SJohnny Huang 		} else {
1070c947ef08SJohnny Huang 			if (length == 1) {
10713cb28812SJohnny Huang 				printf("0x%-9X", strap_info[i].bit_offset);
1072b458cd62SJohnny Huang 			} else {
1073b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
1074b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
1075b458cd62SJohnny Huang 			}
1076b458cd62SJohnny Huang 
1077b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
1078b458cd62SJohnny Huang 
10793cb28812SJohnny Huang 			if (strap_info[i].value != OTP_REG_RESERVED)
10803cb28812SJohnny Huang 				printf("%s\n", strap_info[i].information);
1081b458cd62SJohnny Huang 			else
1082b458cd62SJohnny Huang 				printf("Reserved\n");
1083b458cd62SJohnny Huang 		}
1084b458cd62SJohnny Huang 	}
1085b458cd62SJohnny Huang 
1086b458cd62SJohnny Huang 	if (fail)
1087b458cd62SJohnny Huang 		return OTP_FAILURE;
1088b458cd62SJohnny Huang 
1089b458cd62SJohnny Huang 	return OTP_SUCCESS;
1090b458cd62SJohnny Huang }
1091b458cd62SJohnny Huang 
109269d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
109369d5fd8fSJohnny Huang {
109469d5fd8fSJohnny Huang 	int i;
109569d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
109669d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
109769d5fd8fSJohnny Huang 		if (i % 16 == 0) {
109869d5fd8fSJohnny Huang 			printf("%04X: ", i);
109969d5fd8fSJohnny Huang 		}
110069d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
110169d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
110269d5fd8fSJohnny Huang 			printf("\n");
110369d5fd8fSJohnny Huang 		}
110469d5fd8fSJohnny Huang 	}
110569d5fd8fSJohnny Huang }
110669d5fd8fSJohnny Huang 
11077f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
110869d5fd8fSJohnny Huang {
110969d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
11109a4fe690SJohnny Huang 	struct otpkey_type *key_info_array = info_cb.key_info;
11119a4fe690SJohnny Huang 	struct otpkey_type key_info;
111269d5fd8fSJohnny Huang 	char *byte_buf;
111369d5fd8fSJohnny Huang 	int i = 0, len = 0;
11149a4fe690SJohnny Huang 	int j;
111569d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
111669d5fd8fSJohnny Huang 	while (1) {
111769d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
111869d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
111969d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
112069d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
112169d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
112269d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
11239a4fe690SJohnny Huang 
11249a4fe690SJohnny Huang 		for (j = 0; j < info_cb.key_info_len; j++) {
11259a4fe690SJohnny Huang 			if (key_type == key_info_array[j].value) {
11269a4fe690SJohnny Huang 				key_info = key_info_array[j];
11279a4fe690SJohnny Huang 				break;
11289a4fe690SJohnny Huang 			}
11299a4fe690SJohnny Huang 		}
11309a4fe690SJohnny Huang 
11317f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
113269d5fd8fSJohnny Huang 		printf("Key Type: ");
11339a4fe690SJohnny Huang 		printf("%s\n", key_info.information);
11349a4fe690SJohnny Huang 
11359a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
113669d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
113769d5fd8fSJohnny Huang 			switch (key_length) {
113869d5fd8fSJohnny Huang 			case 0:
113969d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
114069d5fd8fSJohnny Huang 				break;
114169d5fd8fSJohnny Huang 			case 1:
114269d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
114369d5fd8fSJohnny Huang 				break;
114469d5fd8fSJohnny Huang 			case 2:
114569d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
114669d5fd8fSJohnny Huang 				break;
114769d5fd8fSJohnny Huang 			case 3:
114869d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
114969d5fd8fSJohnny Huang 				break;
115069d5fd8fSJohnny Huang 			}
11519a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
115269d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
115369d5fd8fSJohnny Huang 			switch (key_length) {
115469d5fd8fSJohnny Huang 			case 0:
115569d5fd8fSJohnny Huang 				printf("RSA1024\n");
115669d5fd8fSJohnny Huang 				len = 0x100;
115769d5fd8fSJohnny Huang 				break;
115869d5fd8fSJohnny Huang 			case 1:
115969d5fd8fSJohnny Huang 				printf("RSA2048\n");
116069d5fd8fSJohnny Huang 				len = 0x200;
116169d5fd8fSJohnny Huang 				break;
116269d5fd8fSJohnny Huang 			case 2:
116369d5fd8fSJohnny Huang 				printf("RSA3072\n");
116469d5fd8fSJohnny Huang 				len = 0x300;
116569d5fd8fSJohnny Huang 				break;
116669d5fd8fSJohnny Huang 			case 3:
116769d5fd8fSJohnny Huang 				printf("RSA4096\n");
116869d5fd8fSJohnny Huang 				len = 0x400;
116969d5fd8fSJohnny Huang 				break;
117069d5fd8fSJohnny Huang 			}
117169d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
117269d5fd8fSJohnny Huang 		}
11739a4fe690SJohnny Huang 		if (key_info.need_id)
117469d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
117569d5fd8fSJohnny Huang 		printf("Key Value:\n");
11769a4fe690SJohnny Huang 		if (key_info.key_type == OTP_KEY_TYPE_HMAC) {
117769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
11789a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_AES) {
11799a4fe690SJohnny Huang 			printf("AES Key:\n");
11809a4fe690SJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
11819a4fe690SJohnny Huang 			if (info_cb.version == 0) {
11829a4fe690SJohnny Huang 				printf("AES IV:\n");
11839a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
11849a4fe690SJohnny Huang 			}
11859a4fe690SJohnny Huang 
11869a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_VAULT) {
11879a4fe690SJohnny Huang 			if (info_cb.version == 0) {
118869d5fd8fSJohnny Huang 				printf("AES Key:\n");
118969d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
119069d5fd8fSJohnny Huang 				printf("AES IV:\n");
119169d5fd8fSJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x10);
11929a4fe690SJohnny Huang 			} else if (info_cb.version == 1) {
11939a4fe690SJohnny Huang 				printf("AES Key 1:\n");
11949a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset], 0x20);
11959a4fe690SJohnny Huang 				printf("AES Key 2:\n");
11969a4fe690SJohnny Huang 				buf_print(&byte_buf[key_offset + 0x20], 0x20);
11979a4fe690SJohnny Huang 			}
119869d5fd8fSJohnny Huang 
11999a4fe690SJohnny Huang 		} else if (key_info.key_type == OTP_KEY_TYPE_RSA) {
120069d5fd8fSJohnny Huang 			printf("RSA mod:\n");
120169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
120269d5fd8fSJohnny Huang 			printf("RSA exp:\n");
120369d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
120469d5fd8fSJohnny Huang 		}
120569d5fd8fSJohnny Huang 		if (last)
120669d5fd8fSJohnny Huang 			break;
120769d5fd8fSJohnny Huang 		i++;
120869d5fd8fSJohnny Huang 	}
120969d5fd8fSJohnny Huang 	return 0;
121069d5fd8fSJohnny Huang }
121169d5fd8fSJohnny Huang 
1212a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
121369d5fd8fSJohnny Huang {
1214a6d0d645SJohnny Huang 	int i, k;
1215d90825e2SJohnny Huang 	int pass = 0;
1216d90825e2SJohnny Huang 	int soak = 0;
1217a6d0d645SJohnny Huang 	uint32_t prog_address;
1218a6d0d645SJohnny Huang 	uint32_t data[12];
1219a6d0d645SJohnny Huang 	uint32_t compare[2];
1220d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[12];
1221d90825e2SJohnny Huang 	uint32_t data_masked;
1222d90825e2SJohnny Huang 	uint32_t buf_masked;
122369d5fd8fSJohnny Huang 
1224a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
1225a6d0d645SJohnny Huang 
1226a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1227a6d0d645SJohnny Huang 	for (i = 0; i < 12 ; i ++) {
1228a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "");
122969d5fd8fSJohnny Huang 		prog_address = 0x800;
1230a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1231a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1232a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
1233a6d0d645SJohnny Huang 	}
1234a6d0d645SJohnny Huang 
1235a6d0d645SJohnny Huang 	printf("Check writable...\n");
1236a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1237d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1238d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1239d90825e2SJohnny Huang 		if (data_masked == buf_masked)
124069d5fd8fSJohnny Huang 			continue;
1241d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
1242a6d0d645SJohnny Huang 			continue;
1243a6d0d645SJohnny Huang 		} else {
1244a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
1245a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
1246a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
1247a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
12482a856b9aSJohnny Huang 			return OTP_FAILURE;
1249a6d0d645SJohnny Huang 		}
1250a6d0d645SJohnny Huang 	}
1251a6d0d645SJohnny Huang 
1252a6d0d645SJohnny Huang 	printf("Start Programing...\n");
1253a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1254d90825e2SJohnny Huang 	otp_soak(0);
1255a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1256d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1257d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1258a6d0d645SJohnny Huang 		prog_address = 0x800;
1259a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1260a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1261d90825e2SJohnny Huang 		if (data_masked == buf_masked) {
1262a6d0d645SJohnny Huang 			printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]);
1263a6d0d645SJohnny Huang 			continue;
1264a6d0d645SJohnny Huang 		}
1265d90825e2SJohnny Huang 		if (soak) {
1266d90825e2SJohnny Huang 			soak = 0;
1267d90825e2SJohnny Huang 			otp_soak(0);
1268d90825e2SJohnny Huang 		}
1269a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "[%03X]=%08X    ", prog_address, buf[i]);
1270a6d0d645SJohnny Huang 
1271d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1272a6d0d645SJohnny Huang 
127369d5fd8fSJohnny Huang 		pass = 0;
127469d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1275d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1276d90825e2SJohnny Huang 				if (soak == 0) {
1277d90825e2SJohnny Huang 					soak = 1;
1278d90825e2SJohnny Huang 					otp_soak(1);
1279d90825e2SJohnny Huang 				}
1280a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1281a6d0d645SJohnny Huang 			} else {
128269d5fd8fSJohnny Huang 				pass = 1;
128369d5fd8fSJohnny Huang 				break;
128469d5fd8fSJohnny Huang 			}
128569d5fd8fSJohnny Huang 		}
1286a6d0d645SJohnny Huang 	}
1287a6d0d645SJohnny Huang 
128869d5fd8fSJohnny Huang 	if (!pass)
12892a856b9aSJohnny Huang 		return OTP_FAILURE;
1290a6d0d645SJohnny Huang 
12912a856b9aSJohnny Huang 	return OTP_SUCCESS;
1292d90825e2SJohnny Huang 
129369d5fd8fSJohnny Huang }
129469d5fd8fSJohnny Huang 
129569d5fd8fSJohnny Huang 
129676d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
129769d5fd8fSJohnny Huang {
129869d5fd8fSJohnny Huang 	int i;
129969d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
130069d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
130169d5fd8fSJohnny Huang 	int bit, pbit, kbit;
130269d5fd8fSJohnny Huang 	int fail = 0;
1303a6af4a17SJohnny Huang 	int skip = -1;
130466f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
130569d5fd8fSJohnny Huang 
1306541eb887SJohnny Huang 	otp_strap_status(otpstrap);
130769d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
130869d5fd8fSJohnny Huang 		if (i < 32) {
130969d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
131069d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
131169d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
131269d5fd8fSJohnny Huang 		} else {
131369d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
131469d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
131569d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
131669d5fd8fSJohnny Huang 		}
131769d5fd8fSJohnny Huang 
131869d5fd8fSJohnny Huang 		if (kbit == 1) {
131969d5fd8fSJohnny Huang 			continue;
132069d5fd8fSJohnny Huang 		} else {
1321a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
132269d5fd8fSJohnny Huang 		}
132369d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
132469d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1325a6af4a17SJohnny Huang 			if (skip == -1)
1326a6af4a17SJohnny Huang 				skip = 1;
132769d5fd8fSJohnny Huang 			continue;
1328a6af4a17SJohnny Huang 		} else {
1329a6af4a17SJohnny Huang 			skip = 0;
133069d5fd8fSJohnny Huang 		}
133169d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
133269d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
133369d5fd8fSJohnny Huang 			fail = 1;
133469d5fd8fSJohnny Huang 			continue;
133569d5fd8fSJohnny Huang 		}
133669d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1337a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
133869d5fd8fSJohnny Huang 			fail = 1;
133969d5fd8fSJohnny Huang 			continue;
134069d5fd8fSJohnny Huang 		}
134169d5fd8fSJohnny Huang 		if (pbit == 1) {
134269d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
134369d5fd8fSJohnny Huang 		}
1344a6af4a17SJohnny 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);
134569d5fd8fSJohnny Huang 	}
134669d5fd8fSJohnny Huang 	if (fail == 1)
1347a6af4a17SJohnny Huang 		return OTP_FAILURE;
1348a6af4a17SJohnny Huang 	else if (skip == 1)
1349a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
13507e22f42dSJohnny Huang 
13517e22f42dSJohnny Huang 	return 0;
135269d5fd8fSJohnny Huang }
135369d5fd8fSJohnny Huang 
13542a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
135569d5fd8fSJohnny Huang {
135669d5fd8fSJohnny Huang 	int i, j;
135766f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
135869d5fd8fSJohnny Huang 
13592a856b9aSJohnny Huang 	if (start < 0 || start > 64)
13602a856b9aSJohnny Huang 		return OTP_USAGE;
13612a856b9aSJohnny Huang 
13622a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
13632a856b9aSJohnny Huang 		return OTP_USAGE;
13642a856b9aSJohnny Huang 
1365541eb887SJohnny Huang 	otp_strap_status(otpstrap);
136669d5fd8fSJohnny Huang 
136707baa4e8SJohnny Huang 	printf("BIT(hex)  Value  Option           Status\n");
1368a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1369737ed20bSJohnny Huang 
1370cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
137107baa4e8SJohnny Huang 		printf("0x%-8X", i);
1372737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1373737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1374737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1375737ed20bSJohnny Huang 		printf("   ");
137669d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1377737ed20bSJohnny Huang 			printf("protected and not writable");
137869d5fd8fSJohnny Huang 		} else {
1379737ed20bSJohnny Huang 			printf("not protected ");
138069d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1381737ed20bSJohnny Huang 				printf("and no remaining times to write.");
138269d5fd8fSJohnny Huang 			} else {
1383737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
138469d5fd8fSJohnny Huang 			}
138569d5fd8fSJohnny Huang 		}
1386737ed20bSJohnny Huang 		printf("\n");
138769d5fd8fSJohnny Huang 	}
13882a856b9aSJohnny Huang 
13892a856b9aSJohnny Huang 	return OTP_SUCCESS;
139069d5fd8fSJohnny Huang }
139169d5fd8fSJohnny Huang 
139269d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
139369d5fd8fSJohnny Huang {
139469d5fd8fSJohnny Huang 	int i, j;
139569d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
139669d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
139769d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
139869d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
139969d5fd8fSJohnny Huang 	int fail = 0;
14007e22f42dSJohnny Huang 	int pass = 0;
14017e22f42dSJohnny Huang 	int soak = 0;
140266f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
140369d5fd8fSJohnny Huang 
14047f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
1405541eb887SJohnny Huang 	otp_strap_status(otpstrap);
140669d5fd8fSJohnny Huang 
14077f795e57SJohnny Huang 	printf("Check writable...\n");
14087f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
14097f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
14107f795e57SJohnny Huang 		return OTP_FAILURE;
14117f795e57SJohnny Huang 	}
14127e22f42dSJohnny Huang 
14137f795e57SJohnny Huang 	otp_soak(0);
141469d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
14154c1c9b35SJohnny Huang 		printProgress(i + 1, 64, "");
141669d5fd8fSJohnny Huang 		prog_address = 0x800;
141769d5fd8fSJohnny Huang 		if (i < 32) {
141869d5fd8fSJohnny Huang 			offset = i;
141969d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
142069d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
142169d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
142269d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
142369d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
142469d5fd8fSJohnny Huang 
142569d5fd8fSJohnny Huang 		} else {
142669d5fd8fSJohnny Huang 			offset = (i - 32);
142769d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
142869d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
142969d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
143069d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
143169d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
143269d5fd8fSJohnny Huang 		}
143369d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
143469d5fd8fSJohnny Huang 
143569d5fd8fSJohnny Huang 		if (kbit == 1) {
143669d5fd8fSJohnny Huang 			continue;
143769d5fd8fSJohnny Huang 		}
143869d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
143969d5fd8fSJohnny Huang 			continue;
144069d5fd8fSJohnny Huang 		}
144169d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
144269d5fd8fSJohnny Huang 			fail = 1;
144369d5fd8fSJohnny Huang 			continue;
144469d5fd8fSJohnny Huang 		}
144569d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
144669d5fd8fSJohnny Huang 			fail = 1;
144769d5fd8fSJohnny Huang 			continue;
144869d5fd8fSJohnny Huang 		}
14497e22f42dSJohnny Huang 
14507e22f42dSJohnny Huang 		if (soak) {
145169d5fd8fSJohnny Huang 			soak = 0;
14527e22f42dSJohnny Huang 			otp_soak(0);
14537e22f42dSJohnny Huang 		}
14547e22f42dSJohnny Huang 
14557e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
14567e22f42dSJohnny Huang 
14577e22f42dSJohnny Huang 		pass = 0;
14587e22f42dSJohnny Huang 
145969d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1460a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
146169d5fd8fSJohnny Huang 				pass = 1;
146269d5fd8fSJohnny Huang 				break;
146369d5fd8fSJohnny Huang 			}
14647e22f42dSJohnny Huang 			if (soak == 0) {
146569d5fd8fSJohnny Huang 				soak = 1;
14667e22f42dSJohnny Huang 				otp_soak(1);
14674b65a65dSJohnny Huang 			}
146869d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
146969d5fd8fSJohnny Huang 		}
147069d5fd8fSJohnny Huang 		if (!pass)
14712a856b9aSJohnny Huang 			return OTP_FAILURE;
147269d5fd8fSJohnny Huang 
147369d5fd8fSJohnny Huang 		if (pbit == 0)
147469d5fd8fSJohnny Huang 			continue;
147569d5fd8fSJohnny Huang 		prog_address = 0x800;
147669d5fd8fSJohnny Huang 		if (i < 32)
147769d5fd8fSJohnny Huang 			prog_address |= 0x60c;
147869d5fd8fSJohnny Huang 		else
147969d5fd8fSJohnny Huang 			prog_address |= 0x60e;
148069d5fd8fSJohnny Huang 
14817e22f42dSJohnny Huang 
14827e22f42dSJohnny Huang 		if (soak) {
14837e22f42dSJohnny Huang 			soak = 0;
14847e22f42dSJohnny Huang 			otp_soak(0);
14857e22f42dSJohnny Huang 		}
14867e22f42dSJohnny Huang 
14877e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
14887e22f42dSJohnny Huang 
14897e22f42dSJohnny Huang 		pass = 0;
14907e22f42dSJohnny Huang 
149169d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
14927e22f42dSJohnny Huang 
1493a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
149469d5fd8fSJohnny Huang 				pass = 1;
149569d5fd8fSJohnny Huang 				break;
149669d5fd8fSJohnny Huang 			}
14977e22f42dSJohnny Huang 			if (soak == 0) {
149869d5fd8fSJohnny Huang 				soak = 1;
14997e22f42dSJohnny Huang 				otp_soak(1);
150069d5fd8fSJohnny Huang 			}
150169d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
150269d5fd8fSJohnny Huang 		}
150369d5fd8fSJohnny Huang 		if (!pass)
15042a856b9aSJohnny Huang 			return OTP_FAILURE;
150569d5fd8fSJohnny Huang 
150669d5fd8fSJohnny Huang 	}
150769d5fd8fSJohnny Huang 	if (fail == 1)
15082a856b9aSJohnny Huang 		return OTP_FAILURE;
150969d5fd8fSJohnny Huang 	else
15102a856b9aSJohnny Huang 		return OTP_SUCCESS;
151169d5fd8fSJohnny Huang 
151269d5fd8fSJohnny Huang }
151369d5fd8fSJohnny Huang 
1514cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak)
1515cd1610b4SJohnny Huang {
1516cd1610b4SJohnny Huang 	int prog_bit;
1517cd1610b4SJohnny Huang 
15187e22f42dSJohnny Huang 	otp_soak(soak);
15197e22f42dSJohnny Huang 
1520cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1521cd1610b4SJohnny Huang 		if (value)
1522cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1523cd1610b4SJohnny Huang 		else
1524cd1610b4SJohnny Huang 			return;
1525cd1610b4SJohnny Huang 	} else {
1526cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1527cd1610b4SJohnny Huang 		if (!value)
1528cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1529cd1610b4SJohnny Huang 		else
1530cd1610b4SJohnny Huang 			return;
1531cd1610b4SJohnny Huang 	}
1532cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1533cd1610b4SJohnny Huang }
1534cd1610b4SJohnny Huang 
1535d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
15364c1c9b35SJohnny Huang {
15374c1c9b35SJohnny Huang 	int i, k;
15384c1c9b35SJohnny Huang 	int pass;
1539d90825e2SJohnny Huang 	int soak = 0;
15404c1c9b35SJohnny Huang 	uint32_t prog_address;
1541d90825e2SJohnny Huang 	uint32_t data[2048];
15424c1c9b35SJohnny Huang 	uint32_t compare[2];
1543d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
15444c1c9b35SJohnny Huang 
1545d90825e2SJohnny Huang 	uint32_t data0_masked;
1546d90825e2SJohnny Huang 	uint32_t data1_masked;
1547d90825e2SJohnny Huang 	uint32_t buf0_masked;
1548d90825e2SJohnny Huang 	uint32_t buf1_masked;
15494c1c9b35SJohnny Huang 
15504c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
15514c1c9b35SJohnny Huang 
1552d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1553d90825e2SJohnny Huang 	for (i = 0; i < 2048 ; i += 2) {
1554d90825e2SJohnny Huang 		printProgress(i + 2, 2048, "");
1555d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
15564c1c9b35SJohnny Huang 	}
1557d90825e2SJohnny Huang 
15584c1c9b35SJohnny Huang 
15594c1c9b35SJohnny Huang 	printf("Check writable...\n");
1560d90825e2SJohnny Huang 	for (i = 0; i < 2048; i++) {
1561d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1562d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1563d90825e2SJohnny Huang 		if (data0_masked == buf0_masked)
15644c1c9b35SJohnny Huang 			continue;
1565d90825e2SJohnny Huang 		if (i % 2 == 0) {
1566d90825e2SJohnny Huang 			if ((data0_masked | buf0_masked) == buf0_masked) {
15674c1c9b35SJohnny Huang 				continue;
15684c1c9b35SJohnny Huang 			} else {
15694c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1570d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
15714c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1572d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
15732a856b9aSJohnny Huang 				return OTP_FAILURE;
157469d5fd8fSJohnny Huang 			}
1575d90825e2SJohnny Huang 		} else {
1576d90825e2SJohnny Huang 			if ((data0_masked & buf0_masked) == buf0_masked) {
1577d90825e2SJohnny Huang 				continue;
1578d90825e2SJohnny Huang 			} else {
1579d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1580d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1581d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1582d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
15832a856b9aSJohnny Huang 				return OTP_FAILURE;
1584d90825e2SJohnny Huang 			}
1585d90825e2SJohnny Huang 		}
1586d90825e2SJohnny Huang 	}
158769d5fd8fSJohnny Huang 
1588d90825e2SJohnny Huang 	printf("Start Programing...\n");
1589d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1590d90825e2SJohnny Huang 
1591d90825e2SJohnny Huang 	for (i = 0; i < 2048; i += 2) {
1592d90825e2SJohnny Huang 		prog_address = i;
1593d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1594d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1595d90825e2SJohnny Huang 		data1_masked = data[i + 1]  & ~buf_keep[i + 1];
1596d90825e2SJohnny Huang 		buf1_masked  = buf[i + 1] & ~buf_keep[i + 1];
1597d90825e2SJohnny Huang 		if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) {
1598d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1599d90825e2SJohnny Huang 			continue;
1600d90825e2SJohnny Huang 		}
1601d90825e2SJohnny Huang 		if (soak) {
1602d90825e2SJohnny Huang 			soak = 0;
1603d90825e2SJohnny Huang 			otp_soak(0);
1604d90825e2SJohnny Huang 		}
1605d90825e2SJohnny Huang 		if (data1_masked == buf1_masked) {
1606d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1607d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1608d90825e2SJohnny Huang 		} else if (data0_masked == buf0_masked) {
1609d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1610d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1611d90825e2SJohnny Huang 		} else {
1612d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1613d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1614d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1615d90825e2SJohnny Huang 		}
1616d90825e2SJohnny Huang 
1617d90825e2SJohnny Huang 		pass = 0;
1618d90825e2SJohnny Huang 		for (k = 0; k < RETRY; k++) {
1619d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) {
1620d90825e2SJohnny Huang 				if (soak == 0) {
1621d90825e2SJohnny Huang 					soak = 1;
1622d90825e2SJohnny Huang 					otp_soak(1);
1623d90825e2SJohnny Huang 				}
1624d90825e2SJohnny Huang 				if (compare[0] != 0) {
1625d90825e2SJohnny Huang 					otp_prog_dw(compare[0], buf_keep[i], prog_address);
1626d90825e2SJohnny Huang 				}
1627d90825e2SJohnny Huang 				if (compare[1] != ~0) {
1628d90825e2SJohnny Huang 					otp_prog_dw(compare[1], buf_keep[i], prog_address + 1);
1629d90825e2SJohnny Huang 				}
1630d90825e2SJohnny Huang 			} else {
1631d90825e2SJohnny Huang 				pass = 1;
1632d90825e2SJohnny Huang 				break;
1633d90825e2SJohnny Huang 			}
1634d90825e2SJohnny Huang 		}
1635d90825e2SJohnny Huang 
1636d90825e2SJohnny Huang 		if (!pass)
16372a856b9aSJohnny Huang 			return OTP_FAILURE;
1638d90825e2SJohnny Huang 	}
16392a856b9aSJohnny Huang 	return OTP_SUCCESS;
1640d90825e2SJohnny Huang 
1641d90825e2SJohnny Huang }
1642d90825e2SJohnny Huang 
1643d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
164469d5fd8fSJohnny Huang {
164569d5fd8fSJohnny Huang 	int ret;
16467332532cSJohnny Huang 	int mode = 0;
16479a4fe690SJohnny Huang 	int image_version = 0;
164869d5fd8fSJohnny Huang 	uint32_t *buf;
1649d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1650d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1651d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
165269d5fd8fSJohnny Huang 
1653d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
165469d5fd8fSJohnny Huang 	if (!buf) {
165569d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
16562a856b9aSJohnny Huang 		return OTP_FAILURE;
165769d5fd8fSJohnny Huang 	}
1658d90825e2SJohnny Huang 
16599a4fe690SJohnny Huang 	image_version = buf[0] & 0x3;
16609a4fe690SJohnny Huang 	if (image_version != info_cb.version) {
16619a4fe690SJohnny Huang 		puts("Version is not match\n");
16629a4fe690SJohnny Huang 		return OTP_FAILURE;
16639a4fe690SJohnny Huang 	}
16649a4fe690SJohnny Huang 
1665d90825e2SJohnny Huang 	if (buf[0] & BIT(29)) {
16667332532cSJohnny Huang 		mode |= OTP_REGION_DATA;
16677332532cSJohnny Huang 		data_region = &buf[36];
1668d90825e2SJohnny Huang 	}
1669d90825e2SJohnny Huang 	if (buf[0] & BIT(30)) {
16707332532cSJohnny Huang 		mode |= OTP_REGION_CONF;
16717332532cSJohnny Huang 		conf_region = &buf[12];
1672d90825e2SJohnny Huang 	}
1673d90825e2SJohnny Huang 	if (buf[0] & BIT(31)) {
16747332532cSJohnny Huang 		mode |= OTP_REGION_STRAP;
16757332532cSJohnny Huang 		strap_region = &buf[4];
1676d90825e2SJohnny Huang 	}
16777332532cSJohnny Huang 
167869d5fd8fSJohnny Huang 	if (!nconfirm) {
16797332532cSJohnny Huang 		if (mode & OTP_REGION_DATA) {
16807f795e57SJohnny Huang 			printf("\nOTP data region :\n");
16817f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
168269d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
16832a856b9aSJohnny Huang 				return OTP_FAILURE;
168469d5fd8fSJohnny Huang 			}
168569d5fd8fSJohnny Huang 		}
16867332532cSJohnny Huang 		if (mode & OTP_REGION_STRAP) {
16877332532cSJohnny Huang 			printf("\nOTP strap region :\n");
16887332532cSJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
16897332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
16907332532cSJohnny Huang 				return OTP_FAILURE;
16917332532cSJohnny Huang 			}
16927332532cSJohnny Huang 		}
16937332532cSJohnny Huang 		if (mode & OTP_REGION_CONF) {
16947332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
16957332532cSJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
16967332532cSJohnny Huang 				printf("OTP config error, please check.\n");
16977332532cSJohnny Huang 				return OTP_FAILURE;
16987332532cSJohnny Huang 			}
16997332532cSJohnny Huang 		}
17007332532cSJohnny Huang 
170169d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
170269d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
170369d5fd8fSJohnny Huang 			printf(" Aborting\n");
17042a856b9aSJohnny Huang 			return OTP_FAILURE;
170569d5fd8fSJohnny Huang 		}
170669d5fd8fSJohnny Huang 	}
17077332532cSJohnny Huang 
17087332532cSJohnny Huang 	if (mode & OTP_REGION_DATA) {
17097332532cSJohnny Huang 		printf("programing data region ...\n");
1710d90825e2SJohnny Huang 		ret = otp_prog_data(data_region);
17112a856b9aSJohnny Huang 		if (ret != 0) {
171269d5fd8fSJohnny Huang 			printf("Error\n");
171369d5fd8fSJohnny Huang 			return ret;
171469d5fd8fSJohnny Huang 		} else {
171569d5fd8fSJohnny Huang 			printf("Done\n");
171669d5fd8fSJohnny Huang 		}
17177332532cSJohnny Huang 	}
17187332532cSJohnny Huang 	if (mode & OTP_REGION_STRAP) {
17197332532cSJohnny Huang 		printf("programing strap region ...\n");
1720d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
17212a856b9aSJohnny Huang 		if (ret != 0) {
172269d5fd8fSJohnny Huang 			printf("Error\n");
172369d5fd8fSJohnny Huang 			return ret;
172469d5fd8fSJohnny Huang 		} else {
172569d5fd8fSJohnny Huang 			printf("Done\n");
172669d5fd8fSJohnny Huang 		}
17277332532cSJohnny Huang 	}
17287332532cSJohnny Huang 	if (mode & OTP_REGION_CONF) {
17297332532cSJohnny Huang 		printf("programing configuration region ...\n");
1730d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
17312a856b9aSJohnny Huang 		if (ret != 0) {
173269d5fd8fSJohnny Huang 			printf("Error\n");
173369d5fd8fSJohnny Huang 			return ret;
173469d5fd8fSJohnny Huang 		}
173569d5fd8fSJohnny Huang 		printf("Done\n");
173669d5fd8fSJohnny Huang 	}
1737cd1610b4SJohnny Huang 
17387332532cSJohnny Huang 	return OTP_SUCCESS;
17392a856b9aSJohnny Huang }
17402a856b9aSJohnny Huang 
17412a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1742cd1610b4SJohnny Huang {
1743a6af4a17SJohnny Huang 	uint32_t read[2];
1744cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1745d90825e2SJohnny Huang 	uint32_t prog_address = 0;
174666f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1747cd1610b4SJohnny Huang 	int otp_bit;
1748cd1610b4SJohnny Huang 	int i;
1749cd1610b4SJohnny Huang 	int pass;
1750a6af4a17SJohnny Huang 	int ret;
1751cd1610b4SJohnny Huang 
1752cd1610b4SJohnny Huang 	switch (mode) {
1753a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1754a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1755cd1610b4SJohnny Huang 		prog_address = 0x800;
1756cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1757cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1758a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1759cd1610b4SJohnny Huang 		if (otp_bit == value) {
1760a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1761cd1610b4SJohnny Huang 			printf("No need to program\n");
17622a856b9aSJohnny Huang 			return OTP_SUCCESS;
1763cd1610b4SJohnny Huang 		}
1764cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1765a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1766cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
17672a856b9aSJohnny Huang 			return OTP_FAILURE;
1768cd1610b4SJohnny Huang 		}
1769a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1770cd1610b4SJohnny Huang 		break;
1771a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1772cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1773cd1610b4SJohnny Huang 
1774cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1775a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1776a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1777*643b9cfdSJohnny Huang 
1778*643b9cfdSJohnny Huang 			if (otp_bit == 1 && value == 0) {
1779*643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1780*643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be cleaned\n");
1781*643b9cfdSJohnny Huang 				return OTP_FAILURE;
1782*643b9cfdSJohnny Huang 			}
1783cd1610b4SJohnny Huang 		} else {
1784a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1785a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1786*643b9cfdSJohnny Huang 
1787*643b9cfdSJohnny Huang 			if (otp_bit == 0 && value == 1) {
1788*643b9cfdSJohnny Huang 				printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1789*643b9cfdSJohnny Huang 				printf("OTP is programed, which can't be writen\n");
1790*643b9cfdSJohnny Huang 				return OTP_FAILURE;
1791*643b9cfdSJohnny Huang 			}
1792cd1610b4SJohnny Huang 		}
1793cd1610b4SJohnny Huang 		if (otp_bit == value) {
1794a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1795cd1610b4SJohnny Huang 			printf("No need to program\n");
17962a856b9aSJohnny Huang 			return OTP_SUCCESS;
1797cd1610b4SJohnny Huang 		}
1798*643b9cfdSJohnny Huang 
1799a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1800cd1610b4SJohnny Huang 		break;
1801a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1802541eb887SJohnny Huang 		otp_strap_status(otpstrap);
1803cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1804cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1805cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
1806cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1807cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
1808cd1610b4SJohnny Huang 			strap_buf[5] = 0;
18092a856b9aSJohnny Huang 			// if (protect)
18102a856b9aSJohnny Huang 			// 	strap_buf[4] = BIT(bit_offset);
18112a856b9aSJohnny Huang 			// else
18122a856b9aSJohnny Huang 			// 	strap_buf[4] = 0;
1813cd1610b4SJohnny Huang 		} else {
1814cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1815cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1816cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1817cd1610b4SJohnny Huang 			strap_buf[4] = 0;
18182a856b9aSJohnny Huang 			// if (protect)
18192a856b9aSJohnny Huang 			// 	strap_buf[5] = BIT(bit_offset - 32);
18202a856b9aSJohnny Huang 			// else
18212a856b9aSJohnny Huang 			// 	strap_buf[5] = 0;
1822cd1610b4SJohnny Huang 		}
182376d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1824a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
18252a856b9aSJohnny Huang 			return OTP_FAILURE;
1826a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1827a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1828a6af4a17SJohnny Huang 
1829cd1610b4SJohnny Huang 		break;
1830cd1610b4SJohnny Huang 	}
1831cd1610b4SJohnny Huang 
1832cd1610b4SJohnny Huang 	if (!nconfirm) {
1833cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1834cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1835cd1610b4SJohnny Huang 			printf(" Aborting\n");
18362a856b9aSJohnny Huang 			return OTP_FAILURE;
1837cd1610b4SJohnny Huang 		}
1838cd1610b4SJohnny Huang 	}
1839cd1610b4SJohnny Huang 
1840cd1610b4SJohnny Huang 	switch (mode) {
1841a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1842cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
1843a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1844a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1845cd1610b4SJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset, 0);
1846cd1610b4SJohnny Huang 		pass = -1;
1847cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
1848a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
1849cd1610b4SJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset, 1);
1850cd1610b4SJohnny Huang 			} else {
1851cd1610b4SJohnny Huang 				pass = 0;
1852cd1610b4SJohnny Huang 				break;
1853cd1610b4SJohnny Huang 			}
1854cd1610b4SJohnny Huang 		}
18559009c25dSJohnny Huang 		if (pass == 0) {
18569009c25dSJohnny Huang 			printf("SUCCESS\n");
18572a856b9aSJohnny Huang 			return OTP_SUCCESS;
18589009c25dSJohnny Huang 		} else {
18599009c25dSJohnny Huang 			printf("OTP cannot be programed\n");
18609009c25dSJohnny Huang 			printf("FAILED\n");
18619009c25dSJohnny Huang 			return OTP_FAILURE;
18629009c25dSJohnny Huang 		}
1863cd1610b4SJohnny Huang 	}
1864cd1610b4SJohnny Huang 
18652a856b9aSJohnny Huang 	return OTP_USAGE;
1866cd1610b4SJohnny Huang }
1867cd1610b4SJohnny Huang 
18682a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
186969d5fd8fSJohnny Huang {
18702a856b9aSJohnny Huang 	uint32_t offset, count;
18712a856b9aSJohnny Huang 	int ret;
187269d5fd8fSJohnny Huang 
18732a856b9aSJohnny Huang 	if (argc == 4) {
18742a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
18752a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
18762a856b9aSJohnny Huang 	} else if (argc == 3) {
18772a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
18782a856b9aSJohnny Huang 		count = 1;
18792a856b9aSJohnny Huang 	} else {
188069d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
188169d5fd8fSJohnny Huang 	}
188269d5fd8fSJohnny Huang 
188369d5fd8fSJohnny Huang 
18842a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
188569d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18862a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
18872a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
18882a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18892a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
18902a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
18912a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
18922a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
18932a856b9aSJohnny Huang 	} else {
18942a856b9aSJohnny Huang 		return CMD_RET_USAGE;
189569d5fd8fSJohnny Huang 	}
189669d5fd8fSJohnny Huang 
18972a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
18982a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18992a856b9aSJohnny Huang 	else
19002a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19012a856b9aSJohnny Huang 
19022a856b9aSJohnny Huang }
19032a856b9aSJohnny Huang 
19042a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19052a856b9aSJohnny Huang {
19062a856b9aSJohnny Huang 	phys_addr_t addr;
19072a856b9aSJohnny Huang 	uint32_t byte_size;
19082a856b9aSJohnny Huang 	int ret;
19092a856b9aSJohnny Huang 
19102a856b9aSJohnny Huang 	if (argc == 4) {
19112a856b9aSJohnny Huang 		if (strcmp(argv[1], "f"))
19122a856b9aSJohnny Huang 			return CMD_RET_USAGE;
19132a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
19142a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
191569d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
19162a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
19172a856b9aSJohnny Huang 	} else if (argc == 3) {
19182a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
19192a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
19202a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
19212a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
19222a856b9aSJohnny Huang 	} else {
19232a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19242a856b9aSJohnny Huang 	}
19252a856b9aSJohnny Huang 
19262a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19272a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19282a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
19292a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19302a856b9aSJohnny Huang 	else
19312a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19322a856b9aSJohnny Huang }
19332a856b9aSJohnny Huang 
19342a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19352a856b9aSJohnny Huang {
19362a856b9aSJohnny Huang 	int mode = 0;
19372a856b9aSJohnny Huang 	int nconfirm = 0;
19382a856b9aSJohnny Huang 	int otp_addr = 0;
19392a856b9aSJohnny Huang 	int bit_offset;
19402a856b9aSJohnny Huang 	int value;
19412a856b9aSJohnny Huang 	int ret;
19422a856b9aSJohnny Huang 
19432a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
19442a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19452a856b9aSJohnny Huang 
19462a856b9aSJohnny Huang 	/* Drop the pb cmd */
19472a856b9aSJohnny Huang 	argc--;
19482a856b9aSJohnny Huang 	argv++;
19492a856b9aSJohnny Huang 
19502a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1951a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
19522a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1953a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
19542a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1955a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1956cd1610b4SJohnny Huang 	else
19572a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19582a856b9aSJohnny Huang 
19592a856b9aSJohnny Huang 	/* Drop the region cmd */
19602a856b9aSJohnny Huang 	argc--;
19612a856b9aSJohnny Huang 	argv++;
19622a856b9aSJohnny Huang 
19632a856b9aSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1964cd1610b4SJohnny Huang 		nconfirm = 1;
19652a856b9aSJohnny Huang 		/* Drop the force option */
19662a856b9aSJohnny Huang 		argc--;
19672a856b9aSJohnny Huang 		argv++;
19682a856b9aSJohnny Huang 	}
1969cd1610b4SJohnny Huang 
1970a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
19712a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
19722a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
1973cd1610b4SJohnny Huang 		if (bit_offset >= 64)
19742a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1975cd1610b4SJohnny Huang 	} else {
19762a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
19772a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
19782a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
1979cd1610b4SJohnny Huang 		if (bit_offset >= 32)
19802a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1981cd1610b4SJohnny Huang 	}
1982cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
19832a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1984cd1610b4SJohnny Huang 
1985cd1610b4SJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
19862a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
19872a856b9aSJohnny Huang 
19882a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
19892a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
19902a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
19912a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
19922a856b9aSJohnny Huang 	else
19932a856b9aSJohnny Huang 		return CMD_RET_USAGE;
19942a856b9aSJohnny Huang }
19952a856b9aSJohnny Huang 
19962a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
19972a856b9aSJohnny Huang {
19982a856b9aSJohnny Huang 	phys_addr_t addr;
19992a856b9aSJohnny Huang 	int otp_addr = 0;
20002a856b9aSJohnny Huang 
20012a856b9aSJohnny Huang 	if (argc != 3)
20022a856b9aSJohnny Huang 		return CMD_RET_USAGE;
20032a856b9aSJohnny Huang 
200469d5fd8fSJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
20052a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
20062a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
20072a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
200869d5fd8fSJohnny Huang 		printf("Compare pass\n");
20092a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
201069d5fd8fSJohnny Huang 	} else {
201169d5fd8fSJohnny Huang 		printf("Compare fail\n");
20122a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
201369d5fd8fSJohnny Huang 	}
201469d5fd8fSJohnny Huang }
201569d5fd8fSJohnny Huang 
201666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
201766f2f8e5SJohnny Huang {
2018a8bd6d8cSJohnny Huang 	int view = 0;
20192d4b0742SJohnny Huang 	int input;
2020a8bd6d8cSJohnny Huang 
2021a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
202266f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
202366f2f8e5SJohnny Huang 
20242d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
202566f2f8e5SJohnny Huang 
20262d4b0742SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
20272d4b0742SJohnny Huang 		if (argc == 3) {
20282d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
20292d4b0742SJohnny Huang 			otp_print_conf_info(input);
20302d4b0742SJohnny Huang 		} else {
20312d4b0742SJohnny Huang 			otp_print_conf_info(-1);
20322d4b0742SJohnny Huang 		}
20332d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
20342d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
2035a8bd6d8cSJohnny Huang 			view = 1;
2036a8bd6d8cSJohnny Huang 			/* Drop the view option */
2037a8bd6d8cSJohnny Huang 			argc--;
2038a8bd6d8cSJohnny Huang 			argv++;
2039a8bd6d8cSJohnny Huang 		}
204066f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
2041b458cd62SJohnny Huang 		otp_print_strap_info(view);
204266f2f8e5SJohnny Huang 	} else {
204366f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
204466f2f8e5SJohnny Huang 	}
20452d4b0742SJohnny Huang 
204666f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
204766f2f8e5SJohnny Huang }
204866f2f8e5SJohnny Huang 
2049737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2050737ed20bSJohnny Huang {
2051737ed20bSJohnny Huang 	int input;
2052737ed20bSJohnny Huang 	int bit_offset;
2053737ed20bSJohnny Huang 	int prog_address;
2054737ed20bSJohnny Huang 	int pass;
2055737ed20bSJohnny Huang 	int i;
2056737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
2057737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2058737ed20bSJohnny Huang 
2059737ed20bSJohnny Huang 	if (!strcmp(argv[0], "f")) {
2060737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
2061737ed20bSJohnny Huang 	} else {
2062737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
2063737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
2064737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
2065737ed20bSJohnny Huang 		if (!confirm_yesno()) {
2066737ed20bSJohnny Huang 			printf(" Aborting\n");
2067737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
2068737ed20bSJohnny Huang 		}
2069737ed20bSJohnny Huang 	}
2070737ed20bSJohnny Huang 
2071737ed20bSJohnny Huang 	prog_address = 0x800;
2072737ed20bSJohnny Huang 	if (input < 32) {
2073737ed20bSJohnny Huang 		bit_offset = input;
2074737ed20bSJohnny Huang 		prog_address |= 0x60c;
2075737ed20bSJohnny Huang 	} else if (input < 64) {
2076737ed20bSJohnny Huang 		bit_offset = input - 32;
2077737ed20bSJohnny Huang 		prog_address |= 0x60e;
2078737ed20bSJohnny Huang 	} else {
2079737ed20bSJohnny Huang 		return CMD_RET_USAGE;
2080737ed20bSJohnny Huang 	}
2081737ed20bSJohnny Huang 
2082737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
2083737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
2084737ed20bSJohnny Huang 	}
2085737ed20bSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset, 0);
2086737ed20bSJohnny Huang 	pass = -1;
2087737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
2088737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
2089737ed20bSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset, 1);
2090737ed20bSJohnny Huang 		} else {
2091737ed20bSJohnny Huang 			pass = 0;
2092737ed20bSJohnny Huang 			break;
2093737ed20bSJohnny Huang 		}
2094737ed20bSJohnny Huang 	}
2095737ed20bSJohnny Huang 	if (pass == 0) {
2096737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
2097737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
2098737ed20bSJohnny Huang 	}
2099737ed20bSJohnny Huang 
2100737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
2101737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
2102737ed20bSJohnny Huang 
2103737ed20bSJohnny Huang }
21049a4fe690SJohnny Huang 
21052a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
21062a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
2107a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
21082a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
21092a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
2110737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
21112a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
21122a856b9aSJohnny Huang };
21132a856b9aSJohnny Huang 
21142a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
21152a856b9aSJohnny Huang {
21162a856b9aSJohnny Huang 	cmd_tbl_t *cp;
21172a856b9aSJohnny Huang 
21182a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
21192a856b9aSJohnny Huang 
2120737ed20bSJohnny Huang 	/* Drop the otp command */
21212a856b9aSJohnny Huang 	argc--;
21222a856b9aSJohnny Huang 	argv++;
21232a856b9aSJohnny Huang 
21242a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
21252a856b9aSJohnny Huang 		return CMD_RET_USAGE;
21262a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
21272a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
21282a856b9aSJohnny Huang 
21299a4fe690SJohnny Huang 	if (chip_version() == 0) {
21309a4fe690SJohnny Huang 		info_cb.version = 0;
21319a4fe690SJohnny Huang 		info_cb.conf_info = a0_conf_info;
21329a4fe690SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info);
21339a4fe690SJohnny Huang 		info_cb.strap_info = a0_strap_info;
21349a4fe690SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info);
21359a4fe690SJohnny Huang 		info_cb.key_info = a0_key_type;
21369a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a0_key_type);
21379a4fe690SJohnny Huang 	} else if (chip_version() == 1) {
21389a4fe690SJohnny Huang 		info_cb.version = 1;
21393cb28812SJohnny Huang 		info_cb.conf_info = a1_conf_info;
21403cb28812SJohnny Huang 		info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info);
21413cb28812SJohnny Huang 		info_cb.strap_info = a1_strap_info;
21423cb28812SJohnny Huang 		info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info);
21439a4fe690SJohnny Huang 		info_cb.key_info = a1_key_type;
21449a4fe690SJohnny Huang 		info_cb.key_info_len = ARRAY_SIZE(a1_key_type);
21459a4fe690SJohnny Huang 	}
21469a4fe690SJohnny Huang 
21472a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
214869d5fd8fSJohnny Huang }
214969d5fd8fSJohnny Huang 
215069d5fd8fSJohnny Huang U_BOOT_CMD(
215169d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
215269d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
21532a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
21542a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
21552d4b0742SJohnny Huang 	"otp info strap [v]\n"
21562d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
2157d90825e2SJohnny Huang 	"otp prog [f] <addr> <byte_size>\n"
2158cd1610b4SJohnny Huang 	"otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n"
2159737ed20bSJohnny Huang 	"otp pb strap [f] <bit_offset> <value>\n"
2160737ed20bSJohnny Huang 	"otp protect [f] <bit_offset>\n"
21612a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
216269d5fd8fSJohnny Huang );
2163