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