169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 429a4fe690SJohnny Huang 439a4fe690SJohnny Huang 44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 45b458cd62SJohnny Huang #define OTP_REG_VALUE -2 46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4776d13988SJohnny Huang 484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 494c1c9b35SJohnny Huang #define PBWIDTH 60 504c1c9b35SJohnny Huang 5166f2f8e5SJohnny Huang struct otpstrap_status { 5269d5fd8fSJohnny Huang int value; 5369d5fd8fSJohnny Huang int option_array[7]; 5469d5fd8fSJohnny Huang int remain_times; 5569d5fd8fSJohnny Huang int writeable_option; 5669d5fd8fSJohnny Huang int protected; 5769d5fd8fSJohnny Huang }; 5869d5fd8fSJohnny Huang 5966f2f8e5SJohnny Huang struct otpconf_parse { 6066f2f8e5SJohnny Huang int dw_offset; 6166f2f8e5SJohnny Huang int bit; 6266f2f8e5SJohnny Huang int length; 6366f2f8e5SJohnny Huang int value; 6466f2f8e5SJohnny Huang int keep; 6566f2f8e5SJohnny Huang char status[80]; 6666f2f8e5SJohnny Huang }; 6766f2f8e5SJohnny Huang 68a8bd6d8cSJohnny Huang struct otpstrap_info { 69a8bd6d8cSJohnny Huang uint32_t bit_offset; 70a8bd6d8cSJohnny Huang uint32_t length; 7176d13988SJohnny Huang int value; 72a8bd6d8cSJohnny Huang char information[80]; 73a8bd6d8cSJohnny Huang }; 74a8bd6d8cSJohnny Huang 75a8bd6d8cSJohnny Huang struct otpconf_info { 76a8bd6d8cSJohnny Huang uint32_t dw_offset; 77a8bd6d8cSJohnny Huang uint32_t bit_offset; 78a8bd6d8cSJohnny Huang uint32_t length; 79a8bd6d8cSJohnny Huang int value; 80a8bd6d8cSJohnny Huang char information[80]; 81a8bd6d8cSJohnny Huang }; 82a8bd6d8cSJohnny Huang 839a4fe690SJohnny Huang struct otpkey_type { 849a4fe690SJohnny Huang int value; 859a4fe690SJohnny Huang int key_type; 869a4fe690SJohnny Huang int need_id; 879a4fe690SJohnny Huang char information[110]; 889a4fe690SJohnny Huang }; 899a4fe690SJohnny Huang 909a4fe690SJohnny Huang struct otp_info_cb { 919a4fe690SJohnny Huang int version; 929a4fe690SJohnny Huang struct otpstrap_info *strap_info; 939a4fe690SJohnny Huang int strap_info_len; 949a4fe690SJohnny Huang struct otpconf_info *conf_info; 959a4fe690SJohnny Huang int conf_info_len; 969a4fe690SJohnny Huang struct otpkey_type *key_info; 979a4fe690SJohnny Huang int key_info_len; 989a4fe690SJohnny Huang }; 999a4fe690SJohnny Huang 100a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 101a8bd6d8cSJohnny Huang { 102a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 103a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 104a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 105a8bd6d8cSJohnny Huang char buffer[256]; 106a8bd6d8cSJohnny Huang va_list aptr; 107a8bd6d8cSJohnny Huang 108a8bd6d8cSJohnny Huang va_start(aptr, format); 109a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 110a8bd6d8cSJohnny Huang va_end(aptr); 111a8bd6d8cSJohnny Huang 112a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 113a8bd6d8cSJohnny Huang if (numerator == denominator) 114a8bd6d8cSJohnny Huang printf("\n"); 115a8bd6d8cSJohnny Huang } 116a8bd6d8cSJohnny Huang 1179a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1189a4fe690SJohnny Huang 119a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 12091448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 12191448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 12291448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 12391448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 12491448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 12591448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 12691448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 12791448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 128541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 12991448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 13091448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 13191448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 13291448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 13391448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 13491448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 13591448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 13691448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 13791448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 13891448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 13991448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 14091448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 14191448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 14291448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 14391448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 14491448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 14591448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 14691448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 14791448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 14891448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 14991448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 15091448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 15191448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 15291448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 15391448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 15491448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 15591448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 15691448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 15791448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 15891448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 15991448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 16091448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 16191448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 16291448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 16391448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 16491448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 16591448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 16691448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 16791448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 16891448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 16991448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 17091448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 17191448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 17291448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 17391448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 17491448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 17591448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 17691448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 17791448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 17891448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 17991448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 18091448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 18191448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 18291448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 18391448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 18491448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 18591448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 18691448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 18791448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 18891448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 18991448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 19091448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 19191448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 19291448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 19391448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 19491448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 19591448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 19691448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 19791448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 19891448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 19991448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 20091448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 20191448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 20291448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 20391448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 20491448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 20591448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 20691448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 20791448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 20891448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 20991448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 21091448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 21191448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 21291448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 21391448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 21491448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 21591448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 21691448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 21791448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 21891448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 21991448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 22091448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 22191448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 22291448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 22391448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 22491448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 22591448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 22691448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 22791448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 22891448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 22976d13988SJohnny Huang }; 2309a4fe690SJohnny Huang 2313cb28812SJohnny Huang struct otpstrap_info a1_strap_info[] = { 2323cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2333cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2343cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2353cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2363cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2373cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2383cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2393cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2403cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2413cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2423cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2433cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2443cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2453cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2463cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2473cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2483cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2493cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2503cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2513cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2523cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2533cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2543cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2553cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2563cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2573cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2583cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2593cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2603cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2613cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2623cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2633cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2643cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2653cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2663cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2673cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2683cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2693cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2703cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 2713cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 2723cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 2733cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 2743cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 2753cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 2763cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 2773cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 2783cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 2793cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 2803cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 2813cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 2823cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 2833cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 2843cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 2853cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 2863cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 2873cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 2883cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 2893cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 2903cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 2913cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 2923cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 2933cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 2943cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 2953cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 2963cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 2973cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 2983cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 2993cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 3003cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 3013cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 3023cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 3033cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 3043cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 3053cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3063cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3073cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3083cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3093cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3103cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3113cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3123cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3133cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3143cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3153cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3163cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3173cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3183cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3193cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3203cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3213cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3223cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3233cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3243cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3253cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3263cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3273cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3283cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3293cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3303cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3313cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3323cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3333cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3343cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3353cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3363cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3373cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3383cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3393cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3403cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3413cb28812SJohnny Huang }; 3423cb28812SJohnny Huang 343b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 34491448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 34591448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 34691448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 34791448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 34891448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 34991448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 35091448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 35191448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 35291448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 35391448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 35491448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 35591448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 35691448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 35791448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 35891448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 35991448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 36091448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 361541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 36291448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 36391448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 36491448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 36591448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 36691448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 36791448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 36891448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 36991448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 37091448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 37191448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 37291448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 37391448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 37491448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 37591448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 37691448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 37791448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 37891448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 37991448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 38091448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 38191448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 38291448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 38391448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 38491448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 38591448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 38691448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 38791448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 3883cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 3893cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 3903cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 3913cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 3923cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 3933cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 3943cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 3953cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 3963cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 3973cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 3983cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 3993cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 4003cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 4013cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 4023cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 4033cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 4043cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 4053cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4063cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4073cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4083cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4093cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4103cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4113cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4123cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4133cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4143cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4153cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4163cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4173cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4183cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4193cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4203cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4213cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4223cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4233cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4243cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4253cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4263cb28812SJohnny Huang }; 4273cb28812SJohnny Huang 4283cb28812SJohnny Huang struct otpconf_info a1_conf_info[] = { 4293cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4303cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4313cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4323cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4333cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4343cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4353cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4363cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4373cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4383cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4393cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4403cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4413cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4423cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4433cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4443cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4453cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4463cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4473cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4483cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4493cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4503cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4513cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4523cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4533cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4543cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 4553cb28812SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 4563cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4573cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4583cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4593cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4603cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4613cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4623cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4633cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4643cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4653cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4663cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4673cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4683cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4693cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4703cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4713cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4723cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4733cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4743cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4753cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 47691448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 47791448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 47891448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 47973f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 48073f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 48191448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 48291448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 48391448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 48491448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 48591448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 48691448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 48791448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 48891448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 48991448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 49091448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 49191448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 49291448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 49391448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 49491448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 49591448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 49691448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 49791448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 49891448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 49991448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 50091448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 50191448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 50291448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 50391448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 50491448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 50591448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 50691448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 50791448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 50891448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 50991448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 510b458cd62SJohnny Huang }; 5119a4fe690SJohnny Huang 5129a4fe690SJohnny Huang struct otpkey_type a0_key_type[] = { 5139a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5149a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5159a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5169a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5179a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5189a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5199a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5209a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5219a4fe690SJohnny Huang }; 5229a4fe690SJohnny Huang 5239a4fe690SJohnny Huang struct otpkey_type a1_key_type[] = { 5249a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5259a4fe690SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 5269a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5279a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5289a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5299a4fe690SJohnny Huang }; 5309a4fe690SJohnny Huang 5319a4fe690SJohnny Huang static uint32_t chip_version(void) 5329a4fe690SJohnny Huang { 5339a4fe690SJohnny Huang uint32_t rev_id; 5349a4fe690SJohnny Huang 5359a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5369a4fe690SJohnny Huang 5379a4fe690SJohnny Huang return rev_id; 5389a4fe690SJohnny Huang } 5399a4fe690SJohnny Huang 5402a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 54169d5fd8fSJohnny Huang { 54269d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 54369d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 54469d5fd8fSJohnny Huang udelay(2); 54569d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 54669d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 54769d5fd8fSJohnny Huang } 54869d5fd8fSJohnny Huang 5492a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 55069d5fd8fSJohnny Huang { 55169d5fd8fSJohnny Huang int config_offset; 55269d5fd8fSJohnny Huang 55369d5fd8fSJohnny Huang config_offset = 0x800; 55469d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 55569d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 55669d5fd8fSJohnny Huang 55769d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 55869d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 55969d5fd8fSJohnny Huang udelay(2); 56069d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 56169d5fd8fSJohnny Huang } 56269d5fd8fSJohnny Huang 56369d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 56469d5fd8fSJohnny Huang { 56569d5fd8fSJohnny Huang int i; 56669d5fd8fSJohnny Huang uint32_t ret[1]; 56769d5fd8fSJohnny Huang 56869d5fd8fSJohnny Huang if (offset + dw_count > 32) 5692a856b9aSJohnny Huang return OTP_USAGE; 57069d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 57169d5fd8fSJohnny Huang otp_read_config(i, ret); 572a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 57369d5fd8fSJohnny Huang } 57469d5fd8fSJohnny Huang printf("\n"); 5752a856b9aSJohnny Huang return OTP_SUCCESS; 57669d5fd8fSJohnny Huang } 57769d5fd8fSJohnny Huang 57869d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 57969d5fd8fSJohnny Huang { 58069d5fd8fSJohnny Huang int i; 58169d5fd8fSJohnny Huang uint32_t ret[2]; 58269d5fd8fSJohnny Huang 58369d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5842a856b9aSJohnny Huang return OTP_USAGE; 58569d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 58669d5fd8fSJohnny Huang otp_read_data(i, ret); 58769d5fd8fSJohnny Huang if (i % 4 == 0) 58869d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 58969d5fd8fSJohnny Huang else 59069d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 59169d5fd8fSJohnny Huang 59269d5fd8fSJohnny Huang } 59369d5fd8fSJohnny Huang printf("\n"); 5942a856b9aSJohnny Huang return OTP_SUCCESS; 59569d5fd8fSJohnny Huang } 59669d5fd8fSJohnny Huang 59769d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 59869d5fd8fSJohnny Huang { 59969d5fd8fSJohnny Huang uint32_t ret; 60069d5fd8fSJohnny Huang uint32_t *buf; 60169d5fd8fSJohnny Huang 60269d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 60369d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 60469d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 60569d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 60669d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 60769d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 60869d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 60969d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 61069d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 61169d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 61269d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 61369d5fd8fSJohnny Huang udelay(10); 61469d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 61569d5fd8fSJohnny Huang if (ret & 0x1) 61669d5fd8fSJohnny Huang return 0; 61769d5fd8fSJohnny Huang else 61869d5fd8fSJohnny Huang return -1; 61969d5fd8fSJohnny Huang } 62069d5fd8fSJohnny Huang 62169d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 62269d5fd8fSJohnny Huang { 62369d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 62469d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 62569d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 62669d5fd8fSJohnny Huang udelay(100); 62769d5fd8fSJohnny Huang } 62869d5fd8fSJohnny Huang 62969d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 63069d5fd8fSJohnny Huang { 63169d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 63269d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 63369d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 63469d5fd8fSJohnny Huang udelay(85); 63569d5fd8fSJohnny Huang } 63669d5fd8fSJohnny Huang 637a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 63869d5fd8fSJohnny Huang { 63930a8c590SJohnny Huang uint32_t ret[2]; 64069d5fd8fSJohnny Huang 64130a8c590SJohnny Huang if (otp_addr % 2 == 0) 64269d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 64330a8c590SJohnny Huang else 64430a8c590SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 64530a8c590SJohnny Huang 64669d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 64769d5fd8fSJohnny Huang udelay(2); 64830a8c590SJohnny Huang ret[0] = readl(0x1e6f2020); 64930a8c590SJohnny Huang ret[1] = readl(0x1e6f2024); 650a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 65130a8c590SJohnny Huang if (otp_addr % 2 == 0) { 65230a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 65369d5fd8fSJohnny Huang return 0; 65469d5fd8fSJohnny Huang else 65569d5fd8fSJohnny Huang return -1; 65630a8c590SJohnny Huang } else { 65730a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 65830a8c590SJohnny Huang return 0; 65930a8c590SJohnny Huang else 66030a8c590SJohnny Huang return -1; 66130a8c590SJohnny Huang } 66230a8c590SJohnny Huang 66369d5fd8fSJohnny Huang } 66469d5fd8fSJohnny Huang 665d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6664c1c9b35SJohnny Huang { 6674c1c9b35SJohnny Huang uint32_t ret[2]; 6684c1c9b35SJohnny Huang 6694c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6704c1c9b35SJohnny Huang 6714c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6724c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 6734c1c9b35SJohnny Huang else 6744c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 6754c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 6764c1c9b35SJohnny Huang udelay(2); 6774c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 6784c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 6794c1c9b35SJohnny Huang if (size == 1) { 6804c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6814c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 682d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6834c1c9b35SJohnny Huang compare[0] = 0; 6844c1c9b35SJohnny Huang return 0; 6854c1c9b35SJohnny Huang } else { 6864c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6874c1c9b35SJohnny Huang return -1; 6884c1c9b35SJohnny Huang } 6894c1c9b35SJohnny Huang 6904c1c9b35SJohnny Huang } else { 6914c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 692d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 6934c1c9b35SJohnny Huang compare[0] = ~0; 6944c1c9b35SJohnny Huang return 0; 6954c1c9b35SJohnny Huang } else { 696d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 6974c1c9b35SJohnny Huang return -1; 6984c1c9b35SJohnny Huang } 6994c1c9b35SJohnny Huang } 7004c1c9b35SJohnny Huang } else if (size == 2) { 7014c1c9b35SJohnny Huang // otp_addr should be even 702d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7034c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7044c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7054c1c9b35SJohnny Huang compare[0] = 0; 7064c1c9b35SJohnny Huang compare[1] = ~0; 7074c1c9b35SJohnny Huang return 0; 7084c1c9b35SJohnny Huang } else { 7094c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7104c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7114c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7124c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7134c1c9b35SJohnny Huang return -1; 7144c1c9b35SJohnny Huang } 7154c1c9b35SJohnny Huang } else { 7164c1c9b35SJohnny Huang return -1; 7174c1c9b35SJohnny Huang } 7184c1c9b35SJohnny Huang } 7194c1c9b35SJohnny Huang 7207e22f42dSJohnny Huang static void otp_soak(int soak) 721d90825e2SJohnny Huang { 722d90825e2SJohnny Huang if (soak) { 723d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 724d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 725d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 726d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 727d90825e2SJohnny Huang } else { 728d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 729d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 730d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 731d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 732d90825e2SJohnny Huang } 733d90825e2SJohnny Huang } 734d90825e2SJohnny Huang 735d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 736d90825e2SJohnny Huang { 737d90825e2SJohnny Huang int j, bit_value, prog_bit; 738d90825e2SJohnny Huang 739d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 740d90825e2SJohnny Huang if ((keep >> j) & 0x1) 741d90825e2SJohnny Huang continue; 742d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 743d90825e2SJohnny Huang if (prog_address % 2 == 0) { 744d90825e2SJohnny Huang if (bit_value) 745d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 746d90825e2SJohnny Huang else 747d90825e2SJohnny Huang continue; 748d90825e2SJohnny Huang } else { 749d90825e2SJohnny Huang prog_address |= 1 << 15; 750d90825e2SJohnny Huang if (bit_value) 751d90825e2SJohnny Huang continue; 752d90825e2SJohnny Huang else 753d90825e2SJohnny Huang prog_bit = 0x1 << j; 754d90825e2SJohnny Huang } 755d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 756d90825e2SJohnny Huang } 757d90825e2SJohnny Huang } 758d90825e2SJohnny Huang 75976d13988SJohnny Huang 760541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 76176d13988SJohnny Huang { 76276d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 76376d13988SJohnny Huang int i, j; 76476d13988SJohnny Huang 76576d13988SJohnny Huang for (j = 0; j < 64; j++) { 76676d13988SJohnny Huang otpstrap[j].value = 0; 76776d13988SJohnny Huang otpstrap[j].remain_times = 7; 76876d13988SJohnny Huang otpstrap[j].writeable_option = -1; 76976d13988SJohnny Huang otpstrap[j].protected = 0; 77076d13988SJohnny Huang } 77176d13988SJohnny Huang 77276d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 77376d13988SJohnny Huang int option = (i - 16) / 2; 77476d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 77576d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 77676d13988SJohnny Huang for (j = 0; j < 32; j++) { 77776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 77876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 77976d13988SJohnny Huang otpstrap[j].writeable_option = option; 78076d13988SJohnny Huang } 78176d13988SJohnny Huang if (bit_value == 1) 78276d13988SJohnny Huang otpstrap[j].remain_times --; 78376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 78476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 78576d13988SJohnny Huang } 78676d13988SJohnny Huang for (j = 32; j < 64; j++) { 78776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 78876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 78976d13988SJohnny Huang otpstrap[j].writeable_option = option; 79076d13988SJohnny Huang } 79176d13988SJohnny Huang if (bit_value == 1) 79276d13988SJohnny Huang otpstrap[j].remain_times --; 79376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 79476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 79576d13988SJohnny Huang } 79676d13988SJohnny Huang } 79776d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 79876d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 79976d13988SJohnny Huang for (j = 0; j < 32; j++) { 80076d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 80176d13988SJohnny Huang otpstrap[j].protected = 1; 80276d13988SJohnny Huang } 80376d13988SJohnny Huang for (j = 32; j < 64; j++) { 80476d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 80576d13988SJohnny Huang otpstrap[j].protected = 1; 80676d13988SJohnny Huang } 80776d13988SJohnny Huang } 80876d13988SJohnny Huang 809b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 81069d5fd8fSJohnny Huang { 8113cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 812442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 813b458cd62SJohnny Huang uint32_t mask; 814b458cd62SJohnny Huang uint32_t dw_offset; 815b458cd62SJohnny Huang uint32_t bit_offset; 816b458cd62SJohnny Huang uint32_t otp_value; 817b458cd62SJohnny Huang uint32_t otp_keep; 818b458cd62SJohnny Huang int fail = 0; 81973f11549SJohnny Huang char valid_bit[20]; 82066f2f8e5SJohnny Huang int i; 82173f11549SJohnny Huang int j; 82266f2f8e5SJohnny Huang 823737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 82466f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8253cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8263cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8273cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8283cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 829b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 830b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 831b458cd62SJohnny Huang 832b458cd62SJohnny Huang if (otp_keep == mask) { 833b458cd62SJohnny Huang continue; 834b458cd62SJohnny Huang } else if (otp_keep != 0) { 835b458cd62SJohnny Huang fail = 1; 836b458cd62SJohnny Huang } 837b458cd62SJohnny Huang 8383cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 8393cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 8403cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 8413cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 842b458cd62SJohnny Huang continue; 843b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 844b458cd62SJohnny Huang 8453cb28812SJohnny Huang if (conf_info[i].length == 1) { 8463cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 84766f2f8e5SJohnny Huang } else { 848b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 8493cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 8503cb28812SJohnny Huang conf_info[i].bit_offset); 85166f2f8e5SJohnny Huang } 852b458cd62SJohnny Huang printf("0x%-10x", otp_value); 853b458cd62SJohnny Huang 854b458cd62SJohnny Huang if (fail) { 855b458cd62SJohnny Huang printf("Keep mask error\n"); 856b458cd62SJohnny Huang } else { 8573cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 858b458cd62SJohnny Huang printf("Reserved\n"); 8593cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 8603cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 861b458cd62SJohnny Huang printf("\n"); 8623cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 863b458cd62SJohnny Huang if (otp_value != 0) { 86473f11549SJohnny Huang for (j = 0; j < 7; j++) { 86573f11549SJohnny Huang if (otp_value == (1 << j)) { 86673f11549SJohnny Huang valid_bit[j * 2] = '1'; 867b458cd62SJohnny Huang } else { 86873f11549SJohnny Huang valid_bit[j * 2] = '0'; 86973f11549SJohnny Huang } 87073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 87173f11549SJohnny Huang } 87273f11549SJohnny Huang valid_bit[15] = 0; 87373f11549SJohnny Huang } else { 87473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 875b458cd62SJohnny Huang } 8763cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 877b458cd62SJohnny Huang printf("\n"); 878b458cd62SJohnny Huang } else { 8793cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 880b458cd62SJohnny Huang } 881b458cd62SJohnny Huang } 882b458cd62SJohnny Huang } 883b458cd62SJohnny Huang 884b458cd62SJohnny Huang if (fail) 885b458cd62SJohnny Huang return OTP_FAILURE; 886b458cd62SJohnny Huang 88766f2f8e5SJohnny Huang return OTP_SUCCESS; 88866f2f8e5SJohnny Huang } 88966f2f8e5SJohnny Huang 8902d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 89166f2f8e5SJohnny Huang { 8923cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 893b458cd62SJohnny Huang uint32_t OTPCFG[12]; 894b458cd62SJohnny Huang uint32_t mask; 895b458cd62SJohnny Huang uint32_t dw_offset; 896b458cd62SJohnny Huang uint32_t bit_offset; 897b458cd62SJohnny Huang uint32_t otp_value; 89873f11549SJohnny Huang char valid_bit[20]; 89966f2f8e5SJohnny Huang int i; 90073f11549SJohnny Huang int j; 90166f2f8e5SJohnny Huang 90266f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 90366f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 90466f2f8e5SJohnny Huang 90566f2f8e5SJohnny Huang 906b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 907b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9083cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9093cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9102d4b0742SJohnny Huang continue; 9113cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9123cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9133cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 914b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 915b458cd62SJohnny Huang 9163cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9173cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9183cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9193cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 920b458cd62SJohnny Huang continue; 921b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 922b458cd62SJohnny Huang 9233cb28812SJohnny Huang if (conf_info[i].length == 1) { 9243cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 925b458cd62SJohnny Huang } else { 926b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9273cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9283cb28812SJohnny Huang conf_info[i].bit_offset); 929b458cd62SJohnny Huang } 930b458cd62SJohnny Huang printf("0x%-10x", otp_value); 931b458cd62SJohnny Huang 9323cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 933b458cd62SJohnny Huang printf("Reserved\n"); 9343cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9353cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 936b458cd62SJohnny Huang printf("\n"); 9373cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 938b458cd62SJohnny Huang if (otp_value != 0) { 93973f11549SJohnny Huang for (j = 0; j < 7; j++) { 94073f11549SJohnny Huang if (otp_value == (1 << j)) { 94173f11549SJohnny Huang valid_bit[j * 2] = '1'; 942b458cd62SJohnny Huang } else { 94373f11549SJohnny Huang valid_bit[j * 2] = '0'; 94473f11549SJohnny Huang } 94573f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 94673f11549SJohnny Huang } 94773f11549SJohnny Huang valid_bit[15] = 0; 94873f11549SJohnny Huang } else { 94973f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 950b458cd62SJohnny Huang } 9513cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 952b458cd62SJohnny Huang printf("\n"); 953b458cd62SJohnny Huang } else { 9543cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 955b458cd62SJohnny Huang } 956b458cd62SJohnny Huang } 957b458cd62SJohnny Huang return OTP_SUCCESS; 95866f2f8e5SJohnny Huang } 95966f2f8e5SJohnny Huang 960b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 96176d13988SJohnny Huang { 9623cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 963a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 964a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 96576d13988SJohnny Huang int i; 966a8bd6d8cSJohnny Huang int fail = 0; 967a8bd6d8cSJohnny Huang uint32_t bit_offset; 968a8bd6d8cSJohnny Huang uint32_t dw_offset; 969a8bd6d8cSJohnny Huang uint32_t mask; 970a8bd6d8cSJohnny Huang uint32_t otp_value; 971a8bd6d8cSJohnny Huang uint32_t otp_protect; 972a8bd6d8cSJohnny Huang uint32_t otp_keep; 97376d13988SJohnny Huang 974a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 975a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 976b458cd62SJohnny Huang 9773cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 9783cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 979a8bd6d8cSJohnny Huang dw_offset = 1; 9803cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 981a8bd6d8cSJohnny Huang } else { 982a8bd6d8cSJohnny Huang dw_offset = 0; 9833cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 984a8bd6d8cSJohnny Huang } 98576d13988SJohnny Huang 9863cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 987a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 988a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 989a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 990a8bd6d8cSJohnny Huang 991a8bd6d8cSJohnny Huang if (otp_keep == mask) { 992a8bd6d8cSJohnny Huang continue; 993a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 994a8bd6d8cSJohnny Huang fail = 1; 995a8bd6d8cSJohnny Huang } 996a8bd6d8cSJohnny Huang 9973cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 9983cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 999a8bd6d8cSJohnny Huang continue; 1000a8bd6d8cSJohnny Huang 10013cb28812SJohnny Huang if (strap_info[i].length == 1) { 10023cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1003a8bd6d8cSJohnny Huang } else { 1004b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10053cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10063cb28812SJohnny Huang strap_info[i].bit_offset); 1007a8bd6d8cSJohnny Huang } 1008a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1009a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1010a8bd6d8cSJohnny Huang 1011a8bd6d8cSJohnny Huang if (fail) { 1012a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1013a8bd6d8cSJohnny Huang } else { 10143cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10153cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1016a8bd6d8cSJohnny Huang else 1017a8bd6d8cSJohnny Huang printf("Reserved\n"); 1018a8bd6d8cSJohnny Huang } 1019a8bd6d8cSJohnny Huang } 1020a8bd6d8cSJohnny Huang 1021a8bd6d8cSJohnny Huang if (fail) 102276d13988SJohnny Huang return OTP_FAILURE; 102376d13988SJohnny Huang 102476d13988SJohnny Huang return OTP_SUCCESS; 102576d13988SJohnny Huang } 102676d13988SJohnny Huang 1027b458cd62SJohnny Huang static int otp_print_strap_info(int view) 102876d13988SJohnny Huang { 10293cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 103076d13988SJohnny Huang struct otpstrap_status strap_status[64]; 103107baa4e8SJohnny Huang int i, j; 1032b458cd62SJohnny Huang int fail = 0; 1033b458cd62SJohnny Huang uint32_t bit_offset; 1034b458cd62SJohnny Huang uint32_t length; 1035b458cd62SJohnny Huang uint32_t otp_value; 1036b458cd62SJohnny Huang uint32_t otp_protect; 103776d13988SJohnny Huang 1038541eb887SJohnny Huang otp_strap_status(strap_status); 103976d13988SJohnny Huang 1040b458cd62SJohnny Huang if (view) { 104107baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 104207baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 104307baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 104407baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1045b458cd62SJohnny Huang } else { 1046b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1047b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 104876d13988SJohnny Huang } 10493cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1050b458cd62SJohnny Huang otp_value = 0; 10513cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 10523cb28812SJohnny Huang length = strap_info[i].length; 1053b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1054c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1055c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1056b458cd62SJohnny Huang } 10573cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10583cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1059b458cd62SJohnny Huang continue; 1060b458cd62SJohnny Huang if (view) { 1061b458cd62SJohnny Huang for (j = 0; j < length; j++) { 10623cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1063b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 106407baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1065b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 10663cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1067b458cd62SJohnny Huang printf(" Reserved\n"); 1068b458cd62SJohnny Huang continue; 1069b458cd62SJohnny Huang } 1070b458cd62SJohnny Huang if (length == 1) { 10713cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1072b458cd62SJohnny Huang continue; 107376d13988SJohnny Huang } 107476d13988SJohnny Huang 1075b458cd62SJohnny Huang if (j == 0) 10763cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1077b458cd62SJohnny Huang else if (j == length - 1) 1078b458cd62SJohnny Huang printf("\\ \"\n"); 1079b458cd62SJohnny Huang else 1080b458cd62SJohnny Huang printf("| \"\n"); 108176d13988SJohnny Huang } 1082b458cd62SJohnny Huang } else { 1083c947ef08SJohnny Huang if (length == 1) { 10843cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1085b458cd62SJohnny Huang } else { 1086b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1087b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1088b458cd62SJohnny Huang } 1089b458cd62SJohnny Huang 1090b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1091b458cd62SJohnny Huang 10923cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10933cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1094b458cd62SJohnny Huang else 1095b458cd62SJohnny Huang printf("Reserved\n"); 1096b458cd62SJohnny Huang } 1097b458cd62SJohnny Huang } 1098b458cd62SJohnny Huang 1099b458cd62SJohnny Huang if (fail) 1100b458cd62SJohnny Huang return OTP_FAILURE; 1101b458cd62SJohnny Huang 1102b458cd62SJohnny Huang return OTP_SUCCESS; 1103b458cd62SJohnny Huang } 1104b458cd62SJohnny Huang 110569d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 110669d5fd8fSJohnny Huang { 110769d5fd8fSJohnny Huang int i; 110869d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 110969d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 111069d5fd8fSJohnny Huang if (i % 16 == 0) { 111169d5fd8fSJohnny Huang printf("%04X: ", i); 111269d5fd8fSJohnny Huang } 111369d5fd8fSJohnny Huang printf("%02X ", buf[i]); 111469d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 111569d5fd8fSJohnny Huang printf("\n"); 111669d5fd8fSJohnny Huang } 111769d5fd8fSJohnny Huang } 111869d5fd8fSJohnny Huang } 111969d5fd8fSJohnny Huang 11207f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 112169d5fd8fSJohnny Huang { 112269d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 11239a4fe690SJohnny Huang struct otpkey_type *key_info_array = info_cb.key_info; 11249a4fe690SJohnny Huang struct otpkey_type key_info; 112569d5fd8fSJohnny Huang char *byte_buf; 112669d5fd8fSJohnny Huang int i = 0, len = 0; 11279a4fe690SJohnny Huang int j; 112869d5fd8fSJohnny Huang byte_buf = (char *)buf; 112969d5fd8fSJohnny Huang while (1) { 113069d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 113169d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 113269d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 113369d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 113469d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 113569d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 11369a4fe690SJohnny Huang 11379a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 11389a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 11399a4fe690SJohnny Huang key_info = key_info_array[j]; 11409a4fe690SJohnny Huang break; 11419a4fe690SJohnny Huang } 11429a4fe690SJohnny Huang } 11439a4fe690SJohnny Huang 11447f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 114569d5fd8fSJohnny Huang printf("Key Type: "); 11469a4fe690SJohnny Huang printf("%s\n", key_info.information); 11479a4fe690SJohnny Huang 11489a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 114969d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 115069d5fd8fSJohnny Huang switch (key_length) { 115169d5fd8fSJohnny Huang case 0: 115269d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 115369d5fd8fSJohnny Huang break; 115469d5fd8fSJohnny Huang case 1: 115569d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 115669d5fd8fSJohnny Huang break; 115769d5fd8fSJohnny Huang case 2: 115869d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 115969d5fd8fSJohnny Huang break; 116069d5fd8fSJohnny Huang case 3: 116169d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 116269d5fd8fSJohnny Huang break; 116369d5fd8fSJohnny Huang } 11649a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 116569d5fd8fSJohnny Huang printf("RSA SHA Type: "); 116669d5fd8fSJohnny Huang switch (key_length) { 116769d5fd8fSJohnny Huang case 0: 116869d5fd8fSJohnny Huang printf("RSA1024\n"); 116969d5fd8fSJohnny Huang len = 0x100; 117069d5fd8fSJohnny Huang break; 117169d5fd8fSJohnny Huang case 1: 117269d5fd8fSJohnny Huang printf("RSA2048\n"); 117369d5fd8fSJohnny Huang len = 0x200; 117469d5fd8fSJohnny Huang break; 117569d5fd8fSJohnny Huang case 2: 117669d5fd8fSJohnny Huang printf("RSA3072\n"); 117769d5fd8fSJohnny Huang len = 0x300; 117869d5fd8fSJohnny Huang break; 117969d5fd8fSJohnny Huang case 3: 118069d5fd8fSJohnny Huang printf("RSA4096\n"); 118169d5fd8fSJohnny Huang len = 0x400; 118269d5fd8fSJohnny Huang break; 118369d5fd8fSJohnny Huang } 118469d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 118569d5fd8fSJohnny Huang } 11869a4fe690SJohnny Huang if (key_info.need_id) 118769d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 118869d5fd8fSJohnny Huang printf("Key Value:\n"); 11899a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 119069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 11919a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 11929a4fe690SJohnny Huang printf("AES Key:\n"); 11939a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 11949a4fe690SJohnny Huang if (info_cb.version == 0) { 11959a4fe690SJohnny Huang printf("AES IV:\n"); 11969a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 11979a4fe690SJohnny Huang } 11989a4fe690SJohnny Huang 11999a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12009a4fe690SJohnny Huang if (info_cb.version == 0) { 120169d5fd8fSJohnny Huang printf("AES Key:\n"); 120269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 120369d5fd8fSJohnny Huang printf("AES IV:\n"); 120469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12059a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12069a4fe690SJohnny Huang printf("AES Key 1:\n"); 12079a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12089a4fe690SJohnny Huang printf("AES Key 2:\n"); 12099a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12109a4fe690SJohnny Huang } 121169d5fd8fSJohnny Huang 12129a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 121369d5fd8fSJohnny Huang printf("RSA mod:\n"); 121469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 121569d5fd8fSJohnny Huang printf("RSA exp:\n"); 121669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 121769d5fd8fSJohnny Huang } 121869d5fd8fSJohnny Huang if (last) 121969d5fd8fSJohnny Huang break; 122069d5fd8fSJohnny Huang i++; 122169d5fd8fSJohnny Huang } 122269d5fd8fSJohnny Huang return 0; 122369d5fd8fSJohnny Huang } 122469d5fd8fSJohnny Huang 1225a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 122669d5fd8fSJohnny Huang { 1227a6d0d645SJohnny Huang int i, k; 1228d90825e2SJohnny Huang int pass = 0; 1229d90825e2SJohnny Huang int soak = 0; 1230a6d0d645SJohnny Huang uint32_t prog_address; 1231a6d0d645SJohnny Huang uint32_t data[12]; 1232a6d0d645SJohnny Huang uint32_t compare[2]; 1233d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1234d90825e2SJohnny Huang uint32_t data_masked; 1235d90825e2SJohnny Huang uint32_t buf_masked; 123669d5fd8fSJohnny Huang 1237a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1238a6d0d645SJohnny Huang 1239a6d0d645SJohnny Huang printProgress(0, 12, ""); 1240a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1241a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 124269d5fd8fSJohnny Huang prog_address = 0x800; 1243a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1244a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1245a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1246a6d0d645SJohnny Huang } 1247a6d0d645SJohnny Huang 1248a6d0d645SJohnny Huang printf("Check writable...\n"); 1249a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1250d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1251d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1252d90825e2SJohnny Huang if (data_masked == buf_masked) 125369d5fd8fSJohnny Huang continue; 1254d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1255a6d0d645SJohnny Huang continue; 1256a6d0d645SJohnny Huang } else { 1257a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1258a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1259a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1260a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 12612a856b9aSJohnny Huang return OTP_FAILURE; 1262a6d0d645SJohnny Huang } 1263a6d0d645SJohnny Huang } 1264a6d0d645SJohnny Huang 1265a6d0d645SJohnny Huang printf("Start Programing...\n"); 1266a6d0d645SJohnny Huang printProgress(0, 12, ""); 1267d90825e2SJohnny Huang otp_soak(0); 1268a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1269d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1270d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1271a6d0d645SJohnny Huang prog_address = 0x800; 1272a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1273a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1274d90825e2SJohnny Huang if (data_masked == buf_masked) { 1275a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1276a6d0d645SJohnny Huang continue; 1277a6d0d645SJohnny Huang } 1278d90825e2SJohnny Huang if (soak) { 1279d90825e2SJohnny Huang soak = 0; 1280d90825e2SJohnny Huang otp_soak(0); 1281d90825e2SJohnny Huang } 1282a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1283a6d0d645SJohnny Huang 1284d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1285a6d0d645SJohnny Huang 128669d5fd8fSJohnny Huang pass = 0; 128769d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1288d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1289d90825e2SJohnny Huang if (soak == 0) { 1290d90825e2SJohnny Huang soak = 1; 1291d90825e2SJohnny Huang otp_soak(1); 1292d90825e2SJohnny Huang } 1293a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1294a6d0d645SJohnny Huang } else { 129569d5fd8fSJohnny Huang pass = 1; 129669d5fd8fSJohnny Huang break; 129769d5fd8fSJohnny Huang } 129869d5fd8fSJohnny Huang } 1299a6d0d645SJohnny Huang } 1300a6d0d645SJohnny Huang 130169d5fd8fSJohnny Huang if (!pass) 13022a856b9aSJohnny Huang return OTP_FAILURE; 1303a6d0d645SJohnny Huang 13042a856b9aSJohnny Huang return OTP_SUCCESS; 1305d90825e2SJohnny Huang 130669d5fd8fSJohnny Huang } 130769d5fd8fSJohnny Huang 130869d5fd8fSJohnny Huang 130976d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 131069d5fd8fSJohnny Huang { 131169d5fd8fSJohnny Huang int i; 131269d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 131369d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 131469d5fd8fSJohnny Huang int bit, pbit, kbit; 131569d5fd8fSJohnny Huang int fail = 0; 1316a6af4a17SJohnny Huang int skip = -1; 131766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 131869d5fd8fSJohnny Huang 1319541eb887SJohnny Huang otp_strap_status(otpstrap); 132069d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 132169d5fd8fSJohnny Huang if (i < 32) { 132269d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 132369d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 132469d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 132569d5fd8fSJohnny Huang } else { 132669d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 132769d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 132869d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 132969d5fd8fSJohnny Huang } 133069d5fd8fSJohnny Huang 133169d5fd8fSJohnny Huang if (kbit == 1) { 133269d5fd8fSJohnny Huang continue; 133369d5fd8fSJohnny Huang } else { 1334a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 133569d5fd8fSJohnny Huang } 133669d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 133769d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1338a6af4a17SJohnny Huang if (skip == -1) 1339a6af4a17SJohnny Huang skip = 1; 134069d5fd8fSJohnny Huang continue; 1341a6af4a17SJohnny Huang } else { 1342a6af4a17SJohnny Huang skip = 0; 134369d5fd8fSJohnny Huang } 134469d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 134569d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 134669d5fd8fSJohnny Huang fail = 1; 134769d5fd8fSJohnny Huang continue; 134869d5fd8fSJohnny Huang } 134969d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1350a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 135169d5fd8fSJohnny Huang fail = 1; 135269d5fd8fSJohnny Huang continue; 135369d5fd8fSJohnny Huang } 135469d5fd8fSJohnny Huang if (pbit == 1) { 135569d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 135669d5fd8fSJohnny Huang } 1357a6af4a17SJohnny 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); 135869d5fd8fSJohnny Huang } 135969d5fd8fSJohnny Huang if (fail == 1) 1360a6af4a17SJohnny Huang return OTP_FAILURE; 1361a6af4a17SJohnny Huang else if (skip == 1) 1362a6af4a17SJohnny Huang return OTP_PROG_SKIP; 13637e22f42dSJohnny Huang 13647e22f42dSJohnny Huang return 0; 136569d5fd8fSJohnny Huang } 136669d5fd8fSJohnny Huang 13672a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 136869d5fd8fSJohnny Huang { 136969d5fd8fSJohnny Huang int i, j; 137066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 137169d5fd8fSJohnny Huang 13722a856b9aSJohnny Huang if (start < 0 || start > 64) 13732a856b9aSJohnny Huang return OTP_USAGE; 13742a856b9aSJohnny Huang 13752a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 13762a856b9aSJohnny Huang return OTP_USAGE; 13772a856b9aSJohnny Huang 1378541eb887SJohnny Huang otp_strap_status(otpstrap); 137969d5fd8fSJohnny Huang 138007baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1381a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1382737ed20bSJohnny Huang 1383cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 138407baa4e8SJohnny Huang printf("0x%-8X", i); 1385737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1386737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1387737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1388737ed20bSJohnny Huang printf(" "); 138969d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1390737ed20bSJohnny Huang printf("protected and not writable"); 139169d5fd8fSJohnny Huang } else { 1392737ed20bSJohnny Huang printf("not protected "); 139369d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1394737ed20bSJohnny Huang printf("and no remaining times to write."); 139569d5fd8fSJohnny Huang } else { 1396737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 139769d5fd8fSJohnny Huang } 139869d5fd8fSJohnny Huang } 1399737ed20bSJohnny Huang printf("\n"); 140069d5fd8fSJohnny Huang } 14012a856b9aSJohnny Huang 14022a856b9aSJohnny Huang return OTP_SUCCESS; 140369d5fd8fSJohnny Huang } 140469d5fd8fSJohnny Huang 140569d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 140669d5fd8fSJohnny Huang { 140769d5fd8fSJohnny Huang int i, j; 140869d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 140969d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 141069d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 141169d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 141269d5fd8fSJohnny Huang int fail = 0; 14137e22f42dSJohnny Huang int pass = 0; 14147e22f42dSJohnny Huang int soak = 0; 141566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 141669d5fd8fSJohnny Huang 14177f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1418541eb887SJohnny Huang otp_strap_status(otpstrap); 141969d5fd8fSJohnny Huang 14207f795e57SJohnny Huang printf("Check writable...\n"); 14217f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 14227f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14237f795e57SJohnny Huang return OTP_FAILURE; 14247f795e57SJohnny Huang } 14257e22f42dSJohnny Huang 14267f795e57SJohnny Huang otp_soak(0); 142769d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 14284c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 142969d5fd8fSJohnny Huang prog_address = 0x800; 143069d5fd8fSJohnny Huang if (i < 32) { 143169d5fd8fSJohnny Huang offset = i; 143269d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 143369d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 143469d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 143569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 143669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 143769d5fd8fSJohnny Huang 143869d5fd8fSJohnny Huang } else { 143969d5fd8fSJohnny Huang offset = (i - 32); 144069d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 144169d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 144269d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 144369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 144469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 144569d5fd8fSJohnny Huang } 144669d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 144769d5fd8fSJohnny Huang 144869d5fd8fSJohnny Huang if (kbit == 1) { 144969d5fd8fSJohnny Huang continue; 145069d5fd8fSJohnny Huang } 145169d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 145269d5fd8fSJohnny Huang continue; 145369d5fd8fSJohnny Huang } 145469d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 145569d5fd8fSJohnny Huang fail = 1; 145669d5fd8fSJohnny Huang continue; 145769d5fd8fSJohnny Huang } 145869d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 145969d5fd8fSJohnny Huang fail = 1; 146069d5fd8fSJohnny Huang continue; 146169d5fd8fSJohnny Huang } 14627e22f42dSJohnny Huang 14637e22f42dSJohnny Huang if (soak) { 146469d5fd8fSJohnny Huang soak = 0; 14657e22f42dSJohnny Huang otp_soak(0); 14667e22f42dSJohnny Huang } 14677e22f42dSJohnny Huang 14687e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14697e22f42dSJohnny Huang 14707e22f42dSJohnny Huang pass = 0; 14717e22f42dSJohnny Huang 147269d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1473a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 147469d5fd8fSJohnny Huang pass = 1; 147569d5fd8fSJohnny Huang break; 147669d5fd8fSJohnny Huang } 14777e22f42dSJohnny Huang if (soak == 0) { 147869d5fd8fSJohnny Huang soak = 1; 14797e22f42dSJohnny Huang otp_soak(1); 14804b65a65dSJohnny Huang } 148169d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 148269d5fd8fSJohnny Huang } 148369d5fd8fSJohnny Huang if (!pass) 14842a856b9aSJohnny Huang return OTP_FAILURE; 148569d5fd8fSJohnny Huang 148669d5fd8fSJohnny Huang if (pbit == 0) 148769d5fd8fSJohnny Huang continue; 148869d5fd8fSJohnny Huang prog_address = 0x800; 148969d5fd8fSJohnny Huang if (i < 32) 149069d5fd8fSJohnny Huang prog_address |= 0x60c; 149169d5fd8fSJohnny Huang else 149269d5fd8fSJohnny Huang prog_address |= 0x60e; 149369d5fd8fSJohnny Huang 14947e22f42dSJohnny Huang 14957e22f42dSJohnny Huang if (soak) { 14967e22f42dSJohnny Huang soak = 0; 14977e22f42dSJohnny Huang otp_soak(0); 14987e22f42dSJohnny Huang } 14997e22f42dSJohnny Huang 15007e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15017e22f42dSJohnny Huang 15027e22f42dSJohnny Huang pass = 0; 15037e22f42dSJohnny Huang 150469d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 15057e22f42dSJohnny Huang 1506a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 150769d5fd8fSJohnny Huang pass = 1; 150869d5fd8fSJohnny Huang break; 150969d5fd8fSJohnny Huang } 15107e22f42dSJohnny Huang if (soak == 0) { 151169d5fd8fSJohnny Huang soak = 1; 15127e22f42dSJohnny Huang otp_soak(1); 151369d5fd8fSJohnny Huang } 151469d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 151569d5fd8fSJohnny Huang } 151669d5fd8fSJohnny Huang if (!pass) 15172a856b9aSJohnny Huang return OTP_FAILURE; 151869d5fd8fSJohnny Huang 151969d5fd8fSJohnny Huang } 152069d5fd8fSJohnny Huang if (fail == 1) 15212a856b9aSJohnny Huang return OTP_FAILURE; 152269d5fd8fSJohnny Huang else 15232a856b9aSJohnny Huang return OTP_SUCCESS; 152469d5fd8fSJohnny Huang 152569d5fd8fSJohnny Huang } 152669d5fd8fSJohnny Huang 1527cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1528cd1610b4SJohnny Huang { 1529cd1610b4SJohnny Huang int prog_bit; 1530cd1610b4SJohnny Huang 15317e22f42dSJohnny Huang otp_soak(soak); 15327e22f42dSJohnny Huang 1533cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1534cd1610b4SJohnny Huang if (value) 1535cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1536cd1610b4SJohnny Huang else 1537cd1610b4SJohnny Huang return; 1538cd1610b4SJohnny Huang } else { 1539cd1610b4SJohnny Huang prog_address |= 1 << 15; 1540cd1610b4SJohnny Huang if (!value) 1541cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1542cd1610b4SJohnny Huang else 1543cd1610b4SJohnny Huang return; 1544cd1610b4SJohnny Huang } 1545cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1546cd1610b4SJohnny Huang } 1547cd1610b4SJohnny Huang 1548d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 15494c1c9b35SJohnny Huang { 15504c1c9b35SJohnny Huang int i, k; 15514c1c9b35SJohnny Huang int pass; 1552d90825e2SJohnny Huang int soak = 0; 15534c1c9b35SJohnny Huang uint32_t prog_address; 1554d90825e2SJohnny Huang uint32_t data[2048]; 15554c1c9b35SJohnny Huang uint32_t compare[2]; 1556d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 15574c1c9b35SJohnny Huang 1558d90825e2SJohnny Huang uint32_t data0_masked; 1559d90825e2SJohnny Huang uint32_t data1_masked; 1560d90825e2SJohnny Huang uint32_t buf0_masked; 1561d90825e2SJohnny Huang uint32_t buf1_masked; 15624c1c9b35SJohnny Huang 15634c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 15644c1c9b35SJohnny Huang 1565d90825e2SJohnny Huang printProgress(0, 2048, ""); 1566d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1567d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1568d90825e2SJohnny Huang otp_read_data(i, &data[i]); 15694c1c9b35SJohnny Huang } 1570d90825e2SJohnny Huang 15714c1c9b35SJohnny Huang 15724c1c9b35SJohnny Huang printf("Check writable...\n"); 1573d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1574d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1575d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1576d90825e2SJohnny Huang if (data0_masked == buf0_masked) 15774c1c9b35SJohnny Huang continue; 1578d90825e2SJohnny Huang if (i % 2 == 0) { 1579d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 15804c1c9b35SJohnny Huang continue; 15814c1c9b35SJohnny Huang } else { 15824c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1583d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 15844c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1585d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15862a856b9aSJohnny Huang return OTP_FAILURE; 158769d5fd8fSJohnny Huang } 1588d90825e2SJohnny Huang } else { 1589d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1590d90825e2SJohnny Huang continue; 1591d90825e2SJohnny Huang } else { 1592d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1593d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1594d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1595d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15962a856b9aSJohnny Huang return OTP_FAILURE; 1597d90825e2SJohnny Huang } 1598d90825e2SJohnny Huang } 1599d90825e2SJohnny Huang } 160069d5fd8fSJohnny Huang 1601d90825e2SJohnny Huang printf("Start Programing...\n"); 1602d90825e2SJohnny Huang printProgress(0, 2048, ""); 1603d90825e2SJohnny Huang 1604d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1605d90825e2SJohnny Huang prog_address = i; 1606d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1607d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1608d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1609d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1610d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1611d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1612d90825e2SJohnny Huang continue; 1613d90825e2SJohnny Huang } 1614d90825e2SJohnny Huang if (soak) { 1615d90825e2SJohnny Huang soak = 0; 1616d90825e2SJohnny Huang otp_soak(0); 1617d90825e2SJohnny Huang } 1618d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1619d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1620d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1621d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1622d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1623d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1624d90825e2SJohnny Huang } else { 1625d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1626d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1627d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1628d90825e2SJohnny Huang } 1629d90825e2SJohnny Huang 1630d90825e2SJohnny Huang pass = 0; 1631d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1632d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1633d90825e2SJohnny Huang if (soak == 0) { 1634d90825e2SJohnny Huang soak = 1; 1635d90825e2SJohnny Huang otp_soak(1); 1636d90825e2SJohnny Huang } 1637d90825e2SJohnny Huang if (compare[0] != 0) { 1638d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1639d90825e2SJohnny Huang } 1640d90825e2SJohnny Huang if (compare[1] != ~0) { 1641d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1642d90825e2SJohnny Huang } 1643d90825e2SJohnny Huang } else { 1644d90825e2SJohnny Huang pass = 1; 1645d90825e2SJohnny Huang break; 1646d90825e2SJohnny Huang } 1647d90825e2SJohnny Huang } 1648d90825e2SJohnny Huang 1649d90825e2SJohnny Huang if (!pass) 16502a856b9aSJohnny Huang return OTP_FAILURE; 1651d90825e2SJohnny Huang } 16522a856b9aSJohnny Huang return OTP_SUCCESS; 1653d90825e2SJohnny Huang 1654d90825e2SJohnny Huang } 1655d90825e2SJohnny Huang 1656d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 165769d5fd8fSJohnny Huang { 165869d5fd8fSJohnny Huang int ret; 16597332532cSJohnny Huang int mode = 0; 16609a4fe690SJohnny Huang int image_version = 0; 166169d5fd8fSJohnny Huang uint32_t *buf; 1662d90825e2SJohnny Huang uint32_t *data_region = NULL; 1663d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1664d90825e2SJohnny Huang uint32_t *strap_region = NULL; 166569d5fd8fSJohnny Huang 1666d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 166769d5fd8fSJohnny Huang if (!buf) { 166869d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16692a856b9aSJohnny Huang return OTP_FAILURE; 167069d5fd8fSJohnny Huang } 1671d90825e2SJohnny Huang 16729a4fe690SJohnny Huang image_version = buf[0] & 0x3; 16739a4fe690SJohnny Huang if (image_version != info_cb.version) { 16749a4fe690SJohnny Huang puts("Version is not match\n"); 16759a4fe690SJohnny Huang return OTP_FAILURE; 16769a4fe690SJohnny Huang } 16779a4fe690SJohnny Huang 1678d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 16797332532cSJohnny Huang mode |= OTP_REGION_DATA; 16807332532cSJohnny Huang data_region = &buf[36]; 1681d90825e2SJohnny Huang } 1682d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 16837332532cSJohnny Huang mode |= OTP_REGION_CONF; 16847332532cSJohnny Huang conf_region = &buf[12]; 1685d90825e2SJohnny Huang } 1686d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 16877332532cSJohnny Huang mode |= OTP_REGION_STRAP; 16887332532cSJohnny Huang strap_region = &buf[4]; 1689d90825e2SJohnny Huang } 16907332532cSJohnny Huang 169169d5fd8fSJohnny Huang if (!nconfirm) { 16927332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 16937f795e57SJohnny Huang printf("\nOTP data region :\n"); 16947f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 169569d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16962a856b9aSJohnny Huang return OTP_FAILURE; 169769d5fd8fSJohnny Huang } 169869d5fd8fSJohnny Huang } 16997332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17007332532cSJohnny Huang printf("\nOTP strap region :\n"); 17017332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17027332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17037332532cSJohnny Huang return OTP_FAILURE; 17047332532cSJohnny Huang } 17057332532cSJohnny Huang } 17067332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17077332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17087332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17097332532cSJohnny Huang printf("OTP config error, please check.\n"); 17107332532cSJohnny Huang return OTP_FAILURE; 17117332532cSJohnny Huang } 17127332532cSJohnny Huang } 17137332532cSJohnny Huang 171469d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 171569d5fd8fSJohnny Huang if (!confirm_yesno()) { 171669d5fd8fSJohnny Huang printf(" Aborting\n"); 17172a856b9aSJohnny Huang return OTP_FAILURE; 171869d5fd8fSJohnny Huang } 171969d5fd8fSJohnny Huang } 17207332532cSJohnny Huang 17217332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17227332532cSJohnny Huang printf("programing data region ...\n"); 1723d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17242a856b9aSJohnny Huang if (ret != 0) { 172569d5fd8fSJohnny Huang printf("Error\n"); 172669d5fd8fSJohnny Huang return ret; 172769d5fd8fSJohnny Huang } else { 172869d5fd8fSJohnny Huang printf("Done\n"); 172969d5fd8fSJohnny Huang } 17307332532cSJohnny Huang } 17317332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17327332532cSJohnny Huang printf("programing strap region ...\n"); 1733d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17342a856b9aSJohnny Huang if (ret != 0) { 173569d5fd8fSJohnny Huang printf("Error\n"); 173669d5fd8fSJohnny Huang return ret; 173769d5fd8fSJohnny Huang } else { 173869d5fd8fSJohnny Huang printf("Done\n"); 173969d5fd8fSJohnny Huang } 17407332532cSJohnny Huang } 17417332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17427332532cSJohnny Huang printf("programing configuration region ...\n"); 1743d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17442a856b9aSJohnny Huang if (ret != 0) { 174569d5fd8fSJohnny Huang printf("Error\n"); 174669d5fd8fSJohnny Huang return ret; 174769d5fd8fSJohnny Huang } 174869d5fd8fSJohnny Huang printf("Done\n"); 174969d5fd8fSJohnny Huang } 1750cd1610b4SJohnny Huang 17517332532cSJohnny Huang return OTP_SUCCESS; 17522a856b9aSJohnny Huang } 17532a856b9aSJohnny Huang 17542a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1755cd1610b4SJohnny Huang { 1756a6af4a17SJohnny Huang uint32_t read[2]; 1757cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1758d90825e2SJohnny Huang uint32_t prog_address = 0; 175966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1760cd1610b4SJohnny Huang int otp_bit; 1761cd1610b4SJohnny Huang int i; 1762cd1610b4SJohnny Huang int pass; 1763a6af4a17SJohnny Huang int ret; 1764cd1610b4SJohnny Huang 1765cd1610b4SJohnny Huang switch (mode) { 1766a6d0d645SJohnny Huang case OTP_REGION_CONF: 1767a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1768cd1610b4SJohnny Huang prog_address = 0x800; 1769cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1770cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1771a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1772cd1610b4SJohnny Huang if (otp_bit == value) { 1773a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1774cd1610b4SJohnny Huang printf("No need to program\n"); 17752a856b9aSJohnny Huang return OTP_SUCCESS; 1776cd1610b4SJohnny Huang } 1777cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1778a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1779cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17802a856b9aSJohnny Huang return OTP_FAILURE; 1781cd1610b4SJohnny Huang } 1782a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1783cd1610b4SJohnny Huang break; 1784a6d0d645SJohnny Huang case OTP_REGION_DATA: 1785cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1786cd1610b4SJohnny Huang 1787cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1788a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1789a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1790643b9cfdSJohnny Huang 1791643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1792643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1793643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1794643b9cfdSJohnny Huang return OTP_FAILURE; 1795643b9cfdSJohnny Huang } 1796cd1610b4SJohnny Huang } else { 1797a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1798a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1799643b9cfdSJohnny Huang 1800643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1801643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1802643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1803643b9cfdSJohnny Huang return OTP_FAILURE; 1804643b9cfdSJohnny Huang } 1805cd1610b4SJohnny Huang } 1806cd1610b4SJohnny Huang if (otp_bit == value) { 1807a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1808cd1610b4SJohnny Huang printf("No need to program\n"); 18092a856b9aSJohnny Huang return OTP_SUCCESS; 1810cd1610b4SJohnny Huang } 1811643b9cfdSJohnny Huang 1812a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1813cd1610b4SJohnny Huang break; 1814a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1815541eb887SJohnny Huang otp_strap_status(otpstrap); 1816cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1817cd1610b4SJohnny Huang if (bit_offset < 32) { 1818cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1819cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1820cd1610b4SJohnny Huang strap_buf[3] = ~0; 1821cd1610b4SJohnny Huang strap_buf[5] = 0; 18222a856b9aSJohnny Huang // if (protect) 18232a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 18242a856b9aSJohnny Huang // else 18252a856b9aSJohnny Huang // strap_buf[4] = 0; 1826cd1610b4SJohnny Huang } else { 1827cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1828cd1610b4SJohnny Huang strap_buf[2] = ~0; 1829cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1830cd1610b4SJohnny Huang strap_buf[4] = 0; 18312a856b9aSJohnny Huang // if (protect) 18322a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 18332a856b9aSJohnny Huang // else 18342a856b9aSJohnny Huang // strap_buf[5] = 0; 1835cd1610b4SJohnny Huang } 183676d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1837a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18382a856b9aSJohnny Huang return OTP_FAILURE; 1839a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1840a6af4a17SJohnny Huang return OTP_SUCCESS; 1841a6af4a17SJohnny Huang 1842cd1610b4SJohnny Huang break; 1843cd1610b4SJohnny Huang } 1844cd1610b4SJohnny Huang 1845cd1610b4SJohnny Huang if (!nconfirm) { 1846cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1847cd1610b4SJohnny Huang if (!confirm_yesno()) { 1848cd1610b4SJohnny Huang printf(" Aborting\n"); 18492a856b9aSJohnny Huang return OTP_FAILURE; 1850cd1610b4SJohnny Huang } 1851cd1610b4SJohnny Huang } 1852cd1610b4SJohnny Huang 1853cd1610b4SJohnny Huang switch (mode) { 1854a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1855cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1856a6d0d645SJohnny Huang case OTP_REGION_CONF: 1857a6d0d645SJohnny Huang case OTP_REGION_DATA: 1858cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1859cd1610b4SJohnny Huang pass = -1; 1860cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1861a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1862cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1863cd1610b4SJohnny Huang } else { 1864cd1610b4SJohnny Huang pass = 0; 1865cd1610b4SJohnny Huang break; 1866cd1610b4SJohnny Huang } 1867cd1610b4SJohnny Huang } 18689009c25dSJohnny Huang if (pass == 0) { 18699009c25dSJohnny Huang printf("SUCCESS\n"); 18702a856b9aSJohnny Huang return OTP_SUCCESS; 18719009c25dSJohnny Huang } else { 18729009c25dSJohnny Huang printf("OTP cannot be programed\n"); 18739009c25dSJohnny Huang printf("FAILED\n"); 18749009c25dSJohnny Huang return OTP_FAILURE; 18759009c25dSJohnny Huang } 1876cd1610b4SJohnny Huang } 1877cd1610b4SJohnny Huang 18782a856b9aSJohnny Huang return OTP_USAGE; 1879cd1610b4SJohnny Huang } 1880cd1610b4SJohnny Huang 18812a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 188269d5fd8fSJohnny Huang { 18832a856b9aSJohnny Huang uint32_t offset, count; 18842a856b9aSJohnny Huang int ret; 188569d5fd8fSJohnny Huang 18862a856b9aSJohnny Huang if (argc == 4) { 18872a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 18882a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 18892a856b9aSJohnny Huang } else if (argc == 3) { 18902a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 18912a856b9aSJohnny Huang count = 1; 18922a856b9aSJohnny Huang } else { 189369d5fd8fSJohnny Huang return CMD_RET_USAGE; 189469d5fd8fSJohnny Huang } 189569d5fd8fSJohnny Huang 189669d5fd8fSJohnny Huang 18972a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 189869d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18992a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19002a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19012a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19022a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19032a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19042a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19052a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19062a856b9aSJohnny Huang } else { 19072a856b9aSJohnny Huang return CMD_RET_USAGE; 190869d5fd8fSJohnny Huang } 190969d5fd8fSJohnny Huang 19102a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19112a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19122a856b9aSJohnny Huang else 19132a856b9aSJohnny Huang return CMD_RET_USAGE; 19142a856b9aSJohnny Huang 19152a856b9aSJohnny Huang } 19162a856b9aSJohnny Huang 19172a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19182a856b9aSJohnny Huang { 19192a856b9aSJohnny Huang phys_addr_t addr; 19202a856b9aSJohnny Huang uint32_t byte_size; 19212a856b9aSJohnny Huang int ret; 19222a856b9aSJohnny Huang 19232a856b9aSJohnny Huang if (argc == 4) { 19242a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 19252a856b9aSJohnny Huang return CMD_RET_USAGE; 19262a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19272a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 192869d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19292a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19302a856b9aSJohnny Huang } else if (argc == 3) { 19312a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19322a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 19332a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19342a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19352a856b9aSJohnny Huang } else { 19362a856b9aSJohnny Huang return CMD_RET_USAGE; 19372a856b9aSJohnny Huang } 19382a856b9aSJohnny Huang 19392a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19402a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19412a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19422a856b9aSJohnny Huang return CMD_RET_FAILURE; 19432a856b9aSJohnny Huang else 19442a856b9aSJohnny Huang return CMD_RET_USAGE; 19452a856b9aSJohnny Huang } 19462a856b9aSJohnny Huang 19472a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19482a856b9aSJohnny Huang { 19492a856b9aSJohnny Huang int mode = 0; 19502a856b9aSJohnny Huang int nconfirm = 0; 19512a856b9aSJohnny Huang int otp_addr = 0; 19522a856b9aSJohnny Huang int bit_offset; 19532a856b9aSJohnny Huang int value; 19542a856b9aSJohnny Huang int ret; 19552a856b9aSJohnny Huang 19562a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19572a856b9aSJohnny Huang return CMD_RET_USAGE; 19582a856b9aSJohnny Huang 19592a856b9aSJohnny Huang /* Drop the pb cmd */ 19602a856b9aSJohnny Huang argc--; 19612a856b9aSJohnny Huang argv++; 19622a856b9aSJohnny Huang 19632a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1964a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 19652a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1966a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 19672a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1968a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1969cd1610b4SJohnny Huang else 19702a856b9aSJohnny Huang return CMD_RET_USAGE; 19712a856b9aSJohnny Huang 19722a856b9aSJohnny Huang /* Drop the region cmd */ 19732a856b9aSJohnny Huang argc--; 19742a856b9aSJohnny Huang argv++; 19752a856b9aSJohnny Huang 19762a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1977cd1610b4SJohnny Huang nconfirm = 1; 19782a856b9aSJohnny Huang /* Drop the force option */ 19792a856b9aSJohnny Huang argc--; 19802a856b9aSJohnny Huang argv++; 19812a856b9aSJohnny Huang } 1982cd1610b4SJohnny Huang 1983a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 19842a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 19852a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1986*0808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 19872a856b9aSJohnny Huang return CMD_RET_USAGE; 1988cd1610b4SJohnny Huang } else { 19892a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 19902a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 19912a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1992*0808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 19932a856b9aSJohnny Huang return CMD_RET_USAGE; 1994*0808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 1995*0808cc55SJohnny Huang if (otp_addr >= 200) 1996*0808cc55SJohnny Huang return CMD_RET_USAGE; 1997*0808cc55SJohnny Huang }else { 1998*0808cc55SJohnny Huang if (otp_addr >= 32) 1999*0808cc55SJohnny Huang return CMD_RET_USAGE; 2000*0808cc55SJohnny Huang } 2001cd1610b4SJohnny Huang } 2002cd1610b4SJohnny Huang if (value != 0 && value != 1) 20032a856b9aSJohnny Huang return CMD_RET_USAGE; 2004cd1610b4SJohnny Huang 2005cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 20062a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20072a856b9aSJohnny Huang 20082a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20092a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20102a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20112a856b9aSJohnny Huang return CMD_RET_FAILURE; 20122a856b9aSJohnny Huang else 20132a856b9aSJohnny Huang return CMD_RET_USAGE; 20142a856b9aSJohnny Huang } 20152a856b9aSJohnny Huang 20162a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20172a856b9aSJohnny Huang { 20182a856b9aSJohnny Huang phys_addr_t addr; 20192a856b9aSJohnny Huang int otp_addr = 0; 20202a856b9aSJohnny Huang 20212a856b9aSJohnny Huang if (argc != 3) 20222a856b9aSJohnny Huang return CMD_RET_USAGE; 20232a856b9aSJohnny Huang 202469d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 20252a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20262a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20272a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 202869d5fd8fSJohnny Huang printf("Compare pass\n"); 20292a856b9aSJohnny Huang return CMD_RET_SUCCESS; 203069d5fd8fSJohnny Huang } else { 203169d5fd8fSJohnny Huang printf("Compare fail\n"); 20322a856b9aSJohnny Huang return CMD_RET_FAILURE; 203369d5fd8fSJohnny Huang } 203469d5fd8fSJohnny Huang } 203569d5fd8fSJohnny Huang 203666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 203766f2f8e5SJohnny Huang { 2038a8bd6d8cSJohnny Huang int view = 0; 20392d4b0742SJohnny Huang int input; 2040a8bd6d8cSJohnny Huang 2041a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 204266f2f8e5SJohnny Huang return CMD_RET_USAGE; 204366f2f8e5SJohnny Huang 20442d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 204566f2f8e5SJohnny Huang 20462d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 20472d4b0742SJohnny Huang if (argc == 3) { 20482d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20492d4b0742SJohnny Huang otp_print_conf_info(input); 20502d4b0742SJohnny Huang } else { 20512d4b0742SJohnny Huang otp_print_conf_info(-1); 20522d4b0742SJohnny Huang } 20532d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20542d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2055a8bd6d8cSJohnny Huang view = 1; 2056a8bd6d8cSJohnny Huang /* Drop the view option */ 2057a8bd6d8cSJohnny Huang argc--; 2058a8bd6d8cSJohnny Huang argv++; 2059a8bd6d8cSJohnny Huang } 206066f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 2061b458cd62SJohnny Huang otp_print_strap_info(view); 206266f2f8e5SJohnny Huang } else { 206366f2f8e5SJohnny Huang return CMD_RET_USAGE; 206466f2f8e5SJohnny Huang } 20652d4b0742SJohnny Huang 206666f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 206766f2f8e5SJohnny Huang } 206866f2f8e5SJohnny Huang 2069737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2070737ed20bSJohnny Huang { 2071737ed20bSJohnny Huang int input; 2072737ed20bSJohnny Huang int bit_offset; 2073737ed20bSJohnny Huang int prog_address; 2074737ed20bSJohnny Huang int pass; 2075737ed20bSJohnny Huang int i; 2076737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2077737ed20bSJohnny Huang return CMD_RET_USAGE; 2078737ed20bSJohnny Huang 2079737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 2080737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2081737ed20bSJohnny Huang } else { 2082737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2083737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2084737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2085737ed20bSJohnny Huang if (!confirm_yesno()) { 2086737ed20bSJohnny Huang printf(" Aborting\n"); 2087737ed20bSJohnny Huang return CMD_RET_FAILURE; 2088737ed20bSJohnny Huang } 2089737ed20bSJohnny Huang } 2090737ed20bSJohnny Huang 2091737ed20bSJohnny Huang prog_address = 0x800; 2092737ed20bSJohnny Huang if (input < 32) { 2093737ed20bSJohnny Huang bit_offset = input; 2094737ed20bSJohnny Huang prog_address |= 0x60c; 2095737ed20bSJohnny Huang } else if (input < 64) { 2096737ed20bSJohnny Huang bit_offset = input - 32; 2097737ed20bSJohnny Huang prog_address |= 0x60e; 2098737ed20bSJohnny Huang } else { 2099737ed20bSJohnny Huang return CMD_RET_USAGE; 2100737ed20bSJohnny Huang } 2101737ed20bSJohnny Huang 2102737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2103737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2104737ed20bSJohnny Huang } 2105737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 2106737ed20bSJohnny Huang pass = -1; 2107737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2108737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2109737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 2110737ed20bSJohnny Huang } else { 2111737ed20bSJohnny Huang pass = 0; 2112737ed20bSJohnny Huang break; 2113737ed20bSJohnny Huang } 2114737ed20bSJohnny Huang } 2115737ed20bSJohnny Huang if (pass == 0) { 2116737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2117737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2118737ed20bSJohnny Huang } 2119737ed20bSJohnny Huang 2120737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2121737ed20bSJohnny Huang return CMD_RET_FAILURE; 2122737ed20bSJohnny Huang 2123737ed20bSJohnny Huang } 21249a4fe690SJohnny Huang 21252a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21262a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2127a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21282a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21292a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2130737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21312a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21322a856b9aSJohnny Huang }; 21332a856b9aSJohnny Huang 21342a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21352a856b9aSJohnny Huang { 21362a856b9aSJohnny Huang cmd_tbl_t *cp; 21372a856b9aSJohnny Huang 21382a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21392a856b9aSJohnny Huang 2140737ed20bSJohnny Huang /* Drop the otp command */ 21412a856b9aSJohnny Huang argc--; 21422a856b9aSJohnny Huang argv++; 21432a856b9aSJohnny Huang 21442a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 21452a856b9aSJohnny Huang return CMD_RET_USAGE; 21462a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 21472a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21482a856b9aSJohnny Huang 21499a4fe690SJohnny Huang if (chip_version() == 0) { 21509a4fe690SJohnny Huang info_cb.version = 0; 21519a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 21529a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 21539a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 21549a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 21559a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 21569a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 21579a4fe690SJohnny Huang } else if (chip_version() == 1) { 21589a4fe690SJohnny Huang info_cb.version = 1; 21593cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 21603cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 21613cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 21623cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 21639a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 21649a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 21659a4fe690SJohnny Huang } 21669a4fe690SJohnny Huang 21672a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 216869d5fd8fSJohnny Huang } 216969d5fd8fSJohnny Huang 217069d5fd8fSJohnny Huang U_BOOT_CMD( 217169d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 217269d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 21732a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 21742a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 21752d4b0742SJohnny Huang "otp info strap [v]\n" 21762d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2177d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2178cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2179737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2180737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 21812a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 218269d5fd8fSJohnny Huang ); 2183