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 51*3d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 52*3d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 53*3d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 54*3d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 55*3d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 56*3d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 57*3d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 58*3d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 59*3d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 60*3d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 61*3d3688adSJohnny Huang 6266f2f8e5SJohnny Huang struct otpstrap_status { 6369d5fd8fSJohnny Huang int value; 6469d5fd8fSJohnny Huang int option_array[7]; 6569d5fd8fSJohnny Huang int remain_times; 6669d5fd8fSJohnny Huang int writeable_option; 6769d5fd8fSJohnny Huang int protected; 6869d5fd8fSJohnny Huang }; 6969d5fd8fSJohnny Huang 7066f2f8e5SJohnny Huang struct otpconf_parse { 7166f2f8e5SJohnny Huang int dw_offset; 7266f2f8e5SJohnny Huang int bit; 7366f2f8e5SJohnny Huang int length; 7466f2f8e5SJohnny Huang int value; 7566f2f8e5SJohnny Huang int keep; 7666f2f8e5SJohnny Huang char status[80]; 7766f2f8e5SJohnny Huang }; 7866f2f8e5SJohnny Huang 79a8bd6d8cSJohnny Huang struct otpstrap_info { 80a8bd6d8cSJohnny Huang uint32_t bit_offset; 81a8bd6d8cSJohnny Huang uint32_t length; 8276d13988SJohnny Huang int value; 83a8bd6d8cSJohnny Huang char information[80]; 84a8bd6d8cSJohnny Huang }; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang struct otpconf_info { 87a8bd6d8cSJohnny Huang uint32_t dw_offset; 88a8bd6d8cSJohnny Huang uint32_t bit_offset; 89a8bd6d8cSJohnny Huang uint32_t length; 90a8bd6d8cSJohnny Huang int value; 91a8bd6d8cSJohnny Huang char information[80]; 92a8bd6d8cSJohnny Huang }; 93a8bd6d8cSJohnny Huang 949a4fe690SJohnny Huang struct otpkey_type { 959a4fe690SJohnny Huang int value; 969a4fe690SJohnny Huang int key_type; 979a4fe690SJohnny Huang int need_id; 989a4fe690SJohnny Huang char information[110]; 999a4fe690SJohnny Huang }; 1009a4fe690SJohnny Huang 1019a4fe690SJohnny Huang struct otp_info_cb { 1029a4fe690SJohnny Huang int version; 1039a4fe690SJohnny Huang struct otpstrap_info *strap_info; 1049a4fe690SJohnny Huang int strap_info_len; 1059a4fe690SJohnny Huang struct otpconf_info *conf_info; 1069a4fe690SJohnny Huang int conf_info_len; 1079a4fe690SJohnny Huang struct otpkey_type *key_info; 1089a4fe690SJohnny Huang int key_info_len; 1099a4fe690SJohnny Huang }; 1109a4fe690SJohnny Huang 111a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 112a8bd6d8cSJohnny Huang { 113a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 114a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 115a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 116a8bd6d8cSJohnny Huang char buffer[256]; 117a8bd6d8cSJohnny Huang va_list aptr; 118a8bd6d8cSJohnny Huang 119a8bd6d8cSJohnny Huang va_start(aptr, format); 120a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 121a8bd6d8cSJohnny Huang va_end(aptr); 122a8bd6d8cSJohnny Huang 123a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 124a8bd6d8cSJohnny Huang if (numerator == denominator) 125a8bd6d8cSJohnny Huang printf("\n"); 126a8bd6d8cSJohnny Huang } 127a8bd6d8cSJohnny Huang 1289a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1299a4fe690SJohnny Huang 130a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 13191448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 13291448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 13391448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 13491448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 13591448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 13691448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 13791448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 13891448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 139541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 14091448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 14191448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 14291448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 14391448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 14491448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 14591448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 14691448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 14791448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 14891448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 14991448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 15091448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 15191448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 15291448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 15391448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 15491448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 15591448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 15691448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 15791448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 15891448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 15991448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 16091448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 16191448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 16291448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 16391448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 16491448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 16591448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 16691448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 16791448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 16891448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 16991448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 17091448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 17191448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 17291448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 17391448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 17491448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 17591448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 17691448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 17791448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 17891448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 17991448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 18091448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 18191448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 18291448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 18391448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 18491448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 18591448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 18691448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 18791448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 18891448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 18991448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 19091448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 19191448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 19291448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 19391448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 19491448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 19591448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 19691448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 19791448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 19891448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 19991448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 20091448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 20191448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 20291448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 20391448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 20491448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 20591448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 20691448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 20791448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 20891448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 20991448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 21091448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 21191448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 21291448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 21391448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 21491448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 21591448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 21691448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 21791448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 21891448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 21991448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 22091448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 22191448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 22291448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 22391448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 22491448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 22591448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 22691448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 22791448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 22891448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 22991448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 23091448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 23191448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 23291448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 23391448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 23491448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 23591448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 23691448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 23791448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 23891448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 23991448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 24076d13988SJohnny Huang }; 2419a4fe690SJohnny Huang 2423cb28812SJohnny Huang struct otpstrap_info a1_strap_info[] = { 2433cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2443cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2453cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2463cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2473cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2483cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2493cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2503cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2513cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2523cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2533cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2543cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2553cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2563cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2573cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2583cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2593cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2603cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2613cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2623cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2633cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2643cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2653cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2663cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2673cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2683cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2693cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2703cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2713cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2723cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2733cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2743cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2753cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2763cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2773cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2783cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2793cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2803cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2813cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 2823cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 2833cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 2843cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 2853cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 2863cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 2873cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 2883cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 2893cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 2903cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 2913cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 2923cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 2933cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 2943cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 2953cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 2963cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 2973cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 2983cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 2993cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 3003cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 3013cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 3023cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 3033cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 3043cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 3053cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 3063cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 3073cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 3083cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 3093cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 3103cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 3113cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 3123cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 3133cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 3143cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 3153cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 3163cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3173cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3183cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3193cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3203cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3213cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3223cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3233cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3243cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3253cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3263cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3273cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3283cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3293cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3303cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3313cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3323cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3333cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3343cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3353cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3363cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3373cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3383cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3393cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3403cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3413cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3423cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3433cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3443cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3453cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3463cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3473cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3483cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3493cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3503cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3513cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3523cb28812SJohnny Huang }; 3533cb28812SJohnny Huang 354b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 35591448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 35691448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 35791448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 35891448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 35991448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 36091448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 36191448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 36291448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 36391448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 36491448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 36591448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 36691448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 36791448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 36891448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 36991448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 37091448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 37191448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 372541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 37391448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 37491448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 37591448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 37691448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 37791448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 37891448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 37991448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 38091448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 38191448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 38291448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 38391448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 38491448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 38591448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 38691448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 38791448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 38891448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 38991448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 39091448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 39191448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 39291448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 39391448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 39491448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 39591448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 39691448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 39791448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 39891448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 3993cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4003cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4013cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4023cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 4033cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 4043cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 4053cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 4063cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 4073cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 4083cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 4093cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 4103cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 4113cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 4123cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 4133cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 4143cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 4153cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 4163cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4173cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4183cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4193cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4203cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4213cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4223cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4233cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4243cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4253cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4263cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4273cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4283cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4293cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4303cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4313cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4323cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4333cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4343cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4353cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4363cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4373cb28812SJohnny Huang }; 4383cb28812SJohnny Huang 4393cb28812SJohnny Huang struct otpconf_info a1_conf_info[] = { 4403cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4413cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4423cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4433cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4443cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4453cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4463cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4473cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4483cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4493cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4503cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4513cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4523cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4533cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4543cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4553cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4563cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4573cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4583cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4593cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4603cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4613cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4623cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4633cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4643cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4653cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 4663cb28812SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 4673cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4683cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4693cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4703cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4713cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4723cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4733cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4743cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4753cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4763cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4773cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4783cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4793cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4803cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4813cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4823cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4833cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4843cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4853cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4863cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 48791448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 48891448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 48991448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 49073f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 49173f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 49291448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 49391448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 49491448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 49591448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 49691448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 49791448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 49891448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 49991448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 50091448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 50191448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 50291448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 50391448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 50491448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 50591448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 50691448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 50791448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 50891448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 50991448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 51091448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 51191448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 51291448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 51391448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 51491448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 51591448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 51691448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 51791448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 51891448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 51991448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 52091448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 521b458cd62SJohnny Huang }; 5229a4fe690SJohnny Huang 5239a4fe690SJohnny Huang struct otpkey_type a0_key_type[] = { 5249a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5259a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5269a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5279a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5289a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5299a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5309a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5319a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5329a4fe690SJohnny Huang }; 5339a4fe690SJohnny Huang 5349a4fe690SJohnny Huang struct otpkey_type a1_key_type[] = { 5359a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5369a4fe690SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 5379a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5389a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5399a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5409a4fe690SJohnny Huang }; 5419a4fe690SJohnny Huang 5429a4fe690SJohnny Huang static uint32_t chip_version(void) 5439a4fe690SJohnny Huang { 5449a4fe690SJohnny Huang uint32_t rev_id; 5459a4fe690SJohnny Huang 5469a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5479a4fe690SJohnny Huang 5489a4fe690SJohnny Huang return rev_id; 5499a4fe690SJohnny Huang } 5509a4fe690SJohnny Huang 551*3d3688adSJohnny Huang static void wait_complete(void) 552*3d3688adSJohnny Huang { 553*3d3688adSJohnny Huang int reg; 554*3d3688adSJohnny Huang 555*3d3688adSJohnny Huang do { 556*3d3688adSJohnny Huang reg = readl(OTP_STATUS); 557*3d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 558*3d3688adSJohnny Huang } 559*3d3688adSJohnny Huang 5602a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 56169d5fd8fSJohnny Huang { 562*3d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 563*3d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 564*3d3688adSJohnny Huang wait_complete(); 565*3d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 566*3d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 56769d5fd8fSJohnny Huang } 56869d5fd8fSJohnny Huang 5692a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 57069d5fd8fSJohnny Huang { 57169d5fd8fSJohnny Huang int config_offset; 57269d5fd8fSJohnny Huang 57369d5fd8fSJohnny Huang config_offset = 0x800; 57469d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 57569d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 57669d5fd8fSJohnny Huang 577*3d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 578*3d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 579*3d3688adSJohnny Huang wait_complete(); 580*3d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 58169d5fd8fSJohnny Huang } 58269d5fd8fSJohnny Huang 58369d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 58469d5fd8fSJohnny Huang { 58569d5fd8fSJohnny Huang int i; 58669d5fd8fSJohnny Huang uint32_t ret[1]; 58769d5fd8fSJohnny Huang 58869d5fd8fSJohnny Huang if (offset + dw_count > 32) 5892a856b9aSJohnny Huang return OTP_USAGE; 59069d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 59169d5fd8fSJohnny Huang otp_read_config(i, ret); 592a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 59369d5fd8fSJohnny Huang } 59469d5fd8fSJohnny Huang printf("\n"); 5952a856b9aSJohnny Huang return OTP_SUCCESS; 59669d5fd8fSJohnny Huang } 59769d5fd8fSJohnny Huang 59869d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 59969d5fd8fSJohnny Huang { 60069d5fd8fSJohnny Huang int i; 60169d5fd8fSJohnny Huang uint32_t ret[2]; 60269d5fd8fSJohnny Huang 60369d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 6042a856b9aSJohnny Huang return OTP_USAGE; 60569d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 60669d5fd8fSJohnny Huang otp_read_data(i, ret); 60769d5fd8fSJohnny Huang if (i % 4 == 0) 60869d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 60969d5fd8fSJohnny Huang else 61069d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 61169d5fd8fSJohnny Huang 61269d5fd8fSJohnny Huang } 61369d5fd8fSJohnny Huang printf("\n"); 6142a856b9aSJohnny Huang return OTP_SUCCESS; 61569d5fd8fSJohnny Huang } 61669d5fd8fSJohnny Huang 61769d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 61869d5fd8fSJohnny Huang { 61969d5fd8fSJohnny Huang uint32_t ret; 62069d5fd8fSJohnny Huang uint32_t *buf; 62169d5fd8fSJohnny Huang 62269d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 62369d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 62469d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 62569d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 62669d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 627*3d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 628*3d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 629*3d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 630*3d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 631*3d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 632*3d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 633*3d3688adSJohnny Huang wait_complete(); 634*3d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 63569d5fd8fSJohnny Huang if (ret & 0x1) 63669d5fd8fSJohnny Huang return 0; 63769d5fd8fSJohnny Huang else 63869d5fd8fSJohnny Huang return -1; 63969d5fd8fSJohnny Huang } 64069d5fd8fSJohnny Huang 64169d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 64269d5fd8fSJohnny Huang { 643*3d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 644*3d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 645*3d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 646*3d3688adSJohnny Huang wait_complete(); 64769d5fd8fSJohnny Huang } 64869d5fd8fSJohnny Huang 64969d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 65069d5fd8fSJohnny Huang { 651*3d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 652*3d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 653*3d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 654*3d3688adSJohnny Huang wait_complete(); 65569d5fd8fSJohnny Huang } 65669d5fd8fSJohnny Huang 657a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 65869d5fd8fSJohnny Huang { 65930a8c590SJohnny Huang uint32_t ret[2]; 66069d5fd8fSJohnny Huang 66130a8c590SJohnny Huang if (otp_addr % 2 == 0) 662*3d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 66330a8c590SJohnny Huang else 664*3d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 66530a8c590SJohnny Huang 666*3d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 667*3d3688adSJohnny Huang wait_complete(); 668*3d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 669*3d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 670a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 67130a8c590SJohnny Huang if (otp_addr % 2 == 0) { 67230a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 67369d5fd8fSJohnny Huang return 0; 67469d5fd8fSJohnny Huang else 67569d5fd8fSJohnny Huang return -1; 67630a8c590SJohnny Huang } else { 67730a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 67830a8c590SJohnny Huang return 0; 67930a8c590SJohnny Huang else 68030a8c590SJohnny Huang return -1; 68130a8c590SJohnny Huang } 68230a8c590SJohnny Huang 68369d5fd8fSJohnny Huang } 68469d5fd8fSJohnny Huang 685d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6864c1c9b35SJohnny Huang { 6874c1c9b35SJohnny Huang uint32_t ret[2]; 6884c1c9b35SJohnny Huang 6894c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6904c1c9b35SJohnny Huang 6914c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 692*3d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 6934c1c9b35SJohnny Huang else 694*3d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 695*3d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 696*3d3688adSJohnny Huang wait_complete(); 697*3d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 698*3d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 6994c1c9b35SJohnny Huang if (size == 1) { 7004c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 7014c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 702d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 7034c1c9b35SJohnny Huang compare[0] = 0; 7044c1c9b35SJohnny Huang return 0; 7054c1c9b35SJohnny Huang } else { 7064c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7074c1c9b35SJohnny Huang return -1; 7084c1c9b35SJohnny Huang } 7094c1c9b35SJohnny Huang 7104c1c9b35SJohnny Huang } else { 7114c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 712d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 7134c1c9b35SJohnny Huang compare[0] = ~0; 7144c1c9b35SJohnny Huang return 0; 7154c1c9b35SJohnny Huang } else { 716d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7174c1c9b35SJohnny Huang return -1; 7184c1c9b35SJohnny Huang } 7194c1c9b35SJohnny Huang } 7204c1c9b35SJohnny Huang } else if (size == 2) { 7214c1c9b35SJohnny Huang // otp_addr should be even 722d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7234c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7244c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7254c1c9b35SJohnny Huang compare[0] = 0; 7264c1c9b35SJohnny Huang compare[1] = ~0; 7274c1c9b35SJohnny Huang return 0; 7284c1c9b35SJohnny Huang } else { 7294c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7304c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7314c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7324c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7334c1c9b35SJohnny Huang return -1; 7344c1c9b35SJohnny Huang } 7354c1c9b35SJohnny Huang } else { 7364c1c9b35SJohnny Huang return -1; 7374c1c9b35SJohnny Huang } 7384c1c9b35SJohnny Huang } 7394c1c9b35SJohnny Huang 7407e22f42dSJohnny Huang static void otp_soak(int soak) 741d90825e2SJohnny Huang { 742d90825e2SJohnny Huang if (soak) { 743d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 744d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 745d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 746*3d3688adSJohnny Huang writel(0x041930d4, OTP_TIMING); //soak program 747d90825e2SJohnny Huang } else { 748d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 749d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 750d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 751*3d3688adSJohnny Huang writel(0x04190760, OTP_TIMING); //normal program 752d90825e2SJohnny Huang } 753*3d3688adSJohnny Huang wait_complete(); 754d90825e2SJohnny Huang } 755d90825e2SJohnny Huang 756d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 757d90825e2SJohnny Huang { 758d90825e2SJohnny Huang int j, bit_value, prog_bit; 759d90825e2SJohnny Huang 760d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 761d90825e2SJohnny Huang if ((keep >> j) & 0x1) 762d90825e2SJohnny Huang continue; 763d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 764d90825e2SJohnny Huang if (prog_address % 2 == 0) { 765d90825e2SJohnny Huang if (bit_value) 766d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 767d90825e2SJohnny Huang else 768d90825e2SJohnny Huang continue; 769d90825e2SJohnny Huang } else { 770d90825e2SJohnny Huang prog_address |= 1 << 15; 771d90825e2SJohnny Huang if (bit_value) 772d90825e2SJohnny Huang continue; 773d90825e2SJohnny Huang else 774d90825e2SJohnny Huang prog_bit = 0x1 << j; 775d90825e2SJohnny Huang } 776d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 777d90825e2SJohnny Huang } 778d90825e2SJohnny Huang } 779d90825e2SJohnny Huang 78076d13988SJohnny Huang 781541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 78276d13988SJohnny Huang { 78376d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 78476d13988SJohnny Huang int i, j; 78576d13988SJohnny Huang 78676d13988SJohnny Huang for (j = 0; j < 64; j++) { 78776d13988SJohnny Huang otpstrap[j].value = 0; 78876d13988SJohnny Huang otpstrap[j].remain_times = 7; 78976d13988SJohnny Huang otpstrap[j].writeable_option = -1; 79076d13988SJohnny Huang otpstrap[j].protected = 0; 79176d13988SJohnny Huang } 79276d13988SJohnny Huang 79376d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 79476d13988SJohnny Huang int option = (i - 16) / 2; 79576d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 79676d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 79776d13988SJohnny Huang for (j = 0; j < 32; j++) { 79876d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 79976d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 80076d13988SJohnny Huang otpstrap[j].writeable_option = option; 80176d13988SJohnny Huang } 80276d13988SJohnny Huang if (bit_value == 1) 80376d13988SJohnny Huang otpstrap[j].remain_times --; 80476d13988SJohnny Huang otpstrap[j].value ^= bit_value; 80576d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 80676d13988SJohnny Huang } 80776d13988SJohnny Huang for (j = 32; j < 64; j++) { 80876d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 80976d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 81076d13988SJohnny Huang otpstrap[j].writeable_option = option; 81176d13988SJohnny Huang } 81276d13988SJohnny Huang if (bit_value == 1) 81376d13988SJohnny Huang otpstrap[j].remain_times --; 81476d13988SJohnny Huang otpstrap[j].value ^= bit_value; 81576d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 81676d13988SJohnny Huang } 81776d13988SJohnny Huang } 81876d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 81976d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 82076d13988SJohnny Huang for (j = 0; j < 32; j++) { 82176d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 82276d13988SJohnny Huang otpstrap[j].protected = 1; 82376d13988SJohnny Huang } 82476d13988SJohnny Huang for (j = 32; j < 64; j++) { 82576d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 82676d13988SJohnny Huang otpstrap[j].protected = 1; 82776d13988SJohnny Huang } 82876d13988SJohnny Huang } 82976d13988SJohnny Huang 830b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 83169d5fd8fSJohnny Huang { 8323cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 833442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 834b458cd62SJohnny Huang uint32_t mask; 835b458cd62SJohnny Huang uint32_t dw_offset; 836b458cd62SJohnny Huang uint32_t bit_offset; 837b458cd62SJohnny Huang uint32_t otp_value; 838b458cd62SJohnny Huang uint32_t otp_keep; 839b458cd62SJohnny Huang int fail = 0; 84073f11549SJohnny Huang char valid_bit[20]; 84166f2f8e5SJohnny Huang int i; 84273f11549SJohnny Huang int j; 84366f2f8e5SJohnny Huang 844737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 84566f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8463cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8473cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8483cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8493cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 850b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 851b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 852b458cd62SJohnny Huang 853b458cd62SJohnny Huang if (otp_keep == mask) { 854b458cd62SJohnny Huang continue; 855b458cd62SJohnny Huang } else if (otp_keep != 0) { 856b458cd62SJohnny Huang fail = 1; 857b458cd62SJohnny Huang } 858b458cd62SJohnny Huang 8593cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 8603cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 8613cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 8623cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 863b458cd62SJohnny Huang continue; 864b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 865b458cd62SJohnny Huang 8663cb28812SJohnny Huang if (conf_info[i].length == 1) { 8673cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 86866f2f8e5SJohnny Huang } else { 869b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 8703cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 8713cb28812SJohnny Huang conf_info[i].bit_offset); 87266f2f8e5SJohnny Huang } 873b458cd62SJohnny Huang printf("0x%-10x", otp_value); 874b458cd62SJohnny Huang 875b458cd62SJohnny Huang if (fail) { 876b458cd62SJohnny Huang printf("Keep mask error\n"); 877b458cd62SJohnny Huang } else { 8783cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 879b458cd62SJohnny Huang printf("Reserved\n"); 8803cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 8813cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 882b458cd62SJohnny Huang printf("\n"); 8833cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 884b458cd62SJohnny Huang if (otp_value != 0) { 88573f11549SJohnny Huang for (j = 0; j < 7; j++) { 88673f11549SJohnny Huang if (otp_value == (1 << j)) { 88773f11549SJohnny Huang valid_bit[j * 2] = '1'; 888b458cd62SJohnny Huang } else { 88973f11549SJohnny Huang valid_bit[j * 2] = '0'; 89073f11549SJohnny Huang } 89173f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 89273f11549SJohnny Huang } 89373f11549SJohnny Huang valid_bit[15] = 0; 89473f11549SJohnny Huang } else { 89573f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 896b458cd62SJohnny Huang } 8973cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 898b458cd62SJohnny Huang printf("\n"); 899b458cd62SJohnny Huang } else { 9003cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 901b458cd62SJohnny Huang } 902b458cd62SJohnny Huang } 903b458cd62SJohnny Huang } 904b458cd62SJohnny Huang 905b458cd62SJohnny Huang if (fail) 906b458cd62SJohnny Huang return OTP_FAILURE; 907b458cd62SJohnny Huang 90866f2f8e5SJohnny Huang return OTP_SUCCESS; 90966f2f8e5SJohnny Huang } 91066f2f8e5SJohnny Huang 9112d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 91266f2f8e5SJohnny Huang { 9133cb28812SJohnny Huang struct otpconf_info *conf_info = info_cb.conf_info; 914b458cd62SJohnny Huang uint32_t OTPCFG[12]; 915b458cd62SJohnny Huang uint32_t mask; 916b458cd62SJohnny Huang uint32_t dw_offset; 917b458cd62SJohnny Huang uint32_t bit_offset; 918b458cd62SJohnny Huang uint32_t otp_value; 91973f11549SJohnny Huang char valid_bit[20]; 92066f2f8e5SJohnny Huang int i; 92173f11549SJohnny Huang int j; 92266f2f8e5SJohnny Huang 92366f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 92466f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 92566f2f8e5SJohnny Huang 92666f2f8e5SJohnny Huang 927b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 928b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9293cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9303cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9312d4b0742SJohnny Huang continue; 9323cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9333cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9343cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 935b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 936b458cd62SJohnny Huang 9373cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9383cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9393cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9403cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 941b458cd62SJohnny Huang continue; 942b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 943b458cd62SJohnny Huang 9443cb28812SJohnny Huang if (conf_info[i].length == 1) { 9453cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 946b458cd62SJohnny Huang } else { 947b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9483cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9493cb28812SJohnny Huang conf_info[i].bit_offset); 950b458cd62SJohnny Huang } 951b458cd62SJohnny Huang printf("0x%-10x", otp_value); 952b458cd62SJohnny Huang 9533cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 954b458cd62SJohnny Huang printf("Reserved\n"); 9553cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9563cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 957b458cd62SJohnny Huang printf("\n"); 9583cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 959b458cd62SJohnny Huang if (otp_value != 0) { 96073f11549SJohnny Huang for (j = 0; j < 7; j++) { 96173f11549SJohnny Huang if (otp_value == (1 << j)) { 96273f11549SJohnny Huang valid_bit[j * 2] = '1'; 963b458cd62SJohnny Huang } else { 96473f11549SJohnny Huang valid_bit[j * 2] = '0'; 96573f11549SJohnny Huang } 96673f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 96773f11549SJohnny Huang } 96873f11549SJohnny Huang valid_bit[15] = 0; 96973f11549SJohnny Huang } else { 97073f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 971b458cd62SJohnny Huang } 9723cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 973b458cd62SJohnny Huang printf("\n"); 974b458cd62SJohnny Huang } else { 9753cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 976b458cd62SJohnny Huang } 977b458cd62SJohnny Huang } 978b458cd62SJohnny Huang return OTP_SUCCESS; 97966f2f8e5SJohnny Huang } 98066f2f8e5SJohnny Huang 981b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 98276d13988SJohnny Huang { 9833cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 984a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 985a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 98676d13988SJohnny Huang int i; 987a8bd6d8cSJohnny Huang int fail = 0; 988a8bd6d8cSJohnny Huang uint32_t bit_offset; 989a8bd6d8cSJohnny Huang uint32_t dw_offset; 990a8bd6d8cSJohnny Huang uint32_t mask; 991a8bd6d8cSJohnny Huang uint32_t otp_value; 992a8bd6d8cSJohnny Huang uint32_t otp_protect; 993a8bd6d8cSJohnny Huang uint32_t otp_keep; 99476d13988SJohnny Huang 995a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 996a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 997b458cd62SJohnny Huang 9983cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 9993cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 1000a8bd6d8cSJohnny Huang dw_offset = 1; 10013cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1002a8bd6d8cSJohnny Huang } else { 1003a8bd6d8cSJohnny Huang dw_offset = 0; 10043cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1005a8bd6d8cSJohnny Huang } 100676d13988SJohnny Huang 10073cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1008a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1009a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1010a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1011a8bd6d8cSJohnny Huang 1012a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1013a8bd6d8cSJohnny Huang continue; 1014a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1015a8bd6d8cSJohnny Huang fail = 1; 1016a8bd6d8cSJohnny Huang } 1017a8bd6d8cSJohnny Huang 10183cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10193cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1020a8bd6d8cSJohnny Huang continue; 1021a8bd6d8cSJohnny Huang 10223cb28812SJohnny Huang if (strap_info[i].length == 1) { 10233cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1024a8bd6d8cSJohnny Huang } else { 1025b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10263cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10273cb28812SJohnny Huang strap_info[i].bit_offset); 1028a8bd6d8cSJohnny Huang } 1029a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1030a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1031a8bd6d8cSJohnny Huang 1032a8bd6d8cSJohnny Huang if (fail) { 1033a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1034a8bd6d8cSJohnny Huang } else { 10353cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10363cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1037a8bd6d8cSJohnny Huang else 1038a8bd6d8cSJohnny Huang printf("Reserved\n"); 1039a8bd6d8cSJohnny Huang } 1040a8bd6d8cSJohnny Huang } 1041a8bd6d8cSJohnny Huang 1042a8bd6d8cSJohnny Huang if (fail) 104376d13988SJohnny Huang return OTP_FAILURE; 104476d13988SJohnny Huang 104576d13988SJohnny Huang return OTP_SUCCESS; 104676d13988SJohnny Huang } 104776d13988SJohnny Huang 1048b458cd62SJohnny Huang static int otp_print_strap_info(int view) 104976d13988SJohnny Huang { 10503cb28812SJohnny Huang struct otpstrap_info *strap_info = info_cb.strap_info; 105176d13988SJohnny Huang struct otpstrap_status strap_status[64]; 105207baa4e8SJohnny Huang int i, j; 1053b458cd62SJohnny Huang int fail = 0; 1054b458cd62SJohnny Huang uint32_t bit_offset; 1055b458cd62SJohnny Huang uint32_t length; 1056b458cd62SJohnny Huang uint32_t otp_value; 1057b458cd62SJohnny Huang uint32_t otp_protect; 105876d13988SJohnny Huang 1059541eb887SJohnny Huang otp_strap_status(strap_status); 106076d13988SJohnny Huang 1061b458cd62SJohnny Huang if (view) { 106207baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 106307baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 106407baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 106507baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1066b458cd62SJohnny Huang } else { 1067b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1068b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 106976d13988SJohnny Huang } 10703cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1071b458cd62SJohnny Huang otp_value = 0; 10723cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 10733cb28812SJohnny Huang length = strap_info[i].length; 1074b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1075c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1076c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1077b458cd62SJohnny Huang } 10783cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10793cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1080b458cd62SJohnny Huang continue; 1081b458cd62SJohnny Huang if (view) { 1082b458cd62SJohnny Huang for (j = 0; j < length; j++) { 10833cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1084b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 108507baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1086b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 10873cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1088b458cd62SJohnny Huang printf(" Reserved\n"); 1089b458cd62SJohnny Huang continue; 1090b458cd62SJohnny Huang } 1091b458cd62SJohnny Huang if (length == 1) { 10923cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1093b458cd62SJohnny Huang continue; 109476d13988SJohnny Huang } 109576d13988SJohnny Huang 1096b458cd62SJohnny Huang if (j == 0) 10973cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1098b458cd62SJohnny Huang else if (j == length - 1) 1099b458cd62SJohnny Huang printf("\\ \"\n"); 1100b458cd62SJohnny Huang else 1101b458cd62SJohnny Huang printf("| \"\n"); 110276d13988SJohnny Huang } 1103b458cd62SJohnny Huang } else { 1104c947ef08SJohnny Huang if (length == 1) { 11053cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1106b458cd62SJohnny Huang } else { 1107b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1108b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1109b458cd62SJohnny Huang } 1110b458cd62SJohnny Huang 1111b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1112b458cd62SJohnny Huang 11133cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11143cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1115b458cd62SJohnny Huang else 1116b458cd62SJohnny Huang printf("Reserved\n"); 1117b458cd62SJohnny Huang } 1118b458cd62SJohnny Huang } 1119b458cd62SJohnny Huang 1120b458cd62SJohnny Huang if (fail) 1121b458cd62SJohnny Huang return OTP_FAILURE; 1122b458cd62SJohnny Huang 1123b458cd62SJohnny Huang return OTP_SUCCESS; 1124b458cd62SJohnny Huang } 1125b458cd62SJohnny Huang 112669d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 112769d5fd8fSJohnny Huang { 112869d5fd8fSJohnny Huang int i; 112969d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 113069d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 113169d5fd8fSJohnny Huang if (i % 16 == 0) { 113269d5fd8fSJohnny Huang printf("%04X: ", i); 113369d5fd8fSJohnny Huang } 113469d5fd8fSJohnny Huang printf("%02X ", buf[i]); 113569d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 113669d5fd8fSJohnny Huang printf("\n"); 113769d5fd8fSJohnny Huang } 113869d5fd8fSJohnny Huang } 113969d5fd8fSJohnny Huang } 114069d5fd8fSJohnny Huang 11417f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 114269d5fd8fSJohnny Huang { 114369d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 11449a4fe690SJohnny Huang struct otpkey_type *key_info_array = info_cb.key_info; 11459a4fe690SJohnny Huang struct otpkey_type key_info; 114669d5fd8fSJohnny Huang char *byte_buf; 114769d5fd8fSJohnny Huang int i = 0, len = 0; 11489a4fe690SJohnny Huang int j; 114969d5fd8fSJohnny Huang byte_buf = (char *)buf; 115069d5fd8fSJohnny Huang while (1) { 115169d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 115269d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 115369d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 115469d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 115569d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 115669d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 11579a4fe690SJohnny Huang 11589a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 11599a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 11609a4fe690SJohnny Huang key_info = key_info_array[j]; 11619a4fe690SJohnny Huang break; 11629a4fe690SJohnny Huang } 11639a4fe690SJohnny Huang } 11649a4fe690SJohnny Huang 11657f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 116669d5fd8fSJohnny Huang printf("Key Type: "); 11679a4fe690SJohnny Huang printf("%s\n", key_info.information); 11689a4fe690SJohnny Huang 11699a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 117069d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 117169d5fd8fSJohnny Huang switch (key_length) { 117269d5fd8fSJohnny Huang case 0: 117369d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 117469d5fd8fSJohnny Huang break; 117569d5fd8fSJohnny Huang case 1: 117669d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 117769d5fd8fSJohnny Huang break; 117869d5fd8fSJohnny Huang case 2: 117969d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 118069d5fd8fSJohnny Huang break; 118169d5fd8fSJohnny Huang case 3: 118269d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 118369d5fd8fSJohnny Huang break; 118469d5fd8fSJohnny Huang } 11859a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 118669d5fd8fSJohnny Huang printf("RSA SHA Type: "); 118769d5fd8fSJohnny Huang switch (key_length) { 118869d5fd8fSJohnny Huang case 0: 118969d5fd8fSJohnny Huang printf("RSA1024\n"); 119069d5fd8fSJohnny Huang len = 0x100; 119169d5fd8fSJohnny Huang break; 119269d5fd8fSJohnny Huang case 1: 119369d5fd8fSJohnny Huang printf("RSA2048\n"); 119469d5fd8fSJohnny Huang len = 0x200; 119569d5fd8fSJohnny Huang break; 119669d5fd8fSJohnny Huang case 2: 119769d5fd8fSJohnny Huang printf("RSA3072\n"); 119869d5fd8fSJohnny Huang len = 0x300; 119969d5fd8fSJohnny Huang break; 120069d5fd8fSJohnny Huang case 3: 120169d5fd8fSJohnny Huang printf("RSA4096\n"); 120269d5fd8fSJohnny Huang len = 0x400; 120369d5fd8fSJohnny Huang break; 120469d5fd8fSJohnny Huang } 120569d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 120669d5fd8fSJohnny Huang } 12079a4fe690SJohnny Huang if (key_info.need_id) 120869d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 120969d5fd8fSJohnny Huang printf("Key Value:\n"); 12109a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 121169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12129a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12139a4fe690SJohnny Huang printf("AES Key:\n"); 12149a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12159a4fe690SJohnny Huang if (info_cb.version == 0) { 12169a4fe690SJohnny Huang printf("AES IV:\n"); 12179a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12189a4fe690SJohnny Huang } 12199a4fe690SJohnny Huang 12209a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12219a4fe690SJohnny Huang if (info_cb.version == 0) { 122269d5fd8fSJohnny Huang printf("AES Key:\n"); 122369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 122469d5fd8fSJohnny Huang printf("AES IV:\n"); 122569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12269a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12279a4fe690SJohnny Huang printf("AES Key 1:\n"); 12289a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12299a4fe690SJohnny Huang printf("AES Key 2:\n"); 12309a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12319a4fe690SJohnny Huang } 123269d5fd8fSJohnny Huang 12339a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 123469d5fd8fSJohnny Huang printf("RSA mod:\n"); 123569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 123669d5fd8fSJohnny Huang printf("RSA exp:\n"); 123769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 123869d5fd8fSJohnny Huang } 123969d5fd8fSJohnny Huang if (last) 124069d5fd8fSJohnny Huang break; 124169d5fd8fSJohnny Huang i++; 124269d5fd8fSJohnny Huang } 124369d5fd8fSJohnny Huang return 0; 124469d5fd8fSJohnny Huang } 124569d5fd8fSJohnny Huang 1246a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 124769d5fd8fSJohnny Huang { 1248a6d0d645SJohnny Huang int i, k; 1249d90825e2SJohnny Huang int pass = 0; 1250d90825e2SJohnny Huang int soak = 0; 1251a6d0d645SJohnny Huang uint32_t prog_address; 1252a6d0d645SJohnny Huang uint32_t data[12]; 1253a6d0d645SJohnny Huang uint32_t compare[2]; 1254d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1255d90825e2SJohnny Huang uint32_t data_masked; 1256d90825e2SJohnny Huang uint32_t buf_masked; 125769d5fd8fSJohnny Huang 1258a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1259a6d0d645SJohnny Huang 1260a6d0d645SJohnny Huang printProgress(0, 12, ""); 1261a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1262a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 126369d5fd8fSJohnny Huang prog_address = 0x800; 1264a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1265a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1266a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1267a6d0d645SJohnny Huang } 1268a6d0d645SJohnny Huang 1269a6d0d645SJohnny Huang printf("Check writable...\n"); 1270a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1271d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1272d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1273d90825e2SJohnny Huang if (data_masked == buf_masked) 127469d5fd8fSJohnny Huang continue; 1275d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1276a6d0d645SJohnny Huang continue; 1277a6d0d645SJohnny Huang } else { 1278a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1279a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1280a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1281a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 12822a856b9aSJohnny Huang return OTP_FAILURE; 1283a6d0d645SJohnny Huang } 1284a6d0d645SJohnny Huang } 1285a6d0d645SJohnny Huang 1286a6d0d645SJohnny Huang printf("Start Programing...\n"); 1287a6d0d645SJohnny Huang printProgress(0, 12, ""); 1288d90825e2SJohnny Huang otp_soak(0); 1289a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1290d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1291d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1292a6d0d645SJohnny Huang prog_address = 0x800; 1293a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1294a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1295d90825e2SJohnny Huang if (data_masked == buf_masked) { 1296a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1297a6d0d645SJohnny Huang continue; 1298a6d0d645SJohnny Huang } 1299d90825e2SJohnny Huang if (soak) { 1300d90825e2SJohnny Huang soak = 0; 1301d90825e2SJohnny Huang otp_soak(0); 1302d90825e2SJohnny Huang } 1303a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1304a6d0d645SJohnny Huang 1305d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1306a6d0d645SJohnny Huang 130769d5fd8fSJohnny Huang pass = 0; 130869d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1309d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1310d90825e2SJohnny Huang if (soak == 0) { 1311d90825e2SJohnny Huang soak = 1; 1312d90825e2SJohnny Huang otp_soak(1); 1313d90825e2SJohnny Huang } 1314a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1315a6d0d645SJohnny Huang } else { 131669d5fd8fSJohnny Huang pass = 1; 131769d5fd8fSJohnny Huang break; 131869d5fd8fSJohnny Huang } 131969d5fd8fSJohnny Huang } 1320a6d0d645SJohnny Huang } 1321a6d0d645SJohnny Huang 132269d5fd8fSJohnny Huang if (!pass) 13232a856b9aSJohnny Huang return OTP_FAILURE; 1324a6d0d645SJohnny Huang 13252a856b9aSJohnny Huang return OTP_SUCCESS; 1326d90825e2SJohnny Huang 132769d5fd8fSJohnny Huang } 132869d5fd8fSJohnny Huang 132969d5fd8fSJohnny Huang 133076d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 133169d5fd8fSJohnny Huang { 133269d5fd8fSJohnny Huang int i; 133369d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 133469d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 133569d5fd8fSJohnny Huang int bit, pbit, kbit; 133669d5fd8fSJohnny Huang int fail = 0; 1337a6af4a17SJohnny Huang int skip = -1; 133866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 133969d5fd8fSJohnny Huang 1340541eb887SJohnny Huang otp_strap_status(otpstrap); 134169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 134269d5fd8fSJohnny Huang if (i < 32) { 134369d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 134469d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 134569d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 134669d5fd8fSJohnny Huang } else { 134769d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 134869d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 134969d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 135069d5fd8fSJohnny Huang } 135169d5fd8fSJohnny Huang 135269d5fd8fSJohnny Huang if (kbit == 1) { 135369d5fd8fSJohnny Huang continue; 135469d5fd8fSJohnny Huang } else { 1355a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 135669d5fd8fSJohnny Huang } 135769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 135869d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1359a6af4a17SJohnny Huang if (skip == -1) 1360a6af4a17SJohnny Huang skip = 1; 136169d5fd8fSJohnny Huang continue; 1362a6af4a17SJohnny Huang } else { 1363a6af4a17SJohnny Huang skip = 0; 136469d5fd8fSJohnny Huang } 136569d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 136669d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 136769d5fd8fSJohnny Huang fail = 1; 136869d5fd8fSJohnny Huang continue; 136969d5fd8fSJohnny Huang } 137069d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1371a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 137269d5fd8fSJohnny Huang fail = 1; 137369d5fd8fSJohnny Huang continue; 137469d5fd8fSJohnny Huang } 137569d5fd8fSJohnny Huang if (pbit == 1) { 137669d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 137769d5fd8fSJohnny Huang } 1378a6af4a17SJohnny 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); 137969d5fd8fSJohnny Huang } 138069d5fd8fSJohnny Huang if (fail == 1) 1381a6af4a17SJohnny Huang return OTP_FAILURE; 1382a6af4a17SJohnny Huang else if (skip == 1) 1383a6af4a17SJohnny Huang return OTP_PROG_SKIP; 13847e22f42dSJohnny Huang 13857e22f42dSJohnny Huang return 0; 138669d5fd8fSJohnny Huang } 138769d5fd8fSJohnny Huang 13882a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 138969d5fd8fSJohnny Huang { 139069d5fd8fSJohnny Huang int i, j; 139166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 139269d5fd8fSJohnny Huang 13932a856b9aSJohnny Huang if (start < 0 || start > 64) 13942a856b9aSJohnny Huang return OTP_USAGE; 13952a856b9aSJohnny Huang 13962a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 13972a856b9aSJohnny Huang return OTP_USAGE; 13982a856b9aSJohnny Huang 1399541eb887SJohnny Huang otp_strap_status(otpstrap); 140069d5fd8fSJohnny Huang 140107baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1402a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1403737ed20bSJohnny Huang 1404cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 140507baa4e8SJohnny Huang printf("0x%-8X", i); 1406737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1407737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1408737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1409737ed20bSJohnny Huang printf(" "); 141069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1411737ed20bSJohnny Huang printf("protected and not writable"); 141269d5fd8fSJohnny Huang } else { 1413737ed20bSJohnny Huang printf("not protected "); 141469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1415737ed20bSJohnny Huang printf("and no remaining times to write."); 141669d5fd8fSJohnny Huang } else { 1417737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 141869d5fd8fSJohnny Huang } 141969d5fd8fSJohnny Huang } 1420737ed20bSJohnny Huang printf("\n"); 142169d5fd8fSJohnny Huang } 14222a856b9aSJohnny Huang 14232a856b9aSJohnny Huang return OTP_SUCCESS; 142469d5fd8fSJohnny Huang } 142569d5fd8fSJohnny Huang 142669d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 142769d5fd8fSJohnny Huang { 142869d5fd8fSJohnny Huang int i, j; 142969d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 143069d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 143169d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 143269d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 143369d5fd8fSJohnny Huang int fail = 0; 14347e22f42dSJohnny Huang int pass = 0; 14357e22f42dSJohnny Huang int soak = 0; 143666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 143769d5fd8fSJohnny Huang 14387f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1439541eb887SJohnny Huang otp_strap_status(otpstrap); 144069d5fd8fSJohnny Huang 14417f795e57SJohnny Huang printf("Check writable...\n"); 14427f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 14437f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14447f795e57SJohnny Huang return OTP_FAILURE; 14457f795e57SJohnny Huang } 14467e22f42dSJohnny Huang 14477f795e57SJohnny Huang otp_soak(0); 144869d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 14494c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 145069d5fd8fSJohnny Huang prog_address = 0x800; 145169d5fd8fSJohnny Huang if (i < 32) { 145269d5fd8fSJohnny Huang offset = i; 145369d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 145469d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 145569d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 145669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 145769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 145869d5fd8fSJohnny Huang 145969d5fd8fSJohnny Huang } else { 146069d5fd8fSJohnny Huang offset = (i - 32); 146169d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 146269d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 146369d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 146469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 146569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 146669d5fd8fSJohnny Huang } 146769d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 146869d5fd8fSJohnny Huang 146969d5fd8fSJohnny Huang if (kbit == 1) { 147069d5fd8fSJohnny Huang continue; 147169d5fd8fSJohnny Huang } 147269d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 147369d5fd8fSJohnny Huang continue; 147469d5fd8fSJohnny Huang } 147569d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 147669d5fd8fSJohnny Huang fail = 1; 147769d5fd8fSJohnny Huang continue; 147869d5fd8fSJohnny Huang } 147969d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 148069d5fd8fSJohnny Huang fail = 1; 148169d5fd8fSJohnny Huang continue; 148269d5fd8fSJohnny Huang } 14837e22f42dSJohnny Huang 14847e22f42dSJohnny Huang if (soak) { 148569d5fd8fSJohnny Huang soak = 0; 14867e22f42dSJohnny Huang otp_soak(0); 14877e22f42dSJohnny Huang } 14887e22f42dSJohnny Huang 14897e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14907e22f42dSJohnny Huang 14917e22f42dSJohnny Huang pass = 0; 14927e22f42dSJohnny Huang 149369d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1494a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 149569d5fd8fSJohnny Huang pass = 1; 149669d5fd8fSJohnny Huang break; 149769d5fd8fSJohnny Huang } 14987e22f42dSJohnny Huang if (soak == 0) { 149969d5fd8fSJohnny Huang soak = 1; 15007e22f42dSJohnny Huang otp_soak(1); 15014b65a65dSJohnny Huang } 150269d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 150369d5fd8fSJohnny Huang } 150469d5fd8fSJohnny Huang if (!pass) 15052a856b9aSJohnny Huang return OTP_FAILURE; 150669d5fd8fSJohnny Huang 150769d5fd8fSJohnny Huang if (pbit == 0) 150869d5fd8fSJohnny Huang continue; 150969d5fd8fSJohnny Huang prog_address = 0x800; 151069d5fd8fSJohnny Huang if (i < 32) 151169d5fd8fSJohnny Huang prog_address |= 0x60c; 151269d5fd8fSJohnny Huang else 151369d5fd8fSJohnny Huang prog_address |= 0x60e; 151469d5fd8fSJohnny Huang 15157e22f42dSJohnny Huang 15167e22f42dSJohnny Huang if (soak) { 15177e22f42dSJohnny Huang soak = 0; 15187e22f42dSJohnny Huang otp_soak(0); 15197e22f42dSJohnny Huang } 15207e22f42dSJohnny Huang 15217e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15227e22f42dSJohnny Huang 15237e22f42dSJohnny Huang pass = 0; 15247e22f42dSJohnny Huang 152569d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 15267e22f42dSJohnny Huang 1527a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 152869d5fd8fSJohnny Huang pass = 1; 152969d5fd8fSJohnny Huang break; 153069d5fd8fSJohnny Huang } 15317e22f42dSJohnny Huang if (soak == 0) { 153269d5fd8fSJohnny Huang soak = 1; 15337e22f42dSJohnny Huang otp_soak(1); 153469d5fd8fSJohnny Huang } 153569d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 153669d5fd8fSJohnny Huang } 153769d5fd8fSJohnny Huang if (!pass) 15382a856b9aSJohnny Huang return OTP_FAILURE; 153969d5fd8fSJohnny Huang 154069d5fd8fSJohnny Huang } 154169d5fd8fSJohnny Huang if (fail == 1) 15422a856b9aSJohnny Huang return OTP_FAILURE; 154369d5fd8fSJohnny Huang else 15442a856b9aSJohnny Huang return OTP_SUCCESS; 154569d5fd8fSJohnny Huang 154669d5fd8fSJohnny Huang } 154769d5fd8fSJohnny Huang 1548cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1549cd1610b4SJohnny Huang { 1550cd1610b4SJohnny Huang int prog_bit; 1551cd1610b4SJohnny Huang 15527e22f42dSJohnny Huang otp_soak(soak); 15537e22f42dSJohnny Huang 1554cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1555cd1610b4SJohnny Huang if (value) 1556cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1557cd1610b4SJohnny Huang else 1558cd1610b4SJohnny Huang return; 1559cd1610b4SJohnny Huang } else { 1560cd1610b4SJohnny Huang prog_address |= 1 << 15; 1561cd1610b4SJohnny Huang if (!value) 1562cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1563cd1610b4SJohnny Huang else 1564cd1610b4SJohnny Huang return; 1565cd1610b4SJohnny Huang } 1566cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1567cd1610b4SJohnny Huang } 1568cd1610b4SJohnny Huang 1569d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 15704c1c9b35SJohnny Huang { 15714c1c9b35SJohnny Huang int i, k; 15724c1c9b35SJohnny Huang int pass; 1573d90825e2SJohnny Huang int soak = 0; 15744c1c9b35SJohnny Huang uint32_t prog_address; 1575d90825e2SJohnny Huang uint32_t data[2048]; 15764c1c9b35SJohnny Huang uint32_t compare[2]; 1577d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 15784c1c9b35SJohnny Huang 1579d90825e2SJohnny Huang uint32_t data0_masked; 1580d90825e2SJohnny Huang uint32_t data1_masked; 1581d90825e2SJohnny Huang uint32_t buf0_masked; 1582d90825e2SJohnny Huang uint32_t buf1_masked; 15834c1c9b35SJohnny Huang 15844c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 15854c1c9b35SJohnny Huang 1586d90825e2SJohnny Huang printProgress(0, 2048, ""); 1587d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1588d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1589d90825e2SJohnny Huang otp_read_data(i, &data[i]); 15904c1c9b35SJohnny Huang } 1591d90825e2SJohnny Huang 15924c1c9b35SJohnny Huang 15934c1c9b35SJohnny Huang printf("Check writable...\n"); 1594d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1595d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1596d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1597d90825e2SJohnny Huang if (data0_masked == buf0_masked) 15984c1c9b35SJohnny Huang continue; 1599d90825e2SJohnny Huang if (i % 2 == 0) { 1600d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 16014c1c9b35SJohnny Huang continue; 16024c1c9b35SJohnny Huang } else { 16034c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1604d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 16054c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1606d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16072a856b9aSJohnny Huang return OTP_FAILURE; 160869d5fd8fSJohnny Huang } 1609d90825e2SJohnny Huang } else { 1610d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1611d90825e2SJohnny Huang continue; 1612d90825e2SJohnny Huang } else { 1613d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1614d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1615d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1616d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16172a856b9aSJohnny Huang return OTP_FAILURE; 1618d90825e2SJohnny Huang } 1619d90825e2SJohnny Huang } 1620d90825e2SJohnny Huang } 162169d5fd8fSJohnny Huang 1622d90825e2SJohnny Huang printf("Start Programing...\n"); 1623d90825e2SJohnny Huang printProgress(0, 2048, ""); 1624d90825e2SJohnny Huang 1625d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1626d90825e2SJohnny Huang prog_address = i; 1627d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1628d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1629d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1630d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1631d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1632d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1633d90825e2SJohnny Huang continue; 1634d90825e2SJohnny Huang } 1635d90825e2SJohnny Huang if (soak) { 1636d90825e2SJohnny Huang soak = 0; 1637d90825e2SJohnny Huang otp_soak(0); 1638d90825e2SJohnny Huang } 1639d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1640d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1641d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1642d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1643d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1644d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1645d90825e2SJohnny Huang } else { 1646d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1647d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1648d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1649d90825e2SJohnny Huang } 1650d90825e2SJohnny Huang 1651d90825e2SJohnny Huang pass = 0; 1652d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1653d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1654d90825e2SJohnny Huang if (soak == 0) { 1655d90825e2SJohnny Huang soak = 1; 1656d90825e2SJohnny Huang otp_soak(1); 1657d90825e2SJohnny Huang } 1658d90825e2SJohnny Huang if (compare[0] != 0) { 1659d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1660d90825e2SJohnny Huang } 1661d90825e2SJohnny Huang if (compare[1] != ~0) { 1662d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1663d90825e2SJohnny Huang } 1664d90825e2SJohnny Huang } else { 1665d90825e2SJohnny Huang pass = 1; 1666d90825e2SJohnny Huang break; 1667d90825e2SJohnny Huang } 1668d90825e2SJohnny Huang } 1669d90825e2SJohnny Huang 1670d90825e2SJohnny Huang if (!pass) 16712a856b9aSJohnny Huang return OTP_FAILURE; 1672d90825e2SJohnny Huang } 16732a856b9aSJohnny Huang return OTP_SUCCESS; 1674d90825e2SJohnny Huang 1675d90825e2SJohnny Huang } 1676d90825e2SJohnny Huang 1677d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 167869d5fd8fSJohnny Huang { 167969d5fd8fSJohnny Huang int ret; 16807332532cSJohnny Huang int mode = 0; 16819a4fe690SJohnny Huang int image_version = 0; 168269d5fd8fSJohnny Huang uint32_t *buf; 1683d90825e2SJohnny Huang uint32_t *data_region = NULL; 1684d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1685d90825e2SJohnny Huang uint32_t *strap_region = NULL; 168669d5fd8fSJohnny Huang 1687d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 168869d5fd8fSJohnny Huang if (!buf) { 168969d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16902a856b9aSJohnny Huang return OTP_FAILURE; 169169d5fd8fSJohnny Huang } 1692d90825e2SJohnny Huang 16939a4fe690SJohnny Huang image_version = buf[0] & 0x3; 16949a4fe690SJohnny Huang if (image_version != info_cb.version) { 16959a4fe690SJohnny Huang puts("Version is not match\n"); 16969a4fe690SJohnny Huang return OTP_FAILURE; 16979a4fe690SJohnny Huang } 16989a4fe690SJohnny Huang 1699d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 17007332532cSJohnny Huang mode |= OTP_REGION_DATA; 17017332532cSJohnny Huang data_region = &buf[36]; 1702d90825e2SJohnny Huang } 1703d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 17047332532cSJohnny Huang mode |= OTP_REGION_CONF; 17057332532cSJohnny Huang conf_region = &buf[12]; 1706d90825e2SJohnny Huang } 1707d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 17087332532cSJohnny Huang mode |= OTP_REGION_STRAP; 17097332532cSJohnny Huang strap_region = &buf[4]; 1710d90825e2SJohnny Huang } 17117332532cSJohnny Huang 171269d5fd8fSJohnny Huang if (!nconfirm) { 17137332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17147f795e57SJohnny Huang printf("\nOTP data region :\n"); 17157f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 171669d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17172a856b9aSJohnny Huang return OTP_FAILURE; 171869d5fd8fSJohnny Huang } 171969d5fd8fSJohnny Huang } 17207332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17217332532cSJohnny Huang printf("\nOTP strap region :\n"); 17227332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17237332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17247332532cSJohnny Huang return OTP_FAILURE; 17257332532cSJohnny Huang } 17267332532cSJohnny Huang } 17277332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17287332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17297332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17307332532cSJohnny Huang printf("OTP config error, please check.\n"); 17317332532cSJohnny Huang return OTP_FAILURE; 17327332532cSJohnny Huang } 17337332532cSJohnny Huang } 17347332532cSJohnny Huang 173569d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 173669d5fd8fSJohnny Huang if (!confirm_yesno()) { 173769d5fd8fSJohnny Huang printf(" Aborting\n"); 17382a856b9aSJohnny Huang return OTP_FAILURE; 173969d5fd8fSJohnny Huang } 174069d5fd8fSJohnny Huang } 17417332532cSJohnny Huang 17427332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17437332532cSJohnny Huang printf("programing data region ...\n"); 1744d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17452a856b9aSJohnny Huang if (ret != 0) { 174669d5fd8fSJohnny Huang printf("Error\n"); 174769d5fd8fSJohnny Huang return ret; 174869d5fd8fSJohnny Huang } else { 174969d5fd8fSJohnny Huang printf("Done\n"); 175069d5fd8fSJohnny Huang } 17517332532cSJohnny Huang } 17527332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17537332532cSJohnny Huang printf("programing strap region ...\n"); 1754d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17552a856b9aSJohnny Huang if (ret != 0) { 175669d5fd8fSJohnny Huang printf("Error\n"); 175769d5fd8fSJohnny Huang return ret; 175869d5fd8fSJohnny Huang } else { 175969d5fd8fSJohnny Huang printf("Done\n"); 176069d5fd8fSJohnny Huang } 17617332532cSJohnny Huang } 17627332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17637332532cSJohnny Huang printf("programing configuration region ...\n"); 1764d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17652a856b9aSJohnny Huang if (ret != 0) { 176669d5fd8fSJohnny Huang printf("Error\n"); 176769d5fd8fSJohnny Huang return ret; 176869d5fd8fSJohnny Huang } 176969d5fd8fSJohnny Huang printf("Done\n"); 177069d5fd8fSJohnny Huang } 1771cd1610b4SJohnny Huang 17727332532cSJohnny Huang return OTP_SUCCESS; 17732a856b9aSJohnny Huang } 17742a856b9aSJohnny Huang 17752a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1776cd1610b4SJohnny Huang { 1777a6af4a17SJohnny Huang uint32_t read[2]; 1778cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1779d90825e2SJohnny Huang uint32_t prog_address = 0; 178066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1781cd1610b4SJohnny Huang int otp_bit; 1782cd1610b4SJohnny Huang int i; 1783cd1610b4SJohnny Huang int pass; 1784a6af4a17SJohnny Huang int ret; 1785cd1610b4SJohnny Huang 1786cd1610b4SJohnny Huang switch (mode) { 1787a6d0d645SJohnny Huang case OTP_REGION_CONF: 1788a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1789cd1610b4SJohnny Huang prog_address = 0x800; 1790cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1791cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1792a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1793cd1610b4SJohnny Huang if (otp_bit == value) { 1794a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1795cd1610b4SJohnny Huang printf("No need to program\n"); 17962a856b9aSJohnny Huang return OTP_SUCCESS; 1797cd1610b4SJohnny Huang } 1798cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1799a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1800cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 18012a856b9aSJohnny Huang return OTP_FAILURE; 1802cd1610b4SJohnny Huang } 1803a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1804cd1610b4SJohnny Huang break; 1805a6d0d645SJohnny Huang case OTP_REGION_DATA: 1806cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1807cd1610b4SJohnny Huang 1808cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1809a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1810a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1811643b9cfdSJohnny Huang 1812643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1813643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1814643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1815643b9cfdSJohnny Huang return OTP_FAILURE; 1816643b9cfdSJohnny Huang } 1817cd1610b4SJohnny Huang } else { 1818a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1819a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1820643b9cfdSJohnny Huang 1821643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1822643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1823643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1824643b9cfdSJohnny Huang return OTP_FAILURE; 1825643b9cfdSJohnny Huang } 1826cd1610b4SJohnny Huang } 1827cd1610b4SJohnny Huang if (otp_bit == value) { 1828a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1829cd1610b4SJohnny Huang printf("No need to program\n"); 18302a856b9aSJohnny Huang return OTP_SUCCESS; 1831cd1610b4SJohnny Huang } 1832643b9cfdSJohnny Huang 1833a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1834cd1610b4SJohnny Huang break; 1835a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1836541eb887SJohnny Huang otp_strap_status(otpstrap); 1837cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1838cd1610b4SJohnny Huang if (bit_offset < 32) { 1839cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1840cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1841cd1610b4SJohnny Huang strap_buf[3] = ~0; 1842cd1610b4SJohnny Huang strap_buf[5] = 0; 18432a856b9aSJohnny Huang // if (protect) 18442a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 18452a856b9aSJohnny Huang // else 18462a856b9aSJohnny Huang // strap_buf[4] = 0; 1847cd1610b4SJohnny Huang } else { 1848cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1849cd1610b4SJohnny Huang strap_buf[2] = ~0; 1850cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1851cd1610b4SJohnny Huang strap_buf[4] = 0; 18522a856b9aSJohnny Huang // if (protect) 18532a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 18542a856b9aSJohnny Huang // else 18552a856b9aSJohnny Huang // strap_buf[5] = 0; 1856cd1610b4SJohnny Huang } 185776d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1858a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18592a856b9aSJohnny Huang return OTP_FAILURE; 1860a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1861a6af4a17SJohnny Huang return OTP_SUCCESS; 1862a6af4a17SJohnny Huang 1863cd1610b4SJohnny Huang break; 1864cd1610b4SJohnny Huang } 1865cd1610b4SJohnny Huang 1866cd1610b4SJohnny Huang if (!nconfirm) { 1867cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1868cd1610b4SJohnny Huang if (!confirm_yesno()) { 1869cd1610b4SJohnny Huang printf(" Aborting\n"); 18702a856b9aSJohnny Huang return OTP_FAILURE; 1871cd1610b4SJohnny Huang } 1872cd1610b4SJohnny Huang } 1873cd1610b4SJohnny Huang 1874cd1610b4SJohnny Huang switch (mode) { 1875a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1876cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1877a6d0d645SJohnny Huang case OTP_REGION_CONF: 1878a6d0d645SJohnny Huang case OTP_REGION_DATA: 1879cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1880cd1610b4SJohnny Huang pass = -1; 1881cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1882a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1883cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1884cd1610b4SJohnny Huang } else { 1885cd1610b4SJohnny Huang pass = 0; 1886cd1610b4SJohnny Huang break; 1887cd1610b4SJohnny Huang } 1888cd1610b4SJohnny Huang } 18899009c25dSJohnny Huang if (pass == 0) { 18909009c25dSJohnny Huang printf("SUCCESS\n"); 18912a856b9aSJohnny Huang return OTP_SUCCESS; 18929009c25dSJohnny Huang } else { 18939009c25dSJohnny Huang printf("OTP cannot be programed\n"); 18949009c25dSJohnny Huang printf("FAILED\n"); 18959009c25dSJohnny Huang return OTP_FAILURE; 18969009c25dSJohnny Huang } 1897cd1610b4SJohnny Huang } 1898cd1610b4SJohnny Huang 18992a856b9aSJohnny Huang return OTP_USAGE; 1900cd1610b4SJohnny Huang } 1901cd1610b4SJohnny Huang 19022a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 190369d5fd8fSJohnny Huang { 19042a856b9aSJohnny Huang uint32_t offset, count; 19052a856b9aSJohnny Huang int ret; 190669d5fd8fSJohnny Huang 19072a856b9aSJohnny Huang if (argc == 4) { 19082a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19092a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19102a856b9aSJohnny Huang } else if (argc == 3) { 19112a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19122a856b9aSJohnny Huang count = 1; 19132a856b9aSJohnny Huang } else { 191469d5fd8fSJohnny Huang return CMD_RET_USAGE; 191569d5fd8fSJohnny Huang } 191669d5fd8fSJohnny Huang 191769d5fd8fSJohnny Huang 19182a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 1919*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19202a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19212a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 1922*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19232a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19242a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 1925*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19262a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19272a856b9aSJohnny Huang } else { 19282a856b9aSJohnny Huang return CMD_RET_USAGE; 192969d5fd8fSJohnny Huang } 193069d5fd8fSJohnny Huang 19312a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19322a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19332a856b9aSJohnny Huang else 19342a856b9aSJohnny Huang return CMD_RET_USAGE; 19352a856b9aSJohnny Huang 19362a856b9aSJohnny Huang } 19372a856b9aSJohnny Huang 19382a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19392a856b9aSJohnny Huang { 19402a856b9aSJohnny Huang phys_addr_t addr; 19412a856b9aSJohnny Huang uint32_t byte_size; 19422a856b9aSJohnny Huang int ret; 19432a856b9aSJohnny Huang 19442a856b9aSJohnny Huang if (argc == 4) { 1945ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19462a856b9aSJohnny Huang return CMD_RET_USAGE; 19472a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19482a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 1949*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19502a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19512a856b9aSJohnny Huang } else if (argc == 3) { 19522a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19532a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 1954*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19552a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19562a856b9aSJohnny Huang } else { 19572a856b9aSJohnny Huang return CMD_RET_USAGE; 19582a856b9aSJohnny Huang } 19592a856b9aSJohnny Huang 19602a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19612a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19622a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19632a856b9aSJohnny Huang return CMD_RET_FAILURE; 19642a856b9aSJohnny Huang else 19652a856b9aSJohnny Huang return CMD_RET_USAGE; 19662a856b9aSJohnny Huang } 19672a856b9aSJohnny Huang 19682a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19692a856b9aSJohnny Huang { 19702a856b9aSJohnny Huang int mode = 0; 19712a856b9aSJohnny Huang int nconfirm = 0; 19722a856b9aSJohnny Huang int otp_addr = 0; 19732a856b9aSJohnny Huang int bit_offset; 19742a856b9aSJohnny Huang int value; 19752a856b9aSJohnny Huang int ret; 19762a856b9aSJohnny Huang 19772a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19782a856b9aSJohnny Huang return CMD_RET_USAGE; 19792a856b9aSJohnny Huang 19802a856b9aSJohnny Huang /* Drop the pb cmd */ 19812a856b9aSJohnny Huang argc--; 19822a856b9aSJohnny Huang argv++; 19832a856b9aSJohnny Huang 19842a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1985a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 19862a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1987a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 19882a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1989a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1990cd1610b4SJohnny Huang else 19912a856b9aSJohnny Huang return CMD_RET_USAGE; 19922a856b9aSJohnny Huang 19932a856b9aSJohnny Huang /* Drop the region cmd */ 19942a856b9aSJohnny Huang argc--; 19952a856b9aSJohnny Huang argv++; 19962a856b9aSJohnny Huang 1997ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 1998cd1610b4SJohnny Huang nconfirm = 1; 19992a856b9aSJohnny Huang /* Drop the force option */ 20002a856b9aSJohnny Huang argc--; 20012a856b9aSJohnny Huang argv++; 20022a856b9aSJohnny Huang } 2003cd1610b4SJohnny Huang 2004a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20052a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20062a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20070808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20082a856b9aSJohnny Huang return CMD_RET_USAGE; 2009cd1610b4SJohnny Huang } else { 20102a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20112a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20122a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20130808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20142a856b9aSJohnny Huang return CMD_RET_USAGE; 20150808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 20160808cc55SJohnny Huang if (otp_addr >= 200) 20170808cc55SJohnny Huang return CMD_RET_USAGE; 20180808cc55SJohnny Huang } else { 20190808cc55SJohnny Huang if (otp_addr >= 32) 20200808cc55SJohnny Huang return CMD_RET_USAGE; 20210808cc55SJohnny Huang } 2022cd1610b4SJohnny Huang } 2023cd1610b4SJohnny Huang if (value != 0 && value != 1) 20242a856b9aSJohnny Huang return CMD_RET_USAGE; 2025cd1610b4SJohnny Huang 2026*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20272a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20282a856b9aSJohnny Huang 20292a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20302a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20312a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20322a856b9aSJohnny Huang return CMD_RET_FAILURE; 20332a856b9aSJohnny Huang else 20342a856b9aSJohnny Huang return CMD_RET_USAGE; 20352a856b9aSJohnny Huang } 20362a856b9aSJohnny Huang 20372a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20382a856b9aSJohnny Huang { 20392a856b9aSJohnny Huang phys_addr_t addr; 20402a856b9aSJohnny Huang int otp_addr = 0; 20412a856b9aSJohnny Huang 20422a856b9aSJohnny Huang if (argc != 3) 20432a856b9aSJohnny Huang return CMD_RET_USAGE; 20442a856b9aSJohnny Huang 2045*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20462a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20472a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20482a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 204969d5fd8fSJohnny Huang printf("Compare pass\n"); 20502a856b9aSJohnny Huang return CMD_RET_SUCCESS; 205169d5fd8fSJohnny Huang } else { 205269d5fd8fSJohnny Huang printf("Compare fail\n"); 20532a856b9aSJohnny Huang return CMD_RET_FAILURE; 205469d5fd8fSJohnny Huang } 205569d5fd8fSJohnny Huang } 205669d5fd8fSJohnny Huang 205766f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 205866f2f8e5SJohnny Huang { 2059a8bd6d8cSJohnny Huang int view = 0; 20602d4b0742SJohnny Huang int input; 2061a8bd6d8cSJohnny Huang 2062a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 206366f2f8e5SJohnny Huang return CMD_RET_USAGE; 206466f2f8e5SJohnny Huang 20652d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 206666f2f8e5SJohnny Huang 2067*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20682d4b0742SJohnny Huang if (argc == 3) { 20692d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20702d4b0742SJohnny Huang otp_print_conf_info(input); 20712d4b0742SJohnny Huang } else { 20722d4b0742SJohnny Huang otp_print_conf_info(-1); 20732d4b0742SJohnny Huang } 20742d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20752d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2076a8bd6d8cSJohnny Huang view = 1; 2077a8bd6d8cSJohnny Huang /* Drop the view option */ 2078a8bd6d8cSJohnny Huang argc--; 2079a8bd6d8cSJohnny Huang argv++; 2080a8bd6d8cSJohnny Huang } 2081*3d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2082b458cd62SJohnny Huang otp_print_strap_info(view); 208366f2f8e5SJohnny Huang } else { 208466f2f8e5SJohnny Huang return CMD_RET_USAGE; 208566f2f8e5SJohnny Huang } 20862d4b0742SJohnny Huang 208766f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 208866f2f8e5SJohnny Huang } 208966f2f8e5SJohnny Huang 2090737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2091737ed20bSJohnny Huang { 2092737ed20bSJohnny Huang int input; 2093737ed20bSJohnny Huang int bit_offset; 2094737ed20bSJohnny Huang int prog_address; 2095737ed20bSJohnny Huang int pass; 2096737ed20bSJohnny Huang int i; 2097737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2098737ed20bSJohnny Huang return CMD_RET_USAGE; 2099737ed20bSJohnny Huang 2100ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2101737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2102737ed20bSJohnny Huang } else { 2103737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2104737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2105737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2106737ed20bSJohnny Huang if (!confirm_yesno()) { 2107737ed20bSJohnny Huang printf(" Aborting\n"); 2108737ed20bSJohnny Huang return CMD_RET_FAILURE; 2109737ed20bSJohnny Huang } 2110737ed20bSJohnny Huang } 2111737ed20bSJohnny Huang 2112737ed20bSJohnny Huang prog_address = 0x800; 2113737ed20bSJohnny Huang if (input < 32) { 2114737ed20bSJohnny Huang bit_offset = input; 2115737ed20bSJohnny Huang prog_address |= 0x60c; 2116737ed20bSJohnny Huang } else if (input < 64) { 2117737ed20bSJohnny Huang bit_offset = input - 32; 2118737ed20bSJohnny Huang prog_address |= 0x60e; 2119737ed20bSJohnny Huang } else { 2120737ed20bSJohnny Huang return CMD_RET_USAGE; 2121737ed20bSJohnny Huang } 2122737ed20bSJohnny Huang 2123737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2124737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2125737ed20bSJohnny Huang } 2126737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 2127737ed20bSJohnny Huang pass = -1; 2128737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2129737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2130737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 2131737ed20bSJohnny Huang } else { 2132737ed20bSJohnny Huang pass = 0; 2133737ed20bSJohnny Huang break; 2134737ed20bSJohnny Huang } 2135737ed20bSJohnny Huang } 2136737ed20bSJohnny Huang if (pass == 0) { 2137737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2138737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2139737ed20bSJohnny Huang } 2140737ed20bSJohnny Huang 2141737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2142737ed20bSJohnny Huang return CMD_RET_FAILURE; 2143737ed20bSJohnny Huang 2144737ed20bSJohnny Huang } 21459a4fe690SJohnny Huang 21462a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21472a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2148a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21492a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21502a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2151737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21522a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21532a856b9aSJohnny Huang }; 21542a856b9aSJohnny Huang 21552a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21562a856b9aSJohnny Huang { 21572a856b9aSJohnny Huang cmd_tbl_t *cp; 21582a856b9aSJohnny Huang 21592a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21602a856b9aSJohnny Huang 2161737ed20bSJohnny Huang /* Drop the otp command */ 21622a856b9aSJohnny Huang argc--; 21632a856b9aSJohnny Huang argv++; 21642a856b9aSJohnny Huang 21652a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 21662a856b9aSJohnny Huang return CMD_RET_USAGE; 21672a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 21682a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21692a856b9aSJohnny Huang 21709a4fe690SJohnny Huang if (chip_version() == 0) { 21719a4fe690SJohnny Huang info_cb.version = 0; 21729a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 21739a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 21749a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 21759a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 21769a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 21779a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 21789a4fe690SJohnny Huang } else if (chip_version() == 1) { 21799a4fe690SJohnny Huang info_cb.version = 1; 21803cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 21813cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 21823cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 21833cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 21849a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 21859a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 21869a4fe690SJohnny Huang } 21879a4fe690SJohnny Huang 21882a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 218969d5fd8fSJohnny Huang } 219069d5fd8fSJohnny Huang 219169d5fd8fSJohnny Huang U_BOOT_CMD( 219269d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 219369d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 21942a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 21952a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 21962d4b0742SJohnny Huang "otp info strap [v]\n" 21972d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2198ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2199ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2200ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2201ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 22022a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 220369d5fd8fSJohnny Huang ); 2204