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> 23*696656c6SJohnny Huang #include <u-boot/sha256.h> 2469d5fd8fSJohnny Huang 2569d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2669d5fd8fSJohnny Huang 2769d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2869d5fd8fSJohnny Huang #define RETRY 3 297332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 307332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 317332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3269d5fd8fSJohnny Huang 332a856b9aSJohnny Huang #define OTP_USAGE -1 342a856b9aSJohnny Huang #define OTP_FAILURE -2 352a856b9aSJohnny Huang #define OTP_SUCCESS 0 362a856b9aSJohnny Huang 37a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 38a6af4a17SJohnny Huang 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 429a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 439a4fe690SJohnny Huang 449a4fe690SJohnny Huang 45a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 46b458cd62SJohnny Huang #define OTP_REG_VALUE -2 47b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4876d13988SJohnny Huang 494c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 504c1c9b35SJohnny Huang #define PBWIDTH 60 514c1c9b35SJohnny Huang 523d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 533d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 543d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 553d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 563d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 573d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 583d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 593d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 603d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 613d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 623d3688adSJohnny Huang 63*696656c6SJohnny Huang #define OTP_MAGIC "SOCOTP" 64*696656c6SJohnny Huang #define CHECKSUM_LEN 32 65*696656c6SJohnny Huang #define OTP_INC_DATA (1 << 31) 66*696656c6SJohnny Huang #define OTP_INC_CONFIG (1 << 30) 67*696656c6SJohnny Huang #define OTP_INC_STRAP (1 << 29) 68*696656c6SJohnny Huang #define OTP_ECC_EN (1 << 28) 69*696656c6SJohnny Huang #define OTP_REGION_SIZE(info) ((info >> 16) & 0xffff) 70*696656c6SJohnny Huang #define OTP_REGION_OFFSET(info) (info & 0xffff) 71*696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info) (info & 0xffff) 72*696656c6SJohnny Huang 73*696656c6SJohnny Huang #define OTP_AST2600A0 0 74*696656c6SJohnny Huang #define OTP_AST2600A1 1 75*696656c6SJohnny Huang 76*696656c6SJohnny Huang struct otp_header { 77*696656c6SJohnny Huang u8 otp_magic[8]; 78*696656c6SJohnny Huang u8 otp_version[8]; 79*696656c6SJohnny Huang u32 image_info; 80*696656c6SJohnny Huang u32 data_info; 81*696656c6SJohnny Huang u32 config_info; 82*696656c6SJohnny Huang u32 strap_info; 83*696656c6SJohnny Huang u32 checksum_offset; 84*696656c6SJohnny Huang } __attribute__((packed)); 85*696656c6SJohnny Huang 8666f2f8e5SJohnny Huang struct otpstrap_status { 8769d5fd8fSJohnny Huang int value; 8869d5fd8fSJohnny Huang int option_array[7]; 8969d5fd8fSJohnny Huang int remain_times; 9069d5fd8fSJohnny Huang int writeable_option; 9169d5fd8fSJohnny Huang int protected; 9269d5fd8fSJohnny Huang }; 9369d5fd8fSJohnny Huang 9466f2f8e5SJohnny Huang struct otpconf_parse { 9566f2f8e5SJohnny Huang int dw_offset; 9666f2f8e5SJohnny Huang int bit; 9766f2f8e5SJohnny Huang int length; 9866f2f8e5SJohnny Huang int value; 99*696656c6SJohnny Huang int ignore; 10066f2f8e5SJohnny Huang char status[80]; 10166f2f8e5SJohnny Huang }; 10266f2f8e5SJohnny Huang 103a8bd6d8cSJohnny Huang struct otpstrap_info { 10479e42a59SJoel Stanley int8_t bit_offset; 10579e42a59SJoel Stanley int8_t length; 10679e42a59SJoel Stanley int8_t value; 10779e42a59SJoel Stanley char *information; 108a8bd6d8cSJohnny Huang }; 109a8bd6d8cSJohnny Huang 110a8bd6d8cSJohnny Huang struct otpconf_info { 11179e42a59SJoel Stanley int8_t dw_offset; 11279e42a59SJoel Stanley int8_t bit_offset; 11379e42a59SJoel Stanley int8_t length; 11479e42a59SJoel Stanley int8_t value; 11579e42a59SJoel Stanley char *information; 116a8bd6d8cSJohnny Huang }; 117a8bd6d8cSJohnny Huang 1189a4fe690SJohnny Huang struct otpkey_type { 1199a4fe690SJohnny Huang int value; 1209a4fe690SJohnny Huang int key_type; 1219a4fe690SJohnny Huang int need_id; 1229a4fe690SJohnny Huang char information[110]; 1239a4fe690SJohnny Huang }; 1249a4fe690SJohnny Huang 1259a4fe690SJohnny Huang struct otp_info_cb { 1269a4fe690SJohnny Huang int version; 12779e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1289a4fe690SJohnny Huang int strap_info_len; 12979e42a59SJoel Stanley const struct otpconf_info *conf_info; 1309a4fe690SJohnny Huang int conf_info_len; 13179e42a59SJoel Stanley const struct otpkey_type *key_info; 1329a4fe690SJohnny Huang int key_info_len; 1339a4fe690SJohnny Huang }; 1349a4fe690SJohnny Huang 135*696656c6SJohnny Huang struct otp_image_layout { 136*696656c6SJohnny Huang uint8_t *data; 137*696656c6SJohnny Huang uint8_t *data_ignore; 138*696656c6SJohnny Huang uint8_t *conf; 139*696656c6SJohnny Huang uint8_t *conf_ignore; 140*696656c6SJohnny Huang uint8_t *strap; 141*696656c6SJohnny Huang uint8_t *strap_reg_pro; 142*696656c6SJohnny Huang uint8_t *strap_pro; 143*696656c6SJohnny Huang uint8_t *strap_ignore; 144*696656c6SJohnny Huang }; 145*696656c6SJohnny Huang 1469a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1479a4fe690SJohnny Huang 14879e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = { 14991448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 15091448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 15191448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 15291448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 15391448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 15491448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 15591448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 15691448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 157541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 15891448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 15991448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 16091448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 16191448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 16291448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 16391448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 16491448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 16591448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 16691448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 16791448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 16891448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 16991448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 17091448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 17191448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 17291448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 17391448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 17491448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 17591448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 17691448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 17791448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 17891448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 17991448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 18091448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 18191448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 18291448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 18391448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 18491448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 18591448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 18691448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 18791448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 18891448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 18991448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 19091448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 19191448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 19291448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 19391448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 19491448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 19591448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 19691448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 19791448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 19891448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 19991448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 20091448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 20191448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 20291448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 20391448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 20491448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 20591448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 20691448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 20791448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 20891448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 20991448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 21091448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 21191448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 21291448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 21391448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 21491448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 21591448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 21691448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 21791448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 21891448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 21991448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 22091448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 22191448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 22291448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 22391448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 22491448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 22591448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 22691448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 22791448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 22891448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 22991448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 23091448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 23191448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 23291448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 23391448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 23491448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 23591448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 23691448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 23791448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 23891448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 23991448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 24091448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 24191448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 24291448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 24391448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 24491448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 24591448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 24691448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 24791448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 24891448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 24991448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 25091448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 25191448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 25291448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 25391448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 25491448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 25591448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 25691448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 25791448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 25876d13988SJohnny Huang }; 2599a4fe690SJohnny Huang 26079e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = { 2613cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2623cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2633cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2643cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2653cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2663cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2673cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2683cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2693cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2703cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2713cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2723cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2733cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2743cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2753cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2763cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2773cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2783cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2793cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2803cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2813cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2823cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2833cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2843cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2853cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2863cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2873cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2883cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2893cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2903cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2913cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2923cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2933cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2943cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2953cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2963cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2973cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2983cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2993cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 3003cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 3013cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 3023cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 3033cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 3043cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 3053cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 3063cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 3073cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 3083cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 3093cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 3103cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 3113cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 3123cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 3133cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 3143cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 3153cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 3163cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 3173cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 3183cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 3193cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 3203cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 3213cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 3223cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 3233cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 3243cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 3253cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 3263cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 3273cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 3283cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 3293cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 3303cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 3313cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 3323cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 3333cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 3343cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3353cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3363cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3373cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3383cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3393cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3403cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3413cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3423cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3433cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3443cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3453cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3463cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3473cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3483cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3493cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3503cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3513cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3523cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3533cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3543cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3553cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3563cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3573cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3583cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3593cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3603cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3613cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3623cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3633cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3643cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3653cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3663cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3673cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3683cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3693cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3703cb28812SJohnny Huang }; 3713cb28812SJohnny Huang 37279e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = { 37391448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 37491448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 37591448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 37691448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 37791448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 37891448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 37991448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 38091448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 38191448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 38291448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 38391448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 38491448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 38591448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 38691448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 38791448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 38891448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 38991448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 390541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 39191448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 39291448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 39391448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 39491448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 39591448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 39691448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 39791448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 39891448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 39991448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 40091448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 40191448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 40291448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 40391448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 40491448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 40591448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 40691448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 40791448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 40891448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 40991448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 41091448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 41191448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 41291448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 41391448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 41491448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 41591448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 41691448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4173cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4183cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4193cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4203cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 4213cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 4223cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 4233cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 4243cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 4253cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 4263cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 4273cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 4283cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 4293cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 4303cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 4313cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 4323cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 4333cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 4343cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4353cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4363cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4373cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4383cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4393cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4403cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4413cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4423cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4433cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4443cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4453cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4463cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4473cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4483cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4493cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4503cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4513cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4523cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4533cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4543cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4553cb28812SJohnny Huang }; 4563cb28812SJohnny Huang 45779e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = { 4583cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4593cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4603cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4613cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4623cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4633cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4643cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4653cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4663cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4673cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4683cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4693cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4703cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4713cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4723cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4733cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4743cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4753cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4763cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4773cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4783cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4793cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4803cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4813cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4823cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4833cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 484bb34a7bfSJohnny Huang { 0, 14, 1, 0, "Disable Patch code" }, 485bb34a7bfSJohnny Huang { 0, 14, 1, 1, "Enable Patch code" }, 486bb34a7bfSJohnny Huang { 0, 15, 1, OTP_REG_RESERVED, "" }, 4873cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4883cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4893cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4903cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4913cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4923cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4933cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4943cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4953cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4963cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4973cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4983cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4993cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 5003cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 5013cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 5023cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 5033cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 5043cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 5053cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 5063cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 50791448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 50891448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 50991448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 51073f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 51173f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 51291448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 51391448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 51491448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 51591448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 51691448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 51791448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 51891448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 51991448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 52091448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 52191448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 52291448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 52391448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 52491448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 52591448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 52691448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 52791448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 52891448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 52991448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 53091448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 53191448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 53291448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 53391448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 53491448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 53591448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 53691448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 53791448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 53891448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 53991448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 540bb34a7bfSJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }, 541bb34a7bfSJohnny Huang { 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" }, 542bb34a7bfSJohnny Huang { 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" } 543b458cd62SJohnny Huang }; 5449a4fe690SJohnny Huang 54579e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 5469a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5479a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5489a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5499a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5509a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5519a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5529a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5539a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5549a4fe690SJohnny Huang }; 5559a4fe690SJohnny Huang 55679e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 5579a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5589a4fe690SJohnny 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"}, 5599a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5609a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5619a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5629a4fe690SJohnny Huang }; 5639a4fe690SJohnny Huang 5649a4fe690SJohnny Huang static uint32_t chip_version(void) 5659a4fe690SJohnny Huang { 5669a4fe690SJohnny Huang uint32_t rev_id; 5679a4fe690SJohnny Huang 5689a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5699a4fe690SJohnny Huang 5709a4fe690SJohnny Huang return rev_id; 5719a4fe690SJohnny Huang } 5729a4fe690SJohnny Huang 5733d3688adSJohnny Huang static void wait_complete(void) 5743d3688adSJohnny Huang { 5753d3688adSJohnny Huang int reg; 5763d3688adSJohnny Huang 5773d3688adSJohnny Huang do { 5783d3688adSJohnny Huang reg = readl(OTP_STATUS); 5793d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5803d3688adSJohnny Huang } 5813d3688adSJohnny Huang 5822a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 58369d5fd8fSJohnny Huang { 5843d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5853d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5863d3688adSJohnny Huang wait_complete(); 5873d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5883d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 58969d5fd8fSJohnny Huang } 59069d5fd8fSJohnny Huang 5912a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 59269d5fd8fSJohnny Huang { 59369d5fd8fSJohnny Huang int config_offset; 59469d5fd8fSJohnny Huang 59569d5fd8fSJohnny Huang config_offset = 0x800; 59669d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 59769d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 59869d5fd8fSJohnny Huang 5993d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 6003d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6013d3688adSJohnny Huang wait_complete(); 6023d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 60369d5fd8fSJohnny Huang } 60469d5fd8fSJohnny Huang 60569d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 60669d5fd8fSJohnny Huang { 60769d5fd8fSJohnny Huang int i; 60869d5fd8fSJohnny Huang uint32_t ret[1]; 60969d5fd8fSJohnny Huang 61069d5fd8fSJohnny Huang if (offset + dw_count > 32) 6112a856b9aSJohnny Huang return OTP_USAGE; 61269d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 61369d5fd8fSJohnny Huang otp_read_config(i, ret); 614a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 61569d5fd8fSJohnny Huang } 61669d5fd8fSJohnny Huang printf("\n"); 6172a856b9aSJohnny Huang return OTP_SUCCESS; 61869d5fd8fSJohnny Huang } 61969d5fd8fSJohnny Huang 62069d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 62169d5fd8fSJohnny Huang { 62269d5fd8fSJohnny Huang int i; 62369d5fd8fSJohnny Huang uint32_t ret[2]; 62469d5fd8fSJohnny Huang 62569d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 6262a856b9aSJohnny Huang return OTP_USAGE; 62769d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 62869d5fd8fSJohnny Huang otp_read_data(i, ret); 62969d5fd8fSJohnny Huang if (i % 4 == 0) 63069d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 63169d5fd8fSJohnny Huang else 63269d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 63369d5fd8fSJohnny Huang 63469d5fd8fSJohnny Huang } 63569d5fd8fSJohnny Huang printf("\n"); 6362a856b9aSJohnny Huang return OTP_SUCCESS; 63769d5fd8fSJohnny Huang } 63869d5fd8fSJohnny Huang 63969d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 64069d5fd8fSJohnny Huang { 64169d5fd8fSJohnny Huang uint32_t ret; 64269d5fd8fSJohnny Huang uint32_t *buf; 64369d5fd8fSJohnny Huang 64469d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 64569d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 64669d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 64769d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 64869d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6493d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6503d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6513d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6523d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6533d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6543d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6553d3688adSJohnny Huang wait_complete(); 6563d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 65769d5fd8fSJohnny Huang if (ret & 0x1) 65869d5fd8fSJohnny Huang return 0; 65969d5fd8fSJohnny Huang else 66069d5fd8fSJohnny Huang return -1; 66169d5fd8fSJohnny Huang } 66269d5fd8fSJohnny Huang 66369d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 66469d5fd8fSJohnny Huang { 6653d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6663d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6673d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6683d3688adSJohnny Huang wait_complete(); 66969d5fd8fSJohnny Huang } 67069d5fd8fSJohnny Huang 67169d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 67269d5fd8fSJohnny Huang { 6733d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6743d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6753d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6763d3688adSJohnny Huang wait_complete(); 67769d5fd8fSJohnny Huang } 67869d5fd8fSJohnny Huang 679a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 68069d5fd8fSJohnny Huang { 68130a8c590SJohnny Huang uint32_t ret[2]; 68269d5fd8fSJohnny Huang 68330a8c590SJohnny Huang if (otp_addr % 2 == 0) 6843d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 68530a8c590SJohnny Huang else 6863d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 68730a8c590SJohnny Huang 6883d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6893d3688adSJohnny Huang wait_complete(); 6903d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6913d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 692a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 69330a8c590SJohnny Huang if (otp_addr % 2 == 0) { 69430a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 69569d5fd8fSJohnny Huang return 0; 69669d5fd8fSJohnny Huang else 69769d5fd8fSJohnny Huang return -1; 69830a8c590SJohnny Huang } else { 69930a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 70030a8c590SJohnny Huang return 0; 70130a8c590SJohnny Huang else 70230a8c590SJohnny Huang return -1; 70330a8c590SJohnny Huang } 70430a8c590SJohnny Huang 70569d5fd8fSJohnny Huang } 70669d5fd8fSJohnny Huang 707*696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size) 7084c1c9b35SJohnny Huang { 7094c1c9b35SJohnny Huang uint32_t ret[2]; 7104c1c9b35SJohnny Huang 7114c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 7124c1c9b35SJohnny Huang 7134c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 7143d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 7154c1c9b35SJohnny Huang else 7163d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 7173d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 7183d3688adSJohnny Huang wait_complete(); 7193d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 7203d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 7214c1c9b35SJohnny Huang if (size == 1) { 7224c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 7234c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 724*696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) { 7254c1c9b35SJohnny Huang compare[0] = 0; 7264c1c9b35SJohnny Huang return 0; 7274c1c9b35SJohnny Huang } else { 7284c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7294c1c9b35SJohnny Huang return -1; 7304c1c9b35SJohnny Huang } 7314c1c9b35SJohnny Huang 7324c1c9b35SJohnny Huang } else { 7334c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 734*696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) { 7354c1c9b35SJohnny Huang compare[0] = ~0; 7364c1c9b35SJohnny Huang return 0; 7374c1c9b35SJohnny Huang } else { 738d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7394c1c9b35SJohnny Huang return -1; 7404c1c9b35SJohnny Huang } 7414c1c9b35SJohnny Huang } 7424c1c9b35SJohnny Huang } else if (size == 2) { 7434c1c9b35SJohnny Huang // otp_addr should be even 744*696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) { 7454c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7464c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7474c1c9b35SJohnny Huang compare[0] = 0; 7484c1c9b35SJohnny Huang compare[1] = ~0; 7494c1c9b35SJohnny Huang return 0; 7504c1c9b35SJohnny Huang } else { 7514c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7524c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7534c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7544c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7554c1c9b35SJohnny Huang return -1; 7564c1c9b35SJohnny Huang } 7574c1c9b35SJohnny Huang } else { 7584c1c9b35SJohnny Huang return -1; 7594c1c9b35SJohnny Huang } 7604c1c9b35SJohnny Huang } 7614c1c9b35SJohnny Huang 7627e22f42dSJohnny Huang static void otp_soak(int soak) 763d90825e2SJohnny Huang { 764de6fbf1cSJohnny Huang switch (soak) { 765de6fbf1cSJohnny Huang case 0: //default 766de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 767de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 768de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 769de6fbf1cSJohnny Huang break; 770de6fbf1cSJohnny Huang case 1: //normal program 771de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 772de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 773de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 774de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 775de6fbf1cSJohnny Huang break; 776de6fbf1cSJohnny Huang case 2: //soak program 777d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 778d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 779d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 780de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 781de6fbf1cSJohnny Huang break; 782d90825e2SJohnny Huang } 783de6fbf1cSJohnny Huang 7843d3688adSJohnny Huang wait_complete(); 785d90825e2SJohnny Huang } 786d90825e2SJohnny Huang 787*696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address) 788d90825e2SJohnny Huang { 789d90825e2SJohnny Huang int j, bit_value, prog_bit; 790d90825e2SJohnny Huang 791d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 792*696656c6SJohnny Huang if ((ignore >> j) & 0x1) 793d90825e2SJohnny Huang continue; 794d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 795d90825e2SJohnny Huang if (prog_address % 2 == 0) { 796d90825e2SJohnny Huang if (bit_value) 797d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 798d90825e2SJohnny Huang else 799d90825e2SJohnny Huang continue; 800d90825e2SJohnny Huang } else { 801d90825e2SJohnny Huang prog_address |= 1 << 15; 802d90825e2SJohnny Huang if (bit_value) 803d90825e2SJohnny Huang continue; 804d90825e2SJohnny Huang else 805d90825e2SJohnny Huang prog_bit = 0x1 << j; 806d90825e2SJohnny Huang } 807d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 808d90825e2SJohnny Huang } 809d90825e2SJohnny Huang } 810d90825e2SJohnny Huang 81154552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address) 81254552c69SJohnny Huang { 81354552c69SJohnny Huang int pass; 81454552c69SJohnny Huang int i; 81554552c69SJohnny Huang uint32_t data0_masked; 81654552c69SJohnny Huang uint32_t data1_masked; 81754552c69SJohnny Huang uint32_t buf0_masked; 81854552c69SJohnny Huang uint32_t buf1_masked; 81954552c69SJohnny Huang uint32_t compare[2]; 82054552c69SJohnny Huang 82154552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 82254552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 82354552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 82454552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 82554552c69SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) 82654552c69SJohnny Huang return 0; 82754552c69SJohnny Huang 82854552c69SJohnny Huang otp_soak(1); 82954552c69SJohnny Huang if (data0_masked != buf0_masked) 83054552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 83154552c69SJohnny Huang if (data1_masked != buf1_masked) 83254552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 83354552c69SJohnny Huang 83454552c69SJohnny Huang pass = 0; 83554552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 83654552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 83754552c69SJohnny Huang otp_soak(2); 83854552c69SJohnny Huang if (compare[0] != 0) { 83954552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 84054552c69SJohnny Huang } 84154552c69SJohnny Huang if (compare[1] != ~0) { 84254552c69SJohnny Huang otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1); 84354552c69SJohnny Huang } 84454552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 84554552c69SJohnny Huang otp_soak(1); 84654552c69SJohnny Huang } else { 84754552c69SJohnny Huang pass = 1; 84854552c69SJohnny Huang break; 84954552c69SJohnny Huang } 85054552c69SJohnny Huang } else { 85154552c69SJohnny Huang pass = 1; 85254552c69SJohnny Huang break; 85354552c69SJohnny Huang } 85454552c69SJohnny Huang } 85554552c69SJohnny Huang 85654552c69SJohnny Huang if (!pass) { 85754552c69SJohnny Huang otp_soak(0); 85854552c69SJohnny Huang return OTP_FAILURE; 85954552c69SJohnny Huang } 86054552c69SJohnny Huang return OTP_SUCCESS; 86154552c69SJohnny Huang } 86254552c69SJohnny Huang 86376d13988SJohnny Huang 864541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 86576d13988SJohnny Huang { 86676d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 86776d13988SJohnny Huang int i, j; 86876d13988SJohnny Huang 86976d13988SJohnny Huang for (j = 0; j < 64; j++) { 87076d13988SJohnny Huang otpstrap[j].value = 0; 87176d13988SJohnny Huang otpstrap[j].remain_times = 7; 87276d13988SJohnny Huang otpstrap[j].writeable_option = -1; 87376d13988SJohnny Huang otpstrap[j].protected = 0; 87476d13988SJohnny Huang } 87576d13988SJohnny Huang 87676d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 87776d13988SJohnny Huang int option = (i - 16) / 2; 87876d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 87976d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 88076d13988SJohnny Huang for (j = 0; j < 32; j++) { 88176d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 88276d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 88376d13988SJohnny Huang otpstrap[j].writeable_option = option; 88476d13988SJohnny Huang } 88576d13988SJohnny Huang if (bit_value == 1) 88676d13988SJohnny Huang otpstrap[j].remain_times --; 88776d13988SJohnny Huang otpstrap[j].value ^= bit_value; 88876d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 88976d13988SJohnny Huang } 89076d13988SJohnny Huang for (j = 32; j < 64; j++) { 89176d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 89276d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 89376d13988SJohnny Huang otpstrap[j].writeable_option = option; 89476d13988SJohnny Huang } 89576d13988SJohnny Huang if (bit_value == 1) 89676d13988SJohnny Huang otpstrap[j].remain_times --; 89776d13988SJohnny Huang otpstrap[j].value ^= bit_value; 89876d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 89976d13988SJohnny Huang } 90076d13988SJohnny Huang } 90176d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 90276d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 90376d13988SJohnny Huang for (j = 0; j < 32; j++) { 90476d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 90576d13988SJohnny Huang otpstrap[j].protected = 1; 90676d13988SJohnny Huang } 90776d13988SJohnny Huang for (j = 32; j < 64; j++) { 90876d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 90976d13988SJohnny Huang otpstrap[j].protected = 1; 91076d13988SJohnny Huang } 91176d13988SJohnny Huang } 91276d13988SJohnny Huang 913*696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout) 91469d5fd8fSJohnny Huang { 91579e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 916*696656c6SJohnny Huang uint32_t *OTPCFG = (uint32_t *)image_layout->conf; 917*696656c6SJohnny Huang uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore; 918b458cd62SJohnny Huang uint32_t mask; 919b458cd62SJohnny Huang uint32_t dw_offset; 920b458cd62SJohnny Huang uint32_t bit_offset; 921b458cd62SJohnny Huang uint32_t otp_value; 922*696656c6SJohnny Huang uint32_t otp_ignore; 923b458cd62SJohnny Huang int fail = 0; 92473f11549SJohnny Huang char valid_bit[20]; 92566f2f8e5SJohnny Huang int i; 92673f11549SJohnny Huang int j; 92766f2f8e5SJohnny Huang 928737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 92966f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 9303cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9313cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9323cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9333cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 934b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 935*696656c6SJohnny Huang otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask; 936b458cd62SJohnny Huang 937*696656c6SJohnny Huang if (otp_ignore == mask) { 938b458cd62SJohnny Huang continue; 939*696656c6SJohnny Huang } else if (otp_ignore != 0) { 940b458cd62SJohnny Huang fail = 1; 941b458cd62SJohnny Huang } 942b458cd62SJohnny Huang 9433cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9443cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9453cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9463cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 947b458cd62SJohnny Huang continue; 948b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 949b458cd62SJohnny Huang 9503cb28812SJohnny Huang if (conf_info[i].length == 1) { 9513cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 95266f2f8e5SJohnny Huang } else { 953b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9543cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9553cb28812SJohnny Huang conf_info[i].bit_offset); 95666f2f8e5SJohnny Huang } 957b458cd62SJohnny Huang printf("0x%-10x", otp_value); 958b458cd62SJohnny Huang 959b458cd62SJohnny Huang if (fail) { 960*696656c6SJohnny Huang printf("Ignore mask error\n"); 961b458cd62SJohnny Huang } else { 9623cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 963b458cd62SJohnny Huang printf("Reserved\n"); 9643cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9653cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 966b458cd62SJohnny Huang printf("\n"); 9673cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 968b458cd62SJohnny Huang if (otp_value != 0) { 96973f11549SJohnny Huang for (j = 0; j < 7; j++) { 97073f11549SJohnny Huang if (otp_value == (1 << j)) { 97173f11549SJohnny Huang valid_bit[j * 2] = '1'; 972b458cd62SJohnny Huang } else { 97373f11549SJohnny Huang valid_bit[j * 2] = '0'; 97473f11549SJohnny Huang } 97573f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 97673f11549SJohnny Huang } 97773f11549SJohnny Huang valid_bit[15] = 0; 97873f11549SJohnny Huang } else { 97973f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 980b458cd62SJohnny Huang } 9813cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 982b458cd62SJohnny Huang printf("\n"); 983b458cd62SJohnny Huang } else { 9843cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 985b458cd62SJohnny Huang } 986b458cd62SJohnny Huang } 987b458cd62SJohnny Huang } 988b458cd62SJohnny Huang 989b458cd62SJohnny Huang if (fail) 990b458cd62SJohnny Huang return OTP_FAILURE; 991b458cd62SJohnny Huang 99266f2f8e5SJohnny Huang return OTP_SUCCESS; 99366f2f8e5SJohnny Huang } 99466f2f8e5SJohnny Huang 9952d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 99666f2f8e5SJohnny Huang { 99779e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 998bb34a7bfSJohnny Huang uint32_t OTPCFG[16]; 999b458cd62SJohnny Huang uint32_t mask; 1000b458cd62SJohnny Huang uint32_t dw_offset; 1001b458cd62SJohnny Huang uint32_t bit_offset; 1002b458cd62SJohnny Huang uint32_t otp_value; 100373f11549SJohnny Huang char valid_bit[20]; 100466f2f8e5SJohnny Huang int i; 100573f11549SJohnny Huang int j; 100666f2f8e5SJohnny Huang 1007bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 100866f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 100966f2f8e5SJohnny Huang 101066f2f8e5SJohnny Huang 1011b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 1012b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 10133cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 10143cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 10152d4b0742SJohnny Huang continue; 10163cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 10173cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 10183cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 1019b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 1020b458cd62SJohnny Huang 10213cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 10223cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 10233cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 10243cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 1025b458cd62SJohnny Huang continue; 1026b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 1027b458cd62SJohnny Huang 10283cb28812SJohnny Huang if (conf_info[i].length == 1) { 10293cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 1030b458cd62SJohnny Huang } else { 1031b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10323cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 10333cb28812SJohnny Huang conf_info[i].bit_offset); 1034b458cd62SJohnny Huang } 1035b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1036b458cd62SJohnny Huang 10373cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1038b458cd62SJohnny Huang printf("Reserved\n"); 10393cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10403cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1041b458cd62SJohnny Huang printf("\n"); 10423cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1043b458cd62SJohnny Huang if (otp_value != 0) { 104473f11549SJohnny Huang for (j = 0; j < 7; j++) { 104573f11549SJohnny Huang if (otp_value == (1 << j)) { 104673f11549SJohnny Huang valid_bit[j * 2] = '1'; 1047b458cd62SJohnny Huang } else { 104873f11549SJohnny Huang valid_bit[j * 2] = '0'; 104973f11549SJohnny Huang } 105073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 105173f11549SJohnny Huang } 105273f11549SJohnny Huang valid_bit[15] = 0; 105373f11549SJohnny Huang } else { 105473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1055b458cd62SJohnny Huang } 10563cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1057b458cd62SJohnny Huang printf("\n"); 1058b458cd62SJohnny Huang } else { 10593cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1060b458cd62SJohnny Huang } 1061b458cd62SJohnny Huang } 1062b458cd62SJohnny Huang return OTP_SUCCESS; 106366f2f8e5SJohnny Huang } 106466f2f8e5SJohnny Huang 1065*696656c6SJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout, int version) 106676d13988SJohnny Huang { 106779e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1068*696656c6SJohnny Huang uint32_t *OTPSTRAP; 1069*696656c6SJohnny Huang uint32_t *OTPSTRAP_REG_PRO; 1070*696656c6SJohnny Huang uint32_t *OTPSTRAP_PRO; 1071*696656c6SJohnny Huang uint32_t *OTPSTRAP_IGNORE; 107276d13988SJohnny Huang int i; 1073a8bd6d8cSJohnny Huang int fail = 0; 1074a8bd6d8cSJohnny Huang uint32_t bit_offset; 1075a8bd6d8cSJohnny Huang uint32_t dw_offset; 1076a8bd6d8cSJohnny Huang uint32_t mask; 1077a8bd6d8cSJohnny Huang uint32_t otp_value; 1078*696656c6SJohnny Huang uint32_t otp_reg_protect; 1079a8bd6d8cSJohnny Huang uint32_t otp_protect; 1080*696656c6SJohnny Huang uint32_t otp_ignore; 108176d13988SJohnny Huang 1082*696656c6SJohnny Huang OTPSTRAP = (uint32_t *)image_layout->strap; 1083*696656c6SJohnny Huang OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro; 1084*696656c6SJohnny Huang OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore; 1085*696656c6SJohnny Huang if (version == OTP_AST2600A0) { 1086*696656c6SJohnny Huang OTPSTRAP_REG_PRO = NULL; 1087a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1088a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1089*696656c6SJohnny Huang } else { 1090*696656c6SJohnny Huang OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro; 1091*696656c6SJohnny Huang printf("BIT(hex) Value REG_Protect Protect Description\n"); 1092*696656c6SJohnny Huang printf("__________________________________________________________________________________________\n"); 1093*696656c6SJohnny Huang } 1094b458cd62SJohnny Huang 10953cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1096*696656c6SJohnny Huang if (strap_info[i].bit_offset > 31) { 1097a8bd6d8cSJohnny Huang dw_offset = 1; 10983cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1099a8bd6d8cSJohnny Huang } else { 1100a8bd6d8cSJohnny Huang dw_offset = 0; 11013cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1102a8bd6d8cSJohnny Huang } 110376d13988SJohnny Huang 11043cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1105a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1106a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1107*696656c6SJohnny Huang otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask; 1108a8bd6d8cSJohnny Huang 1109*696656c6SJohnny Huang if (version != OTP_AST2600A0) 1110*696656c6SJohnny Huang otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask; 1111*696656c6SJohnny Huang 1112*696656c6SJohnny Huang if (otp_ignore == mask) { 1113a8bd6d8cSJohnny Huang continue; 1114*696656c6SJohnny Huang } else if (otp_ignore != 0) { 1115a8bd6d8cSJohnny Huang fail = 1; 1116a8bd6d8cSJohnny Huang } 1117a8bd6d8cSJohnny Huang 11183cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11193cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1120a8bd6d8cSJohnny Huang continue; 1121a8bd6d8cSJohnny Huang 11223cb28812SJohnny Huang if (strap_info[i].length == 1) { 11233cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1124a8bd6d8cSJohnny Huang } else { 1125b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 11263cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 11273cb28812SJohnny Huang strap_info[i].bit_offset); 1128a8bd6d8cSJohnny Huang } 1129a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1130*696656c6SJohnny Huang if (version != OTP_AST2600A0) 1131*696656c6SJohnny Huang printf("0x%-10x", otp_reg_protect); 1132a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1133a8bd6d8cSJohnny Huang 1134a8bd6d8cSJohnny Huang if (fail) { 1135*696656c6SJohnny Huang printf("Ignore mask error\n"); 1136a8bd6d8cSJohnny Huang } else { 11373cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11383cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1139a8bd6d8cSJohnny Huang else 1140a8bd6d8cSJohnny Huang printf("Reserved\n"); 1141a8bd6d8cSJohnny Huang } 1142a8bd6d8cSJohnny Huang } 1143a8bd6d8cSJohnny Huang 1144a8bd6d8cSJohnny Huang if (fail) 114576d13988SJohnny Huang return OTP_FAILURE; 114676d13988SJohnny Huang 114776d13988SJohnny Huang return OTP_SUCCESS; 114876d13988SJohnny Huang } 114976d13988SJohnny Huang 1150b458cd62SJohnny Huang static int otp_print_strap_info(int view) 115176d13988SJohnny Huang { 115279e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 115376d13988SJohnny Huang struct otpstrap_status strap_status[64]; 115407baa4e8SJohnny Huang int i, j; 1155b458cd62SJohnny Huang int fail = 0; 1156b458cd62SJohnny Huang uint32_t bit_offset; 1157b458cd62SJohnny Huang uint32_t length; 1158b458cd62SJohnny Huang uint32_t otp_value; 1159b458cd62SJohnny Huang uint32_t otp_protect; 116076d13988SJohnny Huang 1161541eb887SJohnny Huang otp_strap_status(strap_status); 116276d13988SJohnny Huang 1163b458cd62SJohnny Huang if (view) { 116407baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 116507baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 116607baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 116707baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1168b458cd62SJohnny Huang } else { 1169b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1170b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 117176d13988SJohnny Huang } 11723cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1173b458cd62SJohnny Huang otp_value = 0; 11743cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 11753cb28812SJohnny Huang length = strap_info[i].length; 1176b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1177c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1178c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1179b458cd62SJohnny Huang } 11803cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11813cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1182b458cd62SJohnny Huang continue; 1183b458cd62SJohnny Huang if (view) { 1184b458cd62SJohnny Huang for (j = 0; j < length; j++) { 11853cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1186b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 118707baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1188b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 11893cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1190b458cd62SJohnny Huang printf(" Reserved\n"); 1191b458cd62SJohnny Huang continue; 1192b458cd62SJohnny Huang } 1193b458cd62SJohnny Huang if (length == 1) { 11943cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1195b458cd62SJohnny Huang continue; 119676d13988SJohnny Huang } 119776d13988SJohnny Huang 1198b458cd62SJohnny Huang if (j == 0) 11993cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1200b458cd62SJohnny Huang else if (j == length - 1) 1201b458cd62SJohnny Huang printf("\\ \"\n"); 1202b458cd62SJohnny Huang else 1203b458cd62SJohnny Huang printf("| \"\n"); 120476d13988SJohnny Huang } 1205b458cd62SJohnny Huang } else { 1206c947ef08SJohnny Huang if (length == 1) { 12073cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1208b458cd62SJohnny Huang } else { 1209b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1210b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1211b458cd62SJohnny Huang } 1212b458cd62SJohnny Huang 1213b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1214b458cd62SJohnny Huang 12153cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 12163cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1217b458cd62SJohnny Huang else 1218b458cd62SJohnny Huang printf("Reserved\n"); 1219b458cd62SJohnny Huang } 1220b458cd62SJohnny Huang } 1221b458cd62SJohnny Huang 1222b458cd62SJohnny Huang if (fail) 1223b458cd62SJohnny Huang return OTP_FAILURE; 1224b458cd62SJohnny Huang 1225b458cd62SJohnny Huang return OTP_SUCCESS; 1226b458cd62SJohnny Huang } 1227b458cd62SJohnny Huang 1228*696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len) 122969d5fd8fSJohnny Huang { 123069d5fd8fSJohnny Huang int i; 123169d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 123269d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 123369d5fd8fSJohnny Huang if (i % 16 == 0) { 123469d5fd8fSJohnny Huang printf("%04X: ", i); 123569d5fd8fSJohnny Huang } 123669d5fd8fSJohnny Huang printf("%02X ", buf[i]); 123769d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 123869d5fd8fSJohnny Huang printf("\n"); 123969d5fd8fSJohnny Huang } 124069d5fd8fSJohnny Huang } 124169d5fd8fSJohnny Huang } 124269d5fd8fSJohnny Huang 1243*696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout) 124469d5fd8fSJohnny Huang { 124569d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 124679e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 12479a4fe690SJohnny Huang struct otpkey_type key_info; 1248*696656c6SJohnny Huang uint32_t *buf; 1249*696656c6SJohnny Huang uint8_t *byte_buf; 12509d998018SJohnny Huang char empty = 1; 125169d5fd8fSJohnny Huang int i = 0, len = 0; 12529a4fe690SJohnny Huang int j; 125354552c69SJohnny Huang 1254*696656c6SJohnny Huang byte_buf = image_layout->data; 1255*696656c6SJohnny Huang buf = (uint32_t *)byte_buf; 12569d998018SJohnny Huang 12579d998018SJohnny Huang for (i = 0; i < 16; i++) { 12589d998018SJohnny Huang if (buf[i] != 0) { 12599d998018SJohnny Huang empty = 0; 12609d998018SJohnny Huang } 12619d998018SJohnny Huang } 12629d998018SJohnny Huang if (empty) 12639d998018SJohnny Huang return 0; 12649d998018SJohnny Huang 12659d998018SJohnny Huang i = 0; 126669d5fd8fSJohnny Huang while (1) { 126769d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 126869d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 126969d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 127069d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 127169d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 127269d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 12739a4fe690SJohnny Huang 12749a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 12759a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 12769a4fe690SJohnny Huang key_info = key_info_array[j]; 12779a4fe690SJohnny Huang break; 12789a4fe690SJohnny Huang } 12799a4fe690SJohnny Huang } 12809a4fe690SJohnny Huang 12817f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 128269d5fd8fSJohnny Huang printf("Key Type: "); 12839a4fe690SJohnny Huang printf("%s\n", key_info.information); 12849a4fe690SJohnny Huang 12859a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 128669d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 128769d5fd8fSJohnny Huang switch (key_length) { 128869d5fd8fSJohnny Huang case 0: 128969d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 129069d5fd8fSJohnny Huang break; 129169d5fd8fSJohnny Huang case 1: 129269d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 129369d5fd8fSJohnny Huang break; 129469d5fd8fSJohnny Huang case 2: 129569d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 129669d5fd8fSJohnny Huang break; 129769d5fd8fSJohnny Huang case 3: 129869d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 129969d5fd8fSJohnny Huang break; 130069d5fd8fSJohnny Huang } 13019a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 130269d5fd8fSJohnny Huang printf("RSA SHA Type: "); 130369d5fd8fSJohnny Huang switch (key_length) { 130469d5fd8fSJohnny Huang case 0: 130569d5fd8fSJohnny Huang printf("RSA1024\n"); 130669d5fd8fSJohnny Huang len = 0x100; 130769d5fd8fSJohnny Huang break; 130869d5fd8fSJohnny Huang case 1: 130969d5fd8fSJohnny Huang printf("RSA2048\n"); 131069d5fd8fSJohnny Huang len = 0x200; 131169d5fd8fSJohnny Huang break; 131269d5fd8fSJohnny Huang case 2: 131369d5fd8fSJohnny Huang printf("RSA3072\n"); 131469d5fd8fSJohnny Huang len = 0x300; 131569d5fd8fSJohnny Huang break; 131669d5fd8fSJohnny Huang case 3: 131769d5fd8fSJohnny Huang printf("RSA4096\n"); 131869d5fd8fSJohnny Huang len = 0x400; 131969d5fd8fSJohnny Huang break; 132069d5fd8fSJohnny Huang } 132169d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 132269d5fd8fSJohnny Huang } 13239a4fe690SJohnny Huang if (key_info.need_id) 132469d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 132569d5fd8fSJohnny Huang printf("Key Value:\n"); 13269a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 132769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 13289a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 13299a4fe690SJohnny Huang printf("AES Key:\n"); 13309a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 13319a4fe690SJohnny Huang if (info_cb.version == 0) { 13329a4fe690SJohnny Huang printf("AES IV:\n"); 13339a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 13349a4fe690SJohnny Huang } 13359a4fe690SJohnny Huang 13369a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 13379a4fe690SJohnny Huang if (info_cb.version == 0) { 133869d5fd8fSJohnny Huang printf("AES Key:\n"); 133969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 134069d5fd8fSJohnny Huang printf("AES IV:\n"); 134169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 13429a4fe690SJohnny Huang } else if (info_cb.version == 1) { 13439a4fe690SJohnny Huang printf("AES Key 1:\n"); 13449a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 13459a4fe690SJohnny Huang printf("AES Key 2:\n"); 13469a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 13479a4fe690SJohnny Huang } 134869d5fd8fSJohnny Huang 13499a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 135069d5fd8fSJohnny Huang printf("RSA mod:\n"); 135169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 135269d5fd8fSJohnny Huang printf("RSA exp:\n"); 135369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 135469d5fd8fSJohnny Huang } 135569d5fd8fSJohnny Huang if (last) 135669d5fd8fSJohnny Huang break; 135769d5fd8fSJohnny Huang i++; 135869d5fd8fSJohnny Huang } 135969d5fd8fSJohnny Huang return 0; 136069d5fd8fSJohnny Huang } 136169d5fd8fSJohnny Huang 1362a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 136369d5fd8fSJohnny Huang { 1364a6d0d645SJohnny Huang int i, k; 1365d90825e2SJohnny Huang int pass = 0; 1366a6d0d645SJohnny Huang uint32_t prog_address; 1367bb34a7bfSJohnny Huang uint32_t data[16]; 1368a6d0d645SJohnny Huang uint32_t compare[2]; 1369*696656c6SJohnny Huang uint32_t *buf_ignore = &buf[16]; 1370d90825e2SJohnny Huang uint32_t data_masked; 1371d90825e2SJohnny Huang uint32_t buf_masked; 137269d5fd8fSJohnny Huang 1373a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1374a6d0d645SJohnny Huang 1375bb34a7bfSJohnny Huang for (i = 0; i < 16 ; i ++) { 137669d5fd8fSJohnny Huang prog_address = 0x800; 1377a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1378a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1379a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1380a6d0d645SJohnny Huang } 1381a6d0d645SJohnny Huang 1382a6d0d645SJohnny Huang printf("Check writable...\n"); 1383bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 1384*696656c6SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1385*696656c6SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 1386d90825e2SJohnny Huang if (data_masked == buf_masked) 138769d5fd8fSJohnny Huang continue; 1388d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1389a6d0d645SJohnny Huang continue; 1390a6d0d645SJohnny Huang } else { 1391a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1392a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1393a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1394*696656c6SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_ignore[i]); 13952a856b9aSJohnny Huang return OTP_FAILURE; 1396a6d0d645SJohnny Huang } 1397a6d0d645SJohnny Huang } 1398a6d0d645SJohnny Huang 1399a6d0d645SJohnny Huang printf("Start Programing...\n"); 1400d90825e2SJohnny Huang otp_soak(0); 1401bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 1402*696656c6SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1403*696656c6SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 1404a6d0d645SJohnny Huang prog_address = 0x800; 1405a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1406a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1407bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1408bb34a7bfSJohnny Huang pass = 1; 1409a6d0d645SJohnny Huang continue; 1410bb34a7bfSJohnny Huang } 1411de6fbf1cSJohnny Huang 1412a6d0d645SJohnny Huang 1413de6fbf1cSJohnny Huang otp_soak(1); 1414*696656c6SJohnny Huang otp_prog_dw(buf[i], buf_ignore[i], prog_address); 1415a6d0d645SJohnny Huang 141669d5fd8fSJohnny Huang pass = 0; 141769d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1418*696656c6SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_ignore[i], compare, 1) != 0) { 1419de6fbf1cSJohnny Huang otp_soak(2); 1420a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1421*696656c6SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_ignore[i], compare, 1) != 0) { 1422de6fbf1cSJohnny Huang otp_soak(1); 1423de6fbf1cSJohnny Huang } else { 1424de6fbf1cSJohnny Huang pass = 1; 1425de6fbf1cSJohnny Huang break; 1426de6fbf1cSJohnny Huang } 1427a6d0d645SJohnny Huang } else { 142869d5fd8fSJohnny Huang pass = 1; 142969d5fd8fSJohnny Huang break; 143069d5fd8fSJohnny Huang } 143169d5fd8fSJohnny Huang } 1432bb34a7bfSJohnny Huang if (pass == 0) { 1433bb34a7bfSJohnny Huang printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n", 1434*696656c6SJohnny Huang i, data[i], buf[i], buf_ignore[i]); 1435bb34a7bfSJohnny Huang break; 1436bb34a7bfSJohnny Huang } 1437a6d0d645SJohnny Huang } 1438a6d0d645SJohnny Huang 1439de6fbf1cSJohnny Huang otp_soak(0); 144069d5fd8fSJohnny Huang if (!pass) 14412a856b9aSJohnny Huang return OTP_FAILURE; 1442a6d0d645SJohnny Huang 14432a856b9aSJohnny Huang return OTP_SUCCESS; 1444d90825e2SJohnny Huang 144569d5fd8fSJohnny Huang } 144669d5fd8fSJohnny Huang 144769d5fd8fSJohnny Huang 144876d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 144969d5fd8fSJohnny Huang { 145069d5fd8fSJohnny Huang int i; 1451*696656c6SJohnny Huang uint32_t *strap_ignore = buf + 2; 145269d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 145369d5fd8fSJohnny Huang int bit, pbit, kbit; 145469d5fd8fSJohnny Huang int fail = 0; 1455a6af4a17SJohnny Huang int skip = -1; 145666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 145769d5fd8fSJohnny Huang 1458541eb887SJohnny Huang otp_strap_status(otpstrap); 145969d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 146069d5fd8fSJohnny Huang if (i < 32) { 146169d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 1462*696656c6SJohnny Huang kbit = (strap_ignore[0] >> i) & 0x1; 146369d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 146469d5fd8fSJohnny Huang } else { 146569d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 1466*696656c6SJohnny Huang kbit = (strap_ignore[1] >> (i - 32)) & 0x1; 146769d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 146869d5fd8fSJohnny Huang } 146969d5fd8fSJohnny Huang 147069d5fd8fSJohnny Huang if (kbit == 1) { 147169d5fd8fSJohnny Huang continue; 147269d5fd8fSJohnny Huang } else { 1473a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 147469d5fd8fSJohnny Huang } 147569d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 147669d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1477a6af4a17SJohnny Huang if (skip == -1) 1478a6af4a17SJohnny Huang skip = 1; 147969d5fd8fSJohnny Huang continue; 1480a6af4a17SJohnny Huang } else { 1481a6af4a17SJohnny Huang skip = 0; 148269d5fd8fSJohnny Huang } 148369d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 148469d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 148569d5fd8fSJohnny Huang fail = 1; 148669d5fd8fSJohnny Huang continue; 148769d5fd8fSJohnny Huang } 148869d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1489a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 149069d5fd8fSJohnny Huang fail = 1; 149169d5fd8fSJohnny Huang continue; 149269d5fd8fSJohnny Huang } 149369d5fd8fSJohnny Huang if (pbit == 1) { 149469d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 149569d5fd8fSJohnny Huang } 1496a6af4a17SJohnny 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); 149769d5fd8fSJohnny Huang } 149869d5fd8fSJohnny Huang if (fail == 1) 1499a6af4a17SJohnny Huang return OTP_FAILURE; 1500a6af4a17SJohnny Huang else if (skip == 1) 1501a6af4a17SJohnny Huang return OTP_PROG_SKIP; 15027e22f42dSJohnny Huang 15037e22f42dSJohnny Huang return 0; 150469d5fd8fSJohnny Huang } 150569d5fd8fSJohnny Huang 15062a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 150769d5fd8fSJohnny Huang { 150869d5fd8fSJohnny Huang int i, j; 150966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 151069d5fd8fSJohnny Huang 15112a856b9aSJohnny Huang if (start < 0 || start > 64) 15122a856b9aSJohnny Huang return OTP_USAGE; 15132a856b9aSJohnny Huang 15142a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 15152a856b9aSJohnny Huang return OTP_USAGE; 15162a856b9aSJohnny Huang 1517541eb887SJohnny Huang otp_strap_status(otpstrap); 151869d5fd8fSJohnny Huang 151907baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1520a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1521737ed20bSJohnny Huang 1522cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 152307baa4e8SJohnny Huang printf("0x%-8X", i); 1524737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1525737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1526737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1527737ed20bSJohnny Huang printf(" "); 152869d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1529737ed20bSJohnny Huang printf("protected and not writable"); 153069d5fd8fSJohnny Huang } else { 1531737ed20bSJohnny Huang printf("not protected "); 153269d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1533737ed20bSJohnny Huang printf("and no remaining times to write."); 153469d5fd8fSJohnny Huang } else { 1535737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 153669d5fd8fSJohnny Huang } 153769d5fd8fSJohnny Huang } 1538737ed20bSJohnny Huang printf("\n"); 153969d5fd8fSJohnny Huang } 15402a856b9aSJohnny Huang 15412a856b9aSJohnny Huang return OTP_SUCCESS; 154269d5fd8fSJohnny Huang } 154369d5fd8fSJohnny Huang 154469d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 154569d5fd8fSJohnny Huang { 154669d5fd8fSJohnny Huang int i, j; 1547*696656c6SJohnny Huang uint32_t *strap_ignore = buf + 2; 154869d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 154969d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 155069d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 155169d5fd8fSJohnny Huang int fail = 0; 15527e22f42dSJohnny Huang int pass = 0; 155366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 155469d5fd8fSJohnny Huang 15557f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1556541eb887SJohnny Huang otp_strap_status(otpstrap); 155769d5fd8fSJohnny Huang 15587f795e57SJohnny Huang printf("Check writable...\n"); 15597f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 15607f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 15617f795e57SJohnny Huang return OTP_FAILURE; 15627f795e57SJohnny Huang } 15637e22f42dSJohnny Huang 156469d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 156569d5fd8fSJohnny Huang prog_address = 0x800; 156669d5fd8fSJohnny Huang if (i < 32) { 156769d5fd8fSJohnny Huang offset = i; 156869d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 1569*696656c6SJohnny Huang kbit = (strap_ignore[0] >> offset) & 0x1; 157069d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 157169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 157269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 157369d5fd8fSJohnny Huang 157469d5fd8fSJohnny Huang } else { 157569d5fd8fSJohnny Huang offset = (i - 32); 157669d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 1577*696656c6SJohnny Huang kbit = (strap_ignore[1] >> offset) & 0x1; 157869d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 157969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 158069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 158169d5fd8fSJohnny Huang } 158269d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 158369d5fd8fSJohnny Huang 158469d5fd8fSJohnny Huang if (kbit == 1) { 158569d5fd8fSJohnny Huang continue; 158669d5fd8fSJohnny Huang } 158769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 158869d5fd8fSJohnny Huang continue; 158969d5fd8fSJohnny Huang } 159069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 159169d5fd8fSJohnny Huang fail = 1; 159269d5fd8fSJohnny Huang continue; 159369d5fd8fSJohnny Huang } 159469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 159569d5fd8fSJohnny Huang fail = 1; 159669d5fd8fSJohnny Huang continue; 159769d5fd8fSJohnny Huang } 15987e22f42dSJohnny Huang 15997e22f42dSJohnny Huang 1600de6fbf1cSJohnny Huang otp_soak(1); 16017e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 16027e22f42dSJohnny Huang 16037e22f42dSJohnny Huang pass = 0; 160469d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1605de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1606de6fbf1cSJohnny Huang otp_soak(2); 1607de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1608de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1609de6fbf1cSJohnny Huang otp_soak(1); 1610de6fbf1cSJohnny Huang } else { 161169d5fd8fSJohnny Huang pass = 1; 161269d5fd8fSJohnny Huang break; 161369d5fd8fSJohnny Huang } 1614de6fbf1cSJohnny Huang } else { 1615de6fbf1cSJohnny Huang pass = 1; 1616de6fbf1cSJohnny Huang break; 16174b65a65dSJohnny Huang } 161869d5fd8fSJohnny Huang } 161969d5fd8fSJohnny Huang if (!pass) 16202a856b9aSJohnny Huang return OTP_FAILURE; 162169d5fd8fSJohnny Huang 162269d5fd8fSJohnny Huang if (pbit == 0) 162369d5fd8fSJohnny Huang continue; 162469d5fd8fSJohnny Huang prog_address = 0x800; 162569d5fd8fSJohnny Huang if (i < 32) 162669d5fd8fSJohnny Huang prog_address |= 0x60c; 162769d5fd8fSJohnny Huang else 162869d5fd8fSJohnny Huang prog_address |= 0x60e; 162969d5fd8fSJohnny Huang 16307e22f42dSJohnny Huang 1631de6fbf1cSJohnny Huang otp_soak(1); 16327e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 16337e22f42dSJohnny Huang 16347e22f42dSJohnny Huang pass = 0; 163569d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1636de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1637de6fbf1cSJohnny Huang otp_soak(2); 1638de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1639de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1640de6fbf1cSJohnny Huang otp_soak(1); 1641de6fbf1cSJohnny Huang } else { 164269d5fd8fSJohnny Huang pass = 1; 164369d5fd8fSJohnny Huang break; 164469d5fd8fSJohnny Huang } 1645de6fbf1cSJohnny Huang } else { 1646de6fbf1cSJohnny Huang pass = 1; 1647de6fbf1cSJohnny Huang break; 164869d5fd8fSJohnny Huang } 164969d5fd8fSJohnny Huang } 165069d5fd8fSJohnny Huang if (!pass) 16512a856b9aSJohnny Huang return OTP_FAILURE; 165269d5fd8fSJohnny Huang 165369d5fd8fSJohnny Huang } 1654de6fbf1cSJohnny Huang otp_soak(0); 165569d5fd8fSJohnny Huang if (fail == 1) 16562a856b9aSJohnny Huang return OTP_FAILURE; 165769d5fd8fSJohnny Huang else 16582a856b9aSJohnny Huang return OTP_SUCCESS; 165969d5fd8fSJohnny Huang 166069d5fd8fSJohnny Huang } 166169d5fd8fSJohnny Huang 1662de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1663cd1610b4SJohnny Huang { 1664cd1610b4SJohnny Huang int prog_bit; 1665cd1610b4SJohnny Huang 1666cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1667cd1610b4SJohnny Huang if (value) 1668cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1669cd1610b4SJohnny Huang else 1670cd1610b4SJohnny Huang return; 1671cd1610b4SJohnny Huang } else { 1672cd1610b4SJohnny Huang prog_address |= 1 << 15; 1673cd1610b4SJohnny Huang if (!value) 1674cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1675cd1610b4SJohnny Huang else 1676cd1610b4SJohnny Huang return; 1677cd1610b4SJohnny Huang } 1678cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1679cd1610b4SJohnny Huang } 1680cd1610b4SJohnny Huang 1681d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 16824c1c9b35SJohnny Huang { 168354552c69SJohnny Huang int i; 168454552c69SJohnny Huang int ret; 1685d90825e2SJohnny Huang uint32_t data[2048]; 1686*696656c6SJohnny Huang uint32_t *buf_ignore = &buf[2048]; 16874c1c9b35SJohnny Huang 168854552c69SJohnny Huang uint32_t data_masked; 168954552c69SJohnny Huang uint32_t buf_masked; 16904c1c9b35SJohnny Huang 16914c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 16924c1c9b35SJohnny Huang 1693d6cdf762SJohnny Huang for (i = 0; i < 2046 ; i += 2) { 1694d90825e2SJohnny Huang otp_read_data(i, &data[i]); 16954c1c9b35SJohnny Huang } 1696d90825e2SJohnny Huang 16974c1c9b35SJohnny Huang printf("Check writable...\n"); 169854552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1699d6cdf762SJohnny Huang for (i = 0; i < 2046; i++) { 1700*696656c6SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1701*696656c6SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 170254552c69SJohnny Huang if (data_masked == buf_masked) 17034c1c9b35SJohnny Huang continue; 1704d90825e2SJohnny Huang if (i % 2 == 0) { 170554552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 17064c1c9b35SJohnny Huang continue; 17074c1c9b35SJohnny Huang } else { 17084c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1709d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 17104c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1711*696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 17122a856b9aSJohnny Huang return OTP_FAILURE; 171369d5fd8fSJohnny Huang } 1714d90825e2SJohnny Huang } else { 171554552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1716d90825e2SJohnny Huang continue; 1717d90825e2SJohnny Huang } else { 1718d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1719d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1720d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1721*696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 17222a856b9aSJohnny Huang return OTP_FAILURE; 1723d90825e2SJohnny Huang } 1724d90825e2SJohnny Huang } 1725d90825e2SJohnny Huang } 172669d5fd8fSJohnny Huang 1727d90825e2SJohnny Huang printf("Start Programing...\n"); 1728d90825e2SJohnny Huang 172954552c69SJohnny Huang // programing ecc region first 173054552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1731*696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 173254552c69SJohnny Huang if (ret != OTP_SUCCESS) { 173354552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1734*696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 173554552c69SJohnny Huang return ret; 1736d90825e2SJohnny Huang } 1737d90825e2SJohnny Huang } 1738d90825e2SJohnny Huang 173954552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 1740*696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 174154552c69SJohnny Huang if (ret != OTP_SUCCESS) { 174254552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1743*696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 174454552c69SJohnny Huang return ret; 1745d90825e2SJohnny Huang } 1746de6fbf1cSJohnny Huang } 1747de6fbf1cSJohnny Huang otp_soak(0); 17482a856b9aSJohnny Huang return OTP_SUCCESS; 1749d90825e2SJohnny Huang 1750d90825e2SJohnny Huang } 1751d90825e2SJohnny Huang 1752*696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf) 1753*696656c6SJohnny Huang { 1754*696656c6SJohnny Huang sha256_context ctx; 1755*696656c6SJohnny Huang u8 digest_ret[CHECKSUM_LEN]; 1756*696656c6SJohnny Huang 1757*696656c6SJohnny Huang sha256_starts(&ctx); 1758*696656c6SJohnny Huang sha256_update(&ctx, src_buf, length); 1759*696656c6SJohnny Huang sha256_finish(&ctx, digest_ret); 1760*696656c6SJohnny Huang 1761*696656c6SJohnny Huang if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN)) 1762*696656c6SJohnny Huang return 0; 1763*696656c6SJohnny Huang else 1764*696656c6SJohnny Huang return -1; 1765*696656c6SJohnny Huang 1766*696656c6SJohnny Huang } 1767*696656c6SJohnny Huang 1768d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 176969d5fd8fSJohnny Huang { 177069d5fd8fSJohnny Huang int ret; 17719a4fe690SJohnny Huang int image_version = 0; 1772*696656c6SJohnny Huang struct otp_header *otp_header; 1773*696656c6SJohnny Huang struct otp_image_layout image_layout; 1774*696656c6SJohnny Huang int image_size; 1775*696656c6SJohnny Huang int data_region_size; 1776*696656c6SJohnny Huang int config_region_size; 1777*696656c6SJohnny Huang int strap_region_size; 1778*696656c6SJohnny Huang uint8_t *buf; 1779*696656c6SJohnny Huang uint8_t *checksum; 178069d5fd8fSJohnny Huang 1781*696656c6SJohnny Huang otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK); 1782*696656c6SJohnny Huang if (!otp_header) { 178369d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 17842a856b9aSJohnny Huang return OTP_FAILURE; 178569d5fd8fSJohnny Huang } 1786d90825e2SJohnny Huang 1787*696656c6SJohnny Huang image_size = OTP_IMAGE_SIZE(otp_header->image_info); 1788*696656c6SJohnny Huang unmap_physmem(otp_header, MAP_WRBACK); 1789*696656c6SJohnny Huang 1790*696656c6SJohnny Huang buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK); 1791*696656c6SJohnny Huang 1792*696656c6SJohnny Huang if (!buf) { 1793*696656c6SJohnny Huang puts("Failed to map physical memory\n"); 1794*696656c6SJohnny Huang return OTP_FAILURE; 1795*696656c6SJohnny Huang } 1796*696656c6SJohnny Huang otp_header = (struct otp_header *) buf; 1797*696656c6SJohnny Huang checksum = buf + otp_header->checksum_offset; 1798*696656c6SJohnny Huang 1799*696656c6SJohnny Huang if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) { 1800*696656c6SJohnny Huang puts("Image is invalid\n"); 1801*696656c6SJohnny Huang return OTP_FAILURE; 1802*696656c6SJohnny Huang } 1803*696656c6SJohnny Huang 1804*696656c6SJohnny Huang data_region_size = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2); 1805*696656c6SJohnny Huang image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info); 1806*696656c6SJohnny Huang image_layout.data_ignore = image_layout.data + data_region_size; 1807*696656c6SJohnny Huang 1808*696656c6SJohnny Huang config_region_size = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2); 1809*696656c6SJohnny Huang image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 1810*696656c6SJohnny Huang image_layout.conf_ignore = image_layout.conf + config_region_size; 1811*696656c6SJohnny Huang 1812*696656c6SJohnny Huang image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 1813*696656c6SJohnny Huang 1814*696656c6SJohnny Huang if (!strcmp("A0", (char *)otp_header->otp_version)) { 1815*696656c6SJohnny Huang image_version = OTP_AST2600A0; 1816*696656c6SJohnny Huang strap_region_size = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3); 1817*696656c6SJohnny Huang image_layout.strap_pro = image_layout.strap + strap_region_size; 1818*696656c6SJohnny Huang image_layout.strap_ignore = image_layout.strap + 2 * strap_region_size; 1819*696656c6SJohnny Huang } else if (!strcmp("A1", (char *)otp_header->otp_version)) { 1820*696656c6SJohnny Huang image_version = OTP_AST2600A1; 1821*696656c6SJohnny Huang strap_region_size = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4); 1822*696656c6SJohnny Huang image_layout.strap_reg_pro = image_layout.strap + strap_region_size; 1823*696656c6SJohnny Huang image_layout.strap_pro = image_layout.strap + 2 * strap_region_size; 1824*696656c6SJohnny Huang image_layout.strap_ignore = image_layout.strap + 3 * strap_region_size; 1825*696656c6SJohnny Huang } else { 1826*696656c6SJohnny Huang puts("Version is not supported\n"); 1827*696656c6SJohnny Huang return OTP_FAILURE; 1828*696656c6SJohnny Huang } 1829*696656c6SJohnny Huang 18309a4fe690SJohnny Huang if (image_version != info_cb.version) { 18319a4fe690SJohnny Huang puts("Version is not match\n"); 18329a4fe690SJohnny Huang return OTP_FAILURE; 18339a4fe690SJohnny Huang } 18349a4fe690SJohnny Huang 1835*696656c6SJohnny Huang if (otp_image_verify(buf, image_size, checksum)) { 1836*696656c6SJohnny Huang puts("checksum is invalid\n"); 1837*696656c6SJohnny Huang return OTP_FAILURE; 1838d90825e2SJohnny Huang } 18397332532cSJohnny Huang 184069d5fd8fSJohnny Huang if (!nconfirm) { 1841*696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 18427f795e57SJohnny Huang printf("\nOTP data region :\n"); 1843*696656c6SJohnny Huang if (otp_print_data_info(&image_layout) < 0) { 184469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 18452a856b9aSJohnny Huang return OTP_FAILURE; 184669d5fd8fSJohnny Huang } 184769d5fd8fSJohnny Huang } 1848*696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 18497332532cSJohnny Huang printf("\nOTP strap region :\n"); 1850*696656c6SJohnny Huang if (otp_print_strap_image(&image_layout, image_version) < 0) { 18517332532cSJohnny Huang printf("OTP strap error, please check.\n"); 18527332532cSJohnny Huang return OTP_FAILURE; 18537332532cSJohnny Huang } 18547332532cSJohnny Huang } 1855*696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 18567332532cSJohnny Huang printf("\nOTP configuration region :\n"); 1857*696656c6SJohnny Huang if (otp_print_conf_image(&image_layout) < 0) { 18587332532cSJohnny Huang printf("OTP config error, please check.\n"); 18597332532cSJohnny Huang return OTP_FAILURE; 18607332532cSJohnny Huang } 18617332532cSJohnny Huang } 18627332532cSJohnny Huang 186369d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 186469d5fd8fSJohnny Huang if (!confirm_yesno()) { 186569d5fd8fSJohnny Huang printf(" Aborting\n"); 18662a856b9aSJohnny Huang return OTP_FAILURE; 186769d5fd8fSJohnny Huang } 186869d5fd8fSJohnny Huang } 18697332532cSJohnny Huang 1870*696656c6SJohnny Huang // if (otp_header->image_info & OTP_INC_DATA) { 1871*696656c6SJohnny Huang // printf("programing data region ...\n"); 1872*696656c6SJohnny Huang // ret = otp_prog_data(data_region); 1873*696656c6SJohnny Huang // if (ret != 0) { 1874*696656c6SJohnny Huang // printf("Error\n"); 1875*696656c6SJohnny Huang // return ret; 1876*696656c6SJohnny Huang // } else { 1877*696656c6SJohnny Huang // printf("Done\n"); 1878*696656c6SJohnny Huang // } 1879*696656c6SJohnny Huang // } 1880*696656c6SJohnny Huang // if (mode & OTP_REGION_STRAP) { 1881*696656c6SJohnny Huang // printf("programing strap region ...\n"); 1882*696656c6SJohnny Huang // ret = otp_prog_strap(strap_region); 1883*696656c6SJohnny Huang // if (ret != 0) { 1884*696656c6SJohnny Huang // printf("Error\n"); 1885*696656c6SJohnny Huang // return ret; 1886*696656c6SJohnny Huang // } else { 1887*696656c6SJohnny Huang // printf("Done\n"); 1888*696656c6SJohnny Huang // } 1889*696656c6SJohnny Huang // } 1890*696656c6SJohnny Huang // if (mode & OTP_REGION_CONF) { 1891*696656c6SJohnny Huang // printf("programing configuration region ...\n"); 1892*696656c6SJohnny Huang // ret = otp_prog_conf(conf_region); 1893*696656c6SJohnny Huang // if (ret != 0) { 1894*696656c6SJohnny Huang // printf("Error\n"); 1895*696656c6SJohnny Huang // return ret; 1896*696656c6SJohnny Huang // } 1897*696656c6SJohnny Huang // printf("Done\n"); 1898*696656c6SJohnny Huang // } 1899cd1610b4SJohnny Huang 19007332532cSJohnny Huang return OTP_SUCCESS; 19012a856b9aSJohnny Huang } 19022a856b9aSJohnny Huang 19032a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1904cd1610b4SJohnny Huang { 1905a6af4a17SJohnny Huang uint32_t read[2]; 1906cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1907d90825e2SJohnny Huang uint32_t prog_address = 0; 190866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1909cd1610b4SJohnny Huang int otp_bit; 1910cd1610b4SJohnny Huang int i; 1911cd1610b4SJohnny Huang int pass; 1912a6af4a17SJohnny Huang int ret; 1913cd1610b4SJohnny Huang 1914cd1610b4SJohnny Huang switch (mode) { 1915a6d0d645SJohnny Huang case OTP_REGION_CONF: 1916a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1917cd1610b4SJohnny Huang prog_address = 0x800; 1918cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1919cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1920a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1921cd1610b4SJohnny Huang if (otp_bit == value) { 1922a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1923cd1610b4SJohnny Huang printf("No need to program\n"); 19242a856b9aSJohnny Huang return OTP_SUCCESS; 1925cd1610b4SJohnny Huang } 1926cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1927a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1928cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 19292a856b9aSJohnny Huang return OTP_FAILURE; 1930cd1610b4SJohnny Huang } 1931a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1932cd1610b4SJohnny Huang break; 1933a6d0d645SJohnny Huang case OTP_REGION_DATA: 1934cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1935cd1610b4SJohnny Huang 1936cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1937a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1938a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1939643b9cfdSJohnny Huang 1940643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1941643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1942643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1943643b9cfdSJohnny Huang return OTP_FAILURE; 1944643b9cfdSJohnny Huang } 1945cd1610b4SJohnny Huang } else { 1946a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1947a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1948643b9cfdSJohnny Huang 1949643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1950643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1951643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1952643b9cfdSJohnny Huang return OTP_FAILURE; 1953643b9cfdSJohnny Huang } 1954cd1610b4SJohnny Huang } 1955cd1610b4SJohnny Huang if (otp_bit == value) { 1956a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1957cd1610b4SJohnny Huang printf("No need to program\n"); 19582a856b9aSJohnny Huang return OTP_SUCCESS; 1959cd1610b4SJohnny Huang } 1960643b9cfdSJohnny Huang 1961a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1962cd1610b4SJohnny Huang break; 1963a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1964541eb887SJohnny Huang otp_strap_status(otpstrap); 1965cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1966cd1610b4SJohnny Huang if (bit_offset < 32) { 1967cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 19683d1cbeb0SJohnny Huang strap_buf[1] = 0; 1969cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1970cd1610b4SJohnny Huang strap_buf[3] = ~0; 19713d1cbeb0SJohnny Huang strap_buf[4] = 0; 1972cd1610b4SJohnny Huang strap_buf[5] = 0; 1973cd1610b4SJohnny Huang } else { 19743d1cbeb0SJohnny Huang strap_buf[0] = 0; 1975cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1976cd1610b4SJohnny Huang strap_buf[2] = ~0; 1977cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1978cd1610b4SJohnny Huang strap_buf[4] = 0; 19793d1cbeb0SJohnny Huang strap_buf[5] = 0; 1980cd1610b4SJohnny Huang } 198176d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1982a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 19832a856b9aSJohnny Huang return OTP_FAILURE; 1984a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1985a6af4a17SJohnny Huang return OTP_SUCCESS; 1986a6af4a17SJohnny Huang 1987cd1610b4SJohnny Huang break; 1988cd1610b4SJohnny Huang } 1989cd1610b4SJohnny Huang 1990cd1610b4SJohnny Huang if (!nconfirm) { 1991cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1992cd1610b4SJohnny Huang if (!confirm_yesno()) { 1993cd1610b4SJohnny Huang printf(" Aborting\n"); 19942a856b9aSJohnny Huang return OTP_FAILURE; 1995cd1610b4SJohnny Huang } 1996cd1610b4SJohnny Huang } 1997cd1610b4SJohnny Huang 1998cd1610b4SJohnny Huang switch (mode) { 1999a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2000cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 2001a6d0d645SJohnny Huang case OTP_REGION_CONF: 2002a6d0d645SJohnny Huang case OTP_REGION_DATA: 2003de6fbf1cSJohnny Huang otp_soak(1); 2004de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 2005de6fbf1cSJohnny Huang pass = 0; 2006de6fbf1cSJohnny Huang 2007cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 2008a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2009de6fbf1cSJohnny Huang otp_soak(2); 2010de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 2011de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2012de6fbf1cSJohnny Huang otp_soak(1); 2013cd1610b4SJohnny Huang } else { 2014de6fbf1cSJohnny Huang pass = 1; 2015de6fbf1cSJohnny Huang break; 2016de6fbf1cSJohnny Huang } 2017de6fbf1cSJohnny Huang } else { 2018de6fbf1cSJohnny Huang pass = 1; 2019cd1610b4SJohnny Huang break; 2020cd1610b4SJohnny Huang } 2021cd1610b4SJohnny Huang } 2022de6fbf1cSJohnny Huang 2023de6fbf1cSJohnny Huang otp_soak(0); 2024de6fbf1cSJohnny Huang if (pass) { 20259009c25dSJohnny Huang printf("SUCCESS\n"); 20262a856b9aSJohnny Huang return OTP_SUCCESS; 20279009c25dSJohnny Huang } else { 20289009c25dSJohnny Huang printf("OTP cannot be programed\n"); 20299009c25dSJohnny Huang printf("FAILED\n"); 20309009c25dSJohnny Huang return OTP_FAILURE; 20319009c25dSJohnny Huang } 2032cd1610b4SJohnny Huang } 2033cd1610b4SJohnny Huang 20342a856b9aSJohnny Huang return OTP_USAGE; 2035cd1610b4SJohnny Huang } 2036cd1610b4SJohnny Huang 20372a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 203869d5fd8fSJohnny Huang { 20392a856b9aSJohnny Huang uint32_t offset, count; 20402a856b9aSJohnny Huang int ret; 204169d5fd8fSJohnny Huang 20422a856b9aSJohnny Huang if (argc == 4) { 20432a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 20442a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 20452a856b9aSJohnny Huang } else if (argc == 3) { 20462a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 20472a856b9aSJohnny Huang count = 1; 20482a856b9aSJohnny Huang } else { 204969d5fd8fSJohnny Huang return CMD_RET_USAGE; 205069d5fd8fSJohnny Huang } 205169d5fd8fSJohnny Huang 205269d5fd8fSJohnny Huang 20532a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 20543d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20552a856b9aSJohnny Huang ret = otp_print_config(offset, count); 20562a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 20573d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20582a856b9aSJohnny Huang ret = otp_print_data(offset, count); 20592a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20603d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20612a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 20622a856b9aSJohnny Huang } else { 20632a856b9aSJohnny Huang return CMD_RET_USAGE; 206469d5fd8fSJohnny Huang } 206569d5fd8fSJohnny Huang 20662a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20672a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20682a856b9aSJohnny Huang else 20692a856b9aSJohnny Huang return CMD_RET_USAGE; 20702a856b9aSJohnny Huang 20712a856b9aSJohnny Huang } 20722a856b9aSJohnny Huang 20732a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20742a856b9aSJohnny Huang { 20752a856b9aSJohnny Huang phys_addr_t addr; 20762a856b9aSJohnny Huang uint32_t byte_size; 20772a856b9aSJohnny Huang int ret; 20782a856b9aSJohnny Huang 20792a856b9aSJohnny Huang if (argc == 4) { 2080ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 20812a856b9aSJohnny Huang return CMD_RET_USAGE; 20822a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 20832a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 20843d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20852a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 20862a856b9aSJohnny Huang } else if (argc == 3) { 20872a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20882a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 20893d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20902a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 20912a856b9aSJohnny Huang } else { 20922a856b9aSJohnny Huang return CMD_RET_USAGE; 20932a856b9aSJohnny Huang } 20942a856b9aSJohnny Huang 20952a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20962a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20972a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20982a856b9aSJohnny Huang return CMD_RET_FAILURE; 20992a856b9aSJohnny Huang else 21002a856b9aSJohnny Huang return CMD_RET_USAGE; 21012a856b9aSJohnny Huang } 21022a856b9aSJohnny Huang 21032a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21042a856b9aSJohnny Huang { 21052a856b9aSJohnny Huang int mode = 0; 21062a856b9aSJohnny Huang int nconfirm = 0; 21072a856b9aSJohnny Huang int otp_addr = 0; 21082a856b9aSJohnny Huang int bit_offset; 21092a856b9aSJohnny Huang int value; 21102a856b9aSJohnny Huang int ret; 21112a856b9aSJohnny Huang 21122a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 21132a856b9aSJohnny Huang return CMD_RET_USAGE; 21142a856b9aSJohnny Huang 21152a856b9aSJohnny Huang /* Drop the pb cmd */ 21162a856b9aSJohnny Huang argc--; 21172a856b9aSJohnny Huang argv++; 21182a856b9aSJohnny Huang 21192a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2120a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 21212a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2122a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 21232a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2124a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2125cd1610b4SJohnny Huang else 21262a856b9aSJohnny Huang return CMD_RET_USAGE; 21272a856b9aSJohnny Huang 21282a856b9aSJohnny Huang /* Drop the region cmd */ 21292a856b9aSJohnny Huang argc--; 21302a856b9aSJohnny Huang argv++; 21312a856b9aSJohnny Huang 2132ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2133cd1610b4SJohnny Huang nconfirm = 1; 21342a856b9aSJohnny Huang /* Drop the force option */ 21352a856b9aSJohnny Huang argc--; 21362a856b9aSJohnny Huang argv++; 21372a856b9aSJohnny Huang } 2138cd1610b4SJohnny Huang 2139a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 21402a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 21412a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 21420808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 21432a856b9aSJohnny Huang return CMD_RET_USAGE; 2144cd1610b4SJohnny Huang } else { 21452a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 21462a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 21472a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 21480808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 21492a856b9aSJohnny Huang return CMD_RET_USAGE; 21500808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 215178855207SJohnny Huang if (otp_addr >= 0x800) 21520808cc55SJohnny Huang return CMD_RET_USAGE; 21530808cc55SJohnny Huang } else { 215478855207SJohnny Huang if (otp_addr >= 0x20) 21550808cc55SJohnny Huang return CMD_RET_USAGE; 21560808cc55SJohnny Huang } 2157cd1610b4SJohnny Huang } 2158cd1610b4SJohnny Huang if (value != 0 && value != 1) 21592a856b9aSJohnny Huang return CMD_RET_USAGE; 2160cd1610b4SJohnny Huang 21613d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 21622a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 21632a856b9aSJohnny Huang 21642a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 21652a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21662a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 21672a856b9aSJohnny Huang return CMD_RET_FAILURE; 21682a856b9aSJohnny Huang else 21692a856b9aSJohnny Huang return CMD_RET_USAGE; 21702a856b9aSJohnny Huang } 21712a856b9aSJohnny Huang 21722a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21732a856b9aSJohnny Huang { 21742a856b9aSJohnny Huang phys_addr_t addr; 21752a856b9aSJohnny Huang int otp_addr = 0; 21762a856b9aSJohnny Huang 21772a856b9aSJohnny Huang if (argc != 3) 21782a856b9aSJohnny Huang return CMD_RET_USAGE; 21792a856b9aSJohnny Huang 21803d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 21812a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 21822a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 21832a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 218469d5fd8fSJohnny Huang printf("Compare pass\n"); 21852a856b9aSJohnny Huang return CMD_RET_SUCCESS; 218669d5fd8fSJohnny Huang } else { 218769d5fd8fSJohnny Huang printf("Compare fail\n"); 21882a856b9aSJohnny Huang return CMD_RET_FAILURE; 218969d5fd8fSJohnny Huang } 219069d5fd8fSJohnny Huang } 219169d5fd8fSJohnny Huang 219266f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 219366f2f8e5SJohnny Huang { 2194a8bd6d8cSJohnny Huang int view = 0; 21952d4b0742SJohnny Huang int input; 2196a8bd6d8cSJohnny Huang 2197a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 219866f2f8e5SJohnny Huang return CMD_RET_USAGE; 219966f2f8e5SJohnny Huang 22002d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 220166f2f8e5SJohnny Huang 22023d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 22032d4b0742SJohnny Huang if (argc == 3) { 22042d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 22052d4b0742SJohnny Huang otp_print_conf_info(input); 22062d4b0742SJohnny Huang } else { 22072d4b0742SJohnny Huang otp_print_conf_info(-1); 22082d4b0742SJohnny Huang } 22092d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 22102d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2211a8bd6d8cSJohnny Huang view = 1; 2212a8bd6d8cSJohnny Huang /* Drop the view option */ 2213a8bd6d8cSJohnny Huang argc--; 2214a8bd6d8cSJohnny Huang argv++; 2215a8bd6d8cSJohnny Huang } 22163d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2217b458cd62SJohnny Huang otp_print_strap_info(view); 221866f2f8e5SJohnny Huang } else { 221966f2f8e5SJohnny Huang return CMD_RET_USAGE; 222066f2f8e5SJohnny Huang } 22212d4b0742SJohnny Huang 222266f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 222366f2f8e5SJohnny Huang } 222466f2f8e5SJohnny Huang 2225737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2226737ed20bSJohnny Huang { 2227737ed20bSJohnny Huang int input; 2228737ed20bSJohnny Huang int bit_offset; 2229737ed20bSJohnny Huang int prog_address; 2230737ed20bSJohnny Huang int pass; 2231737ed20bSJohnny Huang int i; 2232737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2233737ed20bSJohnny Huang return CMD_RET_USAGE; 2234737ed20bSJohnny Huang 2235ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2236737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2237737ed20bSJohnny Huang } else { 2238737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2239737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2240737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2241737ed20bSJohnny Huang if (!confirm_yesno()) { 2242737ed20bSJohnny Huang printf(" Aborting\n"); 2243737ed20bSJohnny Huang return CMD_RET_FAILURE; 2244737ed20bSJohnny Huang } 2245737ed20bSJohnny Huang } 2246737ed20bSJohnny Huang 2247737ed20bSJohnny Huang prog_address = 0x800; 2248737ed20bSJohnny Huang if (input < 32) { 2249737ed20bSJohnny Huang bit_offset = input; 2250737ed20bSJohnny Huang prog_address |= 0x60c; 2251737ed20bSJohnny Huang } else if (input < 64) { 2252737ed20bSJohnny Huang bit_offset = input - 32; 2253737ed20bSJohnny Huang prog_address |= 0x60e; 2254737ed20bSJohnny Huang } else { 2255737ed20bSJohnny Huang return CMD_RET_USAGE; 2256737ed20bSJohnny Huang } 2257737ed20bSJohnny Huang 2258737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2259737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2260737ed20bSJohnny Huang } 2261de6fbf1cSJohnny Huang 2262de6fbf1cSJohnny Huang otp_soak(1); 2263de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2264de6fbf1cSJohnny Huang pass = 0; 2265de6fbf1cSJohnny Huang 2266737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2267737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2268de6fbf1cSJohnny Huang otp_soak(2); 2269de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2270de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2271de6fbf1cSJohnny Huang otp_soak(1); 2272737ed20bSJohnny Huang } else { 2273de6fbf1cSJohnny Huang pass = 1; 2274de6fbf1cSJohnny Huang break; 2275de6fbf1cSJohnny Huang } 2276de6fbf1cSJohnny Huang } else { 2277de6fbf1cSJohnny Huang pass = 1; 2278737ed20bSJohnny Huang break; 2279737ed20bSJohnny Huang } 2280737ed20bSJohnny Huang } 2281de6fbf1cSJohnny Huang otp_soak(0); 2282de6fbf1cSJohnny Huang if (pass) { 2283737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2284737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2285737ed20bSJohnny Huang } 2286737ed20bSJohnny Huang 2287737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2288737ed20bSJohnny Huang return CMD_RET_FAILURE; 2289737ed20bSJohnny Huang 2290737ed20bSJohnny Huang } 22919a4fe690SJohnny Huang 22922a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 22932a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2294a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 22952a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 22962a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2297737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 22982a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 22992a856b9aSJohnny Huang }; 23002a856b9aSJohnny Huang 23012a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 23022a856b9aSJohnny Huang { 23032a856b9aSJohnny Huang cmd_tbl_t *cp; 23042a856b9aSJohnny Huang 23052a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 23062a856b9aSJohnny Huang 2307737ed20bSJohnny Huang /* Drop the otp command */ 23082a856b9aSJohnny Huang argc--; 23092a856b9aSJohnny Huang argv++; 23102a856b9aSJohnny Huang 23112a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 23122a856b9aSJohnny Huang return CMD_RET_USAGE; 23132a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 23142a856b9aSJohnny Huang return CMD_RET_SUCCESS; 23152a856b9aSJohnny Huang 2316*696656c6SJohnny Huang if (chip_version() == OTP_AST2600A0) { 2317*696656c6SJohnny Huang info_cb.version = OTP_AST2600A0; 23189a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 23199a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 23209a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 23219a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 23229a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 23239a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 2324*696656c6SJohnny Huang } else if (chip_version() == OTP_AST2600A1) { 2325*696656c6SJohnny Huang info_cb.version = OTP_AST2600A1; 23263cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 23273cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 23283cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 23293cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 23309a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 23319a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 23329a4fe690SJohnny Huang } 23339a4fe690SJohnny Huang 23342a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 233569d5fd8fSJohnny Huang } 233669d5fd8fSJohnny Huang 233769d5fd8fSJohnny Huang U_BOOT_CMD( 233869d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 233969d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 23402a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 23412a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 23422d4b0742SJohnny Huang "otp info strap [v]\n" 23432d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2344ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2345ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2346ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2347ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 23482a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 234969d5fd8fSJohnny Huang ); 2350