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> 23696656c6SJohnny 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 63696656c6SJohnny Huang #define OTP_MAGIC "SOCOTP" 64696656c6SJohnny Huang #define CHECKSUM_LEN 32 65696656c6SJohnny Huang #define OTP_INC_DATA (1 << 31) 66696656c6SJohnny Huang #define OTP_INC_CONFIG (1 << 30) 67696656c6SJohnny Huang #define OTP_INC_STRAP (1 << 29) 68696656c6SJohnny Huang #define OTP_ECC_EN (1 << 28) 69696656c6SJohnny Huang #define OTP_REGION_SIZE(info) ((info >> 16) & 0xffff) 70696656c6SJohnny Huang #define OTP_REGION_OFFSET(info) (info & 0xffff) 71696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info) (info & 0xffff) 72696656c6SJohnny Huang 73696656c6SJohnny Huang #define OTP_AST2600A0 0 74696656c6SJohnny Huang #define OTP_AST2600A1 1 75696656c6SJohnny Huang 76696656c6SJohnny Huang struct otp_header { 77696656c6SJohnny Huang u8 otp_magic[8]; 78696656c6SJohnny Huang u8 otp_version[8]; 79696656c6SJohnny Huang u32 image_info; 80696656c6SJohnny Huang u32 data_info; 81696656c6SJohnny Huang u32 config_info; 82696656c6SJohnny Huang u32 strap_info; 83696656c6SJohnny Huang u32 checksum_offset; 84696656c6SJohnny Huang } __attribute__((packed)); 85696656c6SJohnny 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; 915010032bSJohnny Huang int reg_protected; 9269d5fd8fSJohnny Huang int protected; 9369d5fd8fSJohnny Huang }; 9469d5fd8fSJohnny Huang 9566f2f8e5SJohnny Huang struct otpconf_parse { 9666f2f8e5SJohnny Huang int dw_offset; 9766f2f8e5SJohnny Huang int bit; 9866f2f8e5SJohnny Huang int length; 9966f2f8e5SJohnny Huang int value; 100696656c6SJohnny Huang int ignore; 10166f2f8e5SJohnny Huang char status[80]; 10266f2f8e5SJohnny Huang }; 10366f2f8e5SJohnny Huang 104a8bd6d8cSJohnny Huang struct otpstrap_info { 10579e42a59SJoel Stanley int8_t bit_offset; 10679e42a59SJoel Stanley int8_t length; 10779e42a59SJoel Stanley int8_t value; 10879e42a59SJoel Stanley char *information; 109a8bd6d8cSJohnny Huang }; 110a8bd6d8cSJohnny Huang 111a8bd6d8cSJohnny Huang struct otpconf_info { 11279e42a59SJoel Stanley int8_t dw_offset; 11379e42a59SJoel Stanley int8_t bit_offset; 11479e42a59SJoel Stanley int8_t length; 11579e42a59SJoel Stanley int8_t value; 11679e42a59SJoel Stanley char *information; 117a8bd6d8cSJohnny Huang }; 118a8bd6d8cSJohnny Huang 1199a4fe690SJohnny Huang struct otpkey_type { 1209a4fe690SJohnny Huang int value; 1219a4fe690SJohnny Huang int key_type; 1229a4fe690SJohnny Huang int need_id; 1239a4fe690SJohnny Huang char information[110]; 1249a4fe690SJohnny Huang }; 1259a4fe690SJohnny Huang 1269a4fe690SJohnny Huang struct otp_info_cb { 1279a4fe690SJohnny Huang int version; 12879e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1299a4fe690SJohnny Huang int strap_info_len; 13079e42a59SJoel Stanley const struct otpconf_info *conf_info; 1319a4fe690SJohnny Huang int conf_info_len; 13279e42a59SJoel Stanley const struct otpkey_type *key_info; 1339a4fe690SJohnny Huang int key_info_len; 1345010032bSJohnny Huang 1359a4fe690SJohnny Huang }; 1369a4fe690SJohnny Huang 137696656c6SJohnny Huang struct otp_image_layout { 1385010032bSJohnny Huang int data_length; 1395010032bSJohnny Huang int conf_length; 1405010032bSJohnny Huang int strap_length; 141696656c6SJohnny Huang uint8_t *data; 142696656c6SJohnny Huang uint8_t *data_ignore; 143696656c6SJohnny Huang uint8_t *conf; 144696656c6SJohnny Huang uint8_t *conf_ignore; 145696656c6SJohnny Huang uint8_t *strap; 146696656c6SJohnny Huang uint8_t *strap_reg_pro; 147696656c6SJohnny Huang uint8_t *strap_pro; 148696656c6SJohnny Huang uint8_t *strap_ignore; 149696656c6SJohnny Huang }; 150696656c6SJohnny Huang 1519a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1529a4fe690SJohnny Huang 15379e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = { 15491448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 15591448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 15691448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 15791448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 15891448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 15991448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 16091448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 16191448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 162541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 16391448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 16491448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 16591448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 16691448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 16791448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 16891448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 16991448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 17091448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 17191448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 17291448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 17391448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 17491448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 17591448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 17691448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 17791448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 17891448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 17991448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 18091448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 18191448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 18291448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 18391448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 18491448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 18591448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 18691448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 18791448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 18891448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 18991448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 19091448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 19191448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 19291448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 19391448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 19491448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 19591448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 19691448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 19791448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 19891448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 19991448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 20091448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 20191448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 20291448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 20391448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 20491448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 20591448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 20691448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 20791448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 20891448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 20991448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 21091448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 21191448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 21291448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 21391448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 21491448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 21591448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 21691448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 21791448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 21891448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 21991448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 22091448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 22191448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 22291448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 22391448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 22491448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 22591448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 22691448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 22791448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 22891448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 22991448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 23091448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 23191448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 23291448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 23391448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 23491448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 23591448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 23691448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 23791448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 23891448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 23991448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 24091448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 24191448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 24291448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 24391448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 24491448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 24591448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 24691448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 24791448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 24891448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 24991448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 25091448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 25191448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 25291448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 25391448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 25491448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 25591448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 25691448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 25791448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 25891448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 25991448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 26091448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 26191448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 26291448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 26376d13988SJohnny Huang }; 2649a4fe690SJohnny Huang 26579e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = { 2663cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2673cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2683cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2693cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2703cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2713cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2723cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2733cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2743cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2753cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2763cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2773cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2783cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2793cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2803cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2813cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2823cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2833cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2843cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2853cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2863cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2873cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2883cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2893cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2903cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2913cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2923cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2933cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2943cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2953cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2963cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2973cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2983cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2993cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 3003cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 3013cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 3023cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 3033cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 3043cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 3053cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 3063cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 3073cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 3083cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 3093cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 3103cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 3113cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 3123cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 3133cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 3143cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 3153cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 3163cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 3173cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 3183cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 3193cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 3203cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 3213cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 3223cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 3233cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 3243cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 3253cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 3263cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 3273cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 3283cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 3293cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 3303cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 3313cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 3323cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 3333cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 3343cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 3353cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 3363cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 3373cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 3383cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 3393cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3403cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3413cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3423cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3433cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3443cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3453cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3463cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3473cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3483cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3493cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3503cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3513cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3523cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3533cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3543cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3553cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3563cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3573cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3583cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3593cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3603cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3613cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3623cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3633cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3643cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3653cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3663cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3673cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3683cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3693cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3703cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3713cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3723cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3733cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3743cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3753cb28812SJohnny Huang }; 3763cb28812SJohnny Huang 37779e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = { 37891448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 37991448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 38091448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 38191448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 38291448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 38391448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 38491448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 38591448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 38691448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 38791448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 38891448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 38991448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 39091448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 39191448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 39291448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 39391448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 39491448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 395541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 39691448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 39791448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 39891448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 39991448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 40091448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 40191448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 40291448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 40391448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 40491448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 40591448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 40691448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 40791448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 40891448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 40991448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 41091448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 41191448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 41291448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 41391448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 41491448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 41591448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 41691448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 41791448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 41891448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 41991448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 42091448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 42191448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4223cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4233cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4243cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4253cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 4263cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 4273cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 4283cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 4293cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 4303cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 4313cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 4323cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 4333cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 4343cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 4353cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 4363cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 4373cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 4383cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 4393cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4403cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4413cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4423cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4433cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4443cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4453cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4463cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4473cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4483cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4493cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4503cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4513cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4523cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4533cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4543cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4553cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4563cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4573cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4583cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4593cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4603cb28812SJohnny Huang }; 4613cb28812SJohnny Huang 46279e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = { 4633cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4643cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4653cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4663cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4673cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4683cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4693cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4703cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4713cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4723cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4733cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4743cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4753cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4763cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4773cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4783cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4793cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4803cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4813cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4823cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4833cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4843cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4853cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4863cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4873cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4883cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 489bb34a7bfSJohnny Huang { 0, 14, 1, 0, "Disable Patch code" }, 490bb34a7bfSJohnny Huang { 0, 14, 1, 1, "Enable Patch code" }, 491bb34a7bfSJohnny Huang { 0, 15, 1, OTP_REG_RESERVED, "" }, 4923cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4933cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4943cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4953cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4963cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4973cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4983cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4993cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 5003cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 5013cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 5023cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 5033cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 5043cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 5053cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 5063cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 5073cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 5083cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 5093cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 5103cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 5113cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 51291448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 51391448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 51491448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 51573f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 51673f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 51791448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 51891448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 51991448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 52091448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 52191448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 52291448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 52391448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 52491448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 52591448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 52691448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 52791448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 52891448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 52991448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 53091448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 53191448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 53291448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 53391448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 53491448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 53591448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 53691448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 53791448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 53891448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 53991448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 54091448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 54191448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 54291448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 54391448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 54491448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 545bb34a7bfSJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }, 546bb34a7bfSJohnny Huang { 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" }, 547bb34a7bfSJohnny Huang { 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" } 548b458cd62SJohnny Huang }; 5499a4fe690SJohnny Huang 55079e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 5519a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5529a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5539a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5549a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5559a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5569a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5579a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5589a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5599a4fe690SJohnny Huang }; 5609a4fe690SJohnny Huang 56179e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 5629a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5639a4fe690SJohnny 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"}, 5649a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5659a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5669a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5679a4fe690SJohnny Huang }; 5689a4fe690SJohnny Huang 5699a4fe690SJohnny Huang static uint32_t chip_version(void) 5709a4fe690SJohnny Huang { 5719a4fe690SJohnny Huang uint32_t rev_id; 5729a4fe690SJohnny Huang 5739a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5749a4fe690SJohnny Huang 5759a4fe690SJohnny Huang return rev_id; 5769a4fe690SJohnny Huang } 5779a4fe690SJohnny Huang 5783d3688adSJohnny Huang static void wait_complete(void) 5793d3688adSJohnny Huang { 5803d3688adSJohnny Huang int reg; 5813d3688adSJohnny Huang 5823d3688adSJohnny Huang do { 5833d3688adSJohnny Huang reg = readl(OTP_STATUS); 5843d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5853d3688adSJohnny Huang } 5863d3688adSJohnny Huang 5872a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 58869d5fd8fSJohnny Huang { 5893d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5903d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5913d3688adSJohnny Huang wait_complete(); 5923d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5933d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 59469d5fd8fSJohnny Huang } 59569d5fd8fSJohnny Huang 5962a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 59769d5fd8fSJohnny Huang { 59869d5fd8fSJohnny Huang int config_offset; 59969d5fd8fSJohnny Huang 60069d5fd8fSJohnny Huang config_offset = 0x800; 60169d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 60269d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 60369d5fd8fSJohnny Huang 6043d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 6053d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6063d3688adSJohnny Huang wait_complete(); 6073d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 60869d5fd8fSJohnny Huang } 60969d5fd8fSJohnny Huang 61069d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 61169d5fd8fSJohnny Huang { 61269d5fd8fSJohnny Huang int i; 61369d5fd8fSJohnny Huang uint32_t ret[1]; 61469d5fd8fSJohnny Huang 61569d5fd8fSJohnny Huang if (offset + dw_count > 32) 6162a856b9aSJohnny Huang return OTP_USAGE; 61769d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 61869d5fd8fSJohnny Huang otp_read_config(i, ret); 619a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 62069d5fd8fSJohnny Huang } 62169d5fd8fSJohnny Huang printf("\n"); 6222a856b9aSJohnny Huang return OTP_SUCCESS; 62369d5fd8fSJohnny Huang } 62469d5fd8fSJohnny Huang 62569d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 62669d5fd8fSJohnny Huang { 62769d5fd8fSJohnny Huang int i; 62869d5fd8fSJohnny Huang uint32_t ret[2]; 62969d5fd8fSJohnny Huang 63069d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 6312a856b9aSJohnny Huang return OTP_USAGE; 63269d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 63369d5fd8fSJohnny Huang otp_read_data(i, ret); 63469d5fd8fSJohnny Huang if (i % 4 == 0) 63569d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 63669d5fd8fSJohnny Huang else 63769d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 63869d5fd8fSJohnny Huang 63969d5fd8fSJohnny Huang } 64069d5fd8fSJohnny Huang printf("\n"); 6412a856b9aSJohnny Huang return OTP_SUCCESS; 64269d5fd8fSJohnny Huang } 64369d5fd8fSJohnny Huang 64469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 64569d5fd8fSJohnny Huang { 64669d5fd8fSJohnny Huang uint32_t ret; 64769d5fd8fSJohnny Huang uint32_t *buf; 64869d5fd8fSJohnny Huang 64969d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 65069d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 65169d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 65269d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 65369d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6543d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6553d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6563d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6573d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6583d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6593d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6603d3688adSJohnny Huang wait_complete(); 6613d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 66269d5fd8fSJohnny Huang if (ret & 0x1) 66369d5fd8fSJohnny Huang return 0; 66469d5fd8fSJohnny Huang else 66569d5fd8fSJohnny Huang return -1; 66669d5fd8fSJohnny Huang } 66769d5fd8fSJohnny Huang 66869d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 66969d5fd8fSJohnny Huang { 6703d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6713d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6723d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6733d3688adSJohnny Huang wait_complete(); 67469d5fd8fSJohnny Huang } 67569d5fd8fSJohnny Huang 67669d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 67769d5fd8fSJohnny Huang { 6783d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6793d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6803d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6813d3688adSJohnny Huang wait_complete(); 68269d5fd8fSJohnny Huang } 68369d5fd8fSJohnny Huang 684a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 68569d5fd8fSJohnny Huang { 68630a8c590SJohnny Huang uint32_t ret[2]; 68769d5fd8fSJohnny Huang 68830a8c590SJohnny Huang if (otp_addr % 2 == 0) 6893d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 69030a8c590SJohnny Huang else 6913d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 69230a8c590SJohnny Huang 6933d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6943d3688adSJohnny Huang wait_complete(); 6953d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6963d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 697a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 69830a8c590SJohnny Huang if (otp_addr % 2 == 0) { 69930a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 70069d5fd8fSJohnny Huang return 0; 70169d5fd8fSJohnny Huang else 70269d5fd8fSJohnny Huang return -1; 70330a8c590SJohnny Huang } else { 70430a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 70530a8c590SJohnny Huang return 0; 70630a8c590SJohnny Huang else 70730a8c590SJohnny Huang return -1; 70830a8c590SJohnny Huang } 70930a8c590SJohnny Huang 71069d5fd8fSJohnny Huang } 71169d5fd8fSJohnny Huang 712696656c6SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *ignore, uint32_t *compare, int size) 7134c1c9b35SJohnny Huang { 7144c1c9b35SJohnny Huang uint32_t ret[2]; 7154c1c9b35SJohnny Huang 7164c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 7174c1c9b35SJohnny Huang 7184c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 7193d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 7204c1c9b35SJohnny Huang else 7213d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 7223d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 7233d3688adSJohnny Huang wait_complete(); 7243d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 7253d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 7264c1c9b35SJohnny Huang if (size == 1) { 7274c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 7284c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 729696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) { 7304c1c9b35SJohnny Huang compare[0] = 0; 7314c1c9b35SJohnny Huang return 0; 7324c1c9b35SJohnny Huang } else { 7334c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7344c1c9b35SJohnny Huang return -1; 7354c1c9b35SJohnny Huang } 7364c1c9b35SJohnny Huang 7374c1c9b35SJohnny Huang } else { 7384c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 739696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) { 7404c1c9b35SJohnny Huang compare[0] = ~0; 7414c1c9b35SJohnny Huang return 0; 7424c1c9b35SJohnny Huang } else { 743d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7444c1c9b35SJohnny Huang return -1; 7454c1c9b35SJohnny Huang } 7464c1c9b35SJohnny Huang } 7474c1c9b35SJohnny Huang } else if (size == 2) { 7484c1c9b35SJohnny Huang // otp_addr should be even 749696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) { 7504c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7514c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7524c1c9b35SJohnny Huang compare[0] = 0; 7534c1c9b35SJohnny Huang compare[1] = ~0; 7544c1c9b35SJohnny Huang return 0; 7554c1c9b35SJohnny Huang } else { 7564c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7574c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7584c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7594c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7604c1c9b35SJohnny Huang return -1; 7614c1c9b35SJohnny Huang } 7624c1c9b35SJohnny Huang } else { 7634c1c9b35SJohnny Huang return -1; 7644c1c9b35SJohnny Huang } 7654c1c9b35SJohnny Huang } 7664c1c9b35SJohnny Huang 7677e22f42dSJohnny Huang static void otp_soak(int soak) 768d90825e2SJohnny Huang { 769de6fbf1cSJohnny Huang switch (soak) { 770de6fbf1cSJohnny Huang case 0: //default 771de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 772de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 773de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 774de6fbf1cSJohnny Huang break; 775de6fbf1cSJohnny Huang case 1: //normal program 776de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 777de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 778de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 779de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 780de6fbf1cSJohnny Huang break; 781de6fbf1cSJohnny Huang case 2: //soak program 782d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 783d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 784d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 785de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 786de6fbf1cSJohnny Huang break; 787d90825e2SJohnny Huang } 788de6fbf1cSJohnny Huang 7893d3688adSJohnny Huang wait_complete(); 790d90825e2SJohnny Huang } 791d90825e2SJohnny Huang 792696656c6SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t ignore, uint32_t prog_address) 793d90825e2SJohnny Huang { 794d90825e2SJohnny Huang int j, bit_value, prog_bit; 795d90825e2SJohnny Huang 796d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 797696656c6SJohnny Huang if ((ignore >> j) & 0x1) 798d90825e2SJohnny Huang continue; 799d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 800d90825e2SJohnny Huang if (prog_address % 2 == 0) { 801d90825e2SJohnny Huang if (bit_value) 802d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 803d90825e2SJohnny Huang else 804d90825e2SJohnny Huang continue; 805d90825e2SJohnny Huang } else { 806d90825e2SJohnny Huang prog_address |= 1 << 15; 807d90825e2SJohnny Huang if (bit_value) 808d90825e2SJohnny Huang continue; 809d90825e2SJohnny Huang else 810d90825e2SJohnny Huang prog_bit = 0x1 << j; 811d90825e2SJohnny Huang } 812d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 813d90825e2SJohnny Huang } 814d90825e2SJohnny Huang } 815d90825e2SJohnny Huang 81654552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address) 81754552c69SJohnny Huang { 81854552c69SJohnny Huang int pass; 81954552c69SJohnny Huang int i; 82054552c69SJohnny Huang uint32_t data0_masked; 82154552c69SJohnny Huang uint32_t data1_masked; 82254552c69SJohnny Huang uint32_t buf0_masked; 82354552c69SJohnny Huang uint32_t buf1_masked; 82454552c69SJohnny Huang uint32_t compare[2]; 82554552c69SJohnny Huang 82654552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 82754552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 82854552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 82954552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 83054552c69SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) 83154552c69SJohnny Huang return 0; 83254552c69SJohnny Huang 83354552c69SJohnny Huang otp_soak(1); 83454552c69SJohnny Huang if (data0_masked != buf0_masked) 83554552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 83654552c69SJohnny Huang if (data1_masked != buf1_masked) 83754552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 83854552c69SJohnny Huang 83954552c69SJohnny Huang pass = 0; 84054552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 84154552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 84254552c69SJohnny Huang otp_soak(2); 84354552c69SJohnny Huang if (compare[0] != 0) { 84454552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 84554552c69SJohnny Huang } 84654552c69SJohnny Huang if (compare[1] != ~0) { 84754552c69SJohnny Huang otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1); 84854552c69SJohnny Huang } 84954552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 85054552c69SJohnny Huang otp_soak(1); 85154552c69SJohnny Huang } else { 85254552c69SJohnny Huang pass = 1; 85354552c69SJohnny Huang break; 85454552c69SJohnny Huang } 85554552c69SJohnny Huang } else { 85654552c69SJohnny Huang pass = 1; 85754552c69SJohnny Huang break; 85854552c69SJohnny Huang } 85954552c69SJohnny Huang } 86054552c69SJohnny Huang 86154552c69SJohnny Huang if (!pass) { 86254552c69SJohnny Huang otp_soak(0); 86354552c69SJohnny Huang return OTP_FAILURE; 86454552c69SJohnny Huang } 86554552c69SJohnny Huang return OTP_SUCCESS; 86654552c69SJohnny Huang } 86754552c69SJohnny Huang 86876d13988SJohnny Huang 869541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 87076d13988SJohnny Huang { 87176d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 8725010032bSJohnny Huang int strap_end; 87376d13988SJohnny Huang int i, j; 87476d13988SJohnny Huang 8755010032bSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 87676d13988SJohnny Huang for (j = 0; j < 64; j++) { 87776d13988SJohnny Huang otpstrap[j].value = 0; 87876d13988SJohnny Huang otpstrap[j].remain_times = 7; 87976d13988SJohnny Huang otpstrap[j].writeable_option = -1; 88076d13988SJohnny Huang otpstrap[j].protected = 0; 88176d13988SJohnny Huang } 8825010032bSJohnny Huang strap_end = 30; 8835010032bSJohnny Huang } else { 8845010032bSJohnny Huang for (j = 0; j < 64; j++) { 8855010032bSJohnny Huang otpstrap[j].value = 0; 8865010032bSJohnny Huang otpstrap[j].remain_times = 6; 8875010032bSJohnny Huang otpstrap[j].writeable_option = -1; 8885010032bSJohnny Huang otpstrap[j].reg_protected = 0; 8895010032bSJohnny Huang otpstrap[j].protected = 0; 8905010032bSJohnny Huang } 8915010032bSJohnny Huang strap_end = 28; 8925010032bSJohnny Huang } 89376d13988SJohnny Huang 8945010032bSJohnny Huang for (i = 16; i < strap_end; i += 2) { 89576d13988SJohnny Huang int option = (i - 16) / 2; 89676d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 89776d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 89876d13988SJohnny Huang for (j = 0; j < 32; j++) { 89976d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 90076d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 90176d13988SJohnny Huang otpstrap[j].writeable_option = option; 90276d13988SJohnny Huang } 90376d13988SJohnny Huang if (bit_value == 1) 90476d13988SJohnny Huang otpstrap[j].remain_times --; 90576d13988SJohnny Huang otpstrap[j].value ^= bit_value; 90676d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 90776d13988SJohnny Huang } 90876d13988SJohnny Huang for (j = 32; j < 64; j++) { 90976d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 91076d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 91176d13988SJohnny Huang otpstrap[j].writeable_option = option; 91276d13988SJohnny Huang } 91376d13988SJohnny Huang if (bit_value == 1) 91476d13988SJohnny Huang otpstrap[j].remain_times --; 91576d13988SJohnny Huang otpstrap[j].value ^= bit_value; 91676d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 91776d13988SJohnny Huang } 91876d13988SJohnny Huang } 9195010032bSJohnny Huang 9205010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 9215010032bSJohnny Huang otp_read_config(28, &OTPSTRAP_RAW[0]); 9225010032bSJohnny Huang otp_read_config(29, &OTPSTRAP_RAW[1]); 9235010032bSJohnny Huang for (j = 0; j < 32; j++) { 9245010032bSJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 9255010032bSJohnny Huang otpstrap[j].reg_protected = 1; 9265010032bSJohnny Huang } 9275010032bSJohnny Huang for (j = 32; j < 64; j++) { 9285010032bSJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 9295010032bSJohnny Huang otpstrap[j].reg_protected = 1; 9305010032bSJohnny Huang } 9315010032bSJohnny Huang 9325010032bSJohnny Huang } 9335010032bSJohnny Huang 93476d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 93576d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 93676d13988SJohnny Huang for (j = 0; j < 32; j++) { 93776d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 93876d13988SJohnny Huang otpstrap[j].protected = 1; 93976d13988SJohnny Huang } 94076d13988SJohnny Huang for (j = 32; j < 64; j++) { 94176d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 94276d13988SJohnny Huang otpstrap[j].protected = 1; 94376d13988SJohnny Huang } 94476d13988SJohnny Huang } 94576d13988SJohnny Huang 946696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout) 94769d5fd8fSJohnny Huang { 94879e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 949696656c6SJohnny Huang uint32_t *OTPCFG = (uint32_t *)image_layout->conf; 950696656c6SJohnny Huang uint32_t *OTPCFG_IGNORE = (uint32_t *)image_layout->conf_ignore; 951b458cd62SJohnny Huang uint32_t mask; 952b458cd62SJohnny Huang uint32_t dw_offset; 953b458cd62SJohnny Huang uint32_t bit_offset; 954b458cd62SJohnny Huang uint32_t otp_value; 955696656c6SJohnny Huang uint32_t otp_ignore; 956b458cd62SJohnny Huang int fail = 0; 95773f11549SJohnny Huang char valid_bit[20]; 95866f2f8e5SJohnny Huang int i; 95973f11549SJohnny Huang int j; 96066f2f8e5SJohnny Huang 961737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 96266f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 9633cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9643cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9653cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9663cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 967b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 968696656c6SJohnny Huang otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask; 969b458cd62SJohnny Huang 970696656c6SJohnny Huang if (otp_ignore == mask) { 971b458cd62SJohnny Huang continue; 972696656c6SJohnny Huang } else if (otp_ignore != 0) { 973b458cd62SJohnny Huang fail = 1; 974b458cd62SJohnny Huang } 975b458cd62SJohnny Huang 9763cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9773cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9783cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9793cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 980b458cd62SJohnny Huang continue; 981b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 982b458cd62SJohnny Huang 9833cb28812SJohnny Huang if (conf_info[i].length == 1) { 9843cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 98566f2f8e5SJohnny Huang } else { 986b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9873cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9883cb28812SJohnny Huang conf_info[i].bit_offset); 98966f2f8e5SJohnny Huang } 990b458cd62SJohnny Huang printf("0x%-10x", otp_value); 991b458cd62SJohnny Huang 992b458cd62SJohnny Huang if (fail) { 993696656c6SJohnny Huang printf("Ignore mask error\n"); 994b458cd62SJohnny Huang } else { 9953cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 996b458cd62SJohnny Huang printf("Reserved\n"); 9973cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9983cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 999b458cd62SJohnny Huang printf("\n"); 10003cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1001b458cd62SJohnny Huang if (otp_value != 0) { 100273f11549SJohnny Huang for (j = 0; j < 7; j++) { 100373f11549SJohnny Huang if (otp_value == (1 << j)) { 100473f11549SJohnny Huang valid_bit[j * 2] = '1'; 1005b458cd62SJohnny Huang } else { 100673f11549SJohnny Huang valid_bit[j * 2] = '0'; 100773f11549SJohnny Huang } 100873f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 100973f11549SJohnny Huang } 101073f11549SJohnny Huang valid_bit[15] = 0; 101173f11549SJohnny Huang } else { 101273f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1013b458cd62SJohnny Huang } 10143cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1015b458cd62SJohnny Huang printf("\n"); 1016b458cd62SJohnny Huang } else { 10173cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1018b458cd62SJohnny Huang } 1019b458cd62SJohnny Huang } 1020b458cd62SJohnny Huang } 1021b458cd62SJohnny Huang 1022b458cd62SJohnny Huang if (fail) 1023b458cd62SJohnny Huang return OTP_FAILURE; 1024b458cd62SJohnny Huang 102566f2f8e5SJohnny Huang return OTP_SUCCESS; 102666f2f8e5SJohnny Huang } 102766f2f8e5SJohnny Huang 10282d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 102966f2f8e5SJohnny Huang { 103079e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 1031bb34a7bfSJohnny Huang uint32_t OTPCFG[16]; 1032b458cd62SJohnny Huang uint32_t mask; 1033b458cd62SJohnny Huang uint32_t dw_offset; 1034b458cd62SJohnny Huang uint32_t bit_offset; 1035b458cd62SJohnny Huang uint32_t otp_value; 103673f11549SJohnny Huang char valid_bit[20]; 103766f2f8e5SJohnny Huang int i; 103873f11549SJohnny Huang int j; 103966f2f8e5SJohnny Huang 1040bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 104166f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 104266f2f8e5SJohnny Huang 104366f2f8e5SJohnny Huang 1044b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 1045b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 10463cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 10473cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 10482d4b0742SJohnny Huang continue; 10493cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 10503cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 10513cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 1052b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 1053b458cd62SJohnny Huang 10543cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 10553cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 10563cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 10573cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 1058b458cd62SJohnny Huang continue; 1059b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 1060b458cd62SJohnny Huang 10613cb28812SJohnny Huang if (conf_info[i].length == 1) { 10623cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 1063b458cd62SJohnny Huang } else { 1064b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10653cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 10663cb28812SJohnny Huang conf_info[i].bit_offset); 1067b458cd62SJohnny Huang } 1068b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1069b458cd62SJohnny Huang 10703cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1071b458cd62SJohnny Huang printf("Reserved\n"); 10723cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10733cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1074b458cd62SJohnny Huang printf("\n"); 10753cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1076b458cd62SJohnny Huang if (otp_value != 0) { 107773f11549SJohnny Huang for (j = 0; j < 7; j++) { 107873f11549SJohnny Huang if (otp_value == (1 << j)) { 107973f11549SJohnny Huang valid_bit[j * 2] = '1'; 1080b458cd62SJohnny Huang } else { 108173f11549SJohnny Huang valid_bit[j * 2] = '0'; 108273f11549SJohnny Huang } 108373f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 108473f11549SJohnny Huang } 108573f11549SJohnny Huang valid_bit[15] = 0; 108673f11549SJohnny Huang } else { 108773f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1088b458cd62SJohnny Huang } 10893cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1090b458cd62SJohnny Huang printf("\n"); 1091b458cd62SJohnny Huang } else { 10923cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1093b458cd62SJohnny Huang } 1094b458cd62SJohnny Huang } 1095b458cd62SJohnny Huang return OTP_SUCCESS; 109666f2f8e5SJohnny Huang } 109766f2f8e5SJohnny Huang 10985010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout) 109976d13988SJohnny Huang { 110079e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1101696656c6SJohnny Huang uint32_t *OTPSTRAP; 1102696656c6SJohnny Huang uint32_t *OTPSTRAP_REG_PRO; 1103696656c6SJohnny Huang uint32_t *OTPSTRAP_PRO; 1104696656c6SJohnny Huang uint32_t *OTPSTRAP_IGNORE; 110576d13988SJohnny Huang int i; 1106a8bd6d8cSJohnny Huang int fail = 0; 1107a8bd6d8cSJohnny Huang uint32_t bit_offset; 1108a8bd6d8cSJohnny Huang uint32_t dw_offset; 1109a8bd6d8cSJohnny Huang uint32_t mask; 1110a8bd6d8cSJohnny Huang uint32_t otp_value; 1111696656c6SJohnny Huang uint32_t otp_reg_protect; 1112a8bd6d8cSJohnny Huang uint32_t otp_protect; 1113696656c6SJohnny Huang uint32_t otp_ignore; 111476d13988SJohnny Huang 1115696656c6SJohnny Huang OTPSTRAP = (uint32_t *)image_layout->strap; 1116696656c6SJohnny Huang OTPSTRAP_PRO = (uint32_t *)image_layout->strap_pro; 1117696656c6SJohnny Huang OTPSTRAP_IGNORE = (uint32_t *)image_layout->strap_ignore; 11185010032bSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 1119696656c6SJohnny Huang OTPSTRAP_REG_PRO = NULL; 1120a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1121696656c6SJohnny Huang } else { 1122696656c6SJohnny Huang OTPSTRAP_REG_PRO = (uint32_t *)image_layout->strap_reg_pro; 1123*de6b0cc4SJohnny Huang printf("BIT(hex) Value Reg_Protect Protect Description\n"); 1124696656c6SJohnny Huang } 1125*de6b0cc4SJohnny Huang printf("__________________________________________________________________________________________\n"); 1126b458cd62SJohnny Huang 11273cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1128696656c6SJohnny Huang if (strap_info[i].bit_offset > 31) { 1129a8bd6d8cSJohnny Huang dw_offset = 1; 11303cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1131a8bd6d8cSJohnny Huang } else { 1132a8bd6d8cSJohnny Huang dw_offset = 0; 11333cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1134a8bd6d8cSJohnny Huang } 113576d13988SJohnny Huang 11363cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1137a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1138a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1139696656c6SJohnny Huang otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask; 1140a8bd6d8cSJohnny Huang 11415010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) 1142696656c6SJohnny Huang otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask; 11435010032bSJohnny Huang else 11445010032bSJohnny Huang otp_reg_protect = 0; 1145696656c6SJohnny Huang 1146696656c6SJohnny Huang if (otp_ignore == mask) { 1147a8bd6d8cSJohnny Huang continue; 1148696656c6SJohnny Huang } else if (otp_ignore != 0) { 1149a8bd6d8cSJohnny Huang fail = 1; 1150a8bd6d8cSJohnny Huang } 1151a8bd6d8cSJohnny Huang 11523cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11533cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1154a8bd6d8cSJohnny Huang continue; 1155a8bd6d8cSJohnny Huang 11563cb28812SJohnny Huang if (strap_info[i].length == 1) { 11573cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1158a8bd6d8cSJohnny Huang } else { 1159b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 11603cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 11613cb28812SJohnny Huang strap_info[i].bit_offset); 1162a8bd6d8cSJohnny Huang } 1163a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 11645010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) 1165696656c6SJohnny Huang printf("0x%-10x", otp_reg_protect); 1166a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1167a8bd6d8cSJohnny Huang 1168a8bd6d8cSJohnny Huang if (fail) { 1169696656c6SJohnny Huang printf("Ignore mask error\n"); 1170a8bd6d8cSJohnny Huang } else { 11713cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11723cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1173a8bd6d8cSJohnny Huang else 1174a8bd6d8cSJohnny Huang printf("Reserved\n"); 1175a8bd6d8cSJohnny Huang } 1176a8bd6d8cSJohnny Huang } 1177a8bd6d8cSJohnny Huang 1178a8bd6d8cSJohnny Huang if (fail) 117976d13988SJohnny Huang return OTP_FAILURE; 118076d13988SJohnny Huang 118176d13988SJohnny Huang return OTP_SUCCESS; 118276d13988SJohnny Huang } 118376d13988SJohnny Huang 1184b458cd62SJohnny Huang static int otp_print_strap_info(int view) 118576d13988SJohnny Huang { 118679e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 118776d13988SJohnny Huang struct otpstrap_status strap_status[64]; 118807baa4e8SJohnny Huang int i, j; 1189b458cd62SJohnny Huang int fail = 0; 1190b458cd62SJohnny Huang uint32_t bit_offset; 1191b458cd62SJohnny Huang uint32_t length; 1192b458cd62SJohnny Huang uint32_t otp_value; 1193b458cd62SJohnny Huang uint32_t otp_protect; 119476d13988SJohnny Huang 1195541eb887SJohnny Huang otp_strap_status(strap_status); 119676d13988SJohnny Huang 1197b458cd62SJohnny Huang if (view) { 119807baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 119907baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 120007baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 120107baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1202b458cd62SJohnny Huang } else { 1203b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1204b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 120576d13988SJohnny Huang } 12063cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1207b458cd62SJohnny Huang otp_value = 0; 12083cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 12093cb28812SJohnny Huang length = strap_info[i].length; 1210b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1211c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1212c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1213b458cd62SJohnny Huang } 12143cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 12153cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1216b458cd62SJohnny Huang continue; 1217b458cd62SJohnny Huang if (view) { 1218b458cd62SJohnny Huang for (j = 0; j < length; j++) { 12193cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1220b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 122107baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1222b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 12233cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1224b458cd62SJohnny Huang printf(" Reserved\n"); 1225b458cd62SJohnny Huang continue; 1226b458cd62SJohnny Huang } 1227b458cd62SJohnny Huang if (length == 1) { 12283cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1229b458cd62SJohnny Huang continue; 123076d13988SJohnny Huang } 123176d13988SJohnny Huang 1232b458cd62SJohnny Huang if (j == 0) 12333cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1234b458cd62SJohnny Huang else if (j == length - 1) 1235b458cd62SJohnny Huang printf("\\ \"\n"); 1236b458cd62SJohnny Huang else 1237b458cd62SJohnny Huang printf("| \"\n"); 123876d13988SJohnny Huang } 1239b458cd62SJohnny Huang } else { 1240c947ef08SJohnny Huang if (length == 1) { 12413cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1242b458cd62SJohnny Huang } else { 1243b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1244b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1245b458cd62SJohnny Huang } 1246b458cd62SJohnny Huang 1247b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1248b458cd62SJohnny Huang 12493cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 12503cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1251b458cd62SJohnny Huang else 1252b458cd62SJohnny Huang printf("Reserved\n"); 1253b458cd62SJohnny Huang } 1254b458cd62SJohnny Huang } 1255b458cd62SJohnny Huang 1256b458cd62SJohnny Huang if (fail) 1257b458cd62SJohnny Huang return OTP_FAILURE; 1258b458cd62SJohnny Huang 1259b458cd62SJohnny Huang return OTP_SUCCESS; 1260b458cd62SJohnny Huang } 1261b458cd62SJohnny Huang 1262696656c6SJohnny Huang static void buf_print(uint8_t *buf, int len) 126369d5fd8fSJohnny Huang { 126469d5fd8fSJohnny Huang int i; 126569d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 126669d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 126769d5fd8fSJohnny Huang if (i % 16 == 0) { 126869d5fd8fSJohnny Huang printf("%04X: ", i); 126969d5fd8fSJohnny Huang } 127069d5fd8fSJohnny Huang printf("%02X ", buf[i]); 127169d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 127269d5fd8fSJohnny Huang printf("\n"); 127369d5fd8fSJohnny Huang } 127469d5fd8fSJohnny Huang } 127569d5fd8fSJohnny Huang } 127669d5fd8fSJohnny Huang 1277696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout) 127869d5fd8fSJohnny Huang { 127969d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 128079e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 12819a4fe690SJohnny Huang struct otpkey_type key_info; 1282696656c6SJohnny Huang uint32_t *buf; 1283696656c6SJohnny Huang uint8_t *byte_buf; 12849d998018SJohnny Huang char empty = 1; 128569d5fd8fSJohnny Huang int i = 0, len = 0; 12869a4fe690SJohnny Huang int j; 128754552c69SJohnny Huang 1288696656c6SJohnny Huang byte_buf = image_layout->data; 1289696656c6SJohnny Huang buf = (uint32_t *)byte_buf; 12909d998018SJohnny Huang 12919d998018SJohnny Huang for (i = 0; i < 16; i++) { 12929d998018SJohnny Huang if (buf[i] != 0) { 12939d998018SJohnny Huang empty = 0; 12949d998018SJohnny Huang } 12959d998018SJohnny Huang } 12969d998018SJohnny Huang if (empty) 12979d998018SJohnny Huang return 0; 12989d998018SJohnny Huang 12999d998018SJohnny Huang i = 0; 130069d5fd8fSJohnny Huang while (1) { 130169d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 130269d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 130369d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 130469d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 130569d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 130669d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 13079a4fe690SJohnny Huang 13089a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 13099a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 13109a4fe690SJohnny Huang key_info = key_info_array[j]; 13119a4fe690SJohnny Huang break; 13129a4fe690SJohnny Huang } 13139a4fe690SJohnny Huang } 13149a4fe690SJohnny Huang 13157f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 131669d5fd8fSJohnny Huang printf("Key Type: "); 13179a4fe690SJohnny Huang printf("%s\n", key_info.information); 13189a4fe690SJohnny Huang 13199a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 132069d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 132169d5fd8fSJohnny Huang switch (key_length) { 132269d5fd8fSJohnny Huang case 0: 132369d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 132469d5fd8fSJohnny Huang break; 132569d5fd8fSJohnny Huang case 1: 132669d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 132769d5fd8fSJohnny Huang break; 132869d5fd8fSJohnny Huang case 2: 132969d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 133069d5fd8fSJohnny Huang break; 133169d5fd8fSJohnny Huang case 3: 133269d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 133369d5fd8fSJohnny Huang break; 133469d5fd8fSJohnny Huang } 13359a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 133669d5fd8fSJohnny Huang printf("RSA SHA Type: "); 133769d5fd8fSJohnny Huang switch (key_length) { 133869d5fd8fSJohnny Huang case 0: 133969d5fd8fSJohnny Huang printf("RSA1024\n"); 134069d5fd8fSJohnny Huang len = 0x100; 134169d5fd8fSJohnny Huang break; 134269d5fd8fSJohnny Huang case 1: 134369d5fd8fSJohnny Huang printf("RSA2048\n"); 134469d5fd8fSJohnny Huang len = 0x200; 134569d5fd8fSJohnny Huang break; 134669d5fd8fSJohnny Huang case 2: 134769d5fd8fSJohnny Huang printf("RSA3072\n"); 134869d5fd8fSJohnny Huang len = 0x300; 134969d5fd8fSJohnny Huang break; 135069d5fd8fSJohnny Huang case 3: 135169d5fd8fSJohnny Huang printf("RSA4096\n"); 135269d5fd8fSJohnny Huang len = 0x400; 135369d5fd8fSJohnny Huang break; 135469d5fd8fSJohnny Huang } 135569d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 135669d5fd8fSJohnny Huang } 13579a4fe690SJohnny Huang if (key_info.need_id) 135869d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 135969d5fd8fSJohnny Huang printf("Key Value:\n"); 13609a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 136169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 13629a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 13639a4fe690SJohnny Huang printf("AES Key:\n"); 13649a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 13659a4fe690SJohnny Huang if (info_cb.version == 0) { 13669a4fe690SJohnny Huang printf("AES IV:\n"); 13679a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 13689a4fe690SJohnny Huang } 13699a4fe690SJohnny Huang 13709a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 13719a4fe690SJohnny Huang if (info_cb.version == 0) { 137269d5fd8fSJohnny Huang printf("AES Key:\n"); 137369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 137469d5fd8fSJohnny Huang printf("AES IV:\n"); 137569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 13769a4fe690SJohnny Huang } else if (info_cb.version == 1) { 13779a4fe690SJohnny Huang printf("AES Key 1:\n"); 13789a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 13799a4fe690SJohnny Huang printf("AES Key 2:\n"); 13809a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 13819a4fe690SJohnny Huang } 138269d5fd8fSJohnny Huang 13839a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 138469d5fd8fSJohnny Huang printf("RSA mod:\n"); 138569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 138669d5fd8fSJohnny Huang printf("RSA exp:\n"); 138769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 138869d5fd8fSJohnny Huang } 138969d5fd8fSJohnny Huang if (last) 139069d5fd8fSJohnny Huang break; 139169d5fd8fSJohnny Huang i++; 139269d5fd8fSJohnny Huang } 139369d5fd8fSJohnny Huang return 0; 139469d5fd8fSJohnny Huang } 139569d5fd8fSJohnny Huang 13965010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout) 139769d5fd8fSJohnny Huang { 1398a6d0d645SJohnny Huang int i, k; 1399d90825e2SJohnny Huang int pass = 0; 1400a6d0d645SJohnny Huang uint32_t prog_address; 1401bb34a7bfSJohnny Huang uint32_t data[16]; 1402a6d0d645SJohnny Huang uint32_t compare[2]; 14035010032bSJohnny Huang uint32_t *conf = (uint32_t *)image_layout->conf; 14045010032bSJohnny Huang uint32_t *conf_ignore = (uint32_t *)image_layout->conf_ignore; 1405d90825e2SJohnny Huang uint32_t data_masked; 1406d90825e2SJohnny Huang uint32_t buf_masked; 140769d5fd8fSJohnny Huang 1408a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1409a6d0d645SJohnny Huang 1410bb34a7bfSJohnny Huang for (i = 0; i < 16 ; i ++) { 141169d5fd8fSJohnny Huang prog_address = 0x800; 1412a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1413a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1414a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1415a6d0d645SJohnny Huang } 1416a6d0d645SJohnny Huang 1417a6d0d645SJohnny Huang printf("Check writable...\n"); 1418bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 14195010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 14205010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1421d90825e2SJohnny Huang if (data_masked == buf_masked) 142269d5fd8fSJohnny Huang continue; 1423d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1424a6d0d645SJohnny Huang continue; 1425a6d0d645SJohnny Huang } else { 1426a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1427a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 14285010032bSJohnny Huang printf("Input [%X] = %x\n", i, conf[i]); 14295010032bSJohnny Huang printf("Mask [%X] = %x\n", i, ~conf_ignore[i]); 14302a856b9aSJohnny Huang return OTP_FAILURE; 1431a6d0d645SJohnny Huang } 1432a6d0d645SJohnny Huang } 1433a6d0d645SJohnny Huang 1434a6d0d645SJohnny Huang printf("Start Programing...\n"); 1435d90825e2SJohnny Huang otp_soak(0); 1436bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 14375010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 14385010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1439a6d0d645SJohnny Huang prog_address = 0x800; 1440a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1441a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1442bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1443bb34a7bfSJohnny Huang pass = 1; 1444a6d0d645SJohnny Huang continue; 1445bb34a7bfSJohnny Huang } 1446de6fbf1cSJohnny Huang 1447a6d0d645SJohnny Huang 1448de6fbf1cSJohnny Huang otp_soak(1); 14495010032bSJohnny Huang otp_prog_dw(conf[i], conf_ignore[i], prog_address); 1450a6d0d645SJohnny Huang 145169d5fd8fSJohnny Huang pass = 0; 145269d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 14535010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1454de6fbf1cSJohnny Huang otp_soak(2); 1455a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 14565010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1457de6fbf1cSJohnny Huang otp_soak(1); 1458de6fbf1cSJohnny Huang } else { 1459de6fbf1cSJohnny Huang pass = 1; 1460de6fbf1cSJohnny Huang break; 1461de6fbf1cSJohnny Huang } 1462a6d0d645SJohnny Huang } else { 146369d5fd8fSJohnny Huang pass = 1; 146469d5fd8fSJohnny Huang break; 146569d5fd8fSJohnny Huang } 146669d5fd8fSJohnny Huang } 1467bb34a7bfSJohnny Huang if (pass == 0) { 1468bb34a7bfSJohnny Huang printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n", 14695010032bSJohnny Huang i, data[i], conf[i], conf_ignore[i]); 1470bb34a7bfSJohnny Huang break; 1471bb34a7bfSJohnny Huang } 1472a6d0d645SJohnny Huang } 1473a6d0d645SJohnny Huang 1474de6fbf1cSJohnny Huang otp_soak(0); 147569d5fd8fSJohnny Huang if (!pass) 14762a856b9aSJohnny Huang return OTP_FAILURE; 1477a6d0d645SJohnny Huang 14782a856b9aSJohnny Huang return OTP_SUCCESS; 1479d90825e2SJohnny Huang 148069d5fd8fSJohnny Huang } 148169d5fd8fSJohnny Huang 1482eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit) 1483eda10d61SJohnny Huang { 1484eda10d61SJohnny Huang if (ibit == 1) { 1485eda10d61SJohnny Huang return OTP_SUCCESS; 1486eda10d61SJohnny Huang } else { 1487eda10d61SJohnny Huang printf("OTPSTRAP[%X]:\n", offset); 1488eda10d61SJohnny Huang } 1489eda10d61SJohnny Huang if (bit == otpstrap->value) { 1490eda10d61SJohnny Huang printf(" The value is same as before, skip it.\n"); 1491eda10d61SJohnny Huang return OTP_PROG_SKIP; 1492eda10d61SJohnny Huang } 1493eda10d61SJohnny Huang if (otpstrap->protected == 1) { 1494eda10d61SJohnny Huang printf(" This bit is protected and is not writable\n"); 1495eda10d61SJohnny Huang return OTP_FAILURE; 1496eda10d61SJohnny Huang } 1497eda10d61SJohnny Huang if (otpstrap->remain_times == 0) { 1498eda10d61SJohnny Huang printf(" This bit is no remaining times to write.\n"); 1499eda10d61SJohnny Huang return OTP_FAILURE; 1500eda10d61SJohnny Huang } 1501eda10d61SJohnny Huang if (pbit == 1) { 1502eda10d61SJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 1503eda10d61SJohnny Huang } 1504eda10d61SJohnny Huang if (rpbit == 1 && info_cb.version != OTP_AST2600A0) { 1505eda10d61SJohnny Huang printf(" The relative register will be protected.\n"); 1506eda10d61SJohnny Huang } 1507eda10d61SJohnny Huang printf(" Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", offset, otpstrap->writeable_option + 1, otpstrap->value, otpstrap->value ^ 1); 1508eda10d61SJohnny Huang return OTP_SUCCESS; 1509eda10d61SJohnny Huang } 1510eda10d61SJohnny Huang 151169d5fd8fSJohnny Huang 15125010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout) 151369d5fd8fSJohnny Huang { 151469d5fd8fSJohnny Huang int i; 15155010032bSJohnny Huang uint32_t *strap; 15165010032bSJohnny Huang uint32_t *strap_ignore; 15175010032bSJohnny Huang uint32_t *strap_reg_protect; 15185010032bSJohnny Huang uint32_t *strap_pro; 1519eda10d61SJohnny Huang int bit, pbit, ibit, rpbit; 152069d5fd8fSJohnny Huang int fail = 0; 1521a6af4a17SJohnny Huang int skip = -1; 1522eda10d61SJohnny Huang int ret; 152366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 152469d5fd8fSJohnny Huang 15255010032bSJohnny Huang strap = (uint32_t *)image_layout->strap; 15265010032bSJohnny Huang strap_pro = (uint32_t *)image_layout->strap_pro; 15275010032bSJohnny Huang strap_ignore = (uint32_t *)image_layout->strap_ignore; 15285010032bSJohnny Huang strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro; 15295010032bSJohnny Huang 1530541eb887SJohnny Huang otp_strap_status(otpstrap); 153169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 153269d5fd8fSJohnny Huang if (i < 32) { 15335010032bSJohnny Huang bit = (strap[0] >> i) & 0x1; 1534eda10d61SJohnny Huang ibit = (strap_ignore[0] >> i) & 0x1; 15355010032bSJohnny Huang pbit = (strap_pro[0] >> i) & 0x1; 153669d5fd8fSJohnny Huang } else { 15375010032bSJohnny Huang bit = (strap[1] >> (i - 32)) & 0x1; 1538eda10d61SJohnny Huang ibit = (strap_ignore[1] >> (i - 32)) & 0x1; 15395010032bSJohnny Huang pbit = (strap_pro[1] >> (i - 32)) & 0x1; 15405010032bSJohnny Huang } 15415010032bSJohnny Huang 15425010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 15435010032bSJohnny Huang if (i < 32) { 15445010032bSJohnny Huang rpbit = (strap_reg_protect[0] >> i) & 0x1; 15455010032bSJohnny Huang } else { 15465010032bSJohnny Huang rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1; 15475010032bSJohnny Huang } 15485010032bSJohnny Huang } else { 15495010032bSJohnny Huang rpbit = 0; 155069d5fd8fSJohnny Huang } 1551eda10d61SJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit); 1552eda10d61SJohnny Huang if (ret == OTP_PROG_SKIP) { 1553a6af4a17SJohnny Huang if (skip == -1) 1554a6af4a17SJohnny Huang skip = 1; 155569d5fd8fSJohnny Huang continue; 1556a6af4a17SJohnny Huang } else { 1557eda10d61SJohnny Huang skip = 1; 155869d5fd8fSJohnny Huang } 1559eda10d61SJohnny Huang 1560eda10d61SJohnny Huang if (ret == OTP_FAILURE) 156169d5fd8fSJohnny Huang fail = 1; 156269d5fd8fSJohnny Huang } 156369d5fd8fSJohnny Huang if (fail == 1) 1564a6af4a17SJohnny Huang return OTP_FAILURE; 1565a6af4a17SJohnny Huang else if (skip == 1) 1566a6af4a17SJohnny Huang return OTP_PROG_SKIP; 15677e22f42dSJohnny Huang 1568eda10d61SJohnny Huang return OTP_SUCCESS; 156969d5fd8fSJohnny Huang } 157069d5fd8fSJohnny Huang 15712a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 157269d5fd8fSJohnny Huang { 157369d5fd8fSJohnny Huang int i, j; 1574*de6b0cc4SJohnny Huang int remains; 157566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 157669d5fd8fSJohnny Huang 15772a856b9aSJohnny Huang if (start < 0 || start > 64) 15782a856b9aSJohnny Huang return OTP_USAGE; 15792a856b9aSJohnny Huang 15802a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 15812a856b9aSJohnny Huang return OTP_USAGE; 15822a856b9aSJohnny Huang 1583541eb887SJohnny Huang otp_strap_status(otpstrap); 158469d5fd8fSJohnny Huang 1585*de6b0cc4SJohnny Huang if (info_cb.version == OTP_AST2600A0) { 1586*de6b0cc4SJohnny Huang remains = 7; 158707baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1588*de6b0cc4SJohnny Huang } else { 1589*de6b0cc4SJohnny Huang remains = 6; 1590*de6b0cc4SJohnny Huang printf("BIT(hex) Value Option Reg_Protect Status\n"); 1591*de6b0cc4SJohnny Huang } 1592*de6b0cc4SJohnny Huang printf("______________________________________________________________________________\n"); 1593737ed20bSJohnny Huang 1594cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 159507baa4e8SJohnny Huang printf("0x%-8X", i); 1596737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1597*de6b0cc4SJohnny Huang for (j = 0; j < remains; j++) 1598737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1599737ed20bSJohnny Huang printf(" "); 1600*de6b0cc4SJohnny Huang if (info_cb.version != OTP_AST2600A0) { 1601*de6b0cc4SJohnny Huang printf("%d ", otpstrap[i].reg_protected); 1602*de6b0cc4SJohnny Huang } 160369d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1604737ed20bSJohnny Huang printf("protected and not writable"); 160569d5fd8fSJohnny Huang } else { 1606737ed20bSJohnny Huang printf("not protected "); 160769d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1608737ed20bSJohnny Huang printf("and no remaining times to write."); 160969d5fd8fSJohnny Huang } else { 1610737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 161169d5fd8fSJohnny Huang } 161269d5fd8fSJohnny Huang } 1613737ed20bSJohnny Huang printf("\n"); 161469d5fd8fSJohnny Huang } 16152a856b9aSJohnny Huang 16162a856b9aSJohnny Huang return OTP_SUCCESS; 161769d5fd8fSJohnny Huang } 161869d5fd8fSJohnny Huang 16198848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value) 16208848d5dcSJohnny Huang { 16218848d5dcSJohnny Huang struct otpstrap_status otpstrap[64]; 16228848d5dcSJohnny Huang uint32_t prog_bit, prog_address; 16238848d5dcSJohnny Huang int offset; 16248848d5dcSJohnny Huang int i; 16258848d5dcSJohnny Huang int pass; 16268848d5dcSJohnny Huang int ret; 16278848d5dcSJohnny Huang 16288848d5dcSJohnny Huang 16298848d5dcSJohnny Huang otp_strap_status(otpstrap); 16308848d5dcSJohnny Huang 16318848d5dcSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0); 16328848d5dcSJohnny Huang 16338848d5dcSJohnny Huang if (ret != OTP_SUCCESS) { 16348848d5dcSJohnny Huang return ret; 16358848d5dcSJohnny Huang } 16368848d5dcSJohnny Huang 16378848d5dcSJohnny Huang prog_address = 0x800; 16388848d5dcSJohnny Huang if (bit_offset < 32) { 16398848d5dcSJohnny Huang offset = bit_offset; 16408848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200; 16418848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2; 16428848d5dcSJohnny Huang 16438848d5dcSJohnny Huang } else { 16448848d5dcSJohnny Huang offset = (bit_offset - 32); 16458848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200; 16468848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2; 16478848d5dcSJohnny Huang } 16488848d5dcSJohnny Huang 16498848d5dcSJohnny Huang prog_bit = ~(0x1 << offset); 16508848d5dcSJohnny Huang 16518848d5dcSJohnny Huang otp_soak(1); 16528848d5dcSJohnny Huang otp_prog(prog_address, prog_bit); 16538848d5dcSJohnny Huang 16548848d5dcSJohnny Huang pass = 0; 16558848d5dcSJohnny Huang for (i = 0; i < RETRY; i++) { 16568848d5dcSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 16578848d5dcSJohnny Huang otp_soak(2); 16588848d5dcSJohnny Huang otp_prog(prog_address, prog_bit); 16598848d5dcSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 16608848d5dcSJohnny Huang otp_soak(1); 16618848d5dcSJohnny Huang } else { 16628848d5dcSJohnny Huang pass = 1; 16638848d5dcSJohnny Huang break; 16648848d5dcSJohnny Huang } 16658848d5dcSJohnny Huang } else { 16668848d5dcSJohnny Huang pass = 1; 16678848d5dcSJohnny Huang break; 16688848d5dcSJohnny Huang } 16698848d5dcSJohnny Huang } 1670*de6b0cc4SJohnny Huang otp_soak(0); 16718848d5dcSJohnny Huang if (!pass) 16728848d5dcSJohnny Huang return OTP_FAILURE; 16738848d5dcSJohnny Huang 16748848d5dcSJohnny Huang return OTP_SUCCESS; 16758848d5dcSJohnny Huang } 16768848d5dcSJohnny Huang 16775010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout) 167869d5fd8fSJohnny Huang { 167969d5fd8fSJohnny Huang int i, j; 16805010032bSJohnny Huang uint32_t *strap; 16815010032bSJohnny Huang uint32_t *strap_ignore; 16825010032bSJohnny Huang uint32_t *strap_pro; 16835010032bSJohnny Huang uint32_t *strap_reg_protect; 168469d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 1685eda10d61SJohnny Huang int bit, pbit, ibit, offset, rpbit; 168669d5fd8fSJohnny Huang int fail = 0; 16877e22f42dSJohnny Huang int pass = 0; 168866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 168969d5fd8fSJohnny Huang 16905010032bSJohnny Huang strap = (uint32_t *)image_layout->strap; 16915010032bSJohnny Huang strap_pro = (uint32_t *)image_layout->strap_pro; 16925010032bSJohnny Huang strap_ignore = (uint32_t *)image_layout->strap_ignore; 16935010032bSJohnny Huang strap_reg_protect = (uint32_t *)image_layout->strap_reg_pro; 16945010032bSJohnny Huang 16957f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1696541eb887SJohnny Huang otp_strap_status(otpstrap); 169769d5fd8fSJohnny Huang 16987f795e57SJohnny Huang printf("Check writable...\n"); 16995010032bSJohnny Huang if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) { 17007f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 17017f795e57SJohnny Huang return OTP_FAILURE; 17027f795e57SJohnny Huang } 17037e22f42dSJohnny Huang 170469d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 170569d5fd8fSJohnny Huang prog_address = 0x800; 170669d5fd8fSJohnny Huang if (i < 32) { 170769d5fd8fSJohnny Huang offset = i; 17085010032bSJohnny Huang bit = (strap[0] >> offset) & 0x1; 1709eda10d61SJohnny Huang ibit = (strap_ignore[0] >> offset) & 0x1; 17105010032bSJohnny Huang pbit = (strap_pro[0] >> offset) & 0x1; 171169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 171269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 171369d5fd8fSJohnny Huang 171469d5fd8fSJohnny Huang } else { 171569d5fd8fSJohnny Huang offset = (i - 32); 17165010032bSJohnny Huang bit = (strap[1] >> offset) & 0x1; 1717eda10d61SJohnny Huang ibit = (strap_ignore[1] >> offset) & 0x1; 17185010032bSJohnny Huang pbit = (strap_pro[1] >> offset) & 0x1; 171969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 172069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 172169d5fd8fSJohnny Huang } 17225010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 17235010032bSJohnny Huang if (i < 32) { 17245010032bSJohnny Huang rpbit = (strap_reg_protect[0] >> i) & 0x1; 17255010032bSJohnny Huang } else { 17265010032bSJohnny Huang rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1; 17275010032bSJohnny Huang } 17285010032bSJohnny Huang } else { 17295010032bSJohnny Huang rpbit = 0; 17305010032bSJohnny Huang } 173169d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 173269d5fd8fSJohnny Huang 1733eda10d61SJohnny Huang if (ibit == 1) { 173469d5fd8fSJohnny Huang continue; 173569d5fd8fSJohnny Huang } 173669d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 173769d5fd8fSJohnny Huang continue; 173869d5fd8fSJohnny Huang } 173969d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 174069d5fd8fSJohnny Huang fail = 1; 174169d5fd8fSJohnny Huang continue; 174269d5fd8fSJohnny Huang } 174369d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 174469d5fd8fSJohnny Huang fail = 1; 174569d5fd8fSJohnny Huang continue; 174669d5fd8fSJohnny Huang } 17477e22f42dSJohnny Huang 17487e22f42dSJohnny Huang 1749de6fbf1cSJohnny Huang otp_soak(1); 17507e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 17517e22f42dSJohnny Huang 17527e22f42dSJohnny Huang pass = 0; 175369d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1754de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1755de6fbf1cSJohnny Huang otp_soak(2); 1756de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1757de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1758de6fbf1cSJohnny Huang otp_soak(1); 1759de6fbf1cSJohnny Huang } else { 176069d5fd8fSJohnny Huang pass = 1; 176169d5fd8fSJohnny Huang break; 176269d5fd8fSJohnny Huang } 1763de6fbf1cSJohnny Huang } else { 1764de6fbf1cSJohnny Huang pass = 1; 1765de6fbf1cSJohnny Huang break; 17664b65a65dSJohnny Huang } 176769d5fd8fSJohnny Huang } 176869d5fd8fSJohnny Huang if (!pass) 17692a856b9aSJohnny Huang return OTP_FAILURE; 177069d5fd8fSJohnny Huang 17715010032bSJohnny Huang if (rpbit == 1 && info_cb.version != OTP_AST2600A0) { 177269d5fd8fSJohnny Huang prog_address = 0x800; 177369d5fd8fSJohnny Huang if (i < 32) 17745010032bSJohnny Huang prog_address |= 0x608; 177569d5fd8fSJohnny Huang else 17765010032bSJohnny Huang prog_address |= 0x60a; 17777e22f42dSJohnny Huang 1778de6fbf1cSJohnny Huang otp_soak(1); 17797e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 17807e22f42dSJohnny Huang 17817e22f42dSJohnny Huang pass = 0; 178269d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1783de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1784de6fbf1cSJohnny Huang otp_soak(2); 1785de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1786de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1787de6fbf1cSJohnny Huang otp_soak(1); 1788de6fbf1cSJohnny Huang } else { 178969d5fd8fSJohnny Huang pass = 1; 179069d5fd8fSJohnny Huang break; 179169d5fd8fSJohnny Huang } 1792de6fbf1cSJohnny Huang } else { 1793de6fbf1cSJohnny Huang pass = 1; 1794de6fbf1cSJohnny Huang break; 179569d5fd8fSJohnny Huang } 179669d5fd8fSJohnny Huang } 179769d5fd8fSJohnny Huang if (!pass) 17982a856b9aSJohnny Huang return OTP_FAILURE; 17995010032bSJohnny Huang } 18005010032bSJohnny Huang 18015010032bSJohnny Huang if (pbit != 0) { 18025010032bSJohnny Huang prog_address = 0x800; 18035010032bSJohnny Huang if (i < 32) 18045010032bSJohnny Huang prog_address |= 0x60c; 18055010032bSJohnny Huang else 18065010032bSJohnny Huang prog_address |= 0x60e; 18075010032bSJohnny Huang 18085010032bSJohnny Huang otp_soak(1); 18095010032bSJohnny Huang otp_prog(prog_address, prog_bit); 18105010032bSJohnny Huang 18115010032bSJohnny Huang pass = 0; 18125010032bSJohnny Huang for (j = 0; j < RETRY; j++) { 18135010032bSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 18145010032bSJohnny Huang otp_soak(2); 18155010032bSJohnny Huang otp_prog(prog_address, prog_bit); 18165010032bSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 18175010032bSJohnny Huang otp_soak(1); 18185010032bSJohnny Huang } else { 18195010032bSJohnny Huang pass = 1; 18205010032bSJohnny Huang break; 18215010032bSJohnny Huang } 18225010032bSJohnny Huang } else { 18235010032bSJohnny Huang pass = 1; 18245010032bSJohnny Huang break; 18255010032bSJohnny Huang } 18265010032bSJohnny Huang } 18275010032bSJohnny Huang if (!pass) 18285010032bSJohnny Huang return OTP_FAILURE; 18295010032bSJohnny Huang } 183069d5fd8fSJohnny Huang 183169d5fd8fSJohnny Huang } 1832de6fbf1cSJohnny Huang otp_soak(0); 183369d5fd8fSJohnny Huang if (fail == 1) 18342a856b9aSJohnny Huang return OTP_FAILURE; 183569d5fd8fSJohnny Huang else 18362a856b9aSJohnny Huang return OTP_SUCCESS; 183769d5fd8fSJohnny Huang 183869d5fd8fSJohnny Huang } 183969d5fd8fSJohnny Huang 1840de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1841cd1610b4SJohnny Huang { 1842cd1610b4SJohnny Huang int prog_bit; 1843cd1610b4SJohnny Huang 1844cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1845cd1610b4SJohnny Huang if (value) 1846cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1847cd1610b4SJohnny Huang else 1848cd1610b4SJohnny Huang return; 1849cd1610b4SJohnny Huang } else { 1850cd1610b4SJohnny Huang prog_address |= 1 << 15; 1851cd1610b4SJohnny Huang if (!value) 1852cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1853cd1610b4SJohnny Huang else 1854cd1610b4SJohnny Huang return; 1855cd1610b4SJohnny Huang } 1856cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1857cd1610b4SJohnny Huang } 1858cd1610b4SJohnny Huang 18595010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout) 18604c1c9b35SJohnny Huang { 186154552c69SJohnny Huang int i; 186254552c69SJohnny Huang int ret; 18635010032bSJohnny Huang int data_dw; 1864d90825e2SJohnny Huang uint32_t data[2048]; 18655010032bSJohnny Huang uint32_t *buf; 18665010032bSJohnny Huang uint32_t *buf_ignore; 18674c1c9b35SJohnny Huang 186854552c69SJohnny Huang uint32_t data_masked; 186954552c69SJohnny Huang uint32_t buf_masked; 18704c1c9b35SJohnny Huang 18715010032bSJohnny Huang buf = (uint32_t *)image_layout->data; 18725010032bSJohnny Huang buf_ignore = (uint32_t *)image_layout->data_ignore; 18735010032bSJohnny Huang 18745010032bSJohnny Huang data_dw = image_layout->data_length / 4; 18755010032bSJohnny Huang 18764c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 18774c1c9b35SJohnny Huang 18785010032bSJohnny Huang for (i = 0; i < data_dw - 2 ; i += 2) { 1879d90825e2SJohnny Huang otp_read_data(i, &data[i]); 18804c1c9b35SJohnny Huang } 1881d90825e2SJohnny Huang 18824c1c9b35SJohnny Huang printf("Check writable...\n"); 188354552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 18845010032bSJohnny Huang for (i = 0; i < data_dw - 2; i++) { 1885696656c6SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1886696656c6SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 188754552c69SJohnny Huang if (data_masked == buf_masked) 18884c1c9b35SJohnny Huang continue; 1889d90825e2SJohnny Huang if (i % 2 == 0) { 189054552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 18914c1c9b35SJohnny Huang continue; 18924c1c9b35SJohnny Huang } else { 18934c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1894d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 18954c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1896696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 18972a856b9aSJohnny Huang return OTP_FAILURE; 189869d5fd8fSJohnny Huang } 1899d90825e2SJohnny Huang } else { 190054552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1901d90825e2SJohnny Huang continue; 1902d90825e2SJohnny Huang } else { 1903d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1904d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1905d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1906696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 19072a856b9aSJohnny Huang return OTP_FAILURE; 1908d90825e2SJohnny Huang } 1909d90825e2SJohnny Huang } 1910d90825e2SJohnny Huang } 191169d5fd8fSJohnny Huang 1912d90825e2SJohnny Huang printf("Start Programing...\n"); 1913d90825e2SJohnny Huang 191454552c69SJohnny Huang // programing ecc region first 191554552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1916696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 191754552c69SJohnny Huang if (ret != OTP_SUCCESS) { 191854552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1919696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 192054552c69SJohnny Huang return ret; 1921d90825e2SJohnny Huang } 1922d90825e2SJohnny Huang } 1923d90825e2SJohnny Huang 192454552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 1925696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 192654552c69SJohnny Huang if (ret != OTP_SUCCESS) { 192754552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1928696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 192954552c69SJohnny Huang return ret; 1930d90825e2SJohnny Huang } 1931de6fbf1cSJohnny Huang } 1932de6fbf1cSJohnny Huang otp_soak(0); 19332a856b9aSJohnny Huang return OTP_SUCCESS; 1934d90825e2SJohnny Huang 1935d90825e2SJohnny Huang } 1936d90825e2SJohnny Huang 1937696656c6SJohnny Huang static int otp_image_verify(uint8_t *src_buf, uint32_t length, uint8_t *digest_buf) 1938696656c6SJohnny Huang { 1939696656c6SJohnny Huang sha256_context ctx; 1940696656c6SJohnny Huang u8 digest_ret[CHECKSUM_LEN]; 1941696656c6SJohnny Huang 1942696656c6SJohnny Huang sha256_starts(&ctx); 1943696656c6SJohnny Huang sha256_update(&ctx, src_buf, length); 1944696656c6SJohnny Huang sha256_finish(&ctx, digest_ret); 1945696656c6SJohnny Huang 1946696656c6SJohnny Huang if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN)) 1947696656c6SJohnny Huang return 0; 1948696656c6SJohnny Huang else 1949696656c6SJohnny Huang return -1; 1950696656c6SJohnny Huang 1951696656c6SJohnny Huang } 1952696656c6SJohnny Huang 1953*de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm) 195469d5fd8fSJohnny Huang { 195569d5fd8fSJohnny Huang int ret; 19569a4fe690SJohnny Huang int image_version = 0; 1957696656c6SJohnny Huang struct otp_header *otp_header; 1958696656c6SJohnny Huang struct otp_image_layout image_layout; 1959696656c6SJohnny Huang int image_size; 1960696656c6SJohnny Huang uint8_t *buf; 1961696656c6SJohnny Huang uint8_t *checksum; 196269d5fd8fSJohnny Huang 1963696656c6SJohnny Huang otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK); 1964696656c6SJohnny Huang if (!otp_header) { 196569d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 19662a856b9aSJohnny Huang return OTP_FAILURE; 196769d5fd8fSJohnny Huang } 1968d90825e2SJohnny Huang 1969696656c6SJohnny Huang image_size = OTP_IMAGE_SIZE(otp_header->image_info); 1970696656c6SJohnny Huang unmap_physmem(otp_header, MAP_WRBACK); 1971696656c6SJohnny Huang 1972696656c6SJohnny Huang buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK); 1973696656c6SJohnny Huang 1974696656c6SJohnny Huang if (!buf) { 1975696656c6SJohnny Huang puts("Failed to map physical memory\n"); 1976696656c6SJohnny Huang return OTP_FAILURE; 1977696656c6SJohnny Huang } 1978696656c6SJohnny Huang otp_header = (struct otp_header *) buf; 1979696656c6SJohnny Huang checksum = buf + otp_header->checksum_offset; 1980696656c6SJohnny Huang 1981696656c6SJohnny Huang if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) { 1982696656c6SJohnny Huang puts("Image is invalid\n"); 1983696656c6SJohnny Huang return OTP_FAILURE; 1984696656c6SJohnny Huang } 1985696656c6SJohnny Huang 1986696656c6SJohnny Huang 19875010032bSJohnny Huang image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2); 19885010032bSJohnny Huang image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info); 19895010032bSJohnny Huang image_layout.data_ignore = image_layout.data + image_layout.data_length; 19905010032bSJohnny Huang 19915010032bSJohnny Huang image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2); 1992696656c6SJohnny Huang image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 19935010032bSJohnny Huang image_layout.conf_ignore = image_layout.conf + image_layout.conf_length; 1994696656c6SJohnny Huang 1995696656c6SJohnny Huang image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 1996696656c6SJohnny Huang 1997696656c6SJohnny Huang if (!strcmp("A0", (char *)otp_header->otp_version)) { 1998696656c6SJohnny Huang image_version = OTP_AST2600A0; 19995010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3); 20005010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + image_layout.strap_length; 20015010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length; 2002696656c6SJohnny Huang } else if (!strcmp("A1", (char *)otp_header->otp_version)) { 2003696656c6SJohnny Huang image_version = OTP_AST2600A1; 20045010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4); 20055010032bSJohnny Huang image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length; 20065010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length; 20075010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length; 2008696656c6SJohnny Huang } else { 2009696656c6SJohnny Huang puts("Version is not supported\n"); 2010696656c6SJohnny Huang return OTP_FAILURE; 2011696656c6SJohnny Huang } 2012696656c6SJohnny Huang 20139a4fe690SJohnny Huang if (image_version != info_cb.version) { 20149a4fe690SJohnny Huang puts("Version is not match\n"); 20159a4fe690SJohnny Huang return OTP_FAILURE; 20169a4fe690SJohnny Huang } 20179a4fe690SJohnny Huang 2018696656c6SJohnny Huang if (otp_image_verify(buf, image_size, checksum)) { 2019696656c6SJohnny Huang puts("checksum is invalid\n"); 2020696656c6SJohnny Huang return OTP_FAILURE; 2021d90825e2SJohnny Huang } 20227332532cSJohnny Huang 202369d5fd8fSJohnny Huang if (!nconfirm) { 2024696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 20257f795e57SJohnny Huang printf("\nOTP data region :\n"); 2026696656c6SJohnny Huang if (otp_print_data_info(&image_layout) < 0) { 202769d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 20282a856b9aSJohnny Huang return OTP_FAILURE; 202969d5fd8fSJohnny Huang } 203069d5fd8fSJohnny Huang } 2031696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 20327332532cSJohnny Huang printf("\nOTP strap region :\n"); 20335010032bSJohnny Huang if (otp_print_strap_image(&image_layout) < 0) { 20347332532cSJohnny Huang printf("OTP strap error, please check.\n"); 20357332532cSJohnny Huang return OTP_FAILURE; 20367332532cSJohnny Huang } 20377332532cSJohnny Huang } 2038696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 20397332532cSJohnny Huang printf("\nOTP configuration region :\n"); 2040696656c6SJohnny Huang if (otp_print_conf_image(&image_layout) < 0) { 20417332532cSJohnny Huang printf("OTP config error, please check.\n"); 20427332532cSJohnny Huang return OTP_FAILURE; 20437332532cSJohnny Huang } 20447332532cSJohnny Huang } 20457332532cSJohnny Huang 204669d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 204769d5fd8fSJohnny Huang if (!confirm_yesno()) { 204869d5fd8fSJohnny Huang printf(" Aborting\n"); 20492a856b9aSJohnny Huang return OTP_FAILURE; 205069d5fd8fSJohnny Huang } 205169d5fd8fSJohnny Huang } 20527332532cSJohnny Huang 20535010032bSJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 20545010032bSJohnny Huang printf("programing data region ...\n"); 20555010032bSJohnny Huang ret = otp_prog_data(&image_layout); 20565010032bSJohnny Huang if (ret != 0) { 20575010032bSJohnny Huang printf("Error\n"); 20585010032bSJohnny Huang return ret; 20595010032bSJohnny Huang } else { 20605010032bSJohnny Huang printf("Done\n"); 20615010032bSJohnny Huang } 20625010032bSJohnny Huang } 20635010032bSJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 20645010032bSJohnny Huang printf("programing strap region ...\n"); 20655010032bSJohnny Huang ret = otp_prog_strap(&image_layout); 20665010032bSJohnny Huang if (ret != 0) { 20675010032bSJohnny Huang printf("Error\n"); 20685010032bSJohnny Huang return ret; 20695010032bSJohnny Huang } else { 20705010032bSJohnny Huang printf("Done\n"); 20715010032bSJohnny Huang } 20725010032bSJohnny Huang } 20735010032bSJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 20745010032bSJohnny Huang printf("programing configuration region ...\n"); 20755010032bSJohnny Huang ret = otp_prog_conf(&image_layout); 20765010032bSJohnny Huang if (ret != 0) { 20775010032bSJohnny Huang printf("Error\n"); 20785010032bSJohnny Huang return ret; 20795010032bSJohnny Huang } 20805010032bSJohnny Huang printf("Done\n"); 20815010032bSJohnny Huang } 2082cd1610b4SJohnny Huang 20837332532cSJohnny Huang return OTP_SUCCESS; 20842a856b9aSJohnny Huang } 20852a856b9aSJohnny Huang 20862a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 2087cd1610b4SJohnny Huang { 2088a6af4a17SJohnny Huang uint32_t read[2]; 2089d90825e2SJohnny Huang uint32_t prog_address = 0; 209066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 2091cd1610b4SJohnny Huang int otp_bit; 2092cd1610b4SJohnny Huang int i; 2093cd1610b4SJohnny Huang int pass; 2094a6af4a17SJohnny Huang int ret; 2095cd1610b4SJohnny Huang 2096cd1610b4SJohnny Huang switch (mode) { 2097a6d0d645SJohnny Huang case OTP_REGION_CONF: 2098a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 2099cd1610b4SJohnny Huang prog_address = 0x800; 2100cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 2101cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 2102a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2103cd1610b4SJohnny Huang if (otp_bit == value) { 2104a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 2105cd1610b4SJohnny Huang printf("No need to program\n"); 21062a856b9aSJohnny Huang return OTP_SUCCESS; 2107cd1610b4SJohnny Huang } 2108cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2109a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 2110cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 21112a856b9aSJohnny Huang return OTP_FAILURE; 2112cd1610b4SJohnny Huang } 2113a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 2114cd1610b4SJohnny Huang break; 2115a6d0d645SJohnny Huang case OTP_REGION_DATA: 2116cd1610b4SJohnny Huang prog_address = otp_dw_offset; 2117cd1610b4SJohnny Huang 2118cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 2119a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 2120a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2121643b9cfdSJohnny Huang 2122643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 2123643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 2124643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 2125643b9cfdSJohnny Huang return OTP_FAILURE; 2126643b9cfdSJohnny Huang } 2127cd1610b4SJohnny Huang } else { 2128a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 2129a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 2130643b9cfdSJohnny Huang 2131643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 2132643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 2133643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 2134643b9cfdSJohnny Huang return OTP_FAILURE; 2135643b9cfdSJohnny Huang } 2136cd1610b4SJohnny Huang } 2137cd1610b4SJohnny Huang if (otp_bit == value) { 2138a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 2139cd1610b4SJohnny Huang printf("No need to program\n"); 21402a856b9aSJohnny Huang return OTP_SUCCESS; 2141cd1610b4SJohnny Huang } 2142643b9cfdSJohnny Huang 2143a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 2144cd1610b4SJohnny Huang break; 2145a6d0d645SJohnny Huang case OTP_REGION_STRAP: 21468848d5dcSJohnny Huang otp_strap_status(otpstrap); 21478848d5dcSJohnny Huang otp_print_strap(bit_offset, 1); 21488848d5dcSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0); 21498848d5dcSJohnny Huang if (ret == OTP_FAILURE) 21508848d5dcSJohnny Huang return OTP_FAILURE; 21518848d5dcSJohnny Huang else if (ret == OTP_PROG_SKIP) 21528848d5dcSJohnny Huang return OTP_SUCCESS; 2153a6af4a17SJohnny Huang 2154cd1610b4SJohnny Huang break; 2155cd1610b4SJohnny Huang } 2156cd1610b4SJohnny Huang 2157cd1610b4SJohnny Huang if (!nconfirm) { 2158cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2159cd1610b4SJohnny Huang if (!confirm_yesno()) { 2160cd1610b4SJohnny Huang printf(" Aborting\n"); 21612a856b9aSJohnny Huang return OTP_FAILURE; 2162cd1610b4SJohnny Huang } 2163cd1610b4SJohnny Huang } 2164cd1610b4SJohnny Huang 2165cd1610b4SJohnny Huang switch (mode) { 2166a6d0d645SJohnny Huang case OTP_REGION_STRAP: 21678848d5dcSJohnny Huang return otp_prog_strap_bit(bit_offset, value); 2168a6d0d645SJohnny Huang case OTP_REGION_CONF: 2169a6d0d645SJohnny Huang case OTP_REGION_DATA: 2170de6fbf1cSJohnny Huang otp_soak(1); 2171de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 2172de6fbf1cSJohnny Huang pass = 0; 2173de6fbf1cSJohnny Huang 2174cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 2175a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2176de6fbf1cSJohnny Huang otp_soak(2); 2177de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 2178de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2179de6fbf1cSJohnny Huang otp_soak(1); 2180cd1610b4SJohnny Huang } else { 2181de6fbf1cSJohnny Huang pass = 1; 2182de6fbf1cSJohnny Huang break; 2183de6fbf1cSJohnny Huang } 2184de6fbf1cSJohnny Huang } else { 2185de6fbf1cSJohnny Huang pass = 1; 2186cd1610b4SJohnny Huang break; 2187cd1610b4SJohnny Huang } 2188cd1610b4SJohnny Huang } 2189de6fbf1cSJohnny Huang 2190de6fbf1cSJohnny Huang otp_soak(0); 2191de6fbf1cSJohnny Huang if (pass) { 21929009c25dSJohnny Huang printf("SUCCESS\n"); 21932a856b9aSJohnny Huang return OTP_SUCCESS; 21949009c25dSJohnny Huang } else { 21959009c25dSJohnny Huang printf("OTP cannot be programed\n"); 21969009c25dSJohnny Huang printf("FAILED\n"); 21979009c25dSJohnny Huang return OTP_FAILURE; 21989009c25dSJohnny Huang } 2199cd1610b4SJohnny Huang } 2200cd1610b4SJohnny Huang 22012a856b9aSJohnny Huang return OTP_USAGE; 2202cd1610b4SJohnny Huang } 2203cd1610b4SJohnny Huang 22042a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 220569d5fd8fSJohnny Huang { 22062a856b9aSJohnny Huang uint32_t offset, count; 22072a856b9aSJohnny Huang int ret; 220869d5fd8fSJohnny Huang 22092a856b9aSJohnny Huang if (argc == 4) { 22102a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 22112a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 22122a856b9aSJohnny Huang } else if (argc == 3) { 22132a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 22142a856b9aSJohnny Huang count = 1; 22152a856b9aSJohnny Huang } else { 221669d5fd8fSJohnny Huang return CMD_RET_USAGE; 221769d5fd8fSJohnny Huang } 221869d5fd8fSJohnny Huang 221969d5fd8fSJohnny Huang 22202a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 22213d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 22222a856b9aSJohnny Huang ret = otp_print_config(offset, count); 22232a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 22243d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 22252a856b9aSJohnny Huang ret = otp_print_data(offset, count); 22262a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 22273d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 22282a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 22292a856b9aSJohnny Huang } else { 22302a856b9aSJohnny Huang return CMD_RET_USAGE; 223169d5fd8fSJohnny Huang } 223269d5fd8fSJohnny Huang 22332a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 22342a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22352a856b9aSJohnny Huang else 22362a856b9aSJohnny Huang return CMD_RET_USAGE; 22372a856b9aSJohnny Huang 22382a856b9aSJohnny Huang } 22392a856b9aSJohnny Huang 22402a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 22412a856b9aSJohnny Huang { 22422a856b9aSJohnny Huang phys_addr_t addr; 22432a856b9aSJohnny Huang int ret; 22442a856b9aSJohnny Huang 2245*de6b0cc4SJohnny Huang if (argc == 3) { 2246ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 22472a856b9aSJohnny Huang return CMD_RET_USAGE; 22482a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 22493d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2250*de6b0cc4SJohnny Huang ret = do_otp_prog(addr, 1); 2251*de6b0cc4SJohnny Huang } else if (argc == 2) { 22522a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 22533d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2254*de6b0cc4SJohnny Huang ret = do_otp_prog(addr, 0); 22552a856b9aSJohnny Huang } else { 22562a856b9aSJohnny Huang return CMD_RET_USAGE; 22572a856b9aSJohnny Huang } 22582a856b9aSJohnny Huang 22592a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 22602a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22612a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 22622a856b9aSJohnny Huang return CMD_RET_FAILURE; 22632a856b9aSJohnny Huang else 22642a856b9aSJohnny Huang return CMD_RET_USAGE; 22652a856b9aSJohnny Huang } 22662a856b9aSJohnny Huang 22672a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 22682a856b9aSJohnny Huang { 22692a856b9aSJohnny Huang int mode = 0; 22702a856b9aSJohnny Huang int nconfirm = 0; 22712a856b9aSJohnny Huang int otp_addr = 0; 22722a856b9aSJohnny Huang int bit_offset; 22732a856b9aSJohnny Huang int value; 22742a856b9aSJohnny Huang int ret; 22752a856b9aSJohnny Huang 22762a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 22772a856b9aSJohnny Huang return CMD_RET_USAGE; 22782a856b9aSJohnny Huang 22792a856b9aSJohnny Huang /* Drop the pb cmd */ 22802a856b9aSJohnny Huang argc--; 22812a856b9aSJohnny Huang argv++; 22822a856b9aSJohnny Huang 22832a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2284a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 22852a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2286a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 22872a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2288a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2289cd1610b4SJohnny Huang else 22902a856b9aSJohnny Huang return CMD_RET_USAGE; 22912a856b9aSJohnny Huang 22922a856b9aSJohnny Huang /* Drop the region cmd */ 22932a856b9aSJohnny Huang argc--; 22942a856b9aSJohnny Huang argv++; 22952a856b9aSJohnny Huang 2296ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2297cd1610b4SJohnny Huang nconfirm = 1; 22982a856b9aSJohnny Huang /* Drop the force option */ 22992a856b9aSJohnny Huang argc--; 23002a856b9aSJohnny Huang argv++; 23012a856b9aSJohnny Huang } 2302cd1610b4SJohnny Huang 2303a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 23042a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 23052a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 23060808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 23072a856b9aSJohnny Huang return CMD_RET_USAGE; 2308cd1610b4SJohnny Huang } else { 23092a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 23102a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 23112a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 23120808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 23132a856b9aSJohnny Huang return CMD_RET_USAGE; 23140808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 231578855207SJohnny Huang if (otp_addr >= 0x800) 23160808cc55SJohnny Huang return CMD_RET_USAGE; 23170808cc55SJohnny Huang } else { 231878855207SJohnny Huang if (otp_addr >= 0x20) 23190808cc55SJohnny Huang return CMD_RET_USAGE; 23200808cc55SJohnny Huang } 2321cd1610b4SJohnny Huang } 2322cd1610b4SJohnny Huang if (value != 0 && value != 1) 23232a856b9aSJohnny Huang return CMD_RET_USAGE; 2324cd1610b4SJohnny Huang 23253d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 23262a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 23272a856b9aSJohnny Huang 23282a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 23292a856b9aSJohnny Huang return CMD_RET_SUCCESS; 23302a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 23312a856b9aSJohnny Huang return CMD_RET_FAILURE; 23322a856b9aSJohnny Huang else 23332a856b9aSJohnny Huang return CMD_RET_USAGE; 23342a856b9aSJohnny Huang } 23352a856b9aSJohnny Huang 23362a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 23372a856b9aSJohnny Huang { 23382a856b9aSJohnny Huang phys_addr_t addr; 23392a856b9aSJohnny Huang int otp_addr = 0; 23402a856b9aSJohnny Huang 23412a856b9aSJohnny Huang if (argc != 3) 23422a856b9aSJohnny Huang return CMD_RET_USAGE; 23432a856b9aSJohnny Huang 23443d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 23452a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 23462a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 23472a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 234869d5fd8fSJohnny Huang printf("Compare pass\n"); 23492a856b9aSJohnny Huang return CMD_RET_SUCCESS; 235069d5fd8fSJohnny Huang } else { 235169d5fd8fSJohnny Huang printf("Compare fail\n"); 23522a856b9aSJohnny Huang return CMD_RET_FAILURE; 235369d5fd8fSJohnny Huang } 235469d5fd8fSJohnny Huang } 235569d5fd8fSJohnny Huang 235666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 235766f2f8e5SJohnny Huang { 2358a8bd6d8cSJohnny Huang int view = 0; 23592d4b0742SJohnny Huang int input; 2360a8bd6d8cSJohnny Huang 2361a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 236266f2f8e5SJohnny Huang return CMD_RET_USAGE; 236366f2f8e5SJohnny Huang 23642d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 236566f2f8e5SJohnny Huang 23663d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 23672d4b0742SJohnny Huang if (argc == 3) { 23682d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 23692d4b0742SJohnny Huang otp_print_conf_info(input); 23702d4b0742SJohnny Huang } else { 23712d4b0742SJohnny Huang otp_print_conf_info(-1); 23722d4b0742SJohnny Huang } 23732d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 23742d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2375a8bd6d8cSJohnny Huang view = 1; 2376a8bd6d8cSJohnny Huang /* Drop the view option */ 2377a8bd6d8cSJohnny Huang argc--; 2378a8bd6d8cSJohnny Huang argv++; 2379a8bd6d8cSJohnny Huang } 23803d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2381b458cd62SJohnny Huang otp_print_strap_info(view); 238266f2f8e5SJohnny Huang } else { 238366f2f8e5SJohnny Huang return CMD_RET_USAGE; 238466f2f8e5SJohnny Huang } 23852d4b0742SJohnny Huang 238666f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 238766f2f8e5SJohnny Huang } 238866f2f8e5SJohnny Huang 2389737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2390737ed20bSJohnny Huang { 2391737ed20bSJohnny Huang int input; 2392737ed20bSJohnny Huang int bit_offset; 2393737ed20bSJohnny Huang int prog_address; 2394737ed20bSJohnny Huang int pass; 2395737ed20bSJohnny Huang int i; 2396737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2397737ed20bSJohnny Huang return CMD_RET_USAGE; 2398737ed20bSJohnny Huang 2399ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2400737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2401737ed20bSJohnny Huang } else { 2402737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2403737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2404737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2405737ed20bSJohnny Huang if (!confirm_yesno()) { 2406737ed20bSJohnny Huang printf(" Aborting\n"); 2407737ed20bSJohnny Huang return CMD_RET_FAILURE; 2408737ed20bSJohnny Huang } 2409737ed20bSJohnny Huang } 2410737ed20bSJohnny Huang 2411737ed20bSJohnny Huang prog_address = 0x800; 2412737ed20bSJohnny Huang if (input < 32) { 2413737ed20bSJohnny Huang bit_offset = input; 2414737ed20bSJohnny Huang prog_address |= 0x60c; 2415737ed20bSJohnny Huang } else if (input < 64) { 2416737ed20bSJohnny Huang bit_offset = input - 32; 2417737ed20bSJohnny Huang prog_address |= 0x60e; 2418737ed20bSJohnny Huang } else { 2419737ed20bSJohnny Huang return CMD_RET_USAGE; 2420737ed20bSJohnny Huang } 2421737ed20bSJohnny Huang 2422737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2423737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2424737ed20bSJohnny Huang } 2425de6fbf1cSJohnny Huang 2426de6fbf1cSJohnny Huang otp_soak(1); 2427de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2428de6fbf1cSJohnny Huang pass = 0; 2429de6fbf1cSJohnny Huang 2430737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2431737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2432de6fbf1cSJohnny Huang otp_soak(2); 2433de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2434de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2435de6fbf1cSJohnny Huang otp_soak(1); 2436737ed20bSJohnny Huang } else { 2437de6fbf1cSJohnny Huang pass = 1; 2438de6fbf1cSJohnny Huang break; 2439de6fbf1cSJohnny Huang } 2440de6fbf1cSJohnny Huang } else { 2441de6fbf1cSJohnny Huang pass = 1; 2442737ed20bSJohnny Huang break; 2443737ed20bSJohnny Huang } 2444737ed20bSJohnny Huang } 2445de6fbf1cSJohnny Huang otp_soak(0); 2446de6fbf1cSJohnny Huang if (pass) { 2447737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2448737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2449737ed20bSJohnny Huang } 2450737ed20bSJohnny Huang 2451737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2452737ed20bSJohnny Huang return CMD_RET_FAILURE; 2453737ed20bSJohnny Huang 2454737ed20bSJohnny Huang } 24559a4fe690SJohnny Huang 24562a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 24572a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2458a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 2459*de6b0cc4SJohnny Huang U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""), 24602a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2461737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 24622a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 24632a856b9aSJohnny Huang }; 24642a856b9aSJohnny Huang 24652a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 24662a856b9aSJohnny Huang { 24672a856b9aSJohnny Huang cmd_tbl_t *cp; 24682a856b9aSJohnny Huang 24692a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 24702a856b9aSJohnny Huang 2471737ed20bSJohnny Huang /* Drop the otp command */ 24722a856b9aSJohnny Huang argc--; 24732a856b9aSJohnny Huang argv++; 24742a856b9aSJohnny Huang 24752a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 24762a856b9aSJohnny Huang return CMD_RET_USAGE; 24772a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 24782a856b9aSJohnny Huang return CMD_RET_SUCCESS; 24792a856b9aSJohnny Huang 2480696656c6SJohnny Huang if (chip_version() == OTP_AST2600A0) { 2481696656c6SJohnny Huang info_cb.version = OTP_AST2600A0; 24829a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 24839a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 24849a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 24859a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 24869a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 24879a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 2488696656c6SJohnny Huang } else if (chip_version() == OTP_AST2600A1) { 2489696656c6SJohnny Huang info_cb.version = OTP_AST2600A1; 24903cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 24913cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 24923cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 24933cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 24949a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 24959a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 24969a4fe690SJohnny Huang } 24979a4fe690SJohnny Huang 24982a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 249969d5fd8fSJohnny Huang } 250069d5fd8fSJohnny Huang 250169d5fd8fSJohnny Huang U_BOOT_CMD( 250269d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 250369d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 25042a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 25052a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 25062d4b0742SJohnny Huang "otp info strap [v]\n" 25072d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2508*de6b0cc4SJohnny Huang "otp prog [o] <addr>\n" 2509ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2510ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2511ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 25122a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 251369d5fd8fSJohnny Huang ); 2514