169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 429a4fe690SJohnny Huang 439a4fe690SJohnny Huang 44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 45b458cd62SJohnny Huang #define OTP_REG_VALUE -2 46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4776d13988SJohnny Huang 484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 494c1c9b35SJohnny Huang #define PBWIDTH 60 504c1c9b35SJohnny Huang 5166f2f8e5SJohnny Huang struct otpstrap_status { 5269d5fd8fSJohnny Huang int value; 5369d5fd8fSJohnny Huang int option_array[7]; 5469d5fd8fSJohnny Huang int remain_times; 5569d5fd8fSJohnny Huang int writeable_option; 5669d5fd8fSJohnny Huang int protected; 5769d5fd8fSJohnny Huang }; 5869d5fd8fSJohnny Huang 5966f2f8e5SJohnny Huang struct otpconf_parse { 6066f2f8e5SJohnny Huang int dw_offset; 6166f2f8e5SJohnny Huang int bit; 6266f2f8e5SJohnny Huang int length; 6366f2f8e5SJohnny Huang int value; 6466f2f8e5SJohnny Huang int keep; 6566f2f8e5SJohnny Huang char status[80]; 6666f2f8e5SJohnny Huang }; 6766f2f8e5SJohnny Huang 68a8bd6d8cSJohnny Huang struct otpstrap_info { 69a8bd6d8cSJohnny Huang uint32_t bit_offset; 70a8bd6d8cSJohnny Huang uint32_t length; 7176d13988SJohnny Huang int value; 72a8bd6d8cSJohnny Huang char information[80]; 73a8bd6d8cSJohnny Huang }; 74a8bd6d8cSJohnny Huang 75a8bd6d8cSJohnny Huang struct otpconf_info { 76a8bd6d8cSJohnny Huang uint32_t dw_offset; 77a8bd6d8cSJohnny Huang uint32_t bit_offset; 78a8bd6d8cSJohnny Huang uint32_t length; 79a8bd6d8cSJohnny Huang int value; 80a8bd6d8cSJohnny Huang char information[80]; 81a8bd6d8cSJohnny Huang }; 82a8bd6d8cSJohnny Huang 839a4fe690SJohnny Huang struct otpkey_type { 849a4fe690SJohnny Huang int value; 859a4fe690SJohnny Huang int key_type; 869a4fe690SJohnny Huang int need_id; 879a4fe690SJohnny Huang char information[110]; 889a4fe690SJohnny Huang }; 899a4fe690SJohnny Huang 909a4fe690SJohnny Huang struct otp_info_cb { 919a4fe690SJohnny Huang int version; 929a4fe690SJohnny Huang struct otpstrap_info *strap_info; 939a4fe690SJohnny Huang int strap_info_len; 949a4fe690SJohnny Huang struct otpconf_info *conf_info; 959a4fe690SJohnny Huang int conf_info_len; 969a4fe690SJohnny Huang struct otpkey_type *key_info; 979a4fe690SJohnny Huang int key_info_len; 989a4fe690SJohnny Huang }; 999a4fe690SJohnny Huang 100a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 101a8bd6d8cSJohnny Huang { 102a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 103a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 104a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 105a8bd6d8cSJohnny Huang char buffer[256]; 106a8bd6d8cSJohnny Huang va_list aptr; 107a8bd6d8cSJohnny Huang 108a8bd6d8cSJohnny Huang va_start(aptr, format); 109a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 110a8bd6d8cSJohnny Huang va_end(aptr); 111a8bd6d8cSJohnny Huang 112a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 113a8bd6d8cSJohnny Huang if (numerator == denominator) 114a8bd6d8cSJohnny Huang printf("\n"); 115a8bd6d8cSJohnny Huang } 116a8bd6d8cSJohnny Huang 1179a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1189a4fe690SJohnny Huang 119a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 12091448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 12191448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 12291448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 12391448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 12491448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 12591448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 12691448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 12791448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 128*541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 12991448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 13091448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 13191448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 13291448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 13391448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 13491448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 13591448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 13691448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 13791448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 13891448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 13991448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 14091448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 14191448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 14291448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 14391448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 14491448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 14591448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 14691448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 14791448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 14891448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 14991448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 15091448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 15191448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 15291448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 15391448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 15491448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 15591448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 15691448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 15791448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 15891448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 15991448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 16091448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 16191448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 16291448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 16391448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 16491448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 16591448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 16691448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 16791448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 16891448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 16991448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 17091448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 17191448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 17291448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 17391448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 17491448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 17591448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 17691448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 17791448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 17891448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 17991448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 18091448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 18191448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 18291448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 18391448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 18491448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 18591448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 18691448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 18791448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 18891448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 18991448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 19091448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 19191448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 19291448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 19391448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 19491448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 19591448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 19691448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 19791448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 19891448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 19991448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 20091448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 20191448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 20291448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 20391448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 20491448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 20591448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 20691448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 20791448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 20891448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 20991448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 21091448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 21191448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 21291448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 21391448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 21491448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 21591448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 21691448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 21791448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 21891448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 21991448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 22091448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 22191448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 22291448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 22391448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 22491448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 22591448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 22691448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 22791448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 22891448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 22976d13988SJohnny Huang }; 2309a4fe690SJohnny Huang 231b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 23291448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 23391448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 23491448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 23591448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 23691448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 23791448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 23891448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 23991448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 24091448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 24191448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 24291448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 24391448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 24491448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 24591448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 24691448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 24791448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 24891448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 249*541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 25091448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 25191448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 25291448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 25391448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 25491448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 25591448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 25691448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 25791448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 25891448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 25991448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 26091448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 26191448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 26291448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 26391448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 26491448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 26591448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 26691448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 26791448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 26891448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 26991448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 27091448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 27191448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 27291448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 27391448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 27491448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 27591448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 27691448c03SJohnny Huang { 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" }, 27791448c03SJohnny Huang { 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" }, 27891448c03SJohnny Huang { 0, 31, 1, 0, "SIPROM Mlock memory lock disable" }, 27991448c03SJohnny Huang { 0, 31, 1, 1, "SIPROM Mlock memory lock enable" }, 28091448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 28191448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 28291448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 28373f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 28473f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 28591448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 28691448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 28791448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 28891448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 28991448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 29091448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 29191448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 29291448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 29391448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 29491448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 29591448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 29691448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 29791448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 29891448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 29991448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 30091448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 30191448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 30291448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 30391448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 30491448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 30591448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 30691448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 30791448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 30891448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 30991448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 31091448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 31191448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 31291448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 31391448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 314b458cd62SJohnny Huang }; 3159a4fe690SJohnny Huang 3169a4fe690SJohnny Huang struct otpkey_type a0_key_type[] = { 3179a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 3189a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 3199a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 3209a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 3219a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 3229a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 3239a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 3249a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 3259a4fe690SJohnny Huang }; 3269a4fe690SJohnny Huang 3279a4fe690SJohnny Huang struct otpkey_type a1_key_type[] = { 3289a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 3299a4fe690SJohnny 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"}, 3309a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 3319a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 3329a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 3339a4fe690SJohnny Huang }; 3349a4fe690SJohnny Huang 3359a4fe690SJohnny Huang static uint32_t chip_version(void) 3369a4fe690SJohnny Huang { 3379a4fe690SJohnny Huang uint32_t rev_id; 3389a4fe690SJohnny Huang 3399a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 3409a4fe690SJohnny Huang 3419a4fe690SJohnny Huang return rev_id; 3429a4fe690SJohnny Huang } 3439a4fe690SJohnny Huang 3442a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 34569d5fd8fSJohnny Huang { 34669d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 34769d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 34869d5fd8fSJohnny Huang udelay(2); 34969d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 35069d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 35169d5fd8fSJohnny Huang } 35269d5fd8fSJohnny Huang 3532a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 35469d5fd8fSJohnny Huang { 35569d5fd8fSJohnny Huang int config_offset; 35669d5fd8fSJohnny Huang 35769d5fd8fSJohnny Huang config_offset = 0x800; 35869d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 35969d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 36069d5fd8fSJohnny Huang 36169d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 36269d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 36369d5fd8fSJohnny Huang udelay(2); 36469d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 36569d5fd8fSJohnny Huang } 36669d5fd8fSJohnny Huang 36769d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 36869d5fd8fSJohnny Huang { 36969d5fd8fSJohnny Huang int i; 37069d5fd8fSJohnny Huang uint32_t ret[1]; 37169d5fd8fSJohnny Huang 37269d5fd8fSJohnny Huang if (offset + dw_count > 32) 3732a856b9aSJohnny Huang return OTP_USAGE; 37469d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 37569d5fd8fSJohnny Huang otp_read_config(i, ret); 376a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 37769d5fd8fSJohnny Huang } 37869d5fd8fSJohnny Huang printf("\n"); 3792a856b9aSJohnny Huang return OTP_SUCCESS; 38069d5fd8fSJohnny Huang } 38169d5fd8fSJohnny Huang 38269d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 38369d5fd8fSJohnny Huang { 38469d5fd8fSJohnny Huang int i; 38569d5fd8fSJohnny Huang uint32_t ret[2]; 38669d5fd8fSJohnny Huang 38769d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 3882a856b9aSJohnny Huang return OTP_USAGE; 38969d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 39069d5fd8fSJohnny Huang otp_read_data(i, ret); 39169d5fd8fSJohnny Huang if (i % 4 == 0) 39269d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 39369d5fd8fSJohnny Huang else 39469d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 39569d5fd8fSJohnny Huang 39669d5fd8fSJohnny Huang } 39769d5fd8fSJohnny Huang printf("\n"); 3982a856b9aSJohnny Huang return OTP_SUCCESS; 39969d5fd8fSJohnny Huang } 40069d5fd8fSJohnny Huang 40169d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 40269d5fd8fSJohnny Huang { 40369d5fd8fSJohnny Huang uint32_t ret; 40469d5fd8fSJohnny Huang uint32_t *buf; 40569d5fd8fSJohnny Huang 40669d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 40769d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 40869d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 40969d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 41069d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 41169d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 41269d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 41369d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 41469d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 41569d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 41669d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 41769d5fd8fSJohnny Huang udelay(10); 41869d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 41969d5fd8fSJohnny Huang if (ret & 0x1) 42069d5fd8fSJohnny Huang return 0; 42169d5fd8fSJohnny Huang else 42269d5fd8fSJohnny Huang return -1; 42369d5fd8fSJohnny Huang } 42469d5fd8fSJohnny Huang 42569d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 42669d5fd8fSJohnny Huang { 42769d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 42869d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 42969d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 43069d5fd8fSJohnny Huang udelay(100); 43169d5fd8fSJohnny Huang } 43269d5fd8fSJohnny Huang 43369d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 43469d5fd8fSJohnny Huang { 43569d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 43669d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 43769d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 43869d5fd8fSJohnny Huang udelay(85); 43969d5fd8fSJohnny Huang } 44069d5fd8fSJohnny Huang 441a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 44269d5fd8fSJohnny Huang { 44369d5fd8fSJohnny Huang int ret; 44469d5fd8fSJohnny Huang 44569d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 44669d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 44769d5fd8fSJohnny Huang udelay(2); 44869d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 449a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 45069d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 45169d5fd8fSJohnny Huang return 0; 45269d5fd8fSJohnny Huang else 45369d5fd8fSJohnny Huang return -1; 45469d5fd8fSJohnny Huang } 45569d5fd8fSJohnny Huang 456d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 4574c1c9b35SJohnny Huang { 4584c1c9b35SJohnny Huang uint32_t ret[2]; 4594c1c9b35SJohnny Huang 4604c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4614c1c9b35SJohnny Huang 4624c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4634c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 4644c1c9b35SJohnny Huang else 4654c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 4664c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 4674c1c9b35SJohnny Huang udelay(2); 4684c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 4694c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 4704c1c9b35SJohnny Huang if (size == 1) { 4714c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4724c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 473d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 4744c1c9b35SJohnny Huang compare[0] = 0; 4754c1c9b35SJohnny Huang return 0; 4764c1c9b35SJohnny Huang } else { 4774c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4784c1c9b35SJohnny Huang return -1; 4794c1c9b35SJohnny Huang } 4804c1c9b35SJohnny Huang 4814c1c9b35SJohnny Huang } else { 4824c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 483d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 4844c1c9b35SJohnny Huang compare[0] = ~0; 4854c1c9b35SJohnny Huang return 0; 4864c1c9b35SJohnny Huang } else { 487d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 4884c1c9b35SJohnny Huang return -1; 4894c1c9b35SJohnny Huang } 4904c1c9b35SJohnny Huang } 4914c1c9b35SJohnny Huang } else if (size == 2) { 4924c1c9b35SJohnny Huang // otp_addr should be even 493d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 4944c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4954c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4964c1c9b35SJohnny Huang compare[0] = 0; 4974c1c9b35SJohnny Huang compare[1] = ~0; 4984c1c9b35SJohnny Huang return 0; 4994c1c9b35SJohnny Huang } else { 5004c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 5014c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 5024c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 5034c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 5044c1c9b35SJohnny Huang return -1; 5054c1c9b35SJohnny Huang } 5064c1c9b35SJohnny Huang } else { 5074c1c9b35SJohnny Huang return -1; 5084c1c9b35SJohnny Huang } 5094c1c9b35SJohnny Huang } 5104c1c9b35SJohnny Huang 5117e22f42dSJohnny Huang static void otp_soak(int soak) 512d90825e2SJohnny Huang { 513d90825e2SJohnny Huang if (soak) { 514d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 515d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 516d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 517d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 518d90825e2SJohnny Huang } else { 519d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 520d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 521d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 522d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 523d90825e2SJohnny Huang } 524d90825e2SJohnny Huang } 525d90825e2SJohnny Huang 526d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 527d90825e2SJohnny Huang { 528d90825e2SJohnny Huang int j, bit_value, prog_bit; 529d90825e2SJohnny Huang 530d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 531d90825e2SJohnny Huang if ((keep >> j) & 0x1) 532d90825e2SJohnny Huang continue; 533d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 534d90825e2SJohnny Huang if (prog_address % 2 == 0) { 535d90825e2SJohnny Huang if (bit_value) 536d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 537d90825e2SJohnny Huang else 538d90825e2SJohnny Huang continue; 539d90825e2SJohnny Huang } else { 540d90825e2SJohnny Huang prog_address |= 1 << 15; 541d90825e2SJohnny Huang if (bit_value) 542d90825e2SJohnny Huang continue; 543d90825e2SJohnny Huang else 544d90825e2SJohnny Huang prog_bit = 0x1 << j; 545d90825e2SJohnny Huang } 546d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 547d90825e2SJohnny Huang } 548d90825e2SJohnny Huang } 549d90825e2SJohnny Huang 55076d13988SJohnny Huang 551*541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 55276d13988SJohnny Huang { 55376d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 55476d13988SJohnny Huang int i, j; 55576d13988SJohnny Huang 55676d13988SJohnny Huang for (j = 0; j < 64; j++) { 55776d13988SJohnny Huang otpstrap[j].value = 0; 55876d13988SJohnny Huang otpstrap[j].remain_times = 7; 55976d13988SJohnny Huang otpstrap[j].writeable_option = -1; 56076d13988SJohnny Huang otpstrap[j].protected = 0; 56176d13988SJohnny Huang } 56276d13988SJohnny Huang 56376d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 56476d13988SJohnny Huang int option = (i - 16) / 2; 56576d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 56676d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 56776d13988SJohnny Huang for (j = 0; j < 32; j++) { 56876d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 56976d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 57076d13988SJohnny Huang otpstrap[j].writeable_option = option; 57176d13988SJohnny Huang } 57276d13988SJohnny Huang if (bit_value == 1) 57376d13988SJohnny Huang otpstrap[j].remain_times --; 57476d13988SJohnny Huang otpstrap[j].value ^= bit_value; 57576d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 57676d13988SJohnny Huang } 57776d13988SJohnny Huang for (j = 32; j < 64; j++) { 57876d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 57976d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 58076d13988SJohnny Huang otpstrap[j].writeable_option = option; 58176d13988SJohnny Huang } 58276d13988SJohnny Huang if (bit_value == 1) 58376d13988SJohnny Huang otpstrap[j].remain_times --; 58476d13988SJohnny Huang otpstrap[j].value ^= bit_value; 58576d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 58676d13988SJohnny Huang } 58776d13988SJohnny Huang } 58876d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 58976d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 59076d13988SJohnny Huang for (j = 0; j < 32; j++) { 59176d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 59276d13988SJohnny Huang otpstrap[j].protected = 1; 59376d13988SJohnny Huang } 59476d13988SJohnny Huang for (j = 32; j < 64; j++) { 59576d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 59676d13988SJohnny Huang otpstrap[j].protected = 1; 59776d13988SJohnny Huang } 59876d13988SJohnny Huang } 59976d13988SJohnny Huang 600b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 60169d5fd8fSJohnny Huang { 602442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 603b458cd62SJohnny Huang uint32_t mask; 604b458cd62SJohnny Huang uint32_t dw_offset; 605b458cd62SJohnny Huang uint32_t bit_offset; 606b458cd62SJohnny Huang uint32_t otp_value; 607b458cd62SJohnny Huang uint32_t otp_keep; 608b458cd62SJohnny Huang int fail = 0; 60973f11549SJohnny Huang char valid_bit[20]; 61066f2f8e5SJohnny Huang int i; 61173f11549SJohnny Huang int j; 61266f2f8e5SJohnny Huang 613737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 61466f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 615b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 616b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 617b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 618b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 619b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 620b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 621b458cd62SJohnny Huang 622b458cd62SJohnny Huang if (otp_keep == mask) { 623b458cd62SJohnny Huang continue; 624b458cd62SJohnny Huang } else if (otp_keep != 0) { 625b458cd62SJohnny Huang fail = 1; 626b458cd62SJohnny Huang } 627b458cd62SJohnny Huang 628b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 629b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 630b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 631b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 632b458cd62SJohnny Huang continue; 633b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 634b458cd62SJohnny Huang 635b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 636b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 63766f2f8e5SJohnny Huang } else { 638b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 639b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 640b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 64166f2f8e5SJohnny Huang } 642b458cd62SJohnny Huang printf("0x%-10x", otp_value); 643b458cd62SJohnny Huang 644b458cd62SJohnny Huang if (fail) { 645b458cd62SJohnny Huang printf("Keep mask error\n"); 646b458cd62SJohnny Huang } else { 647b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 648b458cd62SJohnny Huang printf("Reserved\n"); 649b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 650b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 651b458cd62SJohnny Huang printf("\n"); 652b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 653b458cd62SJohnny Huang if (otp_value != 0) { 65473f11549SJohnny Huang for (j = 0; j < 7; j++) { 65573f11549SJohnny Huang if (otp_value == (1 << j)) { 65673f11549SJohnny Huang valid_bit[j * 2] = '1'; 657b458cd62SJohnny Huang } else { 65873f11549SJohnny Huang valid_bit[j * 2] = '0'; 65973f11549SJohnny Huang } 66073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 66173f11549SJohnny Huang } 66273f11549SJohnny Huang valid_bit[15] = 0; 66373f11549SJohnny Huang } else { 66473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 665b458cd62SJohnny Huang } 666b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 667b458cd62SJohnny Huang printf("\n"); 668b458cd62SJohnny Huang } else { 669b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 670b458cd62SJohnny Huang } 671b458cd62SJohnny Huang } 672b458cd62SJohnny Huang } 673b458cd62SJohnny Huang 674b458cd62SJohnny Huang if (fail) 675b458cd62SJohnny Huang return OTP_FAILURE; 676b458cd62SJohnny Huang 67766f2f8e5SJohnny Huang return OTP_SUCCESS; 67866f2f8e5SJohnny Huang } 67966f2f8e5SJohnny Huang 6802d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 68166f2f8e5SJohnny Huang { 682b458cd62SJohnny Huang uint32_t OTPCFG[12]; 683b458cd62SJohnny Huang uint32_t mask; 684b458cd62SJohnny Huang uint32_t dw_offset; 685b458cd62SJohnny Huang uint32_t bit_offset; 686b458cd62SJohnny Huang uint32_t otp_value; 68773f11549SJohnny Huang char valid_bit[20]; 68866f2f8e5SJohnny Huang int i; 68973f11549SJohnny Huang int j; 69066f2f8e5SJohnny Huang 69166f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 69266f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 69366f2f8e5SJohnny Huang 69466f2f8e5SJohnny Huang 695b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 696b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 697b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 6982d4b0742SJohnny Huang if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset) 6992d4b0742SJohnny Huang continue; 700b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 701b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 702b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 703b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 704b458cd62SJohnny Huang 705b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 706b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 707b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 708b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 709b458cd62SJohnny Huang continue; 710b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 711b458cd62SJohnny Huang 712b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 713b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 714b458cd62SJohnny Huang } else { 715b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 716b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 717b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 718b458cd62SJohnny Huang } 719b458cd62SJohnny Huang printf("0x%-10x", otp_value); 720b458cd62SJohnny Huang 721b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 722b458cd62SJohnny Huang printf("Reserved\n"); 723b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 724b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 725b458cd62SJohnny Huang printf("\n"); 726b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 727b458cd62SJohnny Huang if (otp_value != 0) { 72873f11549SJohnny Huang for (j = 0; j < 7; j++) { 72973f11549SJohnny Huang if (otp_value == (1 << j)) { 73073f11549SJohnny Huang valid_bit[j * 2] = '1'; 731b458cd62SJohnny Huang } else { 73273f11549SJohnny Huang valid_bit[j * 2] = '0'; 73373f11549SJohnny Huang } 73473f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 73573f11549SJohnny Huang } 73673f11549SJohnny Huang valid_bit[15] = 0; 73773f11549SJohnny Huang } else { 73873f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 739b458cd62SJohnny Huang } 740b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 741b458cd62SJohnny Huang printf("\n"); 742b458cd62SJohnny Huang } else { 743b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 744b458cd62SJohnny Huang } 745b458cd62SJohnny Huang } 746b458cd62SJohnny Huang return OTP_SUCCESS; 74766f2f8e5SJohnny Huang } 74866f2f8e5SJohnny Huang 749b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 75076d13988SJohnny Huang { 751a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 752a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 75376d13988SJohnny Huang int i; 754a8bd6d8cSJohnny Huang int fail = 0; 755a8bd6d8cSJohnny Huang uint32_t bit_offset; 756a8bd6d8cSJohnny Huang uint32_t dw_offset; 757a8bd6d8cSJohnny Huang uint32_t mask; 758a8bd6d8cSJohnny Huang uint32_t otp_value; 759a8bd6d8cSJohnny Huang uint32_t otp_protect; 760a8bd6d8cSJohnny Huang uint32_t otp_keep; 76176d13988SJohnny Huang 762a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 763a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 764b458cd62SJohnny Huang 765a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 766a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 767a8bd6d8cSJohnny Huang dw_offset = 1; 768a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 769a8bd6d8cSJohnny Huang } else { 770a8bd6d8cSJohnny Huang dw_offset = 0; 771a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 772a8bd6d8cSJohnny Huang } 77376d13988SJohnny Huang 774a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 775a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 776a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 777a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 778a8bd6d8cSJohnny Huang 779a8bd6d8cSJohnny Huang if (otp_keep == mask) { 780a8bd6d8cSJohnny Huang continue; 781a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 782a8bd6d8cSJohnny Huang fail = 1; 783a8bd6d8cSJohnny Huang } 784a8bd6d8cSJohnny Huang 785a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 786a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 787a8bd6d8cSJohnny Huang continue; 788a8bd6d8cSJohnny Huang 789a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 790b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 791a8bd6d8cSJohnny Huang } else { 792b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 793a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 794a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 795a8bd6d8cSJohnny Huang } 796a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 797a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 798a8bd6d8cSJohnny Huang 799a8bd6d8cSJohnny Huang if (fail) { 800a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 801a8bd6d8cSJohnny Huang } else { 802a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 803a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 804a8bd6d8cSJohnny Huang else 805a8bd6d8cSJohnny Huang printf("Reserved\n"); 806a8bd6d8cSJohnny Huang } 807a8bd6d8cSJohnny Huang } 808a8bd6d8cSJohnny Huang 809a8bd6d8cSJohnny Huang if (fail) 81076d13988SJohnny Huang return OTP_FAILURE; 81176d13988SJohnny Huang 81276d13988SJohnny Huang return OTP_SUCCESS; 81376d13988SJohnny Huang } 81476d13988SJohnny Huang 815b458cd62SJohnny Huang static int otp_print_strap_info(int view) 81676d13988SJohnny Huang { 81776d13988SJohnny Huang struct otpstrap_status strap_status[64]; 81807baa4e8SJohnny Huang int i, j; 819b458cd62SJohnny Huang int fail = 0; 820b458cd62SJohnny Huang uint32_t bit_offset; 821b458cd62SJohnny Huang uint32_t length; 822b458cd62SJohnny Huang uint32_t otp_value; 823b458cd62SJohnny Huang uint32_t otp_protect; 82476d13988SJohnny Huang 825*541eb887SJohnny Huang otp_strap_status(strap_status); 82676d13988SJohnny Huang 827b458cd62SJohnny Huang if (view) { 82807baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 82907baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 83007baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 83107baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 832b458cd62SJohnny Huang } else { 833b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 834b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 83576d13988SJohnny Huang } 836b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 837b458cd62SJohnny Huang otp_value = 0; 838b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 839b458cd62SJohnny Huang length = a0_strap_info[i].length; 840b458cd62SJohnny Huang for (j = 0; j < length; j++) { 841c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 842c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 843b458cd62SJohnny Huang } 844b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 845b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 846b458cd62SJohnny Huang continue; 847b458cd62SJohnny Huang if (view) { 848b458cd62SJohnny Huang for (j = 0; j < length; j++) { 849b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 850b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 85107baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 852b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 853b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 854b458cd62SJohnny Huang printf(" Reserved\n"); 855b458cd62SJohnny Huang continue; 856b458cd62SJohnny Huang } 857b458cd62SJohnny Huang if (length == 1) { 858b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 859b458cd62SJohnny Huang continue; 86076d13988SJohnny Huang } 86176d13988SJohnny Huang 862b458cd62SJohnny Huang if (j == 0) 863b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 864b458cd62SJohnny Huang else if (j == length - 1) 865b458cd62SJohnny Huang printf("\\ \"\n"); 866b458cd62SJohnny Huang else 867b458cd62SJohnny Huang printf("| \"\n"); 86876d13988SJohnny Huang } 869b458cd62SJohnny Huang } else { 870c947ef08SJohnny Huang if (length == 1) { 871b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 872b458cd62SJohnny Huang } else { 873b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 874b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 875b458cd62SJohnny Huang } 876b458cd62SJohnny Huang 877b458cd62SJohnny Huang printf("0x%-10X", otp_value); 878b458cd62SJohnny Huang 879b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 880b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 881b458cd62SJohnny Huang else 882b458cd62SJohnny Huang printf("Reserved\n"); 883b458cd62SJohnny Huang } 884b458cd62SJohnny Huang } 885b458cd62SJohnny Huang 886b458cd62SJohnny Huang if (fail) 887b458cd62SJohnny Huang return OTP_FAILURE; 888b458cd62SJohnny Huang 889b458cd62SJohnny Huang return OTP_SUCCESS; 890b458cd62SJohnny Huang } 891b458cd62SJohnny Huang 89269d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 89369d5fd8fSJohnny Huang { 89469d5fd8fSJohnny Huang int i; 89569d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 89669d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 89769d5fd8fSJohnny Huang if (i % 16 == 0) { 89869d5fd8fSJohnny Huang printf("%04X: ", i); 89969d5fd8fSJohnny Huang } 90069d5fd8fSJohnny Huang printf("%02X ", buf[i]); 90169d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 90269d5fd8fSJohnny Huang printf("\n"); 90369d5fd8fSJohnny Huang } 90469d5fd8fSJohnny Huang } 90569d5fd8fSJohnny Huang } 90669d5fd8fSJohnny Huang 9077f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 90869d5fd8fSJohnny Huang { 90969d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 9109a4fe690SJohnny Huang struct otpkey_type *key_info_array = info_cb.key_info; 9119a4fe690SJohnny Huang struct otpkey_type key_info; 91269d5fd8fSJohnny Huang char *byte_buf; 91369d5fd8fSJohnny Huang int i = 0, len = 0; 9149a4fe690SJohnny Huang int j; 91569d5fd8fSJohnny Huang byte_buf = (char *)buf; 91669d5fd8fSJohnny Huang while (1) { 91769d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 91869d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 91969d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 92069d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 92169d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 92269d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 9239a4fe690SJohnny Huang 9249a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 9259a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 9269a4fe690SJohnny Huang key_info = key_info_array[j]; 9279a4fe690SJohnny Huang break; 9289a4fe690SJohnny Huang } 9299a4fe690SJohnny Huang } 9309a4fe690SJohnny Huang 9317f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 93269d5fd8fSJohnny Huang printf("Key Type: "); 9339a4fe690SJohnny Huang printf("%s\n", key_info.information); 9349a4fe690SJohnny Huang 9359a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 93669d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 93769d5fd8fSJohnny Huang switch (key_length) { 93869d5fd8fSJohnny Huang case 0: 93969d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 94069d5fd8fSJohnny Huang break; 94169d5fd8fSJohnny Huang case 1: 94269d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 94369d5fd8fSJohnny Huang break; 94469d5fd8fSJohnny Huang case 2: 94569d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 94669d5fd8fSJohnny Huang break; 94769d5fd8fSJohnny Huang case 3: 94869d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 94969d5fd8fSJohnny Huang break; 95069d5fd8fSJohnny Huang } 9519a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 95269d5fd8fSJohnny Huang printf("RSA SHA Type: "); 95369d5fd8fSJohnny Huang switch (key_length) { 95469d5fd8fSJohnny Huang case 0: 95569d5fd8fSJohnny Huang printf("RSA1024\n"); 95669d5fd8fSJohnny Huang len = 0x100; 95769d5fd8fSJohnny Huang break; 95869d5fd8fSJohnny Huang case 1: 95969d5fd8fSJohnny Huang printf("RSA2048\n"); 96069d5fd8fSJohnny Huang len = 0x200; 96169d5fd8fSJohnny Huang break; 96269d5fd8fSJohnny Huang case 2: 96369d5fd8fSJohnny Huang printf("RSA3072\n"); 96469d5fd8fSJohnny Huang len = 0x300; 96569d5fd8fSJohnny Huang break; 96669d5fd8fSJohnny Huang case 3: 96769d5fd8fSJohnny Huang printf("RSA4096\n"); 96869d5fd8fSJohnny Huang len = 0x400; 96969d5fd8fSJohnny Huang break; 97069d5fd8fSJohnny Huang } 97169d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 97269d5fd8fSJohnny Huang } 9739a4fe690SJohnny Huang if (key_info.need_id) 97469d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 97569d5fd8fSJohnny Huang printf("Key Value:\n"); 9769a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 97769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 9789a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 9799a4fe690SJohnny Huang printf("AES Key:\n"); 9809a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 9819a4fe690SJohnny Huang if (info_cb.version == 0) { 9829a4fe690SJohnny Huang printf("AES IV:\n"); 9839a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 9849a4fe690SJohnny Huang } 9859a4fe690SJohnny Huang 9869a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 9879a4fe690SJohnny Huang if (info_cb.version == 0) { 98869d5fd8fSJohnny Huang printf("AES Key:\n"); 98969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 99069d5fd8fSJohnny Huang printf("AES IV:\n"); 99169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 9929a4fe690SJohnny Huang } else if (info_cb.version == 1) { 9939a4fe690SJohnny Huang printf("AES Key 1:\n"); 9949a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 9959a4fe690SJohnny Huang printf("AES Key 2:\n"); 9969a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 9979a4fe690SJohnny Huang } 99869d5fd8fSJohnny Huang 9999a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 100069d5fd8fSJohnny Huang printf("RSA mod:\n"); 100169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 100269d5fd8fSJohnny Huang printf("RSA exp:\n"); 100369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 100469d5fd8fSJohnny Huang } 100569d5fd8fSJohnny Huang if (last) 100669d5fd8fSJohnny Huang break; 100769d5fd8fSJohnny Huang i++; 100869d5fd8fSJohnny Huang } 100969d5fd8fSJohnny Huang return 0; 101069d5fd8fSJohnny Huang } 101169d5fd8fSJohnny Huang 1012a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 101369d5fd8fSJohnny Huang { 1014a6d0d645SJohnny Huang int i, k; 1015d90825e2SJohnny Huang int pass = 0; 1016d90825e2SJohnny Huang int soak = 0; 1017a6d0d645SJohnny Huang uint32_t prog_address; 1018a6d0d645SJohnny Huang uint32_t data[12]; 1019a6d0d645SJohnny Huang uint32_t compare[2]; 1020d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1021d90825e2SJohnny Huang uint32_t data_masked; 1022d90825e2SJohnny Huang uint32_t buf_masked; 102369d5fd8fSJohnny Huang 1024a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1025a6d0d645SJohnny Huang 1026a6d0d645SJohnny Huang printProgress(0, 12, ""); 1027a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1028a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 102969d5fd8fSJohnny Huang prog_address = 0x800; 1030a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1031a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1032a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1033a6d0d645SJohnny Huang } 1034a6d0d645SJohnny Huang 1035a6d0d645SJohnny Huang printf("Check writable...\n"); 1036a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1037d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1038d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1039d90825e2SJohnny Huang if (data_masked == buf_masked) 104069d5fd8fSJohnny Huang continue; 1041d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1042a6d0d645SJohnny Huang continue; 1043a6d0d645SJohnny Huang } else { 1044a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1045a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1046a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1047a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 10482a856b9aSJohnny Huang return OTP_FAILURE; 1049a6d0d645SJohnny Huang } 1050a6d0d645SJohnny Huang } 1051a6d0d645SJohnny Huang 1052a6d0d645SJohnny Huang printf("Start Programing...\n"); 1053a6d0d645SJohnny Huang printProgress(0, 12, ""); 1054d90825e2SJohnny Huang otp_soak(0); 1055a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1056d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1057d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1058a6d0d645SJohnny Huang prog_address = 0x800; 1059a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1060a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1061d90825e2SJohnny Huang if (data_masked == buf_masked) { 1062a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1063a6d0d645SJohnny Huang continue; 1064a6d0d645SJohnny Huang } 1065d90825e2SJohnny Huang if (soak) { 1066d90825e2SJohnny Huang soak = 0; 1067d90825e2SJohnny Huang otp_soak(0); 1068d90825e2SJohnny Huang } 1069a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1070a6d0d645SJohnny Huang 1071d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1072a6d0d645SJohnny Huang 107369d5fd8fSJohnny Huang pass = 0; 107469d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1075d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1076d90825e2SJohnny Huang if (soak == 0) { 1077d90825e2SJohnny Huang soak = 1; 1078d90825e2SJohnny Huang otp_soak(1); 1079d90825e2SJohnny Huang } 1080a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1081a6d0d645SJohnny Huang } else { 108269d5fd8fSJohnny Huang pass = 1; 108369d5fd8fSJohnny Huang break; 108469d5fd8fSJohnny Huang } 108569d5fd8fSJohnny Huang } 1086a6d0d645SJohnny Huang } 1087a6d0d645SJohnny Huang 108869d5fd8fSJohnny Huang if (!pass) 10892a856b9aSJohnny Huang return OTP_FAILURE; 1090a6d0d645SJohnny Huang 10912a856b9aSJohnny Huang return OTP_SUCCESS; 1092d90825e2SJohnny Huang 109369d5fd8fSJohnny Huang } 109469d5fd8fSJohnny Huang 109569d5fd8fSJohnny Huang 109676d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 109769d5fd8fSJohnny Huang { 109869d5fd8fSJohnny Huang int i; 109969d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 110069d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 110169d5fd8fSJohnny Huang int bit, pbit, kbit; 110269d5fd8fSJohnny Huang int fail = 0; 1103a6af4a17SJohnny Huang int skip = -1; 110466f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 110569d5fd8fSJohnny Huang 1106*541eb887SJohnny Huang otp_strap_status(otpstrap); 110769d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 110869d5fd8fSJohnny Huang if (i < 32) { 110969d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 111069d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 111169d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 111269d5fd8fSJohnny Huang } else { 111369d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 111469d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 111569d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 111669d5fd8fSJohnny Huang } 111769d5fd8fSJohnny Huang 111869d5fd8fSJohnny Huang if (kbit == 1) { 111969d5fd8fSJohnny Huang continue; 112069d5fd8fSJohnny Huang } else { 1121a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 112269d5fd8fSJohnny Huang } 112369d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 112469d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1125a6af4a17SJohnny Huang if (skip == -1) 1126a6af4a17SJohnny Huang skip = 1; 112769d5fd8fSJohnny Huang continue; 1128a6af4a17SJohnny Huang } else { 1129a6af4a17SJohnny Huang skip = 0; 113069d5fd8fSJohnny Huang } 113169d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 113269d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 113369d5fd8fSJohnny Huang fail = 1; 113469d5fd8fSJohnny Huang continue; 113569d5fd8fSJohnny Huang } 113669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1137a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 113869d5fd8fSJohnny Huang fail = 1; 113969d5fd8fSJohnny Huang continue; 114069d5fd8fSJohnny Huang } 114169d5fd8fSJohnny Huang if (pbit == 1) { 114269d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 114369d5fd8fSJohnny Huang } 1144a6af4a17SJohnny 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); 114569d5fd8fSJohnny Huang } 114669d5fd8fSJohnny Huang if (fail == 1) 1147a6af4a17SJohnny Huang return OTP_FAILURE; 1148a6af4a17SJohnny Huang else if (skip == 1) 1149a6af4a17SJohnny Huang return OTP_PROG_SKIP; 11507e22f42dSJohnny Huang 11517e22f42dSJohnny Huang return 0; 115269d5fd8fSJohnny Huang } 115369d5fd8fSJohnny Huang 11542a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 115569d5fd8fSJohnny Huang { 115669d5fd8fSJohnny Huang int i, j; 115766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 115869d5fd8fSJohnny Huang 11592a856b9aSJohnny Huang if (start < 0 || start > 64) 11602a856b9aSJohnny Huang return OTP_USAGE; 11612a856b9aSJohnny Huang 11622a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 11632a856b9aSJohnny Huang return OTP_USAGE; 11642a856b9aSJohnny Huang 1165*541eb887SJohnny Huang otp_strap_status(otpstrap); 116669d5fd8fSJohnny Huang 116707baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1168a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1169737ed20bSJohnny Huang 1170cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 117107baa4e8SJohnny Huang printf("0x%-8X", i); 1172737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1173737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1174737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1175737ed20bSJohnny Huang printf(" "); 117669d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1177737ed20bSJohnny Huang printf("protected and not writable"); 117869d5fd8fSJohnny Huang } else { 1179737ed20bSJohnny Huang printf("not protected "); 118069d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1181737ed20bSJohnny Huang printf("and no remaining times to write."); 118269d5fd8fSJohnny Huang } else { 1183737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 118469d5fd8fSJohnny Huang } 118569d5fd8fSJohnny Huang } 1186737ed20bSJohnny Huang printf("\n"); 118769d5fd8fSJohnny Huang } 11882a856b9aSJohnny Huang 11892a856b9aSJohnny Huang return OTP_SUCCESS; 119069d5fd8fSJohnny Huang } 119169d5fd8fSJohnny Huang 119269d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 119369d5fd8fSJohnny Huang { 119469d5fd8fSJohnny Huang int i, j; 119569d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 119669d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 119769d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 119869d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 119969d5fd8fSJohnny Huang int fail = 0; 12007e22f42dSJohnny Huang int pass = 0; 12017e22f42dSJohnny Huang int soak = 0; 120266f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 120369d5fd8fSJohnny Huang 12047f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1205*541eb887SJohnny Huang otp_strap_status(otpstrap); 120669d5fd8fSJohnny Huang 12077f795e57SJohnny Huang printf("Check writable...\n"); 12087f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 12097f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 12107f795e57SJohnny Huang return OTP_FAILURE; 12117f795e57SJohnny Huang } 12127e22f42dSJohnny Huang 12137f795e57SJohnny Huang otp_soak(0); 121469d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 12154c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 121669d5fd8fSJohnny Huang prog_address = 0x800; 121769d5fd8fSJohnny Huang if (i < 32) { 121869d5fd8fSJohnny Huang offset = i; 121969d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 122069d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 122169d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 122269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 122369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 122469d5fd8fSJohnny Huang 122569d5fd8fSJohnny Huang } else { 122669d5fd8fSJohnny Huang offset = (i - 32); 122769d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 122869d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 122969d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 123069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 123169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 123269d5fd8fSJohnny Huang } 123369d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 123469d5fd8fSJohnny Huang 123569d5fd8fSJohnny Huang if (kbit == 1) { 123669d5fd8fSJohnny Huang continue; 123769d5fd8fSJohnny Huang } 123869d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 123969d5fd8fSJohnny Huang continue; 124069d5fd8fSJohnny Huang } 124169d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 124269d5fd8fSJohnny Huang fail = 1; 124369d5fd8fSJohnny Huang continue; 124469d5fd8fSJohnny Huang } 124569d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 124669d5fd8fSJohnny Huang fail = 1; 124769d5fd8fSJohnny Huang continue; 124869d5fd8fSJohnny Huang } 12497e22f42dSJohnny Huang 12507e22f42dSJohnny Huang if (soak) { 125169d5fd8fSJohnny Huang soak = 0; 12527e22f42dSJohnny Huang otp_soak(0); 12537e22f42dSJohnny Huang } 12547e22f42dSJohnny Huang 12557e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 12567e22f42dSJohnny Huang 12577e22f42dSJohnny Huang pass = 0; 12587e22f42dSJohnny Huang 125969d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1260a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 126169d5fd8fSJohnny Huang pass = 1; 126269d5fd8fSJohnny Huang break; 126369d5fd8fSJohnny Huang } 12647e22f42dSJohnny Huang if (soak == 0) { 126569d5fd8fSJohnny Huang soak = 1; 12667e22f42dSJohnny Huang otp_soak(1); 12674b65a65dSJohnny Huang } 126869d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 126969d5fd8fSJohnny Huang } 127069d5fd8fSJohnny Huang if (!pass) 12712a856b9aSJohnny Huang return OTP_FAILURE; 127269d5fd8fSJohnny Huang 127369d5fd8fSJohnny Huang if (pbit == 0) 127469d5fd8fSJohnny Huang continue; 127569d5fd8fSJohnny Huang prog_address = 0x800; 127669d5fd8fSJohnny Huang if (i < 32) 127769d5fd8fSJohnny Huang prog_address |= 0x60c; 127869d5fd8fSJohnny Huang else 127969d5fd8fSJohnny Huang prog_address |= 0x60e; 128069d5fd8fSJohnny Huang 12817e22f42dSJohnny Huang 12827e22f42dSJohnny Huang if (soak) { 12837e22f42dSJohnny Huang soak = 0; 12847e22f42dSJohnny Huang otp_soak(0); 12857e22f42dSJohnny Huang } 12867e22f42dSJohnny Huang 12877e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 12887e22f42dSJohnny Huang 12897e22f42dSJohnny Huang pass = 0; 12907e22f42dSJohnny Huang 129169d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 12927e22f42dSJohnny Huang 1293a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 129469d5fd8fSJohnny Huang pass = 1; 129569d5fd8fSJohnny Huang break; 129669d5fd8fSJohnny Huang } 12977e22f42dSJohnny Huang if (soak == 0) { 129869d5fd8fSJohnny Huang soak = 1; 12997e22f42dSJohnny Huang otp_soak(1); 130069d5fd8fSJohnny Huang } 130169d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 130269d5fd8fSJohnny Huang } 130369d5fd8fSJohnny Huang if (!pass) 13042a856b9aSJohnny Huang return OTP_FAILURE; 130569d5fd8fSJohnny Huang 130669d5fd8fSJohnny Huang } 130769d5fd8fSJohnny Huang if (fail == 1) 13082a856b9aSJohnny Huang return OTP_FAILURE; 130969d5fd8fSJohnny Huang else 13102a856b9aSJohnny Huang return OTP_SUCCESS; 131169d5fd8fSJohnny Huang 131269d5fd8fSJohnny Huang } 131369d5fd8fSJohnny Huang 1314cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1315cd1610b4SJohnny Huang { 1316cd1610b4SJohnny Huang int prog_bit; 1317cd1610b4SJohnny Huang 13187e22f42dSJohnny Huang otp_soak(soak); 13197e22f42dSJohnny Huang 1320cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1321cd1610b4SJohnny Huang if (value) 1322cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1323cd1610b4SJohnny Huang else 1324cd1610b4SJohnny Huang return; 1325cd1610b4SJohnny Huang } else { 1326cd1610b4SJohnny Huang prog_address |= 1 << 15; 1327cd1610b4SJohnny Huang if (!value) 1328cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1329cd1610b4SJohnny Huang else 1330cd1610b4SJohnny Huang return; 1331cd1610b4SJohnny Huang } 1332cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1333cd1610b4SJohnny Huang } 1334cd1610b4SJohnny Huang 1335d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 13364c1c9b35SJohnny Huang { 13374c1c9b35SJohnny Huang int i, k; 13384c1c9b35SJohnny Huang int pass; 1339d90825e2SJohnny Huang int soak = 0; 13404c1c9b35SJohnny Huang uint32_t prog_address; 1341d90825e2SJohnny Huang uint32_t data[2048]; 13424c1c9b35SJohnny Huang uint32_t compare[2]; 1343d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 13444c1c9b35SJohnny Huang 1345d90825e2SJohnny Huang uint32_t data0_masked; 1346d90825e2SJohnny Huang uint32_t data1_masked; 1347d90825e2SJohnny Huang uint32_t buf0_masked; 1348d90825e2SJohnny Huang uint32_t buf1_masked; 13494c1c9b35SJohnny Huang 13504c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 13514c1c9b35SJohnny Huang 1352d90825e2SJohnny Huang printProgress(0, 2048, ""); 1353d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1354d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1355d90825e2SJohnny Huang otp_read_data(i, &data[i]); 13564c1c9b35SJohnny Huang } 1357d90825e2SJohnny Huang 13584c1c9b35SJohnny Huang 13594c1c9b35SJohnny Huang printf("Check writable...\n"); 1360d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1361d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1362d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1363d90825e2SJohnny Huang if (data0_masked == buf0_masked) 13644c1c9b35SJohnny Huang continue; 1365d90825e2SJohnny Huang if (i % 2 == 0) { 1366d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 13674c1c9b35SJohnny Huang continue; 13684c1c9b35SJohnny Huang } else { 13694c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1370d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 13714c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1372d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 13732a856b9aSJohnny Huang return OTP_FAILURE; 137469d5fd8fSJohnny Huang } 1375d90825e2SJohnny Huang } else { 1376d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1377d90825e2SJohnny Huang continue; 1378d90825e2SJohnny Huang } else { 1379d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1380d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1381d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1382d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 13832a856b9aSJohnny Huang return OTP_FAILURE; 1384d90825e2SJohnny Huang } 1385d90825e2SJohnny Huang } 1386d90825e2SJohnny Huang } 138769d5fd8fSJohnny Huang 1388d90825e2SJohnny Huang printf("Start Programing...\n"); 1389d90825e2SJohnny Huang printProgress(0, 2048, ""); 1390d90825e2SJohnny Huang 1391d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1392d90825e2SJohnny Huang prog_address = i; 1393d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1394d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1395d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1396d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1397d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1398d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1399d90825e2SJohnny Huang continue; 1400d90825e2SJohnny Huang } 1401d90825e2SJohnny Huang if (soak) { 1402d90825e2SJohnny Huang soak = 0; 1403d90825e2SJohnny Huang otp_soak(0); 1404d90825e2SJohnny Huang } 1405d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1406d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1407d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1408d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1409d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1410d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1411d90825e2SJohnny Huang } else { 1412d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1413d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1414d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1415d90825e2SJohnny Huang } 1416d90825e2SJohnny Huang 1417d90825e2SJohnny Huang pass = 0; 1418d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1419d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1420d90825e2SJohnny Huang if (soak == 0) { 1421d90825e2SJohnny Huang soak = 1; 1422d90825e2SJohnny Huang otp_soak(1); 1423d90825e2SJohnny Huang } 1424d90825e2SJohnny Huang if (compare[0] != 0) { 1425d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1426d90825e2SJohnny Huang } 1427d90825e2SJohnny Huang if (compare[1] != ~0) { 1428d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1429d90825e2SJohnny Huang } 1430d90825e2SJohnny Huang } else { 1431d90825e2SJohnny Huang pass = 1; 1432d90825e2SJohnny Huang break; 1433d90825e2SJohnny Huang } 1434d90825e2SJohnny Huang } 1435d90825e2SJohnny Huang 1436d90825e2SJohnny Huang if (!pass) 14372a856b9aSJohnny Huang return OTP_FAILURE; 1438d90825e2SJohnny Huang } 14392a856b9aSJohnny Huang return OTP_SUCCESS; 1440d90825e2SJohnny Huang 1441d90825e2SJohnny Huang } 1442d90825e2SJohnny Huang 1443d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 144469d5fd8fSJohnny Huang { 144569d5fd8fSJohnny Huang int ret; 14467332532cSJohnny Huang int mode = 0; 14479a4fe690SJohnny Huang int image_version = 0; 144869d5fd8fSJohnny Huang uint32_t *buf; 1449d90825e2SJohnny Huang uint32_t *data_region = NULL; 1450d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1451d90825e2SJohnny Huang uint32_t *strap_region = NULL; 145269d5fd8fSJohnny Huang 1453d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 145469d5fd8fSJohnny Huang if (!buf) { 145569d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 14562a856b9aSJohnny Huang return OTP_FAILURE; 145769d5fd8fSJohnny Huang } 1458d90825e2SJohnny Huang 14599a4fe690SJohnny Huang image_version = buf[0] & 0x3; 14609a4fe690SJohnny Huang if (image_version != info_cb.version) { 14619a4fe690SJohnny Huang puts("Version is not match\n"); 14629a4fe690SJohnny Huang return OTP_FAILURE; 14639a4fe690SJohnny Huang } 14649a4fe690SJohnny Huang 1465d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 14667332532cSJohnny Huang mode |= OTP_REGION_DATA; 14677332532cSJohnny Huang data_region = &buf[36]; 1468d90825e2SJohnny Huang } 1469d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 14707332532cSJohnny Huang mode |= OTP_REGION_CONF; 14717332532cSJohnny Huang conf_region = &buf[12]; 1472d90825e2SJohnny Huang } 1473d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 14747332532cSJohnny Huang mode |= OTP_REGION_STRAP; 14757332532cSJohnny Huang strap_region = &buf[4]; 1476d90825e2SJohnny Huang } 14777332532cSJohnny Huang 147869d5fd8fSJohnny Huang if (!nconfirm) { 14797332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 14807f795e57SJohnny Huang printf("\nOTP data region :\n"); 14817f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 148269d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 14832a856b9aSJohnny Huang return OTP_FAILURE; 148469d5fd8fSJohnny Huang } 148569d5fd8fSJohnny Huang } 14867332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 14877332532cSJohnny Huang printf("\nOTP strap region :\n"); 14887332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 14897332532cSJohnny Huang printf("OTP strap error, please check.\n"); 14907332532cSJohnny Huang return OTP_FAILURE; 14917332532cSJohnny Huang } 14927332532cSJohnny Huang } 14937332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 14947332532cSJohnny Huang printf("\nOTP configuration region :\n"); 14957332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 14967332532cSJohnny Huang printf("OTP config error, please check.\n"); 14977332532cSJohnny Huang return OTP_FAILURE; 14987332532cSJohnny Huang } 14997332532cSJohnny Huang } 15007332532cSJohnny Huang 150169d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 150269d5fd8fSJohnny Huang if (!confirm_yesno()) { 150369d5fd8fSJohnny Huang printf(" Aborting\n"); 15042a856b9aSJohnny Huang return OTP_FAILURE; 150569d5fd8fSJohnny Huang } 150669d5fd8fSJohnny Huang } 15077332532cSJohnny Huang 15087332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 15097332532cSJohnny Huang printf("programing data region ...\n"); 1510d90825e2SJohnny Huang ret = otp_prog_data(data_region); 15112a856b9aSJohnny Huang if (ret != 0) { 151269d5fd8fSJohnny Huang printf("Error\n"); 151369d5fd8fSJohnny Huang return ret; 151469d5fd8fSJohnny Huang } else { 151569d5fd8fSJohnny Huang printf("Done\n"); 151669d5fd8fSJohnny Huang } 15177332532cSJohnny Huang } 15187332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 15197332532cSJohnny Huang printf("programing strap region ...\n"); 1520d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 15212a856b9aSJohnny Huang if (ret != 0) { 152269d5fd8fSJohnny Huang printf("Error\n"); 152369d5fd8fSJohnny Huang return ret; 152469d5fd8fSJohnny Huang } else { 152569d5fd8fSJohnny Huang printf("Done\n"); 152669d5fd8fSJohnny Huang } 15277332532cSJohnny Huang } 15287332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 15297332532cSJohnny Huang printf("programing configuration region ...\n"); 1530d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 15312a856b9aSJohnny Huang if (ret != 0) { 153269d5fd8fSJohnny Huang printf("Error\n"); 153369d5fd8fSJohnny Huang return ret; 153469d5fd8fSJohnny Huang } 153569d5fd8fSJohnny Huang printf("Done\n"); 153669d5fd8fSJohnny Huang } 1537cd1610b4SJohnny Huang 15387332532cSJohnny Huang return OTP_SUCCESS; 15392a856b9aSJohnny Huang } 15402a856b9aSJohnny Huang 15412a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1542cd1610b4SJohnny Huang { 1543a6af4a17SJohnny Huang uint32_t read[2]; 1544cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1545d90825e2SJohnny Huang uint32_t prog_address = 0; 154666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1547cd1610b4SJohnny Huang int otp_bit; 1548cd1610b4SJohnny Huang int i; 1549cd1610b4SJohnny Huang int pass; 1550a6af4a17SJohnny Huang int ret; 1551cd1610b4SJohnny Huang 1552cd1610b4SJohnny Huang switch (mode) { 1553a6d0d645SJohnny Huang case OTP_REGION_CONF: 1554a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1555cd1610b4SJohnny Huang prog_address = 0x800; 1556cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1557cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1558a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1559cd1610b4SJohnny Huang if (otp_bit == value) { 1560a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1561cd1610b4SJohnny Huang printf("No need to program\n"); 15622a856b9aSJohnny Huang return OTP_SUCCESS; 1563cd1610b4SJohnny Huang } 1564cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1565a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1566cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 15672a856b9aSJohnny Huang return OTP_FAILURE; 1568cd1610b4SJohnny Huang } 1569a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1570cd1610b4SJohnny Huang break; 1571a6d0d645SJohnny Huang case OTP_REGION_DATA: 1572cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1573cd1610b4SJohnny Huang 1574cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1575a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1576a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1577cd1610b4SJohnny Huang } else { 1578a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1579a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1580cd1610b4SJohnny Huang } 1581cd1610b4SJohnny Huang if (otp_bit == value) { 1582a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1583cd1610b4SJohnny Huang printf("No need to program\n"); 15842a856b9aSJohnny Huang return OTP_SUCCESS; 1585cd1610b4SJohnny Huang } 1586cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1587a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1588cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 15892a856b9aSJohnny Huang return OTP_FAILURE; 1590cd1610b4SJohnny Huang } 1591a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1592cd1610b4SJohnny Huang break; 1593a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1594*541eb887SJohnny Huang otp_strap_status(otpstrap); 1595cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1596cd1610b4SJohnny Huang if (bit_offset < 32) { 1597cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1598cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1599cd1610b4SJohnny Huang strap_buf[3] = ~0; 1600cd1610b4SJohnny Huang strap_buf[5] = 0; 16012a856b9aSJohnny Huang // if (protect) 16022a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 16032a856b9aSJohnny Huang // else 16042a856b9aSJohnny Huang // strap_buf[4] = 0; 1605cd1610b4SJohnny Huang } else { 1606cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1607cd1610b4SJohnny Huang strap_buf[2] = ~0; 1608cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1609cd1610b4SJohnny Huang strap_buf[4] = 0; 16102a856b9aSJohnny Huang // if (protect) 16112a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 16122a856b9aSJohnny Huang // else 16132a856b9aSJohnny Huang // strap_buf[5] = 0; 1614cd1610b4SJohnny Huang } 161576d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1616a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 16172a856b9aSJohnny Huang return OTP_FAILURE; 1618a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1619a6af4a17SJohnny Huang return OTP_SUCCESS; 1620a6af4a17SJohnny Huang 1621cd1610b4SJohnny Huang break; 1622cd1610b4SJohnny Huang } 1623cd1610b4SJohnny Huang 1624cd1610b4SJohnny Huang if (!nconfirm) { 1625cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1626cd1610b4SJohnny Huang if (!confirm_yesno()) { 1627cd1610b4SJohnny Huang printf(" Aborting\n"); 16282a856b9aSJohnny Huang return OTP_FAILURE; 1629cd1610b4SJohnny Huang } 1630cd1610b4SJohnny Huang } 1631cd1610b4SJohnny Huang 1632cd1610b4SJohnny Huang switch (mode) { 1633a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1634cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1635a6d0d645SJohnny Huang case OTP_REGION_CONF: 1636a6d0d645SJohnny Huang case OTP_REGION_DATA: 1637cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1638cd1610b4SJohnny Huang pass = -1; 1639cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1640a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1641cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1642cd1610b4SJohnny Huang } else { 1643cd1610b4SJohnny Huang pass = 0; 1644cd1610b4SJohnny Huang break; 1645cd1610b4SJohnny Huang } 1646cd1610b4SJohnny Huang } 16472a856b9aSJohnny Huang if (pass == 0) 16482a856b9aSJohnny Huang return OTP_SUCCESS; 1649cd1610b4SJohnny Huang } 1650cd1610b4SJohnny Huang 16512a856b9aSJohnny Huang return OTP_USAGE; 1652cd1610b4SJohnny Huang } 1653cd1610b4SJohnny Huang 16542a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 165569d5fd8fSJohnny Huang { 16562a856b9aSJohnny Huang uint32_t offset, count; 16572a856b9aSJohnny Huang int ret; 165869d5fd8fSJohnny Huang 16592a856b9aSJohnny Huang if (argc == 4) { 16602a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 16612a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 16622a856b9aSJohnny Huang } else if (argc == 3) { 16632a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 16642a856b9aSJohnny Huang count = 1; 16652a856b9aSJohnny Huang } else { 166669d5fd8fSJohnny Huang return CMD_RET_USAGE; 166769d5fd8fSJohnny Huang } 166869d5fd8fSJohnny Huang 166969d5fd8fSJohnny Huang 16702a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 167169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16722a856b9aSJohnny Huang ret = otp_print_config(offset, count); 16732a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 16742a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16752a856b9aSJohnny Huang ret = otp_print_data(offset, count); 16762a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 16772a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16782a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 16792a856b9aSJohnny Huang } else { 16802a856b9aSJohnny Huang return CMD_RET_USAGE; 168169d5fd8fSJohnny Huang } 168269d5fd8fSJohnny Huang 16832a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 16842a856b9aSJohnny Huang return CMD_RET_SUCCESS; 16852a856b9aSJohnny Huang else 16862a856b9aSJohnny Huang return CMD_RET_USAGE; 16872a856b9aSJohnny Huang 16882a856b9aSJohnny Huang } 16892a856b9aSJohnny Huang 16902a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 16912a856b9aSJohnny Huang { 16922a856b9aSJohnny Huang phys_addr_t addr; 16932a856b9aSJohnny Huang uint32_t byte_size; 16942a856b9aSJohnny Huang int ret; 16952a856b9aSJohnny Huang 16962a856b9aSJohnny Huang if (argc == 4) { 16972a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 16982a856b9aSJohnny Huang return CMD_RET_USAGE; 16992a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 17002a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 170169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17022a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 17032a856b9aSJohnny Huang } else if (argc == 3) { 17042a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 17052a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 17062a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17072a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 17082a856b9aSJohnny Huang } else { 17092a856b9aSJohnny Huang return CMD_RET_USAGE; 17102a856b9aSJohnny Huang } 17112a856b9aSJohnny Huang 17122a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 17132a856b9aSJohnny Huang return CMD_RET_SUCCESS; 17142a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 17152a856b9aSJohnny Huang return CMD_RET_FAILURE; 17162a856b9aSJohnny Huang else 17172a856b9aSJohnny Huang return CMD_RET_USAGE; 17182a856b9aSJohnny Huang } 17192a856b9aSJohnny Huang 17202a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 17212a856b9aSJohnny Huang { 17222a856b9aSJohnny Huang int mode = 0; 17232a856b9aSJohnny Huang int nconfirm = 0; 17242a856b9aSJohnny Huang int otp_addr = 0; 17252a856b9aSJohnny Huang int bit_offset; 17262a856b9aSJohnny Huang int value; 17272a856b9aSJohnny Huang int ret; 17282a856b9aSJohnny Huang 17292a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 17302a856b9aSJohnny Huang return CMD_RET_USAGE; 17312a856b9aSJohnny Huang 17322a856b9aSJohnny Huang /* Drop the pb cmd */ 17332a856b9aSJohnny Huang argc--; 17342a856b9aSJohnny Huang argv++; 17352a856b9aSJohnny Huang 17362a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1737a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 17382a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1739a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 17402a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1741a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1742cd1610b4SJohnny Huang else 17432a856b9aSJohnny Huang return CMD_RET_USAGE; 17442a856b9aSJohnny Huang 17452a856b9aSJohnny Huang /* Drop the region cmd */ 17462a856b9aSJohnny Huang argc--; 17472a856b9aSJohnny Huang argv++; 17482a856b9aSJohnny Huang 17492a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1750cd1610b4SJohnny Huang nconfirm = 1; 17512a856b9aSJohnny Huang /* Drop the force option */ 17522a856b9aSJohnny Huang argc--; 17532a856b9aSJohnny Huang argv++; 17542a856b9aSJohnny Huang } 1755cd1610b4SJohnny Huang 1756a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 17572a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 17582a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1759cd1610b4SJohnny Huang if (bit_offset >= 64) 17602a856b9aSJohnny Huang return CMD_RET_USAGE; 1761cd1610b4SJohnny Huang } else { 17622a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 17632a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 17642a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1765cd1610b4SJohnny Huang if (bit_offset >= 32) 17662a856b9aSJohnny Huang return CMD_RET_USAGE; 1767cd1610b4SJohnny Huang } 1768cd1610b4SJohnny Huang if (value != 0 && value != 1) 17692a856b9aSJohnny Huang return CMD_RET_USAGE; 1770cd1610b4SJohnny Huang 1771cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17722a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 17732a856b9aSJohnny Huang 17742a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 17752a856b9aSJohnny Huang return CMD_RET_SUCCESS; 17762a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 17772a856b9aSJohnny Huang return CMD_RET_FAILURE; 17782a856b9aSJohnny Huang else 17792a856b9aSJohnny Huang return CMD_RET_USAGE; 17802a856b9aSJohnny Huang } 17812a856b9aSJohnny Huang 17822a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 17832a856b9aSJohnny Huang { 17842a856b9aSJohnny Huang phys_addr_t addr; 17852a856b9aSJohnny Huang int otp_addr = 0; 17862a856b9aSJohnny Huang 17872a856b9aSJohnny Huang if (argc != 3) 17882a856b9aSJohnny Huang return CMD_RET_USAGE; 17892a856b9aSJohnny Huang 179069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17912a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 17922a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 17932a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 179469d5fd8fSJohnny Huang printf("Compare pass\n"); 17952a856b9aSJohnny Huang return CMD_RET_SUCCESS; 179669d5fd8fSJohnny Huang } else { 179769d5fd8fSJohnny Huang printf("Compare fail\n"); 17982a856b9aSJohnny Huang return CMD_RET_FAILURE; 179969d5fd8fSJohnny Huang } 180069d5fd8fSJohnny Huang } 180169d5fd8fSJohnny Huang 180266f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 180366f2f8e5SJohnny Huang { 1804a8bd6d8cSJohnny Huang int view = 0; 18052d4b0742SJohnny Huang int input; 1806a8bd6d8cSJohnny Huang 1807a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 180866f2f8e5SJohnny Huang return CMD_RET_USAGE; 180966f2f8e5SJohnny Huang 18102d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 181166f2f8e5SJohnny Huang 18122d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18132d4b0742SJohnny Huang if (argc == 3) { 18142d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 18152d4b0742SJohnny Huang otp_print_conf_info(input); 18162d4b0742SJohnny Huang } else { 18172d4b0742SJohnny Huang otp_print_conf_info(-1); 18182d4b0742SJohnny Huang } 18192d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 18202d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 1821a8bd6d8cSJohnny Huang view = 1; 1822a8bd6d8cSJohnny Huang /* Drop the view option */ 1823a8bd6d8cSJohnny Huang argc--; 1824a8bd6d8cSJohnny Huang argv++; 1825a8bd6d8cSJohnny Huang } 182666f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1827b458cd62SJohnny Huang otp_print_strap_info(view); 182866f2f8e5SJohnny Huang } else { 182966f2f8e5SJohnny Huang return CMD_RET_USAGE; 183066f2f8e5SJohnny Huang } 18312d4b0742SJohnny Huang 183266f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 183366f2f8e5SJohnny Huang } 183466f2f8e5SJohnny Huang 1835737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 1836737ed20bSJohnny Huang { 1837737ed20bSJohnny Huang int input; 1838737ed20bSJohnny Huang int bit_offset; 1839737ed20bSJohnny Huang int prog_address; 1840737ed20bSJohnny Huang int pass; 1841737ed20bSJohnny Huang int i; 1842737ed20bSJohnny Huang if (argc != 3 && argc != 2) 1843737ed20bSJohnny Huang return CMD_RET_USAGE; 1844737ed20bSJohnny Huang 1845737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 1846737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1847737ed20bSJohnny Huang } else { 1848737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 1849737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 1850737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1851737ed20bSJohnny Huang if (!confirm_yesno()) { 1852737ed20bSJohnny Huang printf(" Aborting\n"); 1853737ed20bSJohnny Huang return CMD_RET_FAILURE; 1854737ed20bSJohnny Huang } 1855737ed20bSJohnny Huang } 1856737ed20bSJohnny Huang 1857737ed20bSJohnny Huang prog_address = 0x800; 1858737ed20bSJohnny Huang if (input < 32) { 1859737ed20bSJohnny Huang bit_offset = input; 1860737ed20bSJohnny Huang prog_address |= 0x60c; 1861737ed20bSJohnny Huang } else if (input < 64) { 1862737ed20bSJohnny Huang bit_offset = input - 32; 1863737ed20bSJohnny Huang prog_address |= 0x60e; 1864737ed20bSJohnny Huang } else { 1865737ed20bSJohnny Huang return CMD_RET_USAGE; 1866737ed20bSJohnny Huang } 1867737ed20bSJohnny Huang 1868737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 1869737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 1870737ed20bSJohnny Huang } 1871737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 1872737ed20bSJohnny Huang pass = -1; 1873737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 1874737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 1875737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 1876737ed20bSJohnny Huang } else { 1877737ed20bSJohnny Huang pass = 0; 1878737ed20bSJohnny Huang break; 1879737ed20bSJohnny Huang } 1880737ed20bSJohnny Huang } 1881737ed20bSJohnny Huang if (pass == 0) { 1882737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 1883737ed20bSJohnny Huang return CMD_RET_SUCCESS; 1884737ed20bSJohnny Huang } 1885737ed20bSJohnny Huang 1886737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 1887737ed20bSJohnny Huang return CMD_RET_FAILURE; 1888737ed20bSJohnny Huang 1889737ed20bSJohnny Huang } 18909a4fe690SJohnny Huang 18912a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 18922a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 1893a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 18942a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 18952a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 1896737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 18972a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 18982a856b9aSJohnny Huang }; 18992a856b9aSJohnny Huang 19002a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19012a856b9aSJohnny Huang { 19022a856b9aSJohnny Huang cmd_tbl_t *cp; 19032a856b9aSJohnny Huang 19042a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 19052a856b9aSJohnny Huang 1906737ed20bSJohnny Huang /* Drop the otp command */ 19072a856b9aSJohnny Huang argc--; 19082a856b9aSJohnny Huang argv++; 19092a856b9aSJohnny Huang 19102a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 19112a856b9aSJohnny Huang return CMD_RET_USAGE; 19122a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 19132a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19142a856b9aSJohnny Huang 19159a4fe690SJohnny Huang if (chip_version() == 0) { 19169a4fe690SJohnny Huang info_cb.version = 0; 19179a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 19189a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 19199a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 19209a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 19219a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 19229a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 19239a4fe690SJohnny Huang } else if (chip_version() == 1) { 19249a4fe690SJohnny Huang info_cb.version = 1; 19259a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 19269a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 19279a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 19289a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 19299a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 19309a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 19319a4fe690SJohnny Huang } 19329a4fe690SJohnny Huang 19332a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 193469d5fd8fSJohnny Huang } 193569d5fd8fSJohnny Huang 193669d5fd8fSJohnny Huang U_BOOT_CMD( 193769d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 193869d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 19392a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 19402a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 19412d4b0742SJohnny Huang "otp info strap [v]\n" 19422d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 1943d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 1944cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 1945737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 1946737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 19472a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 194869d5fd8fSJohnny Huang ); 1949