xref: /openbmc/u-boot/cmd/otp.c (revision 73f1154949af800590468c439f49ad69aeec2269)
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 
38a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED		-1
39b458cd62SJohnny Huang #define OTP_REG_VALUE			-2
40b458cd62SJohnny Huang #define OTP_REG_VALID_BIT		-3
4176d13988SJohnny Huang 
424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
434c1c9b35SJohnny Huang #define PBWIDTH 60
444c1c9b35SJohnny Huang 
4566f2f8e5SJohnny Huang struct otpstrap_status {
4669d5fd8fSJohnny Huang 	int value;
4769d5fd8fSJohnny Huang 	int option_array[7];
4869d5fd8fSJohnny Huang 	int remain_times;
4969d5fd8fSJohnny Huang 	int writeable_option;
5069d5fd8fSJohnny Huang 	int protected;
5169d5fd8fSJohnny Huang };
5269d5fd8fSJohnny Huang 
5366f2f8e5SJohnny Huang struct otpconf_parse {
5466f2f8e5SJohnny Huang 	int dw_offset;
5566f2f8e5SJohnny Huang 	int bit;
5666f2f8e5SJohnny Huang 	int length;
5766f2f8e5SJohnny Huang 	int value;
5866f2f8e5SJohnny Huang 	int keep;
5966f2f8e5SJohnny Huang 	char status[80];
6066f2f8e5SJohnny Huang };
6166f2f8e5SJohnny Huang 
62a8bd6d8cSJohnny Huang struct otpstrap_info {
63a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
64a8bd6d8cSJohnny Huang 	uint32_t length;
6576d13988SJohnny Huang 	int value;
66a8bd6d8cSJohnny Huang 	char information[80];
67a8bd6d8cSJohnny Huang };
68a8bd6d8cSJohnny Huang 
69a8bd6d8cSJohnny Huang struct otpconf_info {
70a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
71a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
72a8bd6d8cSJohnny Huang 	uint32_t length;
73a8bd6d8cSJohnny Huang 	int value;
74a8bd6d8cSJohnny Huang 	char information[80];
75a8bd6d8cSJohnny Huang };
76a8bd6d8cSJohnny Huang 
77a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...)
78a8bd6d8cSJohnny Huang {
79a8bd6d8cSJohnny Huang 	int val = numerator * 100 / denominator;
80a8bd6d8cSJohnny Huang 	int lpad = numerator * PBWIDTH / denominator;
81a8bd6d8cSJohnny Huang 	int rpad = PBWIDTH - lpad;
82a8bd6d8cSJohnny Huang 	char buffer[256];
83a8bd6d8cSJohnny Huang 	va_list aptr;
84a8bd6d8cSJohnny Huang 
85a8bd6d8cSJohnny Huang 	va_start(aptr, format);
86a8bd6d8cSJohnny Huang 	vsprintf(buffer, format, aptr);
87a8bd6d8cSJohnny Huang 	va_end(aptr);
88a8bd6d8cSJohnny Huang 
89a8bd6d8cSJohnny Huang 	printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer);
90a8bd6d8cSJohnny Huang 	if (numerator == denominator)
91a8bd6d8cSJohnny Huang 		printf("\n");
92a8bd6d8cSJohnny Huang }
93a8bd6d8cSJohnny Huang 
94a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = {
9591448c03SJohnny Huang 	{ 0, 1, 0, "Disable secure boot" },
9691448c03SJohnny Huang 	{ 0, 1, 1, "Enable secure boot"	},
9791448c03SJohnny Huang 	{ 1, 1, 0, "Disable boot from eMMC" },
9891448c03SJohnny Huang 	{ 1, 1, 1, "Enable boot from eMMC" },
9991448c03SJohnny Huang 	{ 2, 1, 0, "Disable Boot from debug SPI" },
10091448c03SJohnny Huang 	{ 2, 1, 1, "Enable Boot from debug SPI" },
10191448c03SJohnny Huang 	{ 3, 1, 0, "Enable ARM CM3" },
10291448c03SJohnny Huang 	{ 3, 1, 1, "Disable ARM CM3" },
10391448c03SJohnny Huang 	{ 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" },
10491448c03SJohnny Huang 	{ 4, 1, 1, "Enable dedicated VGA BIOS ROM" },
10591448c03SJohnny Huang 	{ 5, 1, 0, "MAC 1 : RMII/NCSI" },
10691448c03SJohnny Huang 	{ 5, 1, 1, "MAC 1 : RGMII" },
10791448c03SJohnny Huang 	{ 6, 1, 0, "MAC 2 : RMII/NCSI" },
10891448c03SJohnny Huang 	{ 6, 1, 1, "MAC 2 : RGMII" },
10991448c03SJohnny Huang 	{ 7, 3, 0, "CPU Frequency : 1GHz" },
11091448c03SJohnny Huang 	{ 7, 3, 1, "CPU Frequency : 800MHz" },
11191448c03SJohnny Huang 	{ 7, 3, 2, "CPU Frequency : 1.2GHz" },
11291448c03SJohnny Huang 	{ 7, 3, 3, "CPU Frequency : 1.4GHz" },
11391448c03SJohnny Huang 	{ 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" },
11491448c03SJohnny Huang 	{ 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" },
11591448c03SJohnny Huang 	{ 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" },
11691448c03SJohnny Huang 	{ 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" },
11791448c03SJohnny Huang 	{ 12, 2, 0, "VGA memory size : 8MB" },
11891448c03SJohnny Huang 	{ 12, 2, 1, "VGA memory size : 16MB" },
11991448c03SJohnny Huang 	{ 12, 2, 2, "VGA memory size : 32MB" },
12091448c03SJohnny Huang 	{ 12, 2, 3, "VGA memory size : 64MB" },
12191448c03SJohnny Huang 	{ 14, 3, OTP_REG_RESERVED, "" },
12291448c03SJohnny Huang 	{ 17, 1, 0, "VGA class code : Class Code for video device" },
12391448c03SJohnny Huang 	{ 17, 1, 1, "VGA class code : Class Code for VGA device" },
12491448c03SJohnny Huang 	{ 18, 1, 0, "Enable debug interfaces 0" },
12591448c03SJohnny Huang 	{ 18, 1, 1, "Disable debug interfaces 0" },
12691448c03SJohnny Huang 	{ 19, 1, 0, "Boot from emmc mode : High eMMC speed" },
12791448c03SJohnny Huang 	{ 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" },
12891448c03SJohnny Huang 	{ 20, 1, 0, "Enable Pcie EHCI device" },
12991448c03SJohnny Huang 	{ 20, 1, 1, "Disable Pcie EHCI device" },
13091448c03SJohnny Huang 	{ 21, 1, 0, "Enable VGA XDMA function" },
13191448c03SJohnny Huang 	{ 21, 1, 1, "Disable VGA XDMA function" },
13291448c03SJohnny Huang 	{ 22, 1, 0, "Normal BMC mode" },
13391448c03SJohnny Huang 	{ 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" },
13491448c03SJohnny Huang 	{ 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" },
13591448c03SJohnny Huang 	{ 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" },
13691448c03SJohnny Huang 	{ 24, 1, 0, "DRAM types : DDR4" },
13791448c03SJohnny Huang 	{ 24, 1, 1, "DRAM types : DDR3" },
13891448c03SJohnny Huang 	{ 25, 5, OTP_REG_RESERVED, "" },
13991448c03SJohnny Huang 	{ 30, 2, OTP_REG_RESERVED, "" },
14091448c03SJohnny Huang 	{ 32, 1, 0, "MAC 3 : RMII/NCSI" },
14191448c03SJohnny Huang 	{ 32, 1, 1, "MAC 3 : RGMII" },
14291448c03SJohnny Huang 	{ 33, 1, 0, "MAC 4 : RMII/NCSI" },
14391448c03SJohnny Huang 	{ 33, 1, 1, "MAC 4 : RGMII" },
14491448c03SJohnny Huang 	{ 34, 1, 0, "SuperIO configuration address : 0x2E" },
14591448c03SJohnny Huang 	{ 34, 1, 1, "SuperIO configuration address : 0x4E" },
14691448c03SJohnny Huang 	{ 35, 1, 0, "Enable LPC to decode SuperIO" },
14791448c03SJohnny Huang 	{ 35, 1, 1, "Disable LPC to decode SuperIO" },
14891448c03SJohnny Huang 	{ 36, 1, 0, "Enable debug interfaces 1" },
14991448c03SJohnny Huang 	{ 36, 1, 1, "Disable debug interfaces 1" },
15091448c03SJohnny Huang 	{ 37, 1, 0, "Disable ACPI function" },
15191448c03SJohnny Huang 	{ 37, 1, 1, "Enable ACPI function" },
15291448c03SJohnny Huang 	{ 38, 1, 0, "Enable eSPI mode" },
15391448c03SJohnny Huang 	{ 38, 1, 1, "Enable LPC mode" },
15491448c03SJohnny Huang 	{ 39, 1, 0, "Enable SAFS mode" },
15591448c03SJohnny Huang 	{ 39, 1, 1, "Enable SAFS mode" },
15691448c03SJohnny Huang 	{ 40, 2, OTP_REG_RESERVED, "" },
15791448c03SJohnny Huang 	{ 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" },
15891448c03SJohnny Huang 	{ 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" },
15991448c03SJohnny Huang 	{ 43, 1, 0, "Disable boot SPI ABR" },
16091448c03SJohnny Huang 	{ 43, 1, 1, "Enable boot SPI ABR" },
16191448c03SJohnny Huang 	{ 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" },
16291448c03SJohnny Huang 	{ 44, 1, 1, "Boot SPI ABR mode : single SPI flash" },
16391448c03SJohnny Huang 	{ 45, 3, 0, "Boot SPI flash size : no define size" },
16491448c03SJohnny Huang 	{ 45, 3, 1, "Boot SPI flash size : 2MB" },
16591448c03SJohnny Huang 	{ 45, 3, 2, "Boot SPI flash size : 4MB" },
16691448c03SJohnny Huang 	{ 45, 3, 3, "Boot SPI flash size : 8MB" },
16791448c03SJohnny Huang 	{ 45, 3, 4, "Boot SPI flash size : 16MB" },
16891448c03SJohnny Huang 	{ 45, 3, 5, "Boot SPI flash size : 32MB" },
16991448c03SJohnny Huang 	{ 45, 3, 6, "Boot SPI flash size : 64MB" },
17091448c03SJohnny Huang 	{ 45, 3, 7, "Boot SPI flash size : 128MB" },
17191448c03SJohnny Huang 	{ 48, 1, 0, "Disable host SPI ABR" },
17291448c03SJohnny Huang 	{ 48, 1, 1, "Enable host SPI ABR" },
17391448c03SJohnny Huang 	{ 49, 1, 0, "Disable host SPI ABR mode select pin" },
17491448c03SJohnny Huang 	{ 49, 1, 1, "Enable host SPI ABR mode select pin" },
17591448c03SJohnny Huang 	{ 50, 1, 0, "Host SPI ABR mode : dual SPI flash" },
17691448c03SJohnny Huang 	{ 50, 1, 1, "Host SPI ABR mode : single SPI flash" },
17791448c03SJohnny Huang 	{ 51, 3, 0, "Host SPI flash size : no define size" },
17891448c03SJohnny Huang 	{ 51, 3, 1, "Host SPI flash size : 2MB" },
17991448c03SJohnny Huang 	{ 51, 3, 2, "Host SPI flash size : 4MB" },
18091448c03SJohnny Huang 	{ 51, 3, 3, "Host SPI flash size : 8MB" },
18191448c03SJohnny Huang 	{ 51, 3, 4, "Host SPI flash size : 16MB" },
18291448c03SJohnny Huang 	{ 51, 3, 5, "Host SPI flash size : 32MB" },
18391448c03SJohnny Huang 	{ 51, 3, 6, "Host SPI flash size : 64MB" },
18491448c03SJohnny Huang 	{ 51, 3, 7, "Host SPI flash size : 128MB" },
18591448c03SJohnny Huang 	{ 54, 1, 0, "Disable boot SPI auxiliary control pins" },
18691448c03SJohnny Huang 	{ 54, 1, 1, "Enable boot SPI auxiliary control pins" },
18791448c03SJohnny Huang 	{ 55, 2, 0, "Boot SPI CRTM size : disable CRTM" },
18891448c03SJohnny Huang 	{ 55, 2, 1, "Boot SPI CRTM size : 256KB" },
18991448c03SJohnny Huang 	{ 55, 2, 2, "Boot SPI CRTM size : 512KB" },
19091448c03SJohnny Huang 	{ 55, 2, 3, "Boot SPI CRTM size : 1MB" },
19191448c03SJohnny Huang 	{ 57, 2, 0, "Host SPI CRTM size : disable CRTM" },
19291448c03SJohnny Huang 	{ 57, 2, 1, "Host SPI CRTM size : 256KB" },
19391448c03SJohnny Huang 	{ 57, 2, 2, "Host SPI CRTM size : 512KB" },
19491448c03SJohnny Huang 	{ 57, 2, 3, "Host SPI CRTM size : 1MB" },
19591448c03SJohnny Huang 	{ 59, 1, 0, "Disable host SPI auxiliary control pins" },
19691448c03SJohnny Huang 	{ 59, 1, 1, "Enable host SPI auxiliary control pins" },
19791448c03SJohnny Huang 	{ 60, 1, 0, "Disable GPIO pass through" },
19891448c03SJohnny Huang 	{ 60, 1, 1, "Enable GPIO pass through" },
19991448c03SJohnny Huang 	{ 61, 1, 0, "Enable low security secure boot key" },
20091448c03SJohnny Huang 	{ 61, 1, 1, "Disable low security secure boot key" },
20191448c03SJohnny Huang 	{ 62, 1, 0, "Disable dedicate GPIO strap pins" },
20291448c03SJohnny Huang 	{ 62, 1, 1, "Enable dedicate GPIO strap pins" },
20391448c03SJohnny Huang 	{ 63, 1, OTP_REG_RESERVED, "" }
20476d13988SJohnny Huang };
205b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = {
20691448c03SJohnny Huang 	{ 0, 0,  1,  0, "Enable Secure Region programming" },
20791448c03SJohnny Huang 	{ 0, 0,  1,  1, "Disable Secure Region programming" },
20891448c03SJohnny Huang 	{ 0, 1,  1,  0, "Disable Secure Boot" },
20991448c03SJohnny Huang 	{ 0, 1,  1,  1, "Enable Secure Boot" },
21091448c03SJohnny Huang 	{ 0, 2,  1,  0, "Initialization programming not done" },
21191448c03SJohnny Huang 	{ 0, 2,  1,  1, "Initialization programming done" },
21291448c03SJohnny Huang 	{ 0, 3,  1,  0, "User region ECC disable" },
21391448c03SJohnny Huang 	{ 0, 3,  1,  1, "User region ECC enable" },
21491448c03SJohnny Huang 	{ 0, 4,  1,  0, "Secure Region ECC disable" },
21591448c03SJohnny Huang 	{ 0, 4,  1,  1, "Secure Region ECC enable" },
21691448c03SJohnny Huang 	{ 0, 5,  1,  0, "Enable low security key" },
21791448c03SJohnny Huang 	{ 0, 5,  1,  1, "Disable low security key" },
21891448c03SJohnny Huang 	{ 0, 6,  1,  0, "Do not ignore Secure Boot hardware strap" },
21991448c03SJohnny Huang 	{ 0, 6,  1,  1, "Ignore Secure Boot hardware strap" },
22091448c03SJohnny Huang 	{ 0, 7,  1,  0, "Secure Boot Mode: 1" },
22191448c03SJohnny Huang 	{ 0, 7,  1,  1, "Secure Boot Mode: 2" },
22291448c03SJohnny Huang 	{ 0, 8,  2,  0, "Single cell mode (recommended)" },
22391448c03SJohnny Huang 	{ 0, 8,  2,  1, "Differnetial mode" },
22491448c03SJohnny Huang 	{ 0, 8,  2,  2, "Differential-redundant mode" },
22591448c03SJohnny Huang 	{ 0, 10, 2,  0, "RSA mode : RSA1024" },
22691448c03SJohnny Huang 	{ 0, 10, 2,  1, "RSA mode : RSA2048" },
22791448c03SJohnny Huang 	{ 0, 10, 2,  2, "RSA mode : RSA3072" },
22891448c03SJohnny Huang 	{ 0, 10, 2,  3, "RSA mode : RSA4096" },
22991448c03SJohnny Huang 	{ 0, 12, 2,  0, "SHA mode : SHA224" },
23091448c03SJohnny Huang 	{ 0, 12, 2,  1, "SHA mode : SHA256" },
23191448c03SJohnny Huang 	{ 0, 12, 2,  2, "SHA mode : SHA384" },
23291448c03SJohnny Huang 	{ 0, 12, 2,  3, "SHA mode : SHA512" },
23391448c03SJohnny Huang 	{ 0, 14, 2,  OTP_REG_RESERVED, "" },
23491448c03SJohnny Huang 	{ 0, 16, 6,  OTP_REG_VALUE, "Secure Region size (DW): 0x%x" },
23591448c03SJohnny Huang 	{ 0, 22, 1,  0, "Secure Region : Writable" },
23691448c03SJohnny Huang 	{ 0, 22, 1,  1, "Secure Region : Write Protect" },
23791448c03SJohnny Huang 	{ 0, 23, 1,  0, "User Region : Writable" },
23891448c03SJohnny Huang 	{ 0, 23, 1,  1, "User Region : Write Protect" },
23991448c03SJohnny Huang 	{ 0, 24, 1,  0, "Configure Region : Writable" },
24091448c03SJohnny Huang 	{ 0, 24, 1,  1, "Configure Region : Write Protect" },
24191448c03SJohnny Huang 	{ 0, 25, 1,  0, "OTP strap Region : Writable" },
24291448c03SJohnny Huang 	{ 0, 25, 1,  1, "OTP strap Region : Write Protect" },
24391448c03SJohnny Huang 	{ 0, 26, 1,  0, "Disable Copy Boot Image to Internal SRAM" },
24491448c03SJohnny Huang 	{ 0, 26, 1,  1, "Copy Boot Image to Internal SRAM" },
24591448c03SJohnny Huang 	{ 0, 27, 1,  0, "Disable image encryption" },
24691448c03SJohnny Huang 	{ 0, 27, 1,  1, "Enable image encryption" },
24791448c03SJohnny Huang 	{ 0, 28, 1,  OTP_REG_RESERVED, "" },
24891448c03SJohnny Huang 	{ 0, 29, 1,  0, "OTP key retire Region : Writable" },
24991448c03SJohnny Huang 	{ 0, 29, 1,  1, "OTP key retire Region : Write Protect" },
25091448c03SJohnny Huang 	{ 0, 30, 1,  0, "SIPROM RED_EN redundancy repair disable" },
25191448c03SJohnny Huang 	{ 0, 30, 1,  1, "SIPROM RED_EN redundancy repair enable" },
25291448c03SJohnny Huang 	{ 0, 31, 1,  0, "SIPROM Mlock memory lock disable" },
25391448c03SJohnny Huang 	{ 0, 31, 1,  1, "SIPROM Mlock memory lock enable" },
25491448c03SJohnny Huang 	{ 2, 0,  16, OTP_REG_VALUE, "Vender ID : 0x%x" },
25591448c03SJohnny Huang 	{ 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" },
25691448c03SJohnny Huang 	{ 3, 0,  16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" },
257*73f11549SJohnny Huang 	{ 4, 0,  8,  OTP_REG_VALID_BIT, "Keys valid  : %s" },
258*73f11549SJohnny Huang 	{ 4, 16, 8,  OTP_REG_VALID_BIT, "Keys retire  : %s" },
25991448c03SJohnny Huang 	{ 5, 0,  32, OTP_REG_VALUE, "User define data, random number low : 0x%x" },
26091448c03SJohnny Huang 	{ 6, 0,  32, OTP_REG_VALUE, "User define data, random number high : 0x%x" },
26191448c03SJohnny Huang 	{ 7, 0,  1,  0, "Force enable PCI bus to AHB bus bridge" },
26291448c03SJohnny Huang 	{ 7, 0,  1,  1, "Force disable PCI bus to AHB bus bridge" },
26391448c03SJohnny Huang 	{ 7, 1,  1,  0, "Force enable UART5 debug port function" },
26491448c03SJohnny Huang 	{ 7, 1,  1,  1, "Force disable UART5 debug port function" },
26591448c03SJohnny Huang 	{ 7, 2,  1,  0, "Force enable XDMA function" },
26691448c03SJohnny Huang 	{ 7, 2,  1,  1, "Force disable XDMA function" },
26791448c03SJohnny Huang 	{ 7, 3,  1,  0, "Force enable APB to PCIE device bridge" },
26891448c03SJohnny Huang 	{ 7, 3,  1,  1, "Force disable APB to PCIE device bridge" },
26991448c03SJohnny Huang 	{ 7, 4,  1,  0, "Force enable APB to PCIE bridge config access" },
27091448c03SJohnny Huang 	{ 7, 4,  1,  1, "Force disable APB to PCIE bridge config access" },
27191448c03SJohnny Huang 	{ 7, 5,  1,  0, "Force enable PCIE bus trace buffer" },
27291448c03SJohnny Huang 	{ 7, 5,  1,  1, "Force disable PCIE bus trace buffer" },
27391448c03SJohnny Huang 	{ 7, 6,  1,  0, "Force enable the capability for PCIE device port as a Root Complex" },
27491448c03SJohnny Huang 	{ 7, 6,  1,  1, "Force disable the capability for PCIE device port as a Root Complex" },
27591448c03SJohnny Huang 	{ 7, 16, 1,  0, "Force enable ESPI bus to AHB bus bridge" },
27691448c03SJohnny Huang 	{ 7, 16, 1,  1, "Force disable ESPI bus to AHB bus bridge" },
27791448c03SJohnny Huang 	{ 7, 17, 1,  0, "Force enable LPC bus to AHB bus bridge1" },
27891448c03SJohnny Huang 	{ 7, 17, 1,  1, "Force disable LPC bus to AHB bus bridge1" },
27991448c03SJohnny Huang 	{ 7, 18, 1,  0, "Force enable LPC bus to AHB bus bridge2" },
28091448c03SJohnny Huang 	{ 7, 18, 1,  1, "Force disable LPC bus to AHB bus bridge2" },
28191448c03SJohnny Huang 	{ 7, 19, 1,  0, "Force enable UART1 debug port function" },
28291448c03SJohnny Huang 	{ 7, 19, 1,  1, "Force disable UART1 debug port function" },
28391448c03SJohnny Huang 	{ 7, 31, 1,  0, "Disable chip security setting" },
28491448c03SJohnny Huang 	{ 7, 31, 1,  1, "Enable chip security setting" },
28591448c03SJohnny Huang 	{ 8, 0,  32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" },
28691448c03SJohnny Huang 	{ 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" },
28791448c03SJohnny Huang 	{ 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }
288b458cd62SJohnny Huang };
2892a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data)
29069d5fd8fSJohnny Huang {
29169d5fd8fSJohnny Huang 	writel(offset, 0x1e6f2010); //Read address
29269d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
29369d5fd8fSJohnny Huang 	udelay(2);
29469d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
29569d5fd8fSJohnny Huang 	data[1] = readl(0x1e6f2024);
29669d5fd8fSJohnny Huang }
29769d5fd8fSJohnny Huang 
2982a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data)
29969d5fd8fSJohnny Huang {
30069d5fd8fSJohnny Huang 	int config_offset;
30169d5fd8fSJohnny Huang 
30269d5fd8fSJohnny Huang 	config_offset = 0x800;
30369d5fd8fSJohnny Huang 	config_offset |= (offset / 8) * 0x200;
30469d5fd8fSJohnny Huang 	config_offset |= (offset % 8) * 0x2;
30569d5fd8fSJohnny Huang 
30669d5fd8fSJohnny Huang 	writel(config_offset, 0x1e6f2010);  //Read address
30769d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
30869d5fd8fSJohnny Huang 	udelay(2);
30969d5fd8fSJohnny Huang 	data[0] = readl(0x1e6f2020);
31069d5fd8fSJohnny Huang }
31169d5fd8fSJohnny Huang 
31269d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count)
31369d5fd8fSJohnny Huang {
31469d5fd8fSJohnny Huang 	int i;
31569d5fd8fSJohnny Huang 	uint32_t ret[1];
31669d5fd8fSJohnny Huang 
31769d5fd8fSJohnny Huang 	if (offset + dw_count > 32)
3182a856b9aSJohnny Huang 		return OTP_USAGE;
31969d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i ++) {
32069d5fd8fSJohnny Huang 		otp_read_config(i, ret);
321a6af4a17SJohnny Huang 		printf("OTPCFG%X: %08X\n", i, ret[0]);
32269d5fd8fSJohnny Huang 	}
32369d5fd8fSJohnny Huang 	printf("\n");
3242a856b9aSJohnny Huang 	return OTP_SUCCESS;
32569d5fd8fSJohnny Huang }
32669d5fd8fSJohnny Huang 
32769d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count)
32869d5fd8fSJohnny Huang {
32969d5fd8fSJohnny Huang 	int i;
33069d5fd8fSJohnny Huang 	uint32_t ret[2];
33169d5fd8fSJohnny Huang 
33269d5fd8fSJohnny Huang 	if (offset + dw_count > 2048 || offset % 4 != 0)
3332a856b9aSJohnny Huang 		return OTP_USAGE;
33469d5fd8fSJohnny Huang 	for (i = offset; i < offset + dw_count; i += 2) {
33569d5fd8fSJohnny Huang 		otp_read_data(i, ret);
33669d5fd8fSJohnny Huang 		if (i % 4 == 0)
33769d5fd8fSJohnny Huang 			printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]);
33869d5fd8fSJohnny Huang 		else
33969d5fd8fSJohnny Huang 			printf("%08X %08X\n", ret[0], ret[1]);
34069d5fd8fSJohnny Huang 
34169d5fd8fSJohnny Huang 	}
34269d5fd8fSJohnny Huang 	printf("\n");
3432a856b9aSJohnny Huang 	return OTP_SUCCESS;
34469d5fd8fSJohnny Huang }
34569d5fd8fSJohnny Huang 
34669d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr)
34769d5fd8fSJohnny Huang {
34869d5fd8fSJohnny Huang 	uint32_t ret;
34969d5fd8fSJohnny Huang 	uint32_t *buf;
35069d5fd8fSJohnny Huang 
35169d5fd8fSJohnny Huang 	buf = map_physmem(addr, 16, MAP_WRBACK);
35269d5fd8fSJohnny Huang 	printf("%08X\n", buf[0]);
35369d5fd8fSJohnny Huang 	printf("%08X\n", buf[1]);
35469d5fd8fSJohnny Huang 	printf("%08X\n", buf[2]);
35569d5fd8fSJohnny Huang 	printf("%08X\n", buf[3]);
35669d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Compare address
35769d5fd8fSJohnny Huang 	writel(buf[0], 0x1e6f2020); //Compare data 1
35869d5fd8fSJohnny Huang 	writel(buf[1], 0x1e6f2024); //Compare data 2
35969d5fd8fSJohnny Huang 	writel(buf[2], 0x1e6f2028); //Compare data 3
36069d5fd8fSJohnny Huang 	writel(buf[3], 0x1e6f202c); //Compare data 4
36169d5fd8fSJohnny Huang 	writel(0x23b1e363, 0x1e6f2004); //Compare command
36269d5fd8fSJohnny Huang 	udelay(10);
36369d5fd8fSJohnny Huang 	ret = readl(0x1e6f2014); //Compare command
36469d5fd8fSJohnny Huang 	if (ret & 0x1)
36569d5fd8fSJohnny Huang 		return 0;
36669d5fd8fSJohnny Huang 	else
36769d5fd8fSJohnny Huang 		return -1;
36869d5fd8fSJohnny Huang }
36969d5fd8fSJohnny Huang 
37069d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data)
37169d5fd8fSJohnny Huang {
37269d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
37369d5fd8fSJohnny Huang 	writel(data, 0x1e6f2020); //write data
37469d5fd8fSJohnny Huang 	writel(0x23b1e362, 0x1e6f2004); //write command
37569d5fd8fSJohnny Huang 	udelay(100);
37669d5fd8fSJohnny Huang }
37769d5fd8fSJohnny Huang 
37869d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit)
37969d5fd8fSJohnny Huang {
38069d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //write address
38169d5fd8fSJohnny Huang 	writel(prog_bit, 0x1e6f2020); //write data
38269d5fd8fSJohnny Huang 	writel(0x23b1e364, 0x1e6f2004); //write command
38369d5fd8fSJohnny Huang 	udelay(85);
38469d5fd8fSJohnny Huang }
38569d5fd8fSJohnny Huang 
386a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value)
38769d5fd8fSJohnny Huang {
38869d5fd8fSJohnny Huang 	int ret;
38969d5fd8fSJohnny Huang 
39069d5fd8fSJohnny Huang 	writel(otp_addr, 0x1e6f2010); //Read address
39169d5fd8fSJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
39269d5fd8fSJohnny Huang 	udelay(2);
39369d5fd8fSJohnny Huang 	ret = readl(0x1e6f2020);
394a6d0d645SJohnny Huang 	// printf("verify_bit = %x\n", ret);
39569d5fd8fSJohnny Huang 	if (((ret >> bit_offset) & 1) == value)
39669d5fd8fSJohnny Huang 		return 0;
39769d5fd8fSJohnny Huang 	else
39869d5fd8fSJohnny Huang 		return -1;
39969d5fd8fSJohnny Huang }
40069d5fd8fSJohnny Huang 
401d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size)
4024c1c9b35SJohnny Huang {
4034c1c9b35SJohnny Huang 	uint32_t ret[2];
4044c1c9b35SJohnny Huang 
4054c1c9b35SJohnny Huang 	otp_addr &= ~(1 << 15);
4064c1c9b35SJohnny Huang 
4074c1c9b35SJohnny Huang 	if (otp_addr % 2 == 0)
4084c1c9b35SJohnny Huang 		writel(otp_addr, 0x1e6f2010); //Read address
4094c1c9b35SJohnny Huang 	else
4104c1c9b35SJohnny Huang 		writel(otp_addr - 1, 0x1e6f2010); //Read address
4114c1c9b35SJohnny Huang 	writel(0x23b1e361, 0x1e6f2004); //trigger read
4124c1c9b35SJohnny Huang 	udelay(2);
4134c1c9b35SJohnny Huang 	ret[0] = readl(0x1e6f2020);
4144c1c9b35SJohnny Huang 	ret[1] = readl(0x1e6f2024);
4154c1c9b35SJohnny Huang 	if (size == 1) {
4164c1c9b35SJohnny Huang 		if (otp_addr % 2 == 0) {
4174c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]);
418d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) {
4194c1c9b35SJohnny Huang 				compare[0] = 0;
4204c1c9b35SJohnny Huang 				return 0;
4214c1c9b35SJohnny Huang 			} else {
4224c1c9b35SJohnny Huang 				compare[0] = value[0] ^ ret[0];
4234c1c9b35SJohnny Huang 				return -1;
4244c1c9b35SJohnny Huang 			}
4254c1c9b35SJohnny Huang 
4264c1c9b35SJohnny Huang 		} else {
4274c1c9b35SJohnny Huang 			// printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]);
428d90825e2SJohnny Huang 			if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) {
4294c1c9b35SJohnny Huang 				compare[0] = ~0;
4304c1c9b35SJohnny Huang 				return 0;
4314c1c9b35SJohnny Huang 			} else {
432d90825e2SJohnny Huang 				compare[0] = ~(value[0] ^ ret[1]);
4334c1c9b35SJohnny Huang 				return -1;
4344c1c9b35SJohnny Huang 			}
4354c1c9b35SJohnny Huang 		}
4364c1c9b35SJohnny Huang 	} else if (size == 2) {
4374c1c9b35SJohnny Huang 		// otp_addr should be even
438d90825e2SJohnny Huang 		if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) {
4394c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4404c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4414c1c9b35SJohnny Huang 			compare[0] = 0;
4424c1c9b35SJohnny Huang 			compare[1] = ~0;
4434c1c9b35SJohnny Huang 			return 0;
4444c1c9b35SJohnny Huang 		} else {
4454c1c9b35SJohnny Huang 			// printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]);
4464c1c9b35SJohnny Huang 			// printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]);
4474c1c9b35SJohnny Huang 			compare[0] = value[0] ^ ret[0];
4484c1c9b35SJohnny Huang 			compare[1] = ~(value[1] ^ ret[1]);
4494c1c9b35SJohnny Huang 			return -1;
4504c1c9b35SJohnny Huang 		}
4514c1c9b35SJohnny Huang 	} else {
4524c1c9b35SJohnny Huang 		return -1;
4534c1c9b35SJohnny Huang 	}
4544c1c9b35SJohnny Huang }
4554c1c9b35SJohnny Huang 
4567e22f42dSJohnny Huang static void otp_soak(int soak)
457d90825e2SJohnny Huang {
458d90825e2SJohnny Huang 	if (soak) {
459d90825e2SJohnny Huang 		otp_write(0x3000, 0x4021); // Write MRA
460d90825e2SJohnny Huang 		otp_write(0x5000, 0x1027); // Write MRB
461d90825e2SJohnny Huang 		otp_write(0x1000, 0x4820); // Write MR
462d90825e2SJohnny Huang 		writel(0x041930d4, 0x1e602008); //soak program
463d90825e2SJohnny Huang 	} else {
464d90825e2SJohnny Huang 		otp_write(0x3000, 0x4061); // Write MRA
465d90825e2SJohnny Huang 		otp_write(0x5000, 0x302f); // Write MRB
466d90825e2SJohnny Huang 		otp_write(0x1000, 0x4020); // Write MR
467d90825e2SJohnny Huang 		writel(0x04190760, 0x1e602008); //normal program
468d90825e2SJohnny Huang 	}
469d90825e2SJohnny Huang }
470d90825e2SJohnny Huang 
471d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address)
472d90825e2SJohnny Huang {
473d90825e2SJohnny Huang 	int j, bit_value, prog_bit;
474d90825e2SJohnny Huang 
475d90825e2SJohnny Huang 	for (j = 0; j < 32; j++) {
476d90825e2SJohnny Huang 		if ((keep >> j) & 0x1)
477d90825e2SJohnny Huang 			continue;
478d90825e2SJohnny Huang 		bit_value = (value >> j) & 0x1;
479d90825e2SJohnny Huang 		if (prog_address % 2 == 0) {
480d90825e2SJohnny Huang 			if (bit_value)
481d90825e2SJohnny Huang 				prog_bit = ~(0x1 << j);
482d90825e2SJohnny Huang 			else
483d90825e2SJohnny Huang 				continue;
484d90825e2SJohnny Huang 		} else {
485d90825e2SJohnny Huang 			prog_address |= 1 << 15;
486d90825e2SJohnny Huang 			if (bit_value)
487d90825e2SJohnny Huang 				continue;
488d90825e2SJohnny Huang 			else
489d90825e2SJohnny Huang 				prog_bit = 0x1 << j;
490d90825e2SJohnny Huang 		}
491d90825e2SJohnny Huang 		otp_prog(prog_address, prog_bit);
492d90825e2SJohnny Huang 	}
493d90825e2SJohnny Huang }
494d90825e2SJohnny Huang 
49576d13988SJohnny Huang 
49676d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap)
49776d13988SJohnny Huang {
49876d13988SJohnny Huang 	uint32_t OTPSTRAP_RAW[2];
49976d13988SJohnny Huang 	int i, j;
50076d13988SJohnny Huang 
50176d13988SJohnny Huang 	for (j = 0; j < 64; j++) {
50276d13988SJohnny Huang 		otpstrap[j].value = 0;
50376d13988SJohnny Huang 		otpstrap[j].remain_times = 7;
50476d13988SJohnny Huang 		otpstrap[j].writeable_option = -1;
50576d13988SJohnny Huang 		otpstrap[j].protected = 0;
50676d13988SJohnny Huang 	}
50776d13988SJohnny Huang 
50876d13988SJohnny Huang 	for (i = 16; i < 30; i += 2) {
50976d13988SJohnny Huang 		int option = (i - 16) / 2;
51076d13988SJohnny Huang 		otp_read_config(i, &OTPSTRAP_RAW[0]);
51176d13988SJohnny Huang 		otp_read_config(i + 1, &OTPSTRAP_RAW[1]);
51276d13988SJohnny Huang 		for (j = 0; j < 32; j++) {
51376d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1);
51476d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
51576d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
51676d13988SJohnny Huang 			}
51776d13988SJohnny Huang 			if (bit_value == 1)
51876d13988SJohnny Huang 				otpstrap[j].remain_times --;
51976d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
52076d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
52176d13988SJohnny Huang 		}
52276d13988SJohnny Huang 		for (j = 32; j < 64; j++) {
52376d13988SJohnny Huang 			char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1);
52476d13988SJohnny Huang 			if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) {
52576d13988SJohnny Huang 				otpstrap[j].writeable_option = option;
52676d13988SJohnny Huang 			}
52776d13988SJohnny Huang 			if (bit_value == 1)
52876d13988SJohnny Huang 				otpstrap[j].remain_times --;
52976d13988SJohnny Huang 			otpstrap[j].value ^= bit_value;
53076d13988SJohnny Huang 			otpstrap[j].option_array[option] = bit_value;
53176d13988SJohnny Huang 		}
53276d13988SJohnny Huang 	}
53376d13988SJohnny Huang 	otp_read_config(30, &OTPSTRAP_RAW[0]);
53476d13988SJohnny Huang 	otp_read_config(31, &OTPSTRAP_RAW[1]);
53576d13988SJohnny Huang 	for (j = 0; j < 32; j++) {
53676d13988SJohnny Huang 		if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1)
53776d13988SJohnny Huang 			otpstrap[j].protected = 1;
53876d13988SJohnny Huang 	}
53976d13988SJohnny Huang 	for (j = 32; j < 64; j++) {
54076d13988SJohnny Huang 		if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1)
54176d13988SJohnny Huang 			otpstrap[j].protected = 1;
54276d13988SJohnny Huang 	}
54376d13988SJohnny Huang }
54476d13988SJohnny Huang 
545b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG)
54669d5fd8fSJohnny Huang {
547442839bbSJohnny Huang 	uint32_t *OTPCFG_KEEP = &OTPCFG[12];
548b458cd62SJohnny Huang 	uint32_t mask;
549b458cd62SJohnny Huang 	uint32_t dw_offset;
550b458cd62SJohnny Huang 	uint32_t bit_offset;
551b458cd62SJohnny Huang 	uint32_t otp_value;
552b458cd62SJohnny Huang 	uint32_t otp_keep;
553b458cd62SJohnny Huang 	int fail = 0;
554*73f11549SJohnny Huang 	char valid_bit[20];
55566f2f8e5SJohnny Huang 	int i;
556*73f11549SJohnny Huang 	int j;
55766f2f8e5SJohnny Huang 
558737ed20bSJohnny Huang 	printf("DW    BIT        Value       Description\n");
55966f2f8e5SJohnny Huang 	printf("__________________________________________________________________________\n");
560b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
561b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
562b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
563b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
564b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
565b458cd62SJohnny Huang 		otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask;
566b458cd62SJohnny Huang 
567b458cd62SJohnny Huang 		if (otp_keep == mask) {
568b458cd62SJohnny Huang 			continue;
569b458cd62SJohnny Huang 		} else if (otp_keep != 0) {
570b458cd62SJohnny Huang 			fail = 1;
571b458cd62SJohnny Huang 		}
572b458cd62SJohnny Huang 
573b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
574b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
575b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
576b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
577b458cd62SJohnny Huang 			continue;
578b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
579b458cd62SJohnny Huang 
580b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
581b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
58266f2f8e5SJohnny Huang 		} else {
583b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
584b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
585b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
58666f2f8e5SJohnny Huang 		}
587b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
588b458cd62SJohnny Huang 
589b458cd62SJohnny Huang 		if (fail) {
590b458cd62SJohnny Huang 			printf("Keep mask error\n");
591b458cd62SJohnny Huang 		} else {
592b458cd62SJohnny Huang 			if (a0_conf_info[i].value == OTP_REG_RESERVED) {
593b458cd62SJohnny Huang 				printf("Reserved\n");
594b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
595b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, otp_value);
596b458cd62SJohnny Huang 				printf("\n");
597b458cd62SJohnny Huang 			} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
598b458cd62SJohnny Huang 				if (otp_value != 0) {
599*73f11549SJohnny Huang 					for (j = 0; j < 7; j++) {
600*73f11549SJohnny Huang 						if (otp_value == (1 << j)) {
601*73f11549SJohnny Huang 							valid_bit[j * 2] = '1';
602b458cd62SJohnny Huang 						} else {
603*73f11549SJohnny Huang 							valid_bit[j * 2] = '0';
604*73f11549SJohnny Huang 						}
605*73f11549SJohnny Huang 						valid_bit[j * 2 + 1] = ' ';
606*73f11549SJohnny Huang 					}
607*73f11549SJohnny Huang 					valid_bit[15] = 0;
608*73f11549SJohnny Huang 				} else {
609*73f11549SJohnny Huang 					strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
610b458cd62SJohnny Huang 				}
611b458cd62SJohnny Huang 				printf(a0_conf_info[i].information, valid_bit);
612b458cd62SJohnny Huang 				printf("\n");
613b458cd62SJohnny Huang 			} else {
614b458cd62SJohnny Huang 				printf("%s\n", a0_conf_info[i].information);
615b458cd62SJohnny Huang 			}
616b458cd62SJohnny Huang 		}
617b458cd62SJohnny Huang 	}
618b458cd62SJohnny Huang 
619b458cd62SJohnny Huang 	if (fail)
620b458cd62SJohnny Huang 		return OTP_FAILURE;
621b458cd62SJohnny Huang 
62266f2f8e5SJohnny Huang 	return OTP_SUCCESS;
62366f2f8e5SJohnny Huang }
62466f2f8e5SJohnny Huang 
6252d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset)
62666f2f8e5SJohnny Huang {
627b458cd62SJohnny Huang 	uint32_t OTPCFG[12];
628b458cd62SJohnny Huang 	uint32_t mask;
629b458cd62SJohnny Huang 	uint32_t dw_offset;
630b458cd62SJohnny Huang 	uint32_t bit_offset;
631b458cd62SJohnny Huang 	uint32_t otp_value;
632*73f11549SJohnny Huang 	char valid_bit[20];
63366f2f8e5SJohnny Huang 	int i;
634*73f11549SJohnny Huang 	int j;
63566f2f8e5SJohnny Huang 
63666f2f8e5SJohnny Huang 	for (i = 0; i < 12; i++)
63766f2f8e5SJohnny Huang 		otp_read_config(i, &OTPCFG[i]);
63866f2f8e5SJohnny Huang 
63966f2f8e5SJohnny Huang 
640b458cd62SJohnny Huang 	printf("DW    BIT        Value       Description\n");
641b458cd62SJohnny Huang 	printf("__________________________________________________________________________\n");
642b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) {
6432d4b0742SJohnny Huang 		if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset)
6442d4b0742SJohnny Huang 			continue;
645b458cd62SJohnny Huang 		dw_offset = a0_conf_info[i].dw_offset;
646b458cd62SJohnny Huang 		bit_offset = a0_conf_info[i].bit_offset;
647b458cd62SJohnny Huang 		mask = BIT(a0_conf_info[i].length) - 1;
648b458cd62SJohnny Huang 		otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask;
649b458cd62SJohnny Huang 
650b458cd62SJohnny Huang 		if ((otp_value != a0_conf_info[i].value) &&
651b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_RESERVED &&
652b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALUE &&
653b458cd62SJohnny Huang 		    a0_conf_info[i].value != OTP_REG_VALID_BIT)
654b458cd62SJohnny Huang 			continue;
655b458cd62SJohnny Huang 		printf("0x%-4X", dw_offset);
656b458cd62SJohnny Huang 
657b458cd62SJohnny Huang 		if (a0_conf_info[i].length == 1) {
658b458cd62SJohnny Huang 			printf("0x%-9X", a0_conf_info[i].bit_offset);
659b458cd62SJohnny Huang 		} else {
660b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
661b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1,
662b458cd62SJohnny Huang 			       a0_conf_info[i].bit_offset);
663b458cd62SJohnny Huang 		}
664b458cd62SJohnny Huang 		printf("0x%-10x", otp_value);
665b458cd62SJohnny Huang 
666b458cd62SJohnny Huang 		if (a0_conf_info[i].value == OTP_REG_RESERVED) {
667b458cd62SJohnny Huang 			printf("Reserved\n");
668b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALUE) {
669b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, otp_value);
670b458cd62SJohnny Huang 			printf("\n");
671b458cd62SJohnny Huang 		} else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) {
672b458cd62SJohnny Huang 			if (otp_value != 0) {
673*73f11549SJohnny Huang 				for (j = 0; j < 7; j++) {
674*73f11549SJohnny Huang 					if (otp_value == (1 << j)) {
675*73f11549SJohnny Huang 						valid_bit[j * 2] = '1';
676b458cd62SJohnny Huang 					} else {
677*73f11549SJohnny Huang 						valid_bit[j * 2] = '0';
678*73f11549SJohnny Huang 					}
679*73f11549SJohnny Huang 					valid_bit[j * 2 + 1] = ' ';
680*73f11549SJohnny Huang 				}
681*73f11549SJohnny Huang 				valid_bit[15] = 0;
682*73f11549SJohnny Huang 			} else {
683*73f11549SJohnny Huang 				strcpy(valid_bit, "0 0 0 0 0 0 0 0\0");
684b458cd62SJohnny Huang 			}
685b458cd62SJohnny Huang 			printf(a0_conf_info[i].information, valid_bit);
686b458cd62SJohnny Huang 			printf("\n");
687b458cd62SJohnny Huang 		} else {
688b458cd62SJohnny Huang 			printf("%s\n", a0_conf_info[i].information);
689b458cd62SJohnny Huang 		}
690b458cd62SJohnny Huang 	}
691b458cd62SJohnny Huang 	return OTP_SUCCESS;
69266f2f8e5SJohnny Huang }
69366f2f8e5SJohnny Huang 
694b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP)
69576d13988SJohnny Huang {
696a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4];
697a8bd6d8cSJohnny Huang 	uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2];
69876d13988SJohnny Huang 	int i;
699a8bd6d8cSJohnny Huang 	int fail = 0;
700a8bd6d8cSJohnny Huang 	uint32_t bit_offset;
701a8bd6d8cSJohnny Huang 	uint32_t dw_offset;
702a8bd6d8cSJohnny Huang 	uint32_t mask;
703a8bd6d8cSJohnny Huang 	uint32_t otp_value;
704a8bd6d8cSJohnny Huang 	uint32_t otp_protect;
705a8bd6d8cSJohnny Huang 	uint32_t otp_keep;
70676d13988SJohnny Huang 
707a8bd6d8cSJohnny Huang 	printf("BIT(hex)   Value       Protect     Description\n");
708a8bd6d8cSJohnny Huang 	printf("__________________________________________________________________________________________\n");
709b458cd62SJohnny Huang 
710a8bd6d8cSJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
711a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].bit_offset > 32) {
712a8bd6d8cSJohnny Huang 			dw_offset = 1;
713a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset - 32;
714a8bd6d8cSJohnny Huang 		} else {
715a8bd6d8cSJohnny Huang 			dw_offset = 0;
716a8bd6d8cSJohnny Huang 			bit_offset = a0_strap_info[i].bit_offset;
717a8bd6d8cSJohnny Huang 		}
71876d13988SJohnny Huang 
719a8bd6d8cSJohnny Huang 		mask = BIT(a0_strap_info[i].length) - 1;
720a8bd6d8cSJohnny Huang 		otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask;
721a8bd6d8cSJohnny Huang 		otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask;
722a8bd6d8cSJohnny Huang 		otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask;
723a8bd6d8cSJohnny Huang 
724a8bd6d8cSJohnny Huang 		if (otp_keep == mask) {
725a8bd6d8cSJohnny Huang 			continue;
726a8bd6d8cSJohnny Huang 		} else if (otp_keep != 0) {
727a8bd6d8cSJohnny Huang 			fail = 1;
728a8bd6d8cSJohnny Huang 		}
729a8bd6d8cSJohnny Huang 
730a8bd6d8cSJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
731a8bd6d8cSJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
732a8bd6d8cSJohnny Huang 			continue;
733a8bd6d8cSJohnny Huang 
734a8bd6d8cSJohnny Huang 		if (a0_strap_info[i].length == 1) {
735b458cd62SJohnny Huang 			printf("0x%-9X", a0_strap_info[i].bit_offset);
736a8bd6d8cSJohnny Huang 		} else {
737b458cd62SJohnny Huang 			printf("0x%-2X:0x%-4X",
738a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1,
739a8bd6d8cSJohnny Huang 			       a0_strap_info[i].bit_offset);
740a8bd6d8cSJohnny Huang 		}
741a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_value);
742a8bd6d8cSJohnny Huang 		printf("0x%-10x", otp_protect);
743a8bd6d8cSJohnny Huang 
744a8bd6d8cSJohnny Huang 		if (fail) {
745a8bd6d8cSJohnny Huang 			printf("Keep mask error\n");
746a8bd6d8cSJohnny Huang 		} else {
747a8bd6d8cSJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
748a8bd6d8cSJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
749a8bd6d8cSJohnny Huang 			else
750a8bd6d8cSJohnny Huang 				printf("Reserved\n");
751a8bd6d8cSJohnny Huang 		}
752a8bd6d8cSJohnny Huang 	}
753a8bd6d8cSJohnny Huang 
754a8bd6d8cSJohnny Huang 	if (fail)
75576d13988SJohnny Huang 		return OTP_FAILURE;
75676d13988SJohnny Huang 
75776d13988SJohnny Huang 	return OTP_SUCCESS;
75876d13988SJohnny Huang }
75976d13988SJohnny Huang 
760b458cd62SJohnny Huang static int otp_print_strap_info(int view)
76176d13988SJohnny Huang {
76276d13988SJohnny Huang 	struct otpstrap_status strap_status[64];
76307baa4e8SJohnny Huang 	int i, j;
764b458cd62SJohnny Huang 	int fail = 0;
765b458cd62SJohnny Huang 	uint32_t bit_offset;
766b458cd62SJohnny Huang 	uint32_t length;
767b458cd62SJohnny Huang 	uint32_t otp_value;
768b458cd62SJohnny Huang 	uint32_t otp_protect;
76976d13988SJohnny Huang 
77076d13988SJohnny Huang 	otp_strp_status(strap_status);
77176d13988SJohnny Huang 
772b458cd62SJohnny Huang 	if (view) {
77307baa4e8SJohnny Huang 		// printf("BIT(hex) Value  Option         Protect   Description\n");
77407baa4e8SJohnny Huang 		// printf("                0 1 2 3 4 5 6\n");
77507baa4e8SJohnny Huang 		printf("BIT(hex) Value  Remains  Protect   Description\n");
77607baa4e8SJohnny Huang 		printf("___________________________________________________________________________________________________\n");
777b458cd62SJohnny Huang 	} else {
778b458cd62SJohnny Huang 		printf("BIT(hex)   Value       Description\n");
779b458cd62SJohnny Huang 		printf("________________________________________________________________________________\n");
78076d13988SJohnny Huang 	}
781b458cd62SJohnny Huang 	for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) {
782b458cd62SJohnny Huang 		otp_value = 0;
783b458cd62SJohnny Huang 		bit_offset = a0_strap_info[i].bit_offset;
784b458cd62SJohnny Huang 		length = a0_strap_info[i].length;
785b458cd62SJohnny Huang 		for (j = 0; j < length; j++) {
786c947ef08SJohnny Huang 			otp_value |= strap_status[bit_offset + j].value << j;
787c947ef08SJohnny Huang 			otp_protect |= strap_status[bit_offset + j].protected << j;
788b458cd62SJohnny Huang 		}
789b458cd62SJohnny Huang 		if ((otp_value != a0_strap_info[i].value) &&
790b458cd62SJohnny Huang 		    a0_strap_info[i].value != OTP_REG_RESERVED)
791b458cd62SJohnny Huang 			continue;
792b458cd62SJohnny Huang 		if (view) {
793b458cd62SJohnny Huang 			for (j = 0; j < length; j++) {
794b458cd62SJohnny Huang 				printf("0x%-7X", a0_strap_info[i].bit_offset + j);
795b458cd62SJohnny Huang 				printf("0x%-5X", strap_status[bit_offset + j].value);
79607baa4e8SJohnny Huang 				printf("%-9d", strap_status[bit_offset + j].remain_times);
797b458cd62SJohnny Huang 				printf("0x%-7X", strap_status[bit_offset].protected);
798b458cd62SJohnny Huang 				if (a0_strap_info[i].value == OTP_REG_RESERVED) {
799b458cd62SJohnny Huang 					printf(" Reserved\n");
800b458cd62SJohnny Huang 					continue;
801b458cd62SJohnny Huang 				}
802b458cd62SJohnny Huang 				if (length == 1) {
803b458cd62SJohnny Huang 					printf(" %s\n", a0_strap_info[i].information);
804b458cd62SJohnny Huang 					continue;
80576d13988SJohnny Huang 				}
80676d13988SJohnny Huang 
807b458cd62SJohnny Huang 				if (j == 0)
808b458cd62SJohnny Huang 					printf("/%s\n", a0_strap_info[i].information);
809b458cd62SJohnny Huang 				else if (j == length - 1)
810b458cd62SJohnny Huang 					printf("\\ \"\n");
811b458cd62SJohnny Huang 				else
812b458cd62SJohnny Huang 					printf("| \"\n");
81376d13988SJohnny Huang 			}
814b458cd62SJohnny Huang 		} else {
815c947ef08SJohnny Huang 			if (length == 1) {
816b458cd62SJohnny Huang 				printf("0x%-9X", a0_strap_info[i].bit_offset);
817b458cd62SJohnny Huang 			} else {
818b458cd62SJohnny Huang 				printf("0x%-2X:0x%-4X",
819b458cd62SJohnny Huang 				       bit_offset + length - 1, bit_offset);
820b458cd62SJohnny Huang 			}
821b458cd62SJohnny Huang 
822b458cd62SJohnny Huang 			printf("0x%-10X", otp_value);
823b458cd62SJohnny Huang 
824b458cd62SJohnny Huang 			if (a0_strap_info[i].value != OTP_REG_RESERVED)
825b458cd62SJohnny Huang 				printf("%s\n", a0_strap_info[i].information);
826b458cd62SJohnny Huang 			else
827b458cd62SJohnny Huang 				printf("Reserved\n");
828b458cd62SJohnny Huang 		}
829b458cd62SJohnny Huang 	}
830b458cd62SJohnny Huang 
831b458cd62SJohnny Huang 	if (fail)
832b458cd62SJohnny Huang 		return OTP_FAILURE;
833b458cd62SJohnny Huang 
834b458cd62SJohnny Huang 	return OTP_SUCCESS;
835b458cd62SJohnny Huang }
836b458cd62SJohnny Huang 
83769d5fd8fSJohnny Huang static void buf_print(char *buf, int len)
83869d5fd8fSJohnny Huang {
83969d5fd8fSJohnny Huang 	int i;
84069d5fd8fSJohnny Huang 	printf("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
84169d5fd8fSJohnny Huang 	for (i = 0; i < len; i++) {
84269d5fd8fSJohnny Huang 		if (i % 16 == 0) {
84369d5fd8fSJohnny Huang 			printf("%04X: ", i);
84469d5fd8fSJohnny Huang 		}
84569d5fd8fSJohnny Huang 		printf("%02X ", buf[i]);
84669d5fd8fSJohnny Huang 		if ((i + 1) % 16 == 0) {
84769d5fd8fSJohnny Huang 			printf("\n");
84869d5fd8fSJohnny Huang 		}
84969d5fd8fSJohnny Huang 	}
85069d5fd8fSJohnny Huang }
85169d5fd8fSJohnny Huang 
8527f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf)
85369d5fd8fSJohnny Huang {
85469d5fd8fSJohnny Huang 	int key_id, key_offset, last, key_type, key_length, exp_length;
85569d5fd8fSJohnny Huang 	char *byte_buf;
85669d5fd8fSJohnny Huang 	int i = 0, len = 0;
85769d5fd8fSJohnny Huang 	byte_buf = (char *)buf;
85869d5fd8fSJohnny Huang 	while (1) {
85969d5fd8fSJohnny Huang 		key_id = buf[i] & 0x7;
86069d5fd8fSJohnny Huang 		key_offset = buf[i] & 0x1ff8;
86169d5fd8fSJohnny Huang 		last = (buf[i] >> 13) & 1;
86269d5fd8fSJohnny Huang 		key_type = (buf[i] >> 14) & 0xf;
86369d5fd8fSJohnny Huang 		key_length = (buf[i] >> 18) & 0x3;
86469d5fd8fSJohnny Huang 		exp_length = (buf[i] >> 20) & 0xfff;
8657f795e57SJohnny Huang 		printf("\nKey[%d]:\n", i);
86669d5fd8fSJohnny Huang 		printf("Key Type: ");
86769d5fd8fSJohnny Huang 		switch (key_type) {
86869d5fd8fSJohnny Huang 		case 0:
86969d5fd8fSJohnny Huang 			printf("AES-256 as OEM platform key for image encryption/decryption\n");
87069d5fd8fSJohnny Huang 			break;
87169d5fd8fSJohnny Huang 		case 1:
87269d5fd8fSJohnny Huang 			printf("AES-256 as secret vault key\n");
87369d5fd8fSJohnny Huang 			break;
87469d5fd8fSJohnny Huang 		case 4:
87569d5fd8fSJohnny Huang 			printf("HMAC as encrypted OEM HMAC keys in Mode 1\n");
87669d5fd8fSJohnny Huang 			break;
87769d5fd8fSJohnny Huang 		case 8:
87869d5fd8fSJohnny Huang 			printf("RSA-public as OEM DSS public keys in Mode 2\n");
87969d5fd8fSJohnny Huang 			break;
88069d5fd8fSJohnny Huang 		case 9:
88169d5fd8fSJohnny Huang 			printf("RSA-public as SOC public key\n");
88269d5fd8fSJohnny Huang 			break;
88369d5fd8fSJohnny Huang 		case 10:
88469d5fd8fSJohnny Huang 			printf("RSA-public as AES key decryption key\n");
88569d5fd8fSJohnny Huang 			break;
88669d5fd8fSJohnny Huang 		case 13:
88769d5fd8fSJohnny Huang 			printf("RSA-private as SOC private key\n");
88869d5fd8fSJohnny Huang 			break;
88969d5fd8fSJohnny Huang 		case 14:
89069d5fd8fSJohnny Huang 			printf("RSA-private as AES key decryption key\n");
89169d5fd8fSJohnny Huang 			break;
89269d5fd8fSJohnny Huang 		default:
89369d5fd8fSJohnny Huang 			printf("key_type error: %x\n", key_type);
89469d5fd8fSJohnny Huang 			return -1;
89569d5fd8fSJohnny Huang 		}
89669d5fd8fSJohnny Huang 		if (key_type == 4) {
89769d5fd8fSJohnny Huang 			printf("HMAC SHA Type: ");
89869d5fd8fSJohnny Huang 			switch (key_length) {
89969d5fd8fSJohnny Huang 			case 0:
90069d5fd8fSJohnny Huang 				printf("HMAC(SHA224)\n");
90169d5fd8fSJohnny Huang 				break;
90269d5fd8fSJohnny Huang 			case 1:
90369d5fd8fSJohnny Huang 				printf("HMAC(SHA256)\n");
90469d5fd8fSJohnny Huang 				break;
90569d5fd8fSJohnny Huang 			case 2:
90669d5fd8fSJohnny Huang 				printf("HMAC(SHA384)\n");
90769d5fd8fSJohnny Huang 				break;
90869d5fd8fSJohnny Huang 			case 3:
90969d5fd8fSJohnny Huang 				printf("HMAC(SHA512)\n");
91069d5fd8fSJohnny Huang 				break;
91169d5fd8fSJohnny Huang 			}
912cd1610b4SJohnny Huang 		} else if (key_type != 0 && key_type != 1) {
91369d5fd8fSJohnny Huang 			printf("RSA SHA Type: ");
91469d5fd8fSJohnny Huang 			switch (key_length) {
91569d5fd8fSJohnny Huang 			case 0:
91669d5fd8fSJohnny Huang 				printf("RSA1024\n");
91769d5fd8fSJohnny Huang 				len = 0x100;
91869d5fd8fSJohnny Huang 				break;
91969d5fd8fSJohnny Huang 			case 1:
92069d5fd8fSJohnny Huang 				printf("RSA2048\n");
92169d5fd8fSJohnny Huang 				len = 0x200;
92269d5fd8fSJohnny Huang 				break;
92369d5fd8fSJohnny Huang 			case 2:
92469d5fd8fSJohnny Huang 				printf("RSA3072\n");
92569d5fd8fSJohnny Huang 				len = 0x300;
92669d5fd8fSJohnny Huang 				break;
92769d5fd8fSJohnny Huang 			case 3:
92869d5fd8fSJohnny Huang 				printf("RSA4096\n");
92969d5fd8fSJohnny Huang 				len = 0x400;
93069d5fd8fSJohnny Huang 				break;
93169d5fd8fSJohnny Huang 			}
93269d5fd8fSJohnny Huang 			printf("RSA exponent bit length: %d\n", exp_length);
93369d5fd8fSJohnny Huang 		}
93469d5fd8fSJohnny Huang 		if (key_type == 4 || key_type == 8)
93569d5fd8fSJohnny Huang 			printf("Key Number ID: %d\n", key_id);
93669d5fd8fSJohnny Huang 		printf("Key Value:\n");
93769d5fd8fSJohnny Huang 		if (key_type == 4) {
93869d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x40);
93969d5fd8fSJohnny Huang 		} else if (key_type == 0 || key_type == 1) {
94069d5fd8fSJohnny Huang 			printf("AES Key:\n");
94169d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], 0x20);
94269d5fd8fSJohnny Huang 			printf("AES IV:\n");
94369d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + 0x20], 0x10);
94469d5fd8fSJohnny Huang 
94569d5fd8fSJohnny Huang 		} else {
94669d5fd8fSJohnny Huang 			printf("RSA mod:\n");
94769d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset], len / 2);
94869d5fd8fSJohnny Huang 			printf("RSA exp:\n");
94969d5fd8fSJohnny Huang 			buf_print(&byte_buf[key_offset + (len / 2)], len / 2);
95069d5fd8fSJohnny Huang 		}
95169d5fd8fSJohnny Huang 		if (last)
95269d5fd8fSJohnny Huang 			break;
95369d5fd8fSJohnny Huang 		i++;
95469d5fd8fSJohnny Huang 	}
95569d5fd8fSJohnny Huang 	return 0;
95669d5fd8fSJohnny Huang }
95769d5fd8fSJohnny Huang 
958a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf)
95969d5fd8fSJohnny Huang {
960a6d0d645SJohnny Huang 	int i, k;
961d90825e2SJohnny Huang 	int pass = 0;
962d90825e2SJohnny Huang 	int soak = 0;
963a6d0d645SJohnny Huang 	uint32_t prog_address;
964a6d0d645SJohnny Huang 	uint32_t data[12];
965a6d0d645SJohnny Huang 	uint32_t compare[2];
966d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[12];
967d90825e2SJohnny Huang 	uint32_t data_masked;
968d90825e2SJohnny Huang 	uint32_t buf_masked;
96969d5fd8fSJohnny Huang 
970a6d0d645SJohnny Huang 	printf("Read OTP Config Region:\n");
971a6d0d645SJohnny Huang 
972a6d0d645SJohnny Huang 	printProgress(0, 12, "");
973a6d0d645SJohnny Huang 	for (i = 0; i < 12 ; i ++) {
974a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "");
97569d5fd8fSJohnny Huang 		prog_address = 0x800;
976a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
977a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
978a6d0d645SJohnny Huang 		otp_read_data(prog_address, &data[i]);
979a6d0d645SJohnny Huang 	}
980a6d0d645SJohnny Huang 
981a6d0d645SJohnny Huang 	printf("Check writable...\n");
982a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
983d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
984d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
985d90825e2SJohnny Huang 		if (data_masked == buf_masked)
98669d5fd8fSJohnny Huang 			continue;
987d90825e2SJohnny Huang 		if ((data_masked | buf_masked) == buf_masked) {
988a6d0d645SJohnny Huang 			continue;
989a6d0d645SJohnny Huang 		} else {
990a6d0d645SJohnny Huang 			printf("Input image can't program into OTP, please check.\n");
991a6af4a17SJohnny Huang 			printf("OTPCFG[%X] = %x\n", i, data[i]);
992a6af4a17SJohnny Huang 			printf("Input [%X] = %x\n", i, buf[i]);
993a6af4a17SJohnny Huang 			printf("Mask  [%X] = %x\n", i, ~buf_keep[i]);
9942a856b9aSJohnny Huang 			return OTP_FAILURE;
995a6d0d645SJohnny Huang 		}
996a6d0d645SJohnny Huang 	}
997a6d0d645SJohnny Huang 
998a6d0d645SJohnny Huang 	printf("Start Programing...\n");
999a6d0d645SJohnny Huang 	printProgress(0, 12, "");
1000d90825e2SJohnny Huang 	otp_soak(0);
1001a6d0d645SJohnny Huang 	for (i = 0; i < 12; i++) {
1002d90825e2SJohnny Huang 		data_masked = data[i]  & ~buf_keep[i];
1003d90825e2SJohnny Huang 		buf_masked  = buf[i] & ~buf_keep[i];
1004a6d0d645SJohnny Huang 		prog_address = 0x800;
1005a6d0d645SJohnny Huang 		prog_address |= (i / 8) * 0x200;
1006a6d0d645SJohnny Huang 		prog_address |= (i % 8) * 0x2;
1007d90825e2SJohnny Huang 		if (data_masked == buf_masked) {
1008a6d0d645SJohnny Huang 			printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]);
1009a6d0d645SJohnny Huang 			continue;
1010a6d0d645SJohnny Huang 		}
1011d90825e2SJohnny Huang 		if (soak) {
1012d90825e2SJohnny Huang 			soak = 0;
1013d90825e2SJohnny Huang 			otp_soak(0);
1014d90825e2SJohnny Huang 		}
1015a6d0d645SJohnny Huang 		printProgress(i + 1, 12, "[%03X]=%08X    ", prog_address, buf[i]);
1016a6d0d645SJohnny Huang 
1017d90825e2SJohnny Huang 		otp_prog_dw(buf[i], buf_keep[i], prog_address);
1018a6d0d645SJohnny Huang 
101969d5fd8fSJohnny Huang 		pass = 0;
102069d5fd8fSJohnny Huang 		for (k = 0; k < RETRY; k++) {
1021d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) {
1022d90825e2SJohnny Huang 				if (soak == 0) {
1023d90825e2SJohnny Huang 					soak = 1;
1024d90825e2SJohnny Huang 					otp_soak(1);
1025d90825e2SJohnny Huang 				}
1026a6d0d645SJohnny Huang 				otp_prog_dw(compare[0], prog_address, 1);
1027a6d0d645SJohnny Huang 			} else {
102869d5fd8fSJohnny Huang 				pass = 1;
102969d5fd8fSJohnny Huang 				break;
103069d5fd8fSJohnny Huang 			}
103169d5fd8fSJohnny Huang 		}
1032a6d0d645SJohnny Huang 	}
1033a6d0d645SJohnny Huang 
103469d5fd8fSJohnny Huang 	if (!pass)
10352a856b9aSJohnny Huang 		return OTP_FAILURE;
1036a6d0d645SJohnny Huang 
10372a856b9aSJohnny Huang 	return OTP_SUCCESS;
1038d90825e2SJohnny Huang 
103969d5fd8fSJohnny Huang }
104069d5fd8fSJohnny Huang 
104169d5fd8fSJohnny Huang 
104276d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf)
104369d5fd8fSJohnny Huang {
104469d5fd8fSJohnny Huang 	int i;
104569d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
104669d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
104769d5fd8fSJohnny Huang 	int bit, pbit, kbit;
104869d5fd8fSJohnny Huang 	int fail = 0;
1049a6af4a17SJohnny Huang 	int skip = -1;
105066f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
105169d5fd8fSJohnny Huang 
105269d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
105369d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
105469d5fd8fSJohnny Huang 		if (i < 32) {
105569d5fd8fSJohnny Huang 			bit = (buf[0] >> i) & 0x1;
105669d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> i) & 0x1;
105769d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> i) & 0x1;
105869d5fd8fSJohnny Huang 		} else {
105969d5fd8fSJohnny Huang 			bit = (buf[1] >> (i - 32)) & 0x1;
106069d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> (i - 32)) & 0x1;
106169d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> (i - 32)) & 0x1;
106269d5fd8fSJohnny Huang 		}
106369d5fd8fSJohnny Huang 
106469d5fd8fSJohnny Huang 		if (kbit == 1) {
106569d5fd8fSJohnny Huang 			continue;
106669d5fd8fSJohnny Huang 		} else {
1067a6af4a17SJohnny Huang 			printf("OTPSTRAP[%X]:\n", i);
106869d5fd8fSJohnny Huang 		}
106969d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
107069d5fd8fSJohnny Huang 			printf("    The value is same as before, skip it.\n");
1071a6af4a17SJohnny Huang 			if (skip == -1)
1072a6af4a17SJohnny Huang 				skip = 1;
107369d5fd8fSJohnny Huang 			continue;
1074a6af4a17SJohnny Huang 		} else {
1075a6af4a17SJohnny Huang 			skip = 0;
107669d5fd8fSJohnny Huang 		}
107769d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
107869d5fd8fSJohnny Huang 			printf("    This bit is protected and is not writable\n");
107969d5fd8fSJohnny Huang 			fail = 1;
108069d5fd8fSJohnny Huang 			continue;
108169d5fd8fSJohnny Huang 		}
108269d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
1083a6af4a17SJohnny Huang 			printf("    This bit is no remaining times to write.\n");
108469d5fd8fSJohnny Huang 			fail = 1;
108569d5fd8fSJohnny Huang 			continue;
108669d5fd8fSJohnny Huang 		}
108769d5fd8fSJohnny Huang 		if (pbit == 1) {
108869d5fd8fSJohnny Huang 			printf("    This bit will be protected and become non-writable.\n");
108969d5fd8fSJohnny Huang 		}
1090a6af4a17SJohnny 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);
109169d5fd8fSJohnny Huang 	}
109269d5fd8fSJohnny Huang 	if (fail == 1)
1093a6af4a17SJohnny Huang 		return OTP_FAILURE;
1094a6af4a17SJohnny Huang 	else if (skip == 1)
1095a6af4a17SJohnny Huang 		return OTP_PROG_SKIP;
10967e22f42dSJohnny Huang 
10977e22f42dSJohnny Huang 	return 0;
109869d5fd8fSJohnny Huang }
109969d5fd8fSJohnny Huang 
11002a856b9aSJohnny Huang static int otp_print_strap(int start, int count)
110169d5fd8fSJohnny Huang {
110269d5fd8fSJohnny Huang 	int i, j;
110366f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
110469d5fd8fSJohnny Huang 
11052a856b9aSJohnny Huang 	if (start < 0 || start > 64)
11062a856b9aSJohnny Huang 		return OTP_USAGE;
11072a856b9aSJohnny Huang 
11082a856b9aSJohnny Huang 	if ((start + count) < 0 || (start + count) > 64)
11092a856b9aSJohnny Huang 		return OTP_USAGE;
11102a856b9aSJohnny Huang 
111169d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
111269d5fd8fSJohnny Huang 
111307baa4e8SJohnny Huang 	printf("BIT(hex)  Value  Option           Status\n");
1114a8bd6d8cSJohnny Huang 	printf("___________________________________________________________________________\n");
1115737ed20bSJohnny Huang 
1116cd1610b4SJohnny Huang 	for (i = start; i < start + count; i++) {
111707baa4e8SJohnny Huang 		printf("0x%-8X", i);
1118737ed20bSJohnny Huang 		printf("%-7d", otpstrap[i].value);
1119737ed20bSJohnny Huang 		for (j = 0; j < 7; j++)
1120737ed20bSJohnny Huang 			printf("%d ", otpstrap[i].option_array[j]);
1121737ed20bSJohnny Huang 		printf("   ");
112269d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
1123737ed20bSJohnny Huang 			printf("protected and not writable");
112469d5fd8fSJohnny Huang 		} else {
1125737ed20bSJohnny Huang 			printf("not protected ");
112669d5fd8fSJohnny Huang 			if (otpstrap[i].remain_times == 0) {
1127737ed20bSJohnny Huang 				printf("and no remaining times to write.");
112869d5fd8fSJohnny Huang 			} else {
1129737ed20bSJohnny Huang 				printf("and still can write %d times", otpstrap[i].remain_times);
113069d5fd8fSJohnny Huang 			}
113169d5fd8fSJohnny Huang 		}
1132737ed20bSJohnny Huang 		printf("\n");
113369d5fd8fSJohnny Huang 	}
11342a856b9aSJohnny Huang 
11352a856b9aSJohnny Huang 	return OTP_SUCCESS;
113669d5fd8fSJohnny Huang }
113769d5fd8fSJohnny Huang 
113869d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf)
113969d5fd8fSJohnny Huang {
114069d5fd8fSJohnny Huang 	int i, j;
114169d5fd8fSJohnny Huang 	uint32_t *strap_keep = buf + 2;
114269d5fd8fSJohnny Huang 	uint32_t *strap_protect = buf + 4;
114369d5fd8fSJohnny Huang 	uint32_t prog_bit, prog_address;
114469d5fd8fSJohnny Huang 	int bit, pbit, kbit, offset;
114569d5fd8fSJohnny Huang 	int fail = 0;
11467e22f42dSJohnny Huang 	int pass = 0;
11477e22f42dSJohnny Huang 	int soak = 0;
114866f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
114969d5fd8fSJohnny Huang 
11507f795e57SJohnny Huang 	printf("Read OTP Strap Region:\n");
115169d5fd8fSJohnny Huang 	otp_strp_status(otpstrap);
115269d5fd8fSJohnny Huang 
11537f795e57SJohnny Huang 	printf("Check writable...\n");
11547f795e57SJohnny Huang 	if (otp_strap_image_confirm(buf) == OTP_FAILURE) {
11557f795e57SJohnny Huang 		printf("Input image can't program into OTP, please check.\n");
11567f795e57SJohnny Huang 		return OTP_FAILURE;
11577f795e57SJohnny Huang 	}
11587e22f42dSJohnny Huang 
11597f795e57SJohnny Huang 	otp_soak(0);
116069d5fd8fSJohnny Huang 	for (i = 0; i < 64; i++) {
11614c1c9b35SJohnny Huang 		printProgress(i + 1, 64, "");
116269d5fd8fSJohnny Huang 		prog_address = 0x800;
116369d5fd8fSJohnny Huang 		if (i < 32) {
116469d5fd8fSJohnny Huang 			offset = i;
116569d5fd8fSJohnny Huang 			bit = (buf[0] >> offset) & 0x1;
116669d5fd8fSJohnny Huang 			kbit = (strap_keep[0] >> offset) & 0x1;
116769d5fd8fSJohnny Huang 			pbit = (strap_protect[0] >> offset) & 0x1;
116869d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200;
116969d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2;
117069d5fd8fSJohnny Huang 
117169d5fd8fSJohnny Huang 		} else {
117269d5fd8fSJohnny Huang 			offset = (i - 32);
117369d5fd8fSJohnny Huang 			bit = (buf[1] >> offset) & 0x1;
117469d5fd8fSJohnny Huang 			kbit = (strap_keep[1] >> offset) & 0x1;
117569d5fd8fSJohnny Huang 			pbit = (strap_protect[1] >> offset) & 0x1;
117669d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200;
117769d5fd8fSJohnny Huang 			prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2;
117869d5fd8fSJohnny Huang 		}
117969d5fd8fSJohnny Huang 		prog_bit = ~(0x1 << offset);
118069d5fd8fSJohnny Huang 
118169d5fd8fSJohnny Huang 		if (kbit == 1) {
118269d5fd8fSJohnny Huang 			continue;
118369d5fd8fSJohnny Huang 		}
118469d5fd8fSJohnny Huang 		if (bit == otpstrap[i].value) {
118569d5fd8fSJohnny Huang 			continue;
118669d5fd8fSJohnny Huang 		}
118769d5fd8fSJohnny Huang 		if (otpstrap[i].protected == 1) {
118869d5fd8fSJohnny Huang 			fail = 1;
118969d5fd8fSJohnny Huang 			continue;
119069d5fd8fSJohnny Huang 		}
119169d5fd8fSJohnny Huang 		if (otpstrap[i].remain_times == 0) {
119269d5fd8fSJohnny Huang 			fail = 1;
119369d5fd8fSJohnny Huang 			continue;
119469d5fd8fSJohnny Huang 		}
11957e22f42dSJohnny Huang 
11967e22f42dSJohnny Huang 		if (soak) {
119769d5fd8fSJohnny Huang 			soak = 0;
11987e22f42dSJohnny Huang 			otp_soak(0);
11997e22f42dSJohnny Huang 		}
12007e22f42dSJohnny Huang 
12017e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
12027e22f42dSJohnny Huang 
12037e22f42dSJohnny Huang 		pass = 0;
12047e22f42dSJohnny Huang 
120569d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
1206a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
120769d5fd8fSJohnny Huang 				pass = 1;
120869d5fd8fSJohnny Huang 				break;
120969d5fd8fSJohnny Huang 			}
12107e22f42dSJohnny Huang 			if (soak == 0) {
121169d5fd8fSJohnny Huang 				soak = 1;
12127e22f42dSJohnny Huang 				otp_soak(1);
12134b65a65dSJohnny Huang 			}
121469d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
121569d5fd8fSJohnny Huang 		}
121669d5fd8fSJohnny Huang 		if (!pass)
12172a856b9aSJohnny Huang 			return OTP_FAILURE;
121869d5fd8fSJohnny Huang 
121969d5fd8fSJohnny Huang 		if (pbit == 0)
122069d5fd8fSJohnny Huang 			continue;
122169d5fd8fSJohnny Huang 		prog_address = 0x800;
122269d5fd8fSJohnny Huang 		if (i < 32)
122369d5fd8fSJohnny Huang 			prog_address |= 0x60c;
122469d5fd8fSJohnny Huang 		else
122569d5fd8fSJohnny Huang 			prog_address |= 0x60e;
122669d5fd8fSJohnny Huang 
12277e22f42dSJohnny Huang 
12287e22f42dSJohnny Huang 		if (soak) {
12297e22f42dSJohnny Huang 			soak = 0;
12307e22f42dSJohnny Huang 			otp_soak(0);
12317e22f42dSJohnny Huang 		}
12327e22f42dSJohnny Huang 
12337e22f42dSJohnny Huang 		otp_prog(prog_address, prog_bit);
12347e22f42dSJohnny Huang 
12357e22f42dSJohnny Huang 		pass = 0;
12367e22f42dSJohnny Huang 
123769d5fd8fSJohnny Huang 		for (j = 0; j < RETRY; j++) {
12387e22f42dSJohnny Huang 
1239a6d0d645SJohnny Huang 			if (verify_bit(prog_address, offset, 1) == 0) {
124069d5fd8fSJohnny Huang 				pass = 1;
124169d5fd8fSJohnny Huang 				break;
124269d5fd8fSJohnny Huang 			}
12437e22f42dSJohnny Huang 			if (soak == 0) {
124469d5fd8fSJohnny Huang 				soak = 1;
12457e22f42dSJohnny Huang 				otp_soak(1);
124669d5fd8fSJohnny Huang 			}
124769d5fd8fSJohnny Huang 			otp_prog(prog_address, prog_bit);
124869d5fd8fSJohnny Huang 		}
124969d5fd8fSJohnny Huang 		if (!pass)
12502a856b9aSJohnny Huang 			return OTP_FAILURE;
125169d5fd8fSJohnny Huang 
125269d5fd8fSJohnny Huang 	}
125369d5fd8fSJohnny Huang 	if (fail == 1)
12542a856b9aSJohnny Huang 		return OTP_FAILURE;
125569d5fd8fSJohnny Huang 	else
12562a856b9aSJohnny Huang 		return OTP_SUCCESS;
125769d5fd8fSJohnny Huang 
125869d5fd8fSJohnny Huang }
125969d5fd8fSJohnny Huang 
1260cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak)
1261cd1610b4SJohnny Huang {
1262cd1610b4SJohnny Huang 	int prog_bit;
1263cd1610b4SJohnny Huang 
12647e22f42dSJohnny Huang 	otp_soak(soak);
12657e22f42dSJohnny Huang 
1266cd1610b4SJohnny Huang 	if (prog_address % 2 == 0) {
1267cd1610b4SJohnny Huang 		if (value)
1268cd1610b4SJohnny Huang 			prog_bit = ~(0x1 << bit_offset);
1269cd1610b4SJohnny Huang 		else
1270cd1610b4SJohnny Huang 			return;
1271cd1610b4SJohnny Huang 	} else {
1272cd1610b4SJohnny Huang 		prog_address |= 1 << 15;
1273cd1610b4SJohnny Huang 		if (!value)
1274cd1610b4SJohnny Huang 			prog_bit = 0x1 << bit_offset;
1275cd1610b4SJohnny Huang 		else
1276cd1610b4SJohnny Huang 			return;
1277cd1610b4SJohnny Huang 	}
1278cd1610b4SJohnny Huang 	otp_prog(prog_address, prog_bit);
1279cd1610b4SJohnny Huang }
1280cd1610b4SJohnny Huang 
1281d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf)
12824c1c9b35SJohnny Huang {
12834c1c9b35SJohnny Huang 	int i, k;
12844c1c9b35SJohnny Huang 	int pass;
1285d90825e2SJohnny Huang 	int soak = 0;
12864c1c9b35SJohnny Huang 	uint32_t prog_address;
1287d90825e2SJohnny Huang 	uint32_t data[2048];
12884c1c9b35SJohnny Huang 	uint32_t compare[2];
1289d90825e2SJohnny Huang 	uint32_t *buf_keep = &buf[2048];
12904c1c9b35SJohnny Huang 
1291d90825e2SJohnny Huang 	uint32_t data0_masked;
1292d90825e2SJohnny Huang 	uint32_t data1_masked;
1293d90825e2SJohnny Huang 	uint32_t buf0_masked;
1294d90825e2SJohnny Huang 	uint32_t buf1_masked;
12954c1c9b35SJohnny Huang 
12964c1c9b35SJohnny Huang 	printf("Read OTP Data:\n");
12974c1c9b35SJohnny Huang 
1298d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1299d90825e2SJohnny Huang 	for (i = 0; i < 2048 ; i += 2) {
1300d90825e2SJohnny Huang 		printProgress(i + 2, 2048, "");
1301d90825e2SJohnny Huang 		otp_read_data(i, &data[i]);
13024c1c9b35SJohnny Huang 	}
1303d90825e2SJohnny Huang 
13044c1c9b35SJohnny Huang 
13054c1c9b35SJohnny Huang 	printf("Check writable...\n");
1306d90825e2SJohnny Huang 	for (i = 0; i < 2048; i++) {
1307d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1308d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1309d90825e2SJohnny Huang 		if (data0_masked == buf0_masked)
13104c1c9b35SJohnny Huang 			continue;
1311d90825e2SJohnny Huang 		if (i % 2 == 0) {
1312d90825e2SJohnny Huang 			if ((data0_masked | buf0_masked) == buf0_masked) {
13134c1c9b35SJohnny Huang 				continue;
13144c1c9b35SJohnny Huang 			} else {
13154c1c9b35SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1316d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
13174c1c9b35SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1318d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
13192a856b9aSJohnny Huang 				return OTP_FAILURE;
132069d5fd8fSJohnny Huang 			}
1321d90825e2SJohnny Huang 		} else {
1322d90825e2SJohnny Huang 			if ((data0_masked & buf0_masked) == buf0_masked) {
1323d90825e2SJohnny Huang 				continue;
1324d90825e2SJohnny Huang 			} else {
1325d90825e2SJohnny Huang 				printf("Input image can't program into OTP, please check.\n");
1326d90825e2SJohnny Huang 				printf("OTP_ADDR[%x] = %x\n", i, data[i]);
1327d90825e2SJohnny Huang 				printf("Input   [%x] = %x\n", i, buf[i]);
1328d90825e2SJohnny Huang 				printf("Mask    [%x] = %x\n", i, ~buf_keep[i]);
13292a856b9aSJohnny Huang 				return OTP_FAILURE;
1330d90825e2SJohnny Huang 			}
1331d90825e2SJohnny Huang 		}
1332d90825e2SJohnny Huang 	}
133369d5fd8fSJohnny Huang 
1334d90825e2SJohnny Huang 	printf("Start Programing...\n");
1335d90825e2SJohnny Huang 	printProgress(0, 2048, "");
1336d90825e2SJohnny Huang 
1337d90825e2SJohnny Huang 	for (i = 0; i < 2048; i += 2) {
1338d90825e2SJohnny Huang 		prog_address = i;
1339d90825e2SJohnny Huang 		data0_masked = data[i]  & ~buf_keep[i];
1340d90825e2SJohnny Huang 		buf0_masked  = buf[i] & ~buf_keep[i];
1341d90825e2SJohnny Huang 		data1_masked = data[i + 1]  & ~buf_keep[i + 1];
1342d90825e2SJohnny Huang 		buf1_masked  = buf[i + 1] & ~buf_keep[i + 1];
1343d90825e2SJohnny Huang 		if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) {
1344d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1345d90825e2SJohnny Huang 			continue;
1346d90825e2SJohnny Huang 		}
1347d90825e2SJohnny Huang 		if (soak) {
1348d90825e2SJohnny Huang 			soak = 0;
1349d90825e2SJohnny Huang 			otp_soak(0);
1350d90825e2SJohnny Huang 		}
1351d90825e2SJohnny Huang 		if (data1_masked == buf1_masked) {
1352d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1353d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1354d90825e2SJohnny Huang 		} else if (data0_masked == buf0_masked) {
1355d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1356d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1357d90825e2SJohnny Huang 		} else {
1358d90825e2SJohnny Huang 			printProgress(i + 2, 2048, "[%03X]=%08X    ;[%03X]=%08X    ", prog_address, buf[i], prog_address + 1, buf[i + 1]);
1359d90825e2SJohnny Huang 			otp_prog_dw(buf[i], buf_keep[i], prog_address);
1360d90825e2SJohnny Huang 			otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1);
1361d90825e2SJohnny Huang 		}
1362d90825e2SJohnny Huang 
1363d90825e2SJohnny Huang 		pass = 0;
1364d90825e2SJohnny Huang 		for (k = 0; k < RETRY; k++) {
1365d90825e2SJohnny Huang 			if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) {
1366d90825e2SJohnny Huang 				if (soak == 0) {
1367d90825e2SJohnny Huang 					soak = 1;
1368d90825e2SJohnny Huang 					otp_soak(1);
1369d90825e2SJohnny Huang 				}
1370d90825e2SJohnny Huang 				if (compare[0] != 0) {
1371d90825e2SJohnny Huang 					otp_prog_dw(compare[0], buf_keep[i], prog_address);
1372d90825e2SJohnny Huang 				}
1373d90825e2SJohnny Huang 				if (compare[1] != ~0) {
1374d90825e2SJohnny Huang 					otp_prog_dw(compare[1], buf_keep[i], prog_address + 1);
1375d90825e2SJohnny Huang 				}
1376d90825e2SJohnny Huang 			} else {
1377d90825e2SJohnny Huang 				pass = 1;
1378d90825e2SJohnny Huang 				break;
1379d90825e2SJohnny Huang 			}
1380d90825e2SJohnny Huang 		}
1381d90825e2SJohnny Huang 
1382d90825e2SJohnny Huang 		if (!pass)
13832a856b9aSJohnny Huang 			return OTP_FAILURE;
1384d90825e2SJohnny Huang 	}
13852a856b9aSJohnny Huang 	return OTP_SUCCESS;
1386d90825e2SJohnny Huang 
1387d90825e2SJohnny Huang }
1388d90825e2SJohnny Huang 
1389d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm)
139069d5fd8fSJohnny Huang {
139169d5fd8fSJohnny Huang 	int ret;
13927332532cSJohnny Huang 	int mode = 0;
139369d5fd8fSJohnny Huang 	uint32_t *buf;
1394d90825e2SJohnny Huang 	uint32_t *data_region = NULL;
1395d90825e2SJohnny Huang 	uint32_t *conf_region = NULL;
1396d90825e2SJohnny Huang 	uint32_t *strap_region = NULL;
139769d5fd8fSJohnny Huang 
1398d90825e2SJohnny Huang 	buf = map_physmem(addr, byte_size, MAP_WRBACK);
139969d5fd8fSJohnny Huang 	if (!buf) {
140069d5fd8fSJohnny Huang 		puts("Failed to map physical memory\n");
14012a856b9aSJohnny Huang 		return OTP_FAILURE;
140269d5fd8fSJohnny Huang 	}
1403d90825e2SJohnny Huang 
1404d90825e2SJohnny Huang 	if (buf[0] & BIT(29)) {
14057332532cSJohnny Huang 		mode |= OTP_REGION_DATA;
14067332532cSJohnny Huang 		data_region = &buf[36];
1407d90825e2SJohnny Huang 	}
1408d90825e2SJohnny Huang 	if (buf[0] & BIT(30)) {
14097332532cSJohnny Huang 		mode |= OTP_REGION_CONF;
14107332532cSJohnny Huang 		conf_region = &buf[12];
1411d90825e2SJohnny Huang 	}
1412d90825e2SJohnny Huang 	if (buf[0] & BIT(31)) {
14137332532cSJohnny Huang 		mode |= OTP_REGION_STRAP;
14147332532cSJohnny Huang 		strap_region = &buf[4];
1415d90825e2SJohnny Huang 	}
14167332532cSJohnny Huang 
141769d5fd8fSJohnny Huang 	if (!nconfirm) {
14187332532cSJohnny Huang 		if (mode & OTP_REGION_DATA) {
14197f795e57SJohnny Huang 			printf("\nOTP data region :\n");
14207f795e57SJohnny Huang 			if (otp_print_data_info(data_region) < 0) {
142169d5fd8fSJohnny Huang 				printf("OTP data error, please check.\n");
14222a856b9aSJohnny Huang 				return OTP_FAILURE;
142369d5fd8fSJohnny Huang 			}
142469d5fd8fSJohnny Huang 		}
14257332532cSJohnny Huang 		if (mode & OTP_REGION_STRAP) {
14267332532cSJohnny Huang 			printf("\nOTP strap region :\n");
14277332532cSJohnny Huang 			if (otp_print_strap_image(strap_region) < 0) {
14287332532cSJohnny Huang 				printf("OTP strap error, please check.\n");
14297332532cSJohnny Huang 				return OTP_FAILURE;
14307332532cSJohnny Huang 			}
14317332532cSJohnny Huang 		}
14327332532cSJohnny Huang 		if (mode & OTP_REGION_CONF) {
14337332532cSJohnny Huang 			printf("\nOTP configuration region :\n");
14347332532cSJohnny Huang 			if (otp_print_conf_image(conf_region) < 0) {
14357332532cSJohnny Huang 				printf("OTP config error, please check.\n");
14367332532cSJohnny Huang 				return OTP_FAILURE;
14377332532cSJohnny Huang 			}
14387332532cSJohnny Huang 		}
14397332532cSJohnny Huang 
144069d5fd8fSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
144169d5fd8fSJohnny Huang 		if (!confirm_yesno()) {
144269d5fd8fSJohnny Huang 			printf(" Aborting\n");
14432a856b9aSJohnny Huang 			return OTP_FAILURE;
144469d5fd8fSJohnny Huang 		}
144569d5fd8fSJohnny Huang 	}
14467332532cSJohnny Huang 
14477332532cSJohnny Huang 	if (mode & OTP_REGION_DATA) {
14487332532cSJohnny Huang 		printf("programing data region ...\n");
1449d90825e2SJohnny Huang 		ret = otp_prog_data(data_region);
14502a856b9aSJohnny Huang 		if (ret != 0) {
145169d5fd8fSJohnny Huang 			printf("Error\n");
145269d5fd8fSJohnny Huang 			return ret;
145369d5fd8fSJohnny Huang 		} else {
145469d5fd8fSJohnny Huang 			printf("Done\n");
145569d5fd8fSJohnny Huang 		}
14567332532cSJohnny Huang 	}
14577332532cSJohnny Huang 	if (mode & OTP_REGION_STRAP) {
14587332532cSJohnny Huang 		printf("programing strap region ...\n");
1459d90825e2SJohnny Huang 		ret = otp_prog_strap(strap_region);
14602a856b9aSJohnny Huang 		if (ret != 0) {
146169d5fd8fSJohnny Huang 			printf("Error\n");
146269d5fd8fSJohnny Huang 			return ret;
146369d5fd8fSJohnny Huang 		} else {
146469d5fd8fSJohnny Huang 			printf("Done\n");
146569d5fd8fSJohnny Huang 		}
14667332532cSJohnny Huang 	}
14677332532cSJohnny Huang 	if (mode & OTP_REGION_CONF) {
14687332532cSJohnny Huang 		printf("programing configuration region ...\n");
1469d90825e2SJohnny Huang 		ret = otp_prog_conf(conf_region);
14702a856b9aSJohnny Huang 		if (ret != 0) {
147169d5fd8fSJohnny Huang 			printf("Error\n");
147269d5fd8fSJohnny Huang 			return ret;
147369d5fd8fSJohnny Huang 		}
147469d5fd8fSJohnny Huang 		printf("Done\n");
147569d5fd8fSJohnny Huang 	}
1476cd1610b4SJohnny Huang 
14777332532cSJohnny Huang 	return OTP_SUCCESS;
14782a856b9aSJohnny Huang }
14792a856b9aSJohnny Huang 
14802a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm)
1481cd1610b4SJohnny Huang {
1482a6af4a17SJohnny Huang 	uint32_t read[2];
1483cd1610b4SJohnny Huang 	uint32_t strap_buf[6];
1484d90825e2SJohnny Huang 	uint32_t prog_address = 0;
148566f2f8e5SJohnny Huang 	struct otpstrap_status otpstrap[64];
1486cd1610b4SJohnny Huang 	int otp_bit;
1487cd1610b4SJohnny Huang 	int i;
1488cd1610b4SJohnny Huang 	int pass;
1489a6af4a17SJohnny Huang 	int ret;
1490cd1610b4SJohnny Huang 
1491cd1610b4SJohnny Huang 	switch (mode) {
1492a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1493a6af4a17SJohnny Huang 		otp_read_config(otp_dw_offset, read);
1494cd1610b4SJohnny Huang 		prog_address = 0x800;
1495cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset / 8) * 0x200;
1496cd1610b4SJohnny Huang 		prog_address |= (otp_dw_offset % 8) * 0x2;
1497a6af4a17SJohnny Huang 		otp_bit = (read[0] >> bit_offset) & 0x1;
1498cd1610b4SJohnny Huang 		if (otp_bit == value) {
1499a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1500cd1610b4SJohnny Huang 			printf("No need to program\n");
15012a856b9aSJohnny Huang 			return OTP_SUCCESS;
1502cd1610b4SJohnny Huang 		}
1503cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1504a6af4a17SJohnny Huang 			printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset);
1505cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
15062a856b9aSJohnny Huang 			return OTP_FAILURE;
1507cd1610b4SJohnny Huang 		}
1508a6af4a17SJohnny Huang 		printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset);
1509cd1610b4SJohnny Huang 		break;
1510a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1511cd1610b4SJohnny Huang 		prog_address = otp_dw_offset;
1512cd1610b4SJohnny Huang 
1513cd1610b4SJohnny Huang 		if (otp_dw_offset % 2 == 0) {
1514a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset, read);
1515a6af4a17SJohnny Huang 			otp_bit = (read[0] >> bit_offset) & 0x1;
1516cd1610b4SJohnny Huang 		} else {
1517a6af4a17SJohnny Huang 			otp_read_data(otp_dw_offset - 1, read);
1518a6af4a17SJohnny Huang 			otp_bit = (read[1] >> bit_offset) & 0x1;
1519cd1610b4SJohnny Huang 		}
1520cd1610b4SJohnny Huang 		if (otp_bit == value) {
1521a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value);
1522cd1610b4SJohnny Huang 			printf("No need to program\n");
15232a856b9aSJohnny Huang 			return OTP_SUCCESS;
1524cd1610b4SJohnny Huang 		}
1525cd1610b4SJohnny Huang 		if (otp_bit == 1 && value == 0) {
1526a6af4a17SJohnny Huang 			printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset);
1527cd1610b4SJohnny Huang 			printf("OTP is programed, which can't be clean\n");
15282a856b9aSJohnny Huang 			return OTP_FAILURE;
1529cd1610b4SJohnny Huang 		}
1530a6af4a17SJohnny Huang 		printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset);
1531cd1610b4SJohnny Huang 		break;
1532a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1533cd1610b4SJohnny Huang 		otp_strp_status(otpstrap);
1534cd1610b4SJohnny Huang 		otp_print_strap(bit_offset, 1);
1535cd1610b4SJohnny Huang 		if (bit_offset < 32) {
1536cd1610b4SJohnny Huang 			strap_buf[0] = value << bit_offset;
1537cd1610b4SJohnny Huang 			strap_buf[2] = ~BIT(bit_offset);
1538cd1610b4SJohnny Huang 			strap_buf[3] = ~0;
1539cd1610b4SJohnny Huang 			strap_buf[5] = 0;
15402a856b9aSJohnny Huang 			// if (protect)
15412a856b9aSJohnny Huang 			// 	strap_buf[4] = BIT(bit_offset);
15422a856b9aSJohnny Huang 			// else
15432a856b9aSJohnny Huang 			// 	strap_buf[4] = 0;
1544cd1610b4SJohnny Huang 		} else {
1545cd1610b4SJohnny Huang 			strap_buf[1] = value << (bit_offset - 32);
1546cd1610b4SJohnny Huang 			strap_buf[2] = ~0;
1547cd1610b4SJohnny Huang 			strap_buf[3] = ~BIT(bit_offset - 32);
1548cd1610b4SJohnny Huang 			strap_buf[4] = 0;
15492a856b9aSJohnny Huang 			// if (protect)
15502a856b9aSJohnny Huang 			// 	strap_buf[5] = BIT(bit_offset - 32);
15512a856b9aSJohnny Huang 			// else
15522a856b9aSJohnny Huang 			// 	strap_buf[5] = 0;
1553cd1610b4SJohnny Huang 		}
155476d13988SJohnny Huang 		ret = otp_strap_image_confirm(strap_buf);
1555a6af4a17SJohnny Huang 		if (ret == OTP_FAILURE)
15562a856b9aSJohnny Huang 			return OTP_FAILURE;
1557a6af4a17SJohnny Huang 		else if (ret == OTP_PROG_SKIP)
1558a6af4a17SJohnny Huang 			return OTP_SUCCESS;
1559a6af4a17SJohnny Huang 
1560cd1610b4SJohnny Huang 		break;
1561cd1610b4SJohnny Huang 	}
1562cd1610b4SJohnny Huang 
1563cd1610b4SJohnny Huang 	if (!nconfirm) {
1564cd1610b4SJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1565cd1610b4SJohnny Huang 		if (!confirm_yesno()) {
1566cd1610b4SJohnny Huang 			printf(" Aborting\n");
15672a856b9aSJohnny Huang 			return OTP_FAILURE;
1568cd1610b4SJohnny Huang 		}
1569cd1610b4SJohnny Huang 	}
1570cd1610b4SJohnny Huang 
1571cd1610b4SJohnny Huang 	switch (mode) {
1572a6d0d645SJohnny Huang 	case OTP_REGION_STRAP:
1573cd1610b4SJohnny Huang 		return otp_prog_strap(strap_buf);
1574a6d0d645SJohnny Huang 	case OTP_REGION_CONF:
1575a6d0d645SJohnny Huang 	case OTP_REGION_DATA:
1576cd1610b4SJohnny Huang 		otp_prog_bit(value, prog_address, bit_offset, 0);
1577cd1610b4SJohnny Huang 		pass = -1;
1578cd1610b4SJohnny Huang 		for (i = 0; i < RETRY; i++) {
1579a6d0d645SJohnny Huang 			if (verify_bit(prog_address, bit_offset, value) != 0) {
1580cd1610b4SJohnny Huang 				otp_prog_bit(value, prog_address, bit_offset, 1);
1581cd1610b4SJohnny Huang 			} else {
1582cd1610b4SJohnny Huang 				pass = 0;
1583cd1610b4SJohnny Huang 				break;
1584cd1610b4SJohnny Huang 			}
1585cd1610b4SJohnny Huang 		}
15862a856b9aSJohnny Huang 		if (pass == 0)
15872a856b9aSJohnny Huang 			return OTP_SUCCESS;
1588cd1610b4SJohnny Huang 	}
1589cd1610b4SJohnny Huang 
15902a856b9aSJohnny Huang 	return OTP_USAGE;
1591cd1610b4SJohnny Huang }
1592cd1610b4SJohnny Huang 
15932a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
159469d5fd8fSJohnny Huang {
15952a856b9aSJohnny Huang 	uint32_t offset, count;
15962a856b9aSJohnny Huang 	int ret;
159769d5fd8fSJohnny Huang 
15982a856b9aSJohnny Huang 	if (argc == 4) {
15992a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
16002a856b9aSJohnny Huang 		count = simple_strtoul(argv[3], NULL, 16);
16012a856b9aSJohnny Huang 	} else if (argc == 3) {
16022a856b9aSJohnny Huang 		offset = simple_strtoul(argv[2], NULL, 16);
16032a856b9aSJohnny Huang 		count = 1;
16042a856b9aSJohnny Huang 	} else {
160569d5fd8fSJohnny Huang 		return CMD_RET_USAGE;
160669d5fd8fSJohnny Huang 	}
160769d5fd8fSJohnny Huang 
160869d5fd8fSJohnny Huang 
16092a856b9aSJohnny Huang 	if (!strcmp(argv[1], "conf")) {
161069d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
16112a856b9aSJohnny Huang 		ret = otp_print_config(offset, count);
16122a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "data")) {
16132a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
16142a856b9aSJohnny Huang 		ret = otp_print_data(offset, count);
16152a856b9aSJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
16162a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
16172a856b9aSJohnny Huang 		ret = otp_print_strap(offset, count);
16182a856b9aSJohnny Huang 	} else {
16192a856b9aSJohnny Huang 		return CMD_RET_USAGE;
162069d5fd8fSJohnny Huang 	}
162169d5fd8fSJohnny Huang 
16222a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
16232a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
16242a856b9aSJohnny Huang 	else
16252a856b9aSJohnny Huang 		return CMD_RET_USAGE;
16262a856b9aSJohnny Huang 
16272a856b9aSJohnny Huang }
16282a856b9aSJohnny Huang 
16292a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
16302a856b9aSJohnny Huang {
16312a856b9aSJohnny Huang 	phys_addr_t addr;
16322a856b9aSJohnny Huang 	uint32_t byte_size;
16332a856b9aSJohnny Huang 	int ret;
16342a856b9aSJohnny Huang 
16352a856b9aSJohnny Huang 	if (argc == 4) {
16362a856b9aSJohnny Huang 		if (strcmp(argv[1], "f"))
16372a856b9aSJohnny Huang 			return CMD_RET_USAGE;
16382a856b9aSJohnny Huang 		addr = simple_strtoul(argv[2], NULL, 16);
16392a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[3], NULL, 16);
164069d5fd8fSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
16412a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 1);
16422a856b9aSJohnny Huang 	} else if (argc == 3) {
16432a856b9aSJohnny Huang 		addr = simple_strtoul(argv[1], NULL, 16);
16442a856b9aSJohnny Huang 		byte_size = simple_strtoul(argv[2], NULL, 16);
16452a856b9aSJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
16462a856b9aSJohnny Huang 		ret = do_otp_prog(addr, byte_size, 0);
16472a856b9aSJohnny Huang 	} else {
16482a856b9aSJohnny Huang 		return CMD_RET_USAGE;
16492a856b9aSJohnny Huang 	}
16502a856b9aSJohnny Huang 
16512a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
16522a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
16532a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
16542a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
16552a856b9aSJohnny Huang 	else
16562a856b9aSJohnny Huang 		return CMD_RET_USAGE;
16572a856b9aSJohnny Huang }
16582a856b9aSJohnny Huang 
16592a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
16602a856b9aSJohnny Huang {
16612a856b9aSJohnny Huang 	int mode = 0;
16622a856b9aSJohnny Huang 	int nconfirm = 0;
16632a856b9aSJohnny Huang 	int otp_addr = 0;
16642a856b9aSJohnny Huang 	int bit_offset;
16652a856b9aSJohnny Huang 	int value;
16662a856b9aSJohnny Huang 	int ret;
16672a856b9aSJohnny Huang 
16682a856b9aSJohnny Huang 	if (argc != 4 && argc != 5 && argc != 6)
16692a856b9aSJohnny Huang 		return CMD_RET_USAGE;
16702a856b9aSJohnny Huang 
16712a856b9aSJohnny Huang 	/* Drop the pb cmd */
16722a856b9aSJohnny Huang 	argc--;
16732a856b9aSJohnny Huang 	argv++;
16742a856b9aSJohnny Huang 
16752a856b9aSJohnny Huang 	if (!strcmp(argv[0], "conf"))
1676a6d0d645SJohnny Huang 		mode = OTP_REGION_CONF;
16772a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "strap"))
1678a6d0d645SJohnny Huang 		mode = OTP_REGION_STRAP;
16792a856b9aSJohnny Huang 	else if (!strcmp(argv[0], "data"))
1680a6d0d645SJohnny Huang 		mode = OTP_REGION_DATA;
1681cd1610b4SJohnny Huang 	else
16822a856b9aSJohnny Huang 		return CMD_RET_USAGE;
16832a856b9aSJohnny Huang 
16842a856b9aSJohnny Huang 	/* Drop the region cmd */
16852a856b9aSJohnny Huang 	argc--;
16862a856b9aSJohnny Huang 	argv++;
16872a856b9aSJohnny Huang 
16882a856b9aSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1689cd1610b4SJohnny Huang 		nconfirm = 1;
16902a856b9aSJohnny Huang 		/* Drop the force option */
16912a856b9aSJohnny Huang 		argc--;
16922a856b9aSJohnny Huang 		argv++;
16932a856b9aSJohnny Huang 	}
1694cd1610b4SJohnny Huang 
1695a6d0d645SJohnny Huang 	if (mode == OTP_REGION_STRAP) {
16962a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[0], NULL, 16);
16972a856b9aSJohnny Huang 		value = simple_strtoul(argv[1], NULL, 16);
1698cd1610b4SJohnny Huang 		if (bit_offset >= 64)
16992a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1700cd1610b4SJohnny Huang 	} else {
17012a856b9aSJohnny Huang 		otp_addr = simple_strtoul(argv[0], NULL, 16);
17022a856b9aSJohnny Huang 		bit_offset = simple_strtoul(argv[1], NULL, 16);
17032a856b9aSJohnny Huang 		value = simple_strtoul(argv[2], NULL, 16);
1704cd1610b4SJohnny Huang 		if (bit_offset >= 32)
17052a856b9aSJohnny Huang 			return CMD_RET_USAGE;
1706cd1610b4SJohnny Huang 	}
1707cd1610b4SJohnny Huang 	if (value != 0 && value != 1)
17082a856b9aSJohnny Huang 		return CMD_RET_USAGE;
1709cd1610b4SJohnny Huang 
1710cd1610b4SJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
17112a856b9aSJohnny Huang 	ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm);
17122a856b9aSJohnny Huang 
17132a856b9aSJohnny Huang 	if (ret == OTP_SUCCESS)
17142a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
17152a856b9aSJohnny Huang 	else if (ret == OTP_FAILURE)
17162a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
17172a856b9aSJohnny Huang 	else
17182a856b9aSJohnny Huang 		return CMD_RET_USAGE;
17192a856b9aSJohnny Huang }
17202a856b9aSJohnny Huang 
17212a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
17222a856b9aSJohnny Huang {
17232a856b9aSJohnny Huang 	phys_addr_t addr;
17242a856b9aSJohnny Huang 	int otp_addr = 0;
17252a856b9aSJohnny Huang 
17262a856b9aSJohnny Huang 	if (argc != 3)
17272a856b9aSJohnny Huang 		return CMD_RET_USAGE;
17282a856b9aSJohnny Huang 
172969d5fd8fSJohnny Huang 	writel(OTP_PASSWD, 0x1e6f2000); //password
17302a856b9aSJohnny Huang 	addr = simple_strtoul(argv[1], NULL, 16);
17312a856b9aSJohnny Huang 	otp_addr = simple_strtoul(argv[2], NULL, 16);
17322a856b9aSJohnny Huang 	if (otp_compare(otp_addr, addr) == 0) {
173369d5fd8fSJohnny Huang 		printf("Compare pass\n");
17342a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
173569d5fd8fSJohnny Huang 	} else {
173669d5fd8fSJohnny Huang 		printf("Compare fail\n");
17372a856b9aSJohnny Huang 		return CMD_RET_FAILURE;
173869d5fd8fSJohnny Huang 	}
173969d5fd8fSJohnny Huang }
174069d5fd8fSJohnny Huang 
174166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
174266f2f8e5SJohnny Huang {
1743a8bd6d8cSJohnny Huang 	int view = 0;
17442d4b0742SJohnny Huang 	int input;
1745a8bd6d8cSJohnny Huang 
1746a8bd6d8cSJohnny Huang 	if (argc != 2 && argc != 3)
174766f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
174866f2f8e5SJohnny Huang 
17492d4b0742SJohnny Huang 	if (!strcmp(argv[1], "conf")) {
175066f2f8e5SJohnny Huang 
17512d4b0742SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
17522d4b0742SJohnny Huang 		if (argc == 3) {
17532d4b0742SJohnny Huang 			input = simple_strtoul(argv[2], NULL, 16);
17542d4b0742SJohnny Huang 			otp_print_conf_info(input);
17552d4b0742SJohnny Huang 		} else {
17562d4b0742SJohnny Huang 			otp_print_conf_info(-1);
17572d4b0742SJohnny Huang 		}
17582d4b0742SJohnny Huang 	} else if (!strcmp(argv[1], "strap")) {
17592d4b0742SJohnny Huang 		if (!strcmp(argv[2], "v")) {
1760a8bd6d8cSJohnny Huang 			view = 1;
1761a8bd6d8cSJohnny Huang 			/* Drop the view option */
1762a8bd6d8cSJohnny Huang 			argc--;
1763a8bd6d8cSJohnny Huang 			argv++;
1764a8bd6d8cSJohnny Huang 		}
176566f2f8e5SJohnny Huang 		writel(OTP_PASSWD, 0x1e6f2000); //password
1766b458cd62SJohnny Huang 		otp_print_strap_info(view);
176766f2f8e5SJohnny Huang 	} else {
176866f2f8e5SJohnny Huang 		return CMD_RET_USAGE;
176966f2f8e5SJohnny Huang 	}
17702d4b0742SJohnny Huang 
177166f2f8e5SJohnny Huang 	return CMD_RET_SUCCESS;
177266f2f8e5SJohnny Huang }
177366f2f8e5SJohnny Huang 
1774737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1775737ed20bSJohnny Huang {
1776737ed20bSJohnny Huang 	int input;
1777737ed20bSJohnny Huang 	int bit_offset;
1778737ed20bSJohnny Huang 	int prog_address;
1779737ed20bSJohnny Huang 	int pass;
1780737ed20bSJohnny Huang 	int i;
1781737ed20bSJohnny Huang 	if (argc != 3 && argc != 2)
1782737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1783737ed20bSJohnny Huang 
1784737ed20bSJohnny Huang 	if (!strcmp(argv[0], "f")) {
1785737ed20bSJohnny Huang 		input = simple_strtoul(argv[2], NULL, 16);
1786737ed20bSJohnny Huang 	} else {
1787737ed20bSJohnny Huang 		input = simple_strtoul(argv[1], NULL, 16);
1788737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] will be protected\n", input);
1789737ed20bSJohnny Huang 		printf("type \"YES\" (no quotes) to continue:\n");
1790737ed20bSJohnny Huang 		if (!confirm_yesno()) {
1791737ed20bSJohnny Huang 			printf(" Aborting\n");
1792737ed20bSJohnny Huang 			return CMD_RET_FAILURE;
1793737ed20bSJohnny Huang 		}
1794737ed20bSJohnny Huang 	}
1795737ed20bSJohnny Huang 
1796737ed20bSJohnny Huang 	prog_address = 0x800;
1797737ed20bSJohnny Huang 	if (input < 32) {
1798737ed20bSJohnny Huang 		bit_offset = input;
1799737ed20bSJohnny Huang 		prog_address |= 0x60c;
1800737ed20bSJohnny Huang 	} else if (input < 64) {
1801737ed20bSJohnny Huang 		bit_offset = input - 32;
1802737ed20bSJohnny Huang 		prog_address |= 0x60e;
1803737ed20bSJohnny Huang 	} else {
1804737ed20bSJohnny Huang 		return CMD_RET_USAGE;
1805737ed20bSJohnny Huang 	}
1806737ed20bSJohnny Huang 
1807737ed20bSJohnny Huang 	if (verify_bit(prog_address, bit_offset, 1) == 0) {
1808737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] already protected\n", input);
1809737ed20bSJohnny Huang 	}
1810737ed20bSJohnny Huang 	otp_prog_bit(1, prog_address, bit_offset, 0);
1811737ed20bSJohnny Huang 	pass = -1;
1812737ed20bSJohnny Huang 	for (i = 0; i < RETRY; i++) {
1813737ed20bSJohnny Huang 		if (verify_bit(prog_address, bit_offset, 1) != 0) {
1814737ed20bSJohnny Huang 			otp_prog_bit(1, prog_address, bit_offset, 1);
1815737ed20bSJohnny Huang 		} else {
1816737ed20bSJohnny Huang 			pass = 0;
1817737ed20bSJohnny Huang 			break;
1818737ed20bSJohnny Huang 		}
1819737ed20bSJohnny Huang 	}
1820737ed20bSJohnny Huang 	if (pass == 0) {
1821737ed20bSJohnny Huang 		printf("OTPSTRAP[%d] is protected\n", input);
1822737ed20bSJohnny Huang 		return CMD_RET_SUCCESS;
1823737ed20bSJohnny Huang 	}
1824737ed20bSJohnny Huang 
1825737ed20bSJohnny Huang 	printf("Protect OTPSTRAP[%d] fail\n", input);
1826737ed20bSJohnny Huang 	return CMD_RET_FAILURE;
1827737ed20bSJohnny Huang 
1828737ed20bSJohnny Huang }
18292a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = {
18302a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""),
1831a8bd6d8cSJohnny Huang 	U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""),
18322a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""),
18332a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""),
1834737ed20bSJohnny Huang 	U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""),
18352a856b9aSJohnny Huang 	U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""),
18362a856b9aSJohnny Huang };
18372a856b9aSJohnny Huang 
18382a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
18392a856b9aSJohnny Huang {
18402a856b9aSJohnny Huang 	cmd_tbl_t *cp;
18412a856b9aSJohnny Huang 
18422a856b9aSJohnny Huang 	cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp));
18432a856b9aSJohnny Huang 
1844737ed20bSJohnny Huang 	/* Drop the otp command */
18452a856b9aSJohnny Huang 	argc--;
18462a856b9aSJohnny Huang 	argv++;
18472a856b9aSJohnny Huang 
18482a856b9aSJohnny Huang 	if (cp == NULL || argc > cp->maxargs)
18492a856b9aSJohnny Huang 		return CMD_RET_USAGE;
18502a856b9aSJohnny Huang 	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
18512a856b9aSJohnny Huang 		return CMD_RET_SUCCESS;
18522a856b9aSJohnny Huang 
18532a856b9aSJohnny Huang 	return cp->cmd(cmdtp, flag, argc, argv);
185469d5fd8fSJohnny Huang }
185569d5fd8fSJohnny Huang 
185669d5fd8fSJohnny Huang U_BOOT_CMD(
185769d5fd8fSJohnny Huang 	otp, 7, 0,  do_ast_otp,
185869d5fd8fSJohnny Huang 	"ASPEED One-Time-Programmable sub-system",
18592a856b9aSJohnny Huang 	"read conf|data <otp_dw_offset> <dw_count>\n"
18602a856b9aSJohnny Huang 	"otp read strap <strap_bit_offset> <bit_count>\n"
18612d4b0742SJohnny Huang 	"otp info strap [v]\n"
18622d4b0742SJohnny Huang 	"otp info conf [otp_dw_offset]\n"
1863d90825e2SJohnny Huang 	"otp prog [f] <addr> <byte_size>\n"
1864cd1610b4SJohnny Huang 	"otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n"
1865737ed20bSJohnny Huang 	"otp pb strap [f] <bit_offset> <value>\n"
1866737ed20bSJohnny Huang 	"otp protect [f] <bit_offset>\n"
18672a856b9aSJohnny Huang 	"otp cmp <addr> <otp_dw_offset>\n"
186869d5fd8fSJohnny Huang );
1869