169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 429a4fe690SJohnny Huang 439a4fe690SJohnny Huang 44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 45b458cd62SJohnny Huang #define OTP_REG_VALUE -2 46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4776d13988SJohnny Huang 484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 494c1c9b35SJohnny Huang #define PBWIDTH 60 504c1c9b35SJohnny Huang 513d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 523d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 533d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 543d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 553d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 563d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 573d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 583d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 593d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 603d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 613d3688adSJohnny Huang 6266f2f8e5SJohnny Huang struct otpstrap_status { 6369d5fd8fSJohnny Huang int value; 6469d5fd8fSJohnny Huang int option_array[7]; 6569d5fd8fSJohnny Huang int remain_times; 6669d5fd8fSJohnny Huang int writeable_option; 6769d5fd8fSJohnny Huang int protected; 6869d5fd8fSJohnny Huang }; 6969d5fd8fSJohnny Huang 7066f2f8e5SJohnny Huang struct otpconf_parse { 7166f2f8e5SJohnny Huang int dw_offset; 7266f2f8e5SJohnny Huang int bit; 7366f2f8e5SJohnny Huang int length; 7466f2f8e5SJohnny Huang int value; 7566f2f8e5SJohnny Huang int keep; 7666f2f8e5SJohnny Huang char status[80]; 7766f2f8e5SJohnny Huang }; 7866f2f8e5SJohnny Huang 79a8bd6d8cSJohnny Huang struct otpstrap_info { 80a8bd6d8cSJohnny Huang uint32_t bit_offset; 81a8bd6d8cSJohnny Huang uint32_t length; 8276d13988SJohnny Huang int value; 83a8bd6d8cSJohnny Huang char information[80]; 84a8bd6d8cSJohnny Huang }; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang struct otpconf_info { 87a8bd6d8cSJohnny Huang uint32_t dw_offset; 88a8bd6d8cSJohnny Huang uint32_t bit_offset; 89a8bd6d8cSJohnny Huang uint32_t length; 90a8bd6d8cSJohnny Huang int value; 91a8bd6d8cSJohnny Huang char information[80]; 92a8bd6d8cSJohnny Huang }; 93a8bd6d8cSJohnny Huang 949a4fe690SJohnny Huang struct otpkey_type { 959a4fe690SJohnny Huang int value; 969a4fe690SJohnny Huang int key_type; 979a4fe690SJohnny Huang int need_id; 989a4fe690SJohnny Huang char information[110]; 999a4fe690SJohnny Huang }; 1009a4fe690SJohnny Huang 1019a4fe690SJohnny Huang struct otp_info_cb { 1029a4fe690SJohnny Huang int version; 1039a4fe690SJohnny Huang struct otpstrap_info *strap_info; 1049a4fe690SJohnny Huang int strap_info_len; 1059a4fe690SJohnny Huang struct otpconf_info *conf_info; 1069a4fe690SJohnny Huang int conf_info_len; 1079a4fe690SJohnny Huang struct otpkey_type *key_info; 1089a4fe690SJohnny Huang int key_info_len; 1099a4fe690SJohnny Huang }; 1109a4fe690SJohnny Huang 111a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 112a8bd6d8cSJohnny Huang { 113a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 114a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 115a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 116a8bd6d8cSJohnny Huang char buffer[256]; 117a8bd6d8cSJohnny Huang va_list aptr; 118a8bd6d8cSJohnny Huang 119a8bd6d8cSJohnny Huang va_start(aptr, format); 120a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 121a8bd6d8cSJohnny Huang va_end(aptr); 122a8bd6d8cSJohnny Huang 123a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 124a8bd6d8cSJohnny Huang if (numerator == denominator) 125a8bd6d8cSJohnny Huang printf("\n"); 126a8bd6d8cSJohnny Huang } 127a8bd6d8cSJohnny Huang 1289a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1299a4fe690SJohnny Huang 130a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 13191448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 13291448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 13391448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 13491448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 13591448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 13691448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 13791448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 13891448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 139541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 14091448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 14191448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 14291448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 14391448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 14491448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 14591448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 14691448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 14791448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 14891448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 14991448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 15091448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 15191448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 15291448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 15391448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 15491448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 15591448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 15691448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 15791448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 15891448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 15991448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 16091448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 16191448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 16291448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 16391448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 16491448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 16591448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 16691448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 16791448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 16891448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 16991448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 17091448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 17191448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 17291448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 17391448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 17491448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 17591448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 17691448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 17791448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 17891448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 17991448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 18091448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 18191448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 18291448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 18391448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 18491448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 18591448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 18691448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 18791448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 18891448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 18991448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 19091448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 19191448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 19291448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 19391448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 19491448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 19591448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 19691448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 19791448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 19891448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 19991448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 20091448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 20191448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 20291448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 20391448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 20491448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 20591448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 20691448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 20791448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 20891448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 20991448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 21091448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 21191448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 21291448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 21391448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 21491448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 21591448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 21691448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 21791448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 21891448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 21991448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 22091448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 22191448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 22291448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 22391448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 22491448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 22591448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 22691448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 22791448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 22891448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 22991448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 23091448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 23191448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 23291448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 23391448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 23491448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 23591448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 23691448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 23791448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 23891448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 23991448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 24076d13988SJohnny Huang }; 2419a4fe690SJohnny Huang 2423cb28812SJohnny Huang struct otpstrap_info a1_strap_info[] = { 2433cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2443cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2453cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2463cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2473cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2483cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2493cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2503cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2513cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2523cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2533cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2543cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2553cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2563cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2573cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2583cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2593cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2603cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2613cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2623cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2633cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2643cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2653cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2663cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2673cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2683cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2693cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2703cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2713cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2723cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2733cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2743cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2753cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2763cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2773cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2783cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2793cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2803cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2813cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 2823cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 2833cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 2843cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 2853cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 2863cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 2873cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 2883cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 2893cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 2903cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 2913cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 2923cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 2933cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 2943cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 2953cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 2963cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 2973cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 2983cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 2993cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 3003cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 3013cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 3023cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 3033cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 3043cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 3053cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 3063cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 3073cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 3083cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 3093cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 3103cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 3113cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 3123cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 3133cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 3143cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 3153cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 3163cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3173cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3183cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3193cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3203cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3213cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3223cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3233cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3243cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3253cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3263cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3273cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3283cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3293cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3303cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3313cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3323cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3333cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3343cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3353cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3363cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3373cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3383cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3393cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3403cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3413cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3423cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3433cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3443cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3453cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3463cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3473cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3483cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3493cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3503cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3513cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3523cb28812SJohnny Huang }; 3533cb28812SJohnny Huang 354b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 35591448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 35691448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 35791448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 35891448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 35991448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 36091448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 36191448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 36291448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 36391448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 36491448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 36591448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 36691448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 36791448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 36891448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 36991448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 37091448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 37191448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 372541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 37391448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 37491448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 37591448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 37691448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 37791448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 37891448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 37991448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 38091448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 38191448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 38291448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 38391448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 38491448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 38591448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 38691448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 38791448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 38891448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 38991448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 39091448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 39191448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 39291448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 39391448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 39491448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 39591448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 39691448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 39791448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 39891448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 3993cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4003cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4013cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4023cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 4033cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 4043cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 4053cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 4063cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 4073cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 4083cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 4093cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 4103cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 4113cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 4123cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 4133cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 4143cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 4153cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 4163cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4173cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4183cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4193cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4203cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4213cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4223cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4233cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4243cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4253cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4263cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4273cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4283cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4293cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4303cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4313cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4323cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4333cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4343cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4353cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4363cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4373cb28812SJohnny Huang }; 4383cb28812SJohnny Huang 4393cb28812SJohnny Huang struct otpconf_info a1_conf_info[] = { 4403cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4413cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4423cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4433cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4443cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4453cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4463cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4473cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4483cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4493cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4503cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4513cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4523cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4533cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4543cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4553cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4563cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4573cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4583cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4593cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4603cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4613cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4623cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4633cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4643cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4653cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 4663cb28812SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 4673cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4683cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4693cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4703cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4713cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4723cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4733cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4743cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4753cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4763cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4773cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4783cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4793cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4803cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4813cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4823cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4833cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4843cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4853cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4863cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 48791448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 48891448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 48991448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 49073f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 49173f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 49291448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 49391448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 49491448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 49591448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 49691448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 49791448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 49891448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 49991448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 50091448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 50191448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 50291448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 50391448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 50491448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 50591448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 50691448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 50791448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 50891448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 50991448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 51091448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 51191448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 51291448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 51391448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 51491448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 51591448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 51691448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 51791448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 51891448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 51991448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 52091448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 521b458cd62SJohnny Huang }; 5229a4fe690SJohnny Huang 5239a4fe690SJohnny Huang struct otpkey_type a0_key_type[] = { 5249a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5259a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5269a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5279a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5289a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5299a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5309a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5319a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5329a4fe690SJohnny Huang }; 5339a4fe690SJohnny Huang 5349a4fe690SJohnny Huang struct otpkey_type a1_key_type[] = { 5359a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5369a4fe690SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 5379a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5389a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5399a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5409a4fe690SJohnny Huang }; 5419a4fe690SJohnny Huang 5429a4fe690SJohnny Huang static uint32_t chip_version(void) 5439a4fe690SJohnny Huang { 5449a4fe690SJohnny Huang uint32_t rev_id; 5459a4fe690SJohnny Huang 5469a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5479a4fe690SJohnny Huang 5489a4fe690SJohnny Huang return rev_id; 5499a4fe690SJohnny Huang } 5509a4fe690SJohnny Huang 5513d3688adSJohnny Huang static void wait_complete(void) 5523d3688adSJohnny Huang { 5533d3688adSJohnny Huang int reg; 5543d3688adSJohnny Huang 5553d3688adSJohnny Huang do { 5563d3688adSJohnny Huang reg = readl(OTP_STATUS); 5573d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5583d3688adSJohnny Huang } 5593d3688adSJohnny Huang 5602a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 56169d5fd8fSJohnny Huang { 5623d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5633d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5643d3688adSJohnny Huang wait_complete(); 5653d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5663d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 56769d5fd8fSJohnny Huang } 56869d5fd8fSJohnny Huang 5692a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 57069d5fd8fSJohnny Huang { 57169d5fd8fSJohnny Huang int config_offset; 57269d5fd8fSJohnny Huang 57369d5fd8fSJohnny Huang config_offset = 0x800; 57469d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 57569d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 57669d5fd8fSJohnny Huang 5773d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 5783d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5793d3688adSJohnny Huang wait_complete(); 5803d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 58169d5fd8fSJohnny Huang } 58269d5fd8fSJohnny Huang 58369d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 58469d5fd8fSJohnny Huang { 58569d5fd8fSJohnny Huang int i; 58669d5fd8fSJohnny Huang uint32_t ret[1]; 58769d5fd8fSJohnny Huang 58869d5fd8fSJohnny Huang if (offset + dw_count > 32) 5892a856b9aSJohnny Huang return OTP_USAGE; 59069d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 59169d5fd8fSJohnny Huang otp_read_config(i, ret); 592a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 59369d5fd8fSJohnny Huang } 59469d5fd8fSJohnny Huang printf("\n"); 5952a856b9aSJohnny Huang return OTP_SUCCESS; 59669d5fd8fSJohnny Huang } 59769d5fd8fSJohnny Huang 59869d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 59969d5fd8fSJohnny Huang { 60069d5fd8fSJohnny Huang int i; 60169d5fd8fSJohnny Huang uint32_t ret[2]; 60269d5fd8fSJohnny Huang 60369d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 6042a856b9aSJohnny Huang return OTP_USAGE; 60569d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 60669d5fd8fSJohnny Huang otp_read_data(i, ret); 60769d5fd8fSJohnny Huang if (i % 4 == 0) 60869d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 60969d5fd8fSJohnny Huang else 61069d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 61169d5fd8fSJohnny Huang 61269d5fd8fSJohnny Huang } 61369d5fd8fSJohnny Huang printf("\n"); 6142a856b9aSJohnny Huang return OTP_SUCCESS; 61569d5fd8fSJohnny Huang } 61669d5fd8fSJohnny Huang 61769d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 61869d5fd8fSJohnny Huang { 61969d5fd8fSJohnny Huang uint32_t ret; 62069d5fd8fSJohnny Huang uint32_t *buf; 62169d5fd8fSJohnny Huang 62269d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 62369d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 62469d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 62569d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 62669d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6273d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6283d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6293d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6303d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6313d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6323d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6333d3688adSJohnny Huang wait_complete(); 6343d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 63569d5fd8fSJohnny Huang if (ret & 0x1) 63669d5fd8fSJohnny Huang return 0; 63769d5fd8fSJohnny Huang else 63869d5fd8fSJohnny Huang return -1; 63969d5fd8fSJohnny Huang } 64069d5fd8fSJohnny Huang 64169d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 64269d5fd8fSJohnny Huang { 6433d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6443d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6453d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6463d3688adSJohnny Huang wait_complete(); 64769d5fd8fSJohnny Huang } 64869d5fd8fSJohnny Huang 64969d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 65069d5fd8fSJohnny Huang { 6513d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6523d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6533d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6543d3688adSJohnny Huang wait_complete(); 65569d5fd8fSJohnny Huang } 65669d5fd8fSJohnny Huang 657a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 65869d5fd8fSJohnny Huang { 65930a8c590SJohnny Huang uint32_t ret[2]; 66069d5fd8fSJohnny Huang 66130a8c590SJohnny Huang if (otp_addr % 2 == 0) 6623d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 66330a8c590SJohnny Huang else 6643d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 66530a8c590SJohnny Huang 6663d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6673d3688adSJohnny Huang wait_complete(); 6683d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6693d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 670a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 67130a8c590SJohnny Huang if (otp_addr % 2 == 0) { 67230a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 67369d5fd8fSJohnny Huang return 0; 67469d5fd8fSJohnny Huang else 67569d5fd8fSJohnny Huang return -1; 67630a8c590SJohnny Huang } else { 67730a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 67830a8c590SJohnny Huang return 0; 67930a8c590SJohnny Huang else 68030a8c590SJohnny Huang return -1; 68130a8c590SJohnny Huang } 68230a8c590SJohnny Huang 68369d5fd8fSJohnny Huang } 68469d5fd8fSJohnny Huang 685d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6864c1c9b35SJohnny Huang { 6874c1c9b35SJohnny Huang uint32_t ret[2]; 6884c1c9b35SJohnny Huang 6894c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6904c1c9b35SJohnny Huang 6914c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6923d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 6934c1c9b35SJohnny Huang else 6943d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 6953d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6963d3688adSJohnny Huang wait_complete(); 6973d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6983d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 6994c1c9b35SJohnny Huang if (size == 1) { 7004c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 7014c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 702d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 7034c1c9b35SJohnny Huang compare[0] = 0; 7044c1c9b35SJohnny Huang return 0; 7054c1c9b35SJohnny Huang } else { 7064c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7074c1c9b35SJohnny Huang return -1; 7084c1c9b35SJohnny Huang } 7094c1c9b35SJohnny Huang 7104c1c9b35SJohnny Huang } else { 7114c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 712d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 7134c1c9b35SJohnny Huang compare[0] = ~0; 7144c1c9b35SJohnny Huang return 0; 7154c1c9b35SJohnny Huang } else { 716d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7174c1c9b35SJohnny Huang return -1; 7184c1c9b35SJohnny Huang } 7194c1c9b35SJohnny Huang } 7204c1c9b35SJohnny Huang } else if (size == 2) { 7214c1c9b35SJohnny Huang // otp_addr should be even 722d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7234c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7244c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7254c1c9b35SJohnny Huang compare[0] = 0; 7264c1c9b35SJohnny Huang compare[1] = ~0; 7274c1c9b35SJohnny Huang return 0; 7284c1c9b35SJohnny Huang } else { 7294c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7304c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7314c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7324c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7334c1c9b35SJohnny Huang return -1; 7344c1c9b35SJohnny Huang } 7354c1c9b35SJohnny Huang } else { 7364c1c9b35SJohnny Huang return -1; 7374c1c9b35SJohnny Huang } 7384c1c9b35SJohnny Huang } 7394c1c9b35SJohnny Huang 7407e22f42dSJohnny Huang static void otp_soak(int soak) 741d90825e2SJohnny Huang { 742*de6fbf1cSJohnny Huang switch (soak) { 743*de6fbf1cSJohnny Huang case 0: //default 744*de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 745*de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 746*de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 747*de6fbf1cSJohnny Huang break; 748*de6fbf1cSJohnny Huang case 1: //normal program 749*de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 750*de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 751*de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 752*de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 753*de6fbf1cSJohnny Huang break; 754*de6fbf1cSJohnny Huang case 2: //soak program 755d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 756d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 757d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 758*de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 759*de6fbf1cSJohnny Huang break; 760d90825e2SJohnny Huang } 761*de6fbf1cSJohnny Huang 7623d3688adSJohnny Huang wait_complete(); 763d90825e2SJohnny Huang } 764d90825e2SJohnny Huang 765d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 766d90825e2SJohnny Huang { 767d90825e2SJohnny Huang int j, bit_value, prog_bit; 768d90825e2SJohnny Huang 769d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 770d90825e2SJohnny Huang if ((keep >> j) & 0x1) 771d90825e2SJohnny Huang continue; 772d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 773d90825e2SJohnny Huang if (prog_address % 2 == 0) { 774d90825e2SJohnny Huang if (bit_value) 775d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 776d90825e2SJohnny Huang else 777d90825e2SJohnny Huang continue; 778d90825e2SJohnny Huang } else { 779d90825e2SJohnny Huang prog_address |= 1 << 15; 780d90825e2SJohnny Huang if (bit_value) 781d90825e2SJohnny Huang continue; 782d90825e2SJohnny Huang else 783d90825e2SJohnny Huang prog_bit = 0x1 << j; 784d90825e2SJohnny Huang } 785d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 786d90825e2SJohnny Huang } 787d90825e2SJohnny Huang } 788d90825e2SJohnny Huang 78976d13988SJohnny Huang 790541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 79176d13988SJohnny Huang { 79276d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 79376d13988SJohnny Huang int i, j; 79476d13988SJohnny Huang 79576d13988SJohnny Huang for (j = 0; j < 64; j++) { 79676d13988SJohnny Huang otpstrap[j].value = 0; 79776d13988SJohnny Huang otpstrap[j].remain_times = 7; 79876d13988SJohnny Huang otpstrap[j].writeable_option = -1; 79976d13988SJohnny Huang otpstrap[j].protected = 0; 80076d13988SJohnny Huang } 80176d13988SJohnny Huang 80276d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 80376d13988SJohnny Huang int option = (i - 16) / 2; 80476d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 80576d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 80676d13988SJohnny Huang for (j = 0; j < 32; j++) { 80776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 80876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 80976d13988SJohnny Huang otpstrap[j].writeable_option = option; 81076d13988SJohnny Huang } 81176d13988SJohnny Huang if (bit_value == 1) 81276d13988SJohnny Huang otpstrap[j].remain_times --; 81376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 81476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 81576d13988SJohnny Huang } 81676d13988SJohnny Huang for (j = 32; j < 64; j++) { 81776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 81876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 81976d13988SJohnny Huang otpstrap[j].writeable_option = option; 82076d13988SJohnny Huang } 82176d13988SJohnny Huang if (bit_value == 1) 82276d13988SJohnny Huang otpstrap[j].remain_times --; 82376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 82476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 82576d13988SJohnny Huang } 82676d13988SJohnny Huang } 82776d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 82876d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 82976d13988SJohnny Huang for (j = 0; j < 32; j++) { 83076d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 83176d13988SJohnny Huang otpstrap[j].protected = 1; 83276d13988SJohnny Huang } 83376d13988SJohnny Huang for (j = 32; j < 64; j++) { 83476d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 83576d13988SJohnny Huang otpstrap[j].protected = 1; 83676d13988SJohnny Huang } 83776d13988SJohnny Huang } 83876d13988SJohnny Huang 839b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 84069d5fd8fSJohnny Huang { 8413cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 842442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 843b458cd62SJohnny Huang uint32_t mask; 844b458cd62SJohnny Huang uint32_t dw_offset; 845b458cd62SJohnny Huang uint32_t bit_offset; 846b458cd62SJohnny Huang uint32_t otp_value; 847b458cd62SJohnny Huang uint32_t otp_keep; 848b458cd62SJohnny Huang int fail = 0; 84973f11549SJohnny Huang char valid_bit[20]; 85066f2f8e5SJohnny Huang int i; 85173f11549SJohnny Huang int j; 85266f2f8e5SJohnny Huang 853737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 85466f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8553cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8563cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8573cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8583cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 859b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 860b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 861b458cd62SJohnny Huang 862b458cd62SJohnny Huang if (otp_keep == mask) { 863b458cd62SJohnny Huang continue; 864b458cd62SJohnny Huang } else if (otp_keep != 0) { 865b458cd62SJohnny Huang fail = 1; 866b458cd62SJohnny Huang } 867b458cd62SJohnny Huang 8683cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 8693cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 8703cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 8713cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 872b458cd62SJohnny Huang continue; 873b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 874b458cd62SJohnny Huang 8753cb28812SJohnny Huang if (conf_info[i].length == 1) { 8763cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 87766f2f8e5SJohnny Huang } else { 878b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 8793cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 8803cb28812SJohnny Huang conf_info[i].bit_offset); 88166f2f8e5SJohnny Huang } 882b458cd62SJohnny Huang printf("0x%-10x", otp_value); 883b458cd62SJohnny Huang 884b458cd62SJohnny Huang if (fail) { 885b458cd62SJohnny Huang printf("Keep mask error\n"); 886b458cd62SJohnny Huang } else { 8873cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 888b458cd62SJohnny Huang printf("Reserved\n"); 8893cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 8903cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 891b458cd62SJohnny Huang printf("\n"); 8923cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 893b458cd62SJohnny Huang if (otp_value != 0) { 89473f11549SJohnny Huang for (j = 0; j < 7; j++) { 89573f11549SJohnny Huang if (otp_value == (1 << j)) { 89673f11549SJohnny Huang valid_bit[j * 2] = '1'; 897b458cd62SJohnny Huang } else { 89873f11549SJohnny Huang valid_bit[j * 2] = '0'; 89973f11549SJohnny Huang } 90073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 90173f11549SJohnny Huang } 90273f11549SJohnny Huang valid_bit[15] = 0; 90373f11549SJohnny Huang } else { 90473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 905b458cd62SJohnny Huang } 9063cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 907b458cd62SJohnny Huang printf("\n"); 908b458cd62SJohnny Huang } else { 9093cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 910b458cd62SJohnny Huang } 911b458cd62SJohnny Huang } 912b458cd62SJohnny Huang } 913b458cd62SJohnny Huang 914b458cd62SJohnny Huang if (fail) 915b458cd62SJohnny Huang return OTP_FAILURE; 916b458cd62SJohnny Huang 91766f2f8e5SJohnny Huang return OTP_SUCCESS; 91866f2f8e5SJohnny Huang } 91966f2f8e5SJohnny Huang 9202d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 92166f2f8e5SJohnny Huang { 9223cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 923b458cd62SJohnny Huang uint32_t OTPCFG[12]; 924b458cd62SJohnny Huang uint32_t mask; 925b458cd62SJohnny Huang uint32_t dw_offset; 926b458cd62SJohnny Huang uint32_t bit_offset; 927b458cd62SJohnny Huang uint32_t otp_value; 92873f11549SJohnny Huang char valid_bit[20]; 92966f2f8e5SJohnny Huang int i; 93073f11549SJohnny Huang int j; 93166f2f8e5SJohnny Huang 93266f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 93366f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 93466f2f8e5SJohnny Huang 93566f2f8e5SJohnny Huang 936b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 937b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9383cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9393cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9402d4b0742SJohnny Huang continue; 9413cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9423cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9433cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 944b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 945b458cd62SJohnny Huang 9463cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9473cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9483cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9493cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 950b458cd62SJohnny Huang continue; 951b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 952b458cd62SJohnny Huang 9533cb28812SJohnny Huang if (conf_info[i].length == 1) { 9543cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 955b458cd62SJohnny Huang } else { 956b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9573cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9583cb28812SJohnny Huang conf_info[i].bit_offset); 959b458cd62SJohnny Huang } 960b458cd62SJohnny Huang printf("0x%-10x", otp_value); 961b458cd62SJohnny Huang 9623cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 963b458cd62SJohnny Huang printf("Reserved\n"); 9643cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9653cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 966b458cd62SJohnny Huang printf("\n"); 9673cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 968b458cd62SJohnny Huang if (otp_value != 0) { 96973f11549SJohnny Huang for (j = 0; j < 7; j++) { 97073f11549SJohnny Huang if (otp_value == (1 << j)) { 97173f11549SJohnny Huang valid_bit[j * 2] = '1'; 972b458cd62SJohnny Huang } else { 97373f11549SJohnny Huang valid_bit[j * 2] = '0'; 97473f11549SJohnny Huang } 97573f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 97673f11549SJohnny Huang } 97773f11549SJohnny Huang valid_bit[15] = 0; 97873f11549SJohnny Huang } else { 97973f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 980b458cd62SJohnny Huang } 9813cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 982b458cd62SJohnny Huang printf("\n"); 983b458cd62SJohnny Huang } else { 9843cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 985b458cd62SJohnny Huang } 986b458cd62SJohnny Huang } 987b458cd62SJohnny Huang return OTP_SUCCESS; 98866f2f8e5SJohnny Huang } 98966f2f8e5SJohnny Huang 990b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 99176d13988SJohnny Huang { 9923cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 993a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 994a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 99576d13988SJohnny Huang int i; 996a8bd6d8cSJohnny Huang int fail = 0; 997a8bd6d8cSJohnny Huang uint32_t bit_offset; 998a8bd6d8cSJohnny Huang uint32_t dw_offset; 999a8bd6d8cSJohnny Huang uint32_t mask; 1000a8bd6d8cSJohnny Huang uint32_t otp_value; 1001a8bd6d8cSJohnny Huang uint32_t otp_protect; 1002a8bd6d8cSJohnny Huang uint32_t otp_keep; 100376d13988SJohnny Huang 1004a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1005a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1006b458cd62SJohnny Huang 10073cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 10083cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 1009a8bd6d8cSJohnny Huang dw_offset = 1; 10103cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1011a8bd6d8cSJohnny Huang } else { 1012a8bd6d8cSJohnny Huang dw_offset = 0; 10133cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1014a8bd6d8cSJohnny Huang } 101576d13988SJohnny Huang 10163cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1017a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1018a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1019a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1020a8bd6d8cSJohnny Huang 1021a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1022a8bd6d8cSJohnny Huang continue; 1023a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1024a8bd6d8cSJohnny Huang fail = 1; 1025a8bd6d8cSJohnny Huang } 1026a8bd6d8cSJohnny Huang 10273cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10283cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1029a8bd6d8cSJohnny Huang continue; 1030a8bd6d8cSJohnny Huang 10313cb28812SJohnny Huang if (strap_info[i].length == 1) { 10323cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1033a8bd6d8cSJohnny Huang } else { 1034b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10353cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10363cb28812SJohnny Huang strap_info[i].bit_offset); 1037a8bd6d8cSJohnny Huang } 1038a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1039a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1040a8bd6d8cSJohnny Huang 1041a8bd6d8cSJohnny Huang if (fail) { 1042a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1043a8bd6d8cSJohnny Huang } else { 10443cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10453cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1046a8bd6d8cSJohnny Huang else 1047a8bd6d8cSJohnny Huang printf("Reserved\n"); 1048a8bd6d8cSJohnny Huang } 1049a8bd6d8cSJohnny Huang } 1050a8bd6d8cSJohnny Huang 1051a8bd6d8cSJohnny Huang if (fail) 105276d13988SJohnny Huang return OTP_FAILURE; 105376d13988SJohnny Huang 105476d13988SJohnny Huang return OTP_SUCCESS; 105576d13988SJohnny Huang } 105676d13988SJohnny Huang 1057b458cd62SJohnny Huang static int otp_print_strap_info(int view) 105876d13988SJohnny Huang { 10593cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 106076d13988SJohnny Huang struct otpstrap_status strap_status[64]; 106107baa4e8SJohnny Huang int i, j; 1062b458cd62SJohnny Huang int fail = 0; 1063b458cd62SJohnny Huang uint32_t bit_offset; 1064b458cd62SJohnny Huang uint32_t length; 1065b458cd62SJohnny Huang uint32_t otp_value; 1066b458cd62SJohnny Huang uint32_t otp_protect; 106776d13988SJohnny Huang 1068541eb887SJohnny Huang otp_strap_status(strap_status); 106976d13988SJohnny Huang 1070b458cd62SJohnny Huang if (view) { 107107baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 107207baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 107307baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 107407baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1075b458cd62SJohnny Huang } else { 1076b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1077b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 107876d13988SJohnny Huang } 10793cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1080b458cd62SJohnny Huang otp_value = 0; 10813cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 10823cb28812SJohnny Huang length = strap_info[i].length; 1083b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1084c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1085c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1086b458cd62SJohnny Huang } 10873cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10883cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1089b458cd62SJohnny Huang continue; 1090b458cd62SJohnny Huang if (view) { 1091b458cd62SJohnny Huang for (j = 0; j < length; j++) { 10923cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1093b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 109407baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1095b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 10963cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1097b458cd62SJohnny Huang printf(" Reserved\n"); 1098b458cd62SJohnny Huang continue; 1099b458cd62SJohnny Huang } 1100b458cd62SJohnny Huang if (length == 1) { 11013cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1102b458cd62SJohnny Huang continue; 110376d13988SJohnny Huang } 110476d13988SJohnny Huang 1105b458cd62SJohnny Huang if (j == 0) 11063cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1107b458cd62SJohnny Huang else if (j == length - 1) 1108b458cd62SJohnny Huang printf("\\ \"\n"); 1109b458cd62SJohnny Huang else 1110b458cd62SJohnny Huang printf("| \"\n"); 111176d13988SJohnny Huang } 1112b458cd62SJohnny Huang } else { 1113c947ef08SJohnny Huang if (length == 1) { 11143cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1115b458cd62SJohnny Huang } else { 1116b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1117b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1118b458cd62SJohnny Huang } 1119b458cd62SJohnny Huang 1120b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1121b458cd62SJohnny Huang 11223cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11233cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1124b458cd62SJohnny Huang else 1125b458cd62SJohnny Huang printf("Reserved\n"); 1126b458cd62SJohnny Huang } 1127b458cd62SJohnny Huang } 1128b458cd62SJohnny Huang 1129b458cd62SJohnny Huang if (fail) 1130b458cd62SJohnny Huang return OTP_FAILURE; 1131b458cd62SJohnny Huang 1132b458cd62SJohnny Huang return OTP_SUCCESS; 1133b458cd62SJohnny Huang } 1134b458cd62SJohnny Huang 113569d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 113669d5fd8fSJohnny Huang { 113769d5fd8fSJohnny Huang int i; 113869d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 113969d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 114069d5fd8fSJohnny Huang if (i % 16 == 0) { 114169d5fd8fSJohnny Huang printf("%04X: ", i); 114269d5fd8fSJohnny Huang } 114369d5fd8fSJohnny Huang printf("%02X ", buf[i]); 114469d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 114569d5fd8fSJohnny Huang printf("\n"); 114669d5fd8fSJohnny Huang } 114769d5fd8fSJohnny Huang } 114869d5fd8fSJohnny Huang } 114969d5fd8fSJohnny Huang 11507f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 115169d5fd8fSJohnny Huang { 115269d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 11539a4fe690SJohnny Huang struct otpkey_type *key_info_array = info_cb.key_info; 11549a4fe690SJohnny Huang struct otpkey_type key_info; 115569d5fd8fSJohnny Huang char *byte_buf; 115669d5fd8fSJohnny Huang int i = 0, len = 0; 11579a4fe690SJohnny Huang int j; 115869d5fd8fSJohnny Huang byte_buf = (char *)buf; 115969d5fd8fSJohnny Huang while (1) { 116069d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 116169d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 116269d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 116369d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 116469d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 116569d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 11669a4fe690SJohnny Huang 11679a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 11689a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 11699a4fe690SJohnny Huang key_info = key_info_array[j]; 11709a4fe690SJohnny Huang break; 11719a4fe690SJohnny Huang } 11729a4fe690SJohnny Huang } 11739a4fe690SJohnny Huang 11747f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 117569d5fd8fSJohnny Huang printf("Key Type: "); 11769a4fe690SJohnny Huang printf("%s\n", key_info.information); 11779a4fe690SJohnny Huang 11789a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 117969d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 118069d5fd8fSJohnny Huang switch (key_length) { 118169d5fd8fSJohnny Huang case 0: 118269d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 118369d5fd8fSJohnny Huang break; 118469d5fd8fSJohnny Huang case 1: 118569d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 118669d5fd8fSJohnny Huang break; 118769d5fd8fSJohnny Huang case 2: 118869d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 118969d5fd8fSJohnny Huang break; 119069d5fd8fSJohnny Huang case 3: 119169d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 119269d5fd8fSJohnny Huang break; 119369d5fd8fSJohnny Huang } 11949a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 119569d5fd8fSJohnny Huang printf("RSA SHA Type: "); 119669d5fd8fSJohnny Huang switch (key_length) { 119769d5fd8fSJohnny Huang case 0: 119869d5fd8fSJohnny Huang printf("RSA1024\n"); 119969d5fd8fSJohnny Huang len = 0x100; 120069d5fd8fSJohnny Huang break; 120169d5fd8fSJohnny Huang case 1: 120269d5fd8fSJohnny Huang printf("RSA2048\n"); 120369d5fd8fSJohnny Huang len = 0x200; 120469d5fd8fSJohnny Huang break; 120569d5fd8fSJohnny Huang case 2: 120669d5fd8fSJohnny Huang printf("RSA3072\n"); 120769d5fd8fSJohnny Huang len = 0x300; 120869d5fd8fSJohnny Huang break; 120969d5fd8fSJohnny Huang case 3: 121069d5fd8fSJohnny Huang printf("RSA4096\n"); 121169d5fd8fSJohnny Huang len = 0x400; 121269d5fd8fSJohnny Huang break; 121369d5fd8fSJohnny Huang } 121469d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 121569d5fd8fSJohnny Huang } 12169a4fe690SJohnny Huang if (key_info.need_id) 121769d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 121869d5fd8fSJohnny Huang printf("Key Value:\n"); 12199a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 122069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12219a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12229a4fe690SJohnny Huang printf("AES Key:\n"); 12239a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12249a4fe690SJohnny Huang if (info_cb.version == 0) { 12259a4fe690SJohnny Huang printf("AES IV:\n"); 12269a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12279a4fe690SJohnny Huang } 12289a4fe690SJohnny Huang 12299a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12309a4fe690SJohnny Huang if (info_cb.version == 0) { 123169d5fd8fSJohnny Huang printf("AES Key:\n"); 123269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 123369d5fd8fSJohnny Huang printf("AES IV:\n"); 123469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12359a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12369a4fe690SJohnny Huang printf("AES Key 1:\n"); 12379a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12389a4fe690SJohnny Huang printf("AES Key 2:\n"); 12399a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12409a4fe690SJohnny Huang } 124169d5fd8fSJohnny Huang 12429a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 124369d5fd8fSJohnny Huang printf("RSA mod:\n"); 124469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 124569d5fd8fSJohnny Huang printf("RSA exp:\n"); 124669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 124769d5fd8fSJohnny Huang } 124869d5fd8fSJohnny Huang if (last) 124969d5fd8fSJohnny Huang break; 125069d5fd8fSJohnny Huang i++; 125169d5fd8fSJohnny Huang } 125269d5fd8fSJohnny Huang return 0; 125369d5fd8fSJohnny Huang } 125469d5fd8fSJohnny Huang 1255a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 125669d5fd8fSJohnny Huang { 1257a6d0d645SJohnny Huang int i, k; 1258d90825e2SJohnny Huang int pass = 0; 1259a6d0d645SJohnny Huang uint32_t prog_address; 1260a6d0d645SJohnny Huang uint32_t data[12]; 1261a6d0d645SJohnny Huang uint32_t compare[2]; 1262d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1263d90825e2SJohnny Huang uint32_t data_masked; 1264d90825e2SJohnny Huang uint32_t buf_masked; 126569d5fd8fSJohnny Huang 1266a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1267a6d0d645SJohnny Huang 1268a6d0d645SJohnny Huang printProgress(0, 12, ""); 1269a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1270a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 127169d5fd8fSJohnny Huang prog_address = 0x800; 1272a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1273a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1274a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1275a6d0d645SJohnny Huang } 1276a6d0d645SJohnny Huang 1277a6d0d645SJohnny Huang printf("Check writable...\n"); 1278a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1279d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1280d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1281d90825e2SJohnny Huang if (data_masked == buf_masked) 128269d5fd8fSJohnny Huang continue; 1283d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1284a6d0d645SJohnny Huang continue; 1285a6d0d645SJohnny Huang } else { 1286a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1287a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1288a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1289a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 12902a856b9aSJohnny Huang return OTP_FAILURE; 1291a6d0d645SJohnny Huang } 1292a6d0d645SJohnny Huang } 1293a6d0d645SJohnny Huang 1294a6d0d645SJohnny Huang printf("Start Programing...\n"); 1295a6d0d645SJohnny Huang printProgress(0, 12, ""); 1296d90825e2SJohnny Huang otp_soak(0); 1297a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1298d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1299d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1300a6d0d645SJohnny Huang prog_address = 0x800; 1301a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1302a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1303d90825e2SJohnny Huang if (data_masked == buf_masked) { 1304a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1305a6d0d645SJohnny Huang continue; 1306a6d0d645SJohnny Huang } 1307*de6fbf1cSJohnny Huang 1308a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1309a6d0d645SJohnny Huang 1310*de6fbf1cSJohnny Huang otp_soak(1); 1311d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1312a6d0d645SJohnny Huang 131369d5fd8fSJohnny Huang pass = 0; 131469d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1315d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1316*de6fbf1cSJohnny Huang otp_soak(2); 1317a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1318*de6fbf1cSJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1319*de6fbf1cSJohnny Huang otp_soak(1); 1320*de6fbf1cSJohnny Huang } else { 1321*de6fbf1cSJohnny Huang pass = 1; 1322*de6fbf1cSJohnny Huang break; 1323*de6fbf1cSJohnny Huang } 1324a6d0d645SJohnny Huang } else { 132569d5fd8fSJohnny Huang pass = 1; 132669d5fd8fSJohnny Huang break; 132769d5fd8fSJohnny Huang } 132869d5fd8fSJohnny Huang } 1329a6d0d645SJohnny Huang } 1330a6d0d645SJohnny Huang 1331*de6fbf1cSJohnny Huang otp_soak(0); 133269d5fd8fSJohnny Huang if (!pass) 13332a856b9aSJohnny Huang return OTP_FAILURE; 1334a6d0d645SJohnny Huang 13352a856b9aSJohnny Huang return OTP_SUCCESS; 1336d90825e2SJohnny Huang 133769d5fd8fSJohnny Huang } 133869d5fd8fSJohnny Huang 133969d5fd8fSJohnny Huang 134076d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 134169d5fd8fSJohnny Huang { 134269d5fd8fSJohnny Huang int i; 134369d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 134469d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 134569d5fd8fSJohnny Huang int bit, pbit, kbit; 134669d5fd8fSJohnny Huang int fail = 0; 1347a6af4a17SJohnny Huang int skip = -1; 134866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 134969d5fd8fSJohnny Huang 1350541eb887SJohnny Huang otp_strap_status(otpstrap); 135169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 135269d5fd8fSJohnny Huang if (i < 32) { 135369d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 135469d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 135569d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 135669d5fd8fSJohnny Huang } else { 135769d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 135869d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 135969d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 136069d5fd8fSJohnny Huang } 136169d5fd8fSJohnny Huang 136269d5fd8fSJohnny Huang if (kbit == 1) { 136369d5fd8fSJohnny Huang continue; 136469d5fd8fSJohnny Huang } else { 1365a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 136669d5fd8fSJohnny Huang } 136769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 136869d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1369a6af4a17SJohnny Huang if (skip == -1) 1370a6af4a17SJohnny Huang skip = 1; 137169d5fd8fSJohnny Huang continue; 1372a6af4a17SJohnny Huang } else { 1373a6af4a17SJohnny Huang skip = 0; 137469d5fd8fSJohnny Huang } 137569d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 137669d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 137769d5fd8fSJohnny Huang fail = 1; 137869d5fd8fSJohnny Huang continue; 137969d5fd8fSJohnny Huang } 138069d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1381a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 138269d5fd8fSJohnny Huang fail = 1; 138369d5fd8fSJohnny Huang continue; 138469d5fd8fSJohnny Huang } 138569d5fd8fSJohnny Huang if (pbit == 1) { 138669d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 138769d5fd8fSJohnny Huang } 1388a6af4a17SJohnny 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); 138969d5fd8fSJohnny Huang } 139069d5fd8fSJohnny Huang if (fail == 1) 1391a6af4a17SJohnny Huang return OTP_FAILURE; 1392a6af4a17SJohnny Huang else if (skip == 1) 1393a6af4a17SJohnny Huang return OTP_PROG_SKIP; 13947e22f42dSJohnny Huang 13957e22f42dSJohnny Huang return 0; 139669d5fd8fSJohnny Huang } 139769d5fd8fSJohnny Huang 13982a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 139969d5fd8fSJohnny Huang { 140069d5fd8fSJohnny Huang int i, j; 140166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 140269d5fd8fSJohnny Huang 14032a856b9aSJohnny Huang if (start < 0 || start > 64) 14042a856b9aSJohnny Huang return OTP_USAGE; 14052a856b9aSJohnny Huang 14062a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 14072a856b9aSJohnny Huang return OTP_USAGE; 14082a856b9aSJohnny Huang 1409541eb887SJohnny Huang otp_strap_status(otpstrap); 141069d5fd8fSJohnny Huang 141107baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1412a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1413737ed20bSJohnny Huang 1414cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 141507baa4e8SJohnny Huang printf("0x%-8X", i); 1416737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1417737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1418737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1419737ed20bSJohnny Huang printf(" "); 142069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1421737ed20bSJohnny Huang printf("protected and not writable"); 142269d5fd8fSJohnny Huang } else { 1423737ed20bSJohnny Huang printf("not protected "); 142469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1425737ed20bSJohnny Huang printf("and no remaining times to write."); 142669d5fd8fSJohnny Huang } else { 1427737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 142869d5fd8fSJohnny Huang } 142969d5fd8fSJohnny Huang } 1430737ed20bSJohnny Huang printf("\n"); 143169d5fd8fSJohnny Huang } 14322a856b9aSJohnny Huang 14332a856b9aSJohnny Huang return OTP_SUCCESS; 143469d5fd8fSJohnny Huang } 143569d5fd8fSJohnny Huang 143669d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 143769d5fd8fSJohnny Huang { 143869d5fd8fSJohnny Huang int i, j; 143969d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 144069d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 144169d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 144269d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 144369d5fd8fSJohnny Huang int fail = 0; 14447e22f42dSJohnny Huang int pass = 0; 144566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 144669d5fd8fSJohnny Huang 14477f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1448541eb887SJohnny Huang otp_strap_status(otpstrap); 144969d5fd8fSJohnny Huang 14507f795e57SJohnny Huang printf("Check writable...\n"); 14517f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 14527f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14537f795e57SJohnny Huang return OTP_FAILURE; 14547f795e57SJohnny Huang } 14557e22f42dSJohnny Huang 145669d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 14574c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 145869d5fd8fSJohnny Huang prog_address = 0x800; 145969d5fd8fSJohnny Huang if (i < 32) { 146069d5fd8fSJohnny Huang offset = i; 146169d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 146269d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 146369d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 146469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 146569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 146669d5fd8fSJohnny Huang 146769d5fd8fSJohnny Huang } else { 146869d5fd8fSJohnny Huang offset = (i - 32); 146969d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 147069d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 147169d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 147269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 147369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 147469d5fd8fSJohnny Huang } 147569d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 147669d5fd8fSJohnny Huang 147769d5fd8fSJohnny Huang if (kbit == 1) { 147869d5fd8fSJohnny Huang continue; 147969d5fd8fSJohnny Huang } 148069d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 148169d5fd8fSJohnny Huang continue; 148269d5fd8fSJohnny Huang } 148369d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 148469d5fd8fSJohnny Huang fail = 1; 148569d5fd8fSJohnny Huang continue; 148669d5fd8fSJohnny Huang } 148769d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 148869d5fd8fSJohnny Huang fail = 1; 148969d5fd8fSJohnny Huang continue; 149069d5fd8fSJohnny Huang } 14917e22f42dSJohnny Huang 14927e22f42dSJohnny Huang 1493*de6fbf1cSJohnny Huang otp_soak(1); 14947e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14957e22f42dSJohnny Huang 14967e22f42dSJohnny Huang pass = 0; 149769d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1498*de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1499*de6fbf1cSJohnny Huang otp_soak(2); 1500*de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1501*de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1502*de6fbf1cSJohnny Huang otp_soak(1); 1503*de6fbf1cSJohnny Huang } else { 150469d5fd8fSJohnny Huang pass = 1; 150569d5fd8fSJohnny Huang break; 150669d5fd8fSJohnny Huang } 1507*de6fbf1cSJohnny Huang } else { 1508*de6fbf1cSJohnny Huang pass = 1; 1509*de6fbf1cSJohnny Huang break; 15104b65a65dSJohnny Huang } 151169d5fd8fSJohnny Huang } 151269d5fd8fSJohnny Huang if (!pass) 15132a856b9aSJohnny Huang return OTP_FAILURE; 151469d5fd8fSJohnny Huang 151569d5fd8fSJohnny Huang if (pbit == 0) 151669d5fd8fSJohnny Huang continue; 151769d5fd8fSJohnny Huang prog_address = 0x800; 151869d5fd8fSJohnny Huang if (i < 32) 151969d5fd8fSJohnny Huang prog_address |= 0x60c; 152069d5fd8fSJohnny Huang else 152169d5fd8fSJohnny Huang prog_address |= 0x60e; 152269d5fd8fSJohnny Huang 15237e22f42dSJohnny Huang 1524*de6fbf1cSJohnny Huang otp_soak(1); 15257e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15267e22f42dSJohnny Huang 15277e22f42dSJohnny Huang pass = 0; 152869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1529*de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1530*de6fbf1cSJohnny Huang otp_soak(2); 1531*de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1532*de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1533*de6fbf1cSJohnny Huang otp_soak(1); 1534*de6fbf1cSJohnny Huang } else { 153569d5fd8fSJohnny Huang pass = 1; 153669d5fd8fSJohnny Huang break; 153769d5fd8fSJohnny Huang } 1538*de6fbf1cSJohnny Huang } else { 1539*de6fbf1cSJohnny Huang pass = 1; 1540*de6fbf1cSJohnny Huang break; 154169d5fd8fSJohnny Huang } 154269d5fd8fSJohnny Huang } 154369d5fd8fSJohnny Huang if (!pass) 15442a856b9aSJohnny Huang return OTP_FAILURE; 154569d5fd8fSJohnny Huang 154669d5fd8fSJohnny Huang } 1547*de6fbf1cSJohnny Huang otp_soak(0); 154869d5fd8fSJohnny Huang if (fail == 1) 15492a856b9aSJohnny Huang return OTP_FAILURE; 155069d5fd8fSJohnny Huang else 15512a856b9aSJohnny Huang return OTP_SUCCESS; 155269d5fd8fSJohnny Huang 155369d5fd8fSJohnny Huang } 155469d5fd8fSJohnny Huang 1555*de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1556cd1610b4SJohnny Huang { 1557cd1610b4SJohnny Huang int prog_bit; 1558cd1610b4SJohnny Huang 1559cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1560cd1610b4SJohnny Huang if (value) 1561cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1562cd1610b4SJohnny Huang else 1563cd1610b4SJohnny Huang return; 1564cd1610b4SJohnny Huang } else { 1565cd1610b4SJohnny Huang prog_address |= 1 << 15; 1566cd1610b4SJohnny Huang if (!value) 1567cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1568cd1610b4SJohnny Huang else 1569cd1610b4SJohnny Huang return; 1570cd1610b4SJohnny Huang } 1571cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1572cd1610b4SJohnny Huang } 1573cd1610b4SJohnny Huang 1574d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 15754c1c9b35SJohnny Huang { 15764c1c9b35SJohnny Huang int i, k; 15774c1c9b35SJohnny Huang int pass; 15784c1c9b35SJohnny Huang uint32_t prog_address; 1579d90825e2SJohnny Huang uint32_t data[2048]; 15804c1c9b35SJohnny Huang uint32_t compare[2]; 1581d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 15824c1c9b35SJohnny Huang 1583d90825e2SJohnny Huang uint32_t data0_masked; 1584d90825e2SJohnny Huang uint32_t data1_masked; 1585d90825e2SJohnny Huang uint32_t buf0_masked; 1586d90825e2SJohnny Huang uint32_t buf1_masked; 15874c1c9b35SJohnny Huang 15884c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 15894c1c9b35SJohnny Huang 1590d90825e2SJohnny Huang printProgress(0, 2048, ""); 1591d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1592d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1593d90825e2SJohnny Huang otp_read_data(i, &data[i]); 15944c1c9b35SJohnny Huang } 1595d90825e2SJohnny Huang 15964c1c9b35SJohnny Huang 15974c1c9b35SJohnny Huang printf("Check writable...\n"); 1598d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1599d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1600d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1601d90825e2SJohnny Huang if (data0_masked == buf0_masked) 16024c1c9b35SJohnny Huang continue; 1603d90825e2SJohnny Huang if (i % 2 == 0) { 1604d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 16054c1c9b35SJohnny Huang continue; 16064c1c9b35SJohnny Huang } else { 16074c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1608d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 16094c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1610d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16112a856b9aSJohnny Huang return OTP_FAILURE; 161269d5fd8fSJohnny Huang } 1613d90825e2SJohnny Huang } else { 1614d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1615d90825e2SJohnny Huang continue; 1616d90825e2SJohnny Huang } else { 1617d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1618d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1619d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1620d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16212a856b9aSJohnny Huang return OTP_FAILURE; 1622d90825e2SJohnny Huang } 1623d90825e2SJohnny Huang } 1624d90825e2SJohnny Huang } 162569d5fd8fSJohnny Huang 1626d90825e2SJohnny Huang printf("Start Programing...\n"); 1627d90825e2SJohnny Huang printProgress(0, 2048, ""); 1628d90825e2SJohnny Huang 1629d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1630d90825e2SJohnny Huang prog_address = i; 1631d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1632d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1633d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1634d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1635d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1636d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1637d90825e2SJohnny Huang continue; 1638d90825e2SJohnny Huang } 1639*de6fbf1cSJohnny Huang 1640*de6fbf1cSJohnny Huang otp_soak(1); 1641d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1642d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1643d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1644d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1645d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1646d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1647d90825e2SJohnny Huang } else { 1648d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1649d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1650d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1651d90825e2SJohnny Huang } 1652d90825e2SJohnny Huang 1653d90825e2SJohnny Huang pass = 0; 1654d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1655d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1656*de6fbf1cSJohnny Huang otp_soak(2); 1657d90825e2SJohnny Huang if (compare[0] != 0) { 1658d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1659d90825e2SJohnny Huang } 1660d90825e2SJohnny Huang if (compare[1] != ~0) { 1661d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1662d90825e2SJohnny Huang } 1663*de6fbf1cSJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1664*de6fbf1cSJohnny Huang otp_soak(1); 1665*de6fbf1cSJohnny Huang } else { 1666*de6fbf1cSJohnny Huang pass = 1; 1667*de6fbf1cSJohnny Huang break; 1668*de6fbf1cSJohnny Huang } 1669d90825e2SJohnny Huang } else { 1670d90825e2SJohnny Huang pass = 1; 1671d90825e2SJohnny Huang break; 1672d90825e2SJohnny Huang } 1673d90825e2SJohnny Huang } 1674d90825e2SJohnny Huang 1675*de6fbf1cSJohnny Huang if (!pass) { 1676*de6fbf1cSJohnny Huang otp_soak(0); 16772a856b9aSJohnny Huang return OTP_FAILURE; 1678d90825e2SJohnny Huang } 1679*de6fbf1cSJohnny Huang } 1680*de6fbf1cSJohnny Huang otp_soak(0); 16812a856b9aSJohnny Huang return OTP_SUCCESS; 1682d90825e2SJohnny Huang 1683d90825e2SJohnny Huang } 1684d90825e2SJohnny Huang 1685d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 168669d5fd8fSJohnny Huang { 168769d5fd8fSJohnny Huang int ret; 16887332532cSJohnny Huang int mode = 0; 16899a4fe690SJohnny Huang int image_version = 0; 169069d5fd8fSJohnny Huang uint32_t *buf; 1691d90825e2SJohnny Huang uint32_t *data_region = NULL; 1692d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1693d90825e2SJohnny Huang uint32_t *strap_region = NULL; 169469d5fd8fSJohnny Huang 1695d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 169669d5fd8fSJohnny Huang if (!buf) { 169769d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16982a856b9aSJohnny Huang return OTP_FAILURE; 169969d5fd8fSJohnny Huang } 1700d90825e2SJohnny Huang 17019a4fe690SJohnny Huang image_version = buf[0] & 0x3; 17029a4fe690SJohnny Huang if (image_version != info_cb.version) { 17039a4fe690SJohnny Huang puts("Version is not match\n"); 17049a4fe690SJohnny Huang return OTP_FAILURE; 17059a4fe690SJohnny Huang } 17069a4fe690SJohnny Huang 1707d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 17087332532cSJohnny Huang mode |= OTP_REGION_DATA; 17097332532cSJohnny Huang data_region = &buf[36]; 1710d90825e2SJohnny Huang } 1711d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 17127332532cSJohnny Huang mode |= OTP_REGION_CONF; 17137332532cSJohnny Huang conf_region = &buf[12]; 1714d90825e2SJohnny Huang } 1715d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 17167332532cSJohnny Huang mode |= OTP_REGION_STRAP; 17177332532cSJohnny Huang strap_region = &buf[4]; 1718d90825e2SJohnny Huang } 17197332532cSJohnny Huang 172069d5fd8fSJohnny Huang if (!nconfirm) { 17217332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17227f795e57SJohnny Huang printf("\nOTP data region :\n"); 17237f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 172469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17252a856b9aSJohnny Huang return OTP_FAILURE; 172669d5fd8fSJohnny Huang } 172769d5fd8fSJohnny Huang } 17287332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17297332532cSJohnny Huang printf("\nOTP strap region :\n"); 17307332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17317332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17327332532cSJohnny Huang return OTP_FAILURE; 17337332532cSJohnny Huang } 17347332532cSJohnny Huang } 17357332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17367332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17377332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17387332532cSJohnny Huang printf("OTP config error, please check.\n"); 17397332532cSJohnny Huang return OTP_FAILURE; 17407332532cSJohnny Huang } 17417332532cSJohnny Huang } 17427332532cSJohnny Huang 174369d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 174469d5fd8fSJohnny Huang if (!confirm_yesno()) { 174569d5fd8fSJohnny Huang printf(" Aborting\n"); 17462a856b9aSJohnny Huang return OTP_FAILURE; 174769d5fd8fSJohnny Huang } 174869d5fd8fSJohnny Huang } 17497332532cSJohnny Huang 17507332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17517332532cSJohnny Huang printf("programing data region ...\n"); 1752d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17532a856b9aSJohnny Huang if (ret != 0) { 175469d5fd8fSJohnny Huang printf("Error\n"); 175569d5fd8fSJohnny Huang return ret; 175669d5fd8fSJohnny Huang } else { 175769d5fd8fSJohnny Huang printf("Done\n"); 175869d5fd8fSJohnny Huang } 17597332532cSJohnny Huang } 17607332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17617332532cSJohnny Huang printf("programing strap region ...\n"); 1762d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17632a856b9aSJohnny Huang if (ret != 0) { 176469d5fd8fSJohnny Huang printf("Error\n"); 176569d5fd8fSJohnny Huang return ret; 176669d5fd8fSJohnny Huang } else { 176769d5fd8fSJohnny Huang printf("Done\n"); 176869d5fd8fSJohnny Huang } 17697332532cSJohnny Huang } 17707332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17717332532cSJohnny Huang printf("programing configuration region ...\n"); 1772d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17732a856b9aSJohnny Huang if (ret != 0) { 177469d5fd8fSJohnny Huang printf("Error\n"); 177569d5fd8fSJohnny Huang return ret; 177669d5fd8fSJohnny Huang } 177769d5fd8fSJohnny Huang printf("Done\n"); 177869d5fd8fSJohnny Huang } 1779cd1610b4SJohnny Huang 17807332532cSJohnny Huang return OTP_SUCCESS; 17812a856b9aSJohnny Huang } 17822a856b9aSJohnny Huang 17832a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1784cd1610b4SJohnny Huang { 1785a6af4a17SJohnny Huang uint32_t read[2]; 1786cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1787d90825e2SJohnny Huang uint32_t prog_address = 0; 178866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1789cd1610b4SJohnny Huang int otp_bit; 1790cd1610b4SJohnny Huang int i; 1791cd1610b4SJohnny Huang int pass; 1792a6af4a17SJohnny Huang int ret; 1793cd1610b4SJohnny Huang 1794cd1610b4SJohnny Huang switch (mode) { 1795a6d0d645SJohnny Huang case OTP_REGION_CONF: 1796a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1797cd1610b4SJohnny Huang prog_address = 0x800; 1798cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1799cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1800a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1801cd1610b4SJohnny Huang if (otp_bit == value) { 1802a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1803cd1610b4SJohnny Huang printf("No need to program\n"); 18042a856b9aSJohnny Huang return OTP_SUCCESS; 1805cd1610b4SJohnny Huang } 1806cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1807a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1808cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 18092a856b9aSJohnny Huang return OTP_FAILURE; 1810cd1610b4SJohnny Huang } 1811a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1812cd1610b4SJohnny Huang break; 1813a6d0d645SJohnny Huang case OTP_REGION_DATA: 1814cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1815cd1610b4SJohnny Huang 1816cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1817a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1818a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1819643b9cfdSJohnny Huang 1820643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1821643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1822643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1823643b9cfdSJohnny Huang return OTP_FAILURE; 1824643b9cfdSJohnny Huang } 1825cd1610b4SJohnny Huang } else { 1826a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1827a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1828643b9cfdSJohnny Huang 1829643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1830643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1831643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1832643b9cfdSJohnny Huang return OTP_FAILURE; 1833643b9cfdSJohnny Huang } 1834cd1610b4SJohnny Huang } 1835cd1610b4SJohnny Huang if (otp_bit == value) { 1836a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1837cd1610b4SJohnny Huang printf("No need to program\n"); 18382a856b9aSJohnny Huang return OTP_SUCCESS; 1839cd1610b4SJohnny Huang } 1840643b9cfdSJohnny Huang 1841a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1842cd1610b4SJohnny Huang break; 1843a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1844541eb887SJohnny Huang otp_strap_status(otpstrap); 1845cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1846cd1610b4SJohnny Huang if (bit_offset < 32) { 1847cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1848cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1849cd1610b4SJohnny Huang strap_buf[3] = ~0; 1850cd1610b4SJohnny Huang strap_buf[5] = 0; 18512a856b9aSJohnny Huang // if (protect) 18522a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 18532a856b9aSJohnny Huang // else 18542a856b9aSJohnny Huang // strap_buf[4] = 0; 1855cd1610b4SJohnny Huang } else { 1856cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1857cd1610b4SJohnny Huang strap_buf[2] = ~0; 1858cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1859cd1610b4SJohnny Huang strap_buf[4] = 0; 18602a856b9aSJohnny Huang // if (protect) 18612a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 18622a856b9aSJohnny Huang // else 18632a856b9aSJohnny Huang // strap_buf[5] = 0; 1864cd1610b4SJohnny Huang } 186576d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1866a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18672a856b9aSJohnny Huang return OTP_FAILURE; 1868a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1869a6af4a17SJohnny Huang return OTP_SUCCESS; 1870a6af4a17SJohnny Huang 1871cd1610b4SJohnny Huang break; 1872cd1610b4SJohnny Huang } 1873cd1610b4SJohnny Huang 1874cd1610b4SJohnny Huang if (!nconfirm) { 1875cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1876cd1610b4SJohnny Huang if (!confirm_yesno()) { 1877cd1610b4SJohnny Huang printf(" Aborting\n"); 18782a856b9aSJohnny Huang return OTP_FAILURE; 1879cd1610b4SJohnny Huang } 1880cd1610b4SJohnny Huang } 1881cd1610b4SJohnny Huang 1882cd1610b4SJohnny Huang switch (mode) { 1883a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1884cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1885a6d0d645SJohnny Huang case OTP_REGION_CONF: 1886a6d0d645SJohnny Huang case OTP_REGION_DATA: 1887*de6fbf1cSJohnny Huang otp_soak(1); 1888*de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1889*de6fbf1cSJohnny Huang pass = 0; 1890*de6fbf1cSJohnny Huang 1891cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1892a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1893*de6fbf1cSJohnny Huang otp_soak(2); 1894*de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1895*de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1896*de6fbf1cSJohnny Huang otp_soak(1); 1897cd1610b4SJohnny Huang } else { 1898*de6fbf1cSJohnny Huang pass = 1; 1899*de6fbf1cSJohnny Huang break; 1900*de6fbf1cSJohnny Huang } 1901*de6fbf1cSJohnny Huang } else { 1902*de6fbf1cSJohnny Huang pass = 1; 1903cd1610b4SJohnny Huang break; 1904cd1610b4SJohnny Huang } 1905cd1610b4SJohnny Huang } 1906*de6fbf1cSJohnny Huang 1907*de6fbf1cSJohnny Huang otp_soak(0); 1908*de6fbf1cSJohnny Huang if (pass) { 19099009c25dSJohnny Huang printf("SUCCESS\n"); 19102a856b9aSJohnny Huang return OTP_SUCCESS; 19119009c25dSJohnny Huang } else { 19129009c25dSJohnny Huang printf("OTP cannot be programed\n"); 19139009c25dSJohnny Huang printf("FAILED\n"); 19149009c25dSJohnny Huang return OTP_FAILURE; 19159009c25dSJohnny Huang } 1916cd1610b4SJohnny Huang } 1917cd1610b4SJohnny Huang 19182a856b9aSJohnny Huang return OTP_USAGE; 1919cd1610b4SJohnny Huang } 1920cd1610b4SJohnny Huang 19212a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 192269d5fd8fSJohnny Huang { 19232a856b9aSJohnny Huang uint32_t offset, count; 19242a856b9aSJohnny Huang int ret; 192569d5fd8fSJohnny Huang 19262a856b9aSJohnny Huang if (argc == 4) { 19272a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19282a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19292a856b9aSJohnny Huang } else if (argc == 3) { 19302a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19312a856b9aSJohnny Huang count = 1; 19322a856b9aSJohnny Huang } else { 193369d5fd8fSJohnny Huang return CMD_RET_USAGE; 193469d5fd8fSJohnny Huang } 193569d5fd8fSJohnny Huang 193669d5fd8fSJohnny Huang 19372a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19383d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19392a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19402a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19413d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19422a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19432a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19443d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19452a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19462a856b9aSJohnny Huang } else { 19472a856b9aSJohnny Huang return CMD_RET_USAGE; 194869d5fd8fSJohnny Huang } 194969d5fd8fSJohnny Huang 19502a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19512a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19522a856b9aSJohnny Huang else 19532a856b9aSJohnny Huang return CMD_RET_USAGE; 19542a856b9aSJohnny Huang 19552a856b9aSJohnny Huang } 19562a856b9aSJohnny Huang 19572a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19582a856b9aSJohnny Huang { 19592a856b9aSJohnny Huang phys_addr_t addr; 19602a856b9aSJohnny Huang uint32_t byte_size; 19612a856b9aSJohnny Huang int ret; 19622a856b9aSJohnny Huang 19632a856b9aSJohnny Huang if (argc == 4) { 1964ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19652a856b9aSJohnny Huang return CMD_RET_USAGE; 19662a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19672a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 19683d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19692a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19702a856b9aSJohnny Huang } else if (argc == 3) { 19712a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19722a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 19733d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19742a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19752a856b9aSJohnny Huang } else { 19762a856b9aSJohnny Huang return CMD_RET_USAGE; 19772a856b9aSJohnny Huang } 19782a856b9aSJohnny Huang 19792a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19802a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19812a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19822a856b9aSJohnny Huang return CMD_RET_FAILURE; 19832a856b9aSJohnny Huang else 19842a856b9aSJohnny Huang return CMD_RET_USAGE; 19852a856b9aSJohnny Huang } 19862a856b9aSJohnny Huang 19872a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19882a856b9aSJohnny Huang { 19892a856b9aSJohnny Huang int mode = 0; 19902a856b9aSJohnny Huang int nconfirm = 0; 19912a856b9aSJohnny Huang int otp_addr = 0; 19922a856b9aSJohnny Huang int bit_offset; 19932a856b9aSJohnny Huang int value; 19942a856b9aSJohnny Huang int ret; 19952a856b9aSJohnny Huang 19962a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19972a856b9aSJohnny Huang return CMD_RET_USAGE; 19982a856b9aSJohnny Huang 19992a856b9aSJohnny Huang /* Drop the pb cmd */ 20002a856b9aSJohnny Huang argc--; 20012a856b9aSJohnny Huang argv++; 20022a856b9aSJohnny Huang 20032a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2004a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 20052a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2006a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 20072a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2008a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2009cd1610b4SJohnny Huang else 20102a856b9aSJohnny Huang return CMD_RET_USAGE; 20112a856b9aSJohnny Huang 20122a856b9aSJohnny Huang /* Drop the region cmd */ 20132a856b9aSJohnny Huang argc--; 20142a856b9aSJohnny Huang argv++; 20152a856b9aSJohnny Huang 2016ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2017cd1610b4SJohnny Huang nconfirm = 1; 20182a856b9aSJohnny Huang /* Drop the force option */ 20192a856b9aSJohnny Huang argc--; 20202a856b9aSJohnny Huang argv++; 20212a856b9aSJohnny Huang } 2022cd1610b4SJohnny Huang 2023a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20242a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20252a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20260808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20272a856b9aSJohnny Huang return CMD_RET_USAGE; 2028cd1610b4SJohnny Huang } else { 20292a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20302a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20312a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20320808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20332a856b9aSJohnny Huang return CMD_RET_USAGE; 20340808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 203578855207SJohnny Huang if (otp_addr >= 0x800) 20360808cc55SJohnny Huang return CMD_RET_USAGE; 20370808cc55SJohnny Huang } else { 203878855207SJohnny Huang if (otp_addr >= 0x20) 20390808cc55SJohnny Huang return CMD_RET_USAGE; 20400808cc55SJohnny Huang } 2041cd1610b4SJohnny Huang } 2042cd1610b4SJohnny Huang if (value != 0 && value != 1) 20432a856b9aSJohnny Huang return CMD_RET_USAGE; 2044cd1610b4SJohnny Huang 20453d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20462a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20472a856b9aSJohnny Huang 20482a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20492a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20502a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20512a856b9aSJohnny Huang return CMD_RET_FAILURE; 20522a856b9aSJohnny Huang else 20532a856b9aSJohnny Huang return CMD_RET_USAGE; 20542a856b9aSJohnny Huang } 20552a856b9aSJohnny Huang 20562a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20572a856b9aSJohnny Huang { 20582a856b9aSJohnny Huang phys_addr_t addr; 20592a856b9aSJohnny Huang int otp_addr = 0; 20602a856b9aSJohnny Huang 20612a856b9aSJohnny Huang if (argc != 3) 20622a856b9aSJohnny Huang return CMD_RET_USAGE; 20632a856b9aSJohnny Huang 20643d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20652a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20662a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20672a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 206869d5fd8fSJohnny Huang printf("Compare pass\n"); 20692a856b9aSJohnny Huang return CMD_RET_SUCCESS; 207069d5fd8fSJohnny Huang } else { 207169d5fd8fSJohnny Huang printf("Compare fail\n"); 20722a856b9aSJohnny Huang return CMD_RET_FAILURE; 207369d5fd8fSJohnny Huang } 207469d5fd8fSJohnny Huang } 207569d5fd8fSJohnny Huang 207666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 207766f2f8e5SJohnny Huang { 2078a8bd6d8cSJohnny Huang int view = 0; 20792d4b0742SJohnny Huang int input; 2080a8bd6d8cSJohnny Huang 2081a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 208266f2f8e5SJohnny Huang return CMD_RET_USAGE; 208366f2f8e5SJohnny Huang 20842d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 208566f2f8e5SJohnny Huang 20863d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20872d4b0742SJohnny Huang if (argc == 3) { 20882d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20892d4b0742SJohnny Huang otp_print_conf_info(input); 20902d4b0742SJohnny Huang } else { 20912d4b0742SJohnny Huang otp_print_conf_info(-1); 20922d4b0742SJohnny Huang } 20932d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20942d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2095a8bd6d8cSJohnny Huang view = 1; 2096a8bd6d8cSJohnny Huang /* Drop the view option */ 2097a8bd6d8cSJohnny Huang argc--; 2098a8bd6d8cSJohnny Huang argv++; 2099a8bd6d8cSJohnny Huang } 21003d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2101b458cd62SJohnny Huang otp_print_strap_info(view); 210266f2f8e5SJohnny Huang } else { 210366f2f8e5SJohnny Huang return CMD_RET_USAGE; 210466f2f8e5SJohnny Huang } 21052d4b0742SJohnny Huang 210666f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 210766f2f8e5SJohnny Huang } 210866f2f8e5SJohnny Huang 2109737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2110737ed20bSJohnny Huang { 2111737ed20bSJohnny Huang int input; 2112737ed20bSJohnny Huang int bit_offset; 2113737ed20bSJohnny Huang int prog_address; 2114737ed20bSJohnny Huang int pass; 2115737ed20bSJohnny Huang int i; 2116737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2117737ed20bSJohnny Huang return CMD_RET_USAGE; 2118737ed20bSJohnny Huang 2119ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2120737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2121737ed20bSJohnny Huang } else { 2122737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2123737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2124737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2125737ed20bSJohnny Huang if (!confirm_yesno()) { 2126737ed20bSJohnny Huang printf(" Aborting\n"); 2127737ed20bSJohnny Huang return CMD_RET_FAILURE; 2128737ed20bSJohnny Huang } 2129737ed20bSJohnny Huang } 2130737ed20bSJohnny Huang 2131737ed20bSJohnny Huang prog_address = 0x800; 2132737ed20bSJohnny Huang if (input < 32) { 2133737ed20bSJohnny Huang bit_offset = input; 2134737ed20bSJohnny Huang prog_address |= 0x60c; 2135737ed20bSJohnny Huang } else if (input < 64) { 2136737ed20bSJohnny Huang bit_offset = input - 32; 2137737ed20bSJohnny Huang prog_address |= 0x60e; 2138737ed20bSJohnny Huang } else { 2139737ed20bSJohnny Huang return CMD_RET_USAGE; 2140737ed20bSJohnny Huang } 2141737ed20bSJohnny Huang 2142737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2143737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2144737ed20bSJohnny Huang } 2145*de6fbf1cSJohnny Huang 2146*de6fbf1cSJohnny Huang otp_soak(1); 2147*de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2148*de6fbf1cSJohnny Huang pass = 0; 2149*de6fbf1cSJohnny Huang 2150737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2151737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2152*de6fbf1cSJohnny Huang otp_soak(2); 2153*de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2154*de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2155*de6fbf1cSJohnny Huang otp_soak(1); 2156737ed20bSJohnny Huang } else { 2157*de6fbf1cSJohnny Huang pass = 1; 2158*de6fbf1cSJohnny Huang break; 2159*de6fbf1cSJohnny Huang } 2160*de6fbf1cSJohnny Huang } else { 2161*de6fbf1cSJohnny Huang pass = 1; 2162737ed20bSJohnny Huang break; 2163737ed20bSJohnny Huang } 2164737ed20bSJohnny Huang } 2165*de6fbf1cSJohnny Huang otp_soak(0); 2166*de6fbf1cSJohnny Huang if (pass) { 2167737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2168737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2169737ed20bSJohnny Huang } 2170737ed20bSJohnny Huang 2171737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2172737ed20bSJohnny Huang return CMD_RET_FAILURE; 2173737ed20bSJohnny Huang 2174737ed20bSJohnny Huang } 21759a4fe690SJohnny Huang 21762a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21772a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2178a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21792a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21802a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2181737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21822a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21832a856b9aSJohnny Huang }; 21842a856b9aSJohnny Huang 21852a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21862a856b9aSJohnny Huang { 21872a856b9aSJohnny Huang cmd_tbl_t *cp; 21882a856b9aSJohnny Huang 21892a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21902a856b9aSJohnny Huang 2191737ed20bSJohnny Huang /* Drop the otp command */ 21922a856b9aSJohnny Huang argc--; 21932a856b9aSJohnny Huang argv++; 21942a856b9aSJohnny Huang 21952a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 21962a856b9aSJohnny Huang return CMD_RET_USAGE; 21972a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 21982a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21992a856b9aSJohnny Huang 22009a4fe690SJohnny Huang if (chip_version() == 0) { 22019a4fe690SJohnny Huang info_cb.version = 0; 22029a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 22039a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 22049a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 22059a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 22069a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 22079a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 22089a4fe690SJohnny Huang } else if (chip_version() == 1) { 22099a4fe690SJohnny Huang info_cb.version = 1; 22103cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 22113cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 22123cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 22133cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 22149a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 22159a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 22169a4fe690SJohnny Huang } 22179a4fe690SJohnny Huang 22182a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 221969d5fd8fSJohnny Huang } 222069d5fd8fSJohnny Huang 222169d5fd8fSJohnny Huang U_BOOT_CMD( 222269d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 222369d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 22242a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 22252a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 22262d4b0742SJohnny Huang "otp info strap [v]\n" 22272d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2228ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2229ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2230ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2231ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 22322a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 223369d5fd8fSJohnny Huang ); 2234