169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 429a4fe690SJohnny Huang 439a4fe690SJohnny Huang 44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 45b458cd62SJohnny Huang #define OTP_REG_VALUE -2 46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4776d13988SJohnny Huang 484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 494c1c9b35SJohnny Huang #define PBWIDTH 60 504c1c9b35SJohnny Huang 513d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 523d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 533d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 543d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 553d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 563d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 573d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 583d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 593d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 603d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 613d3688adSJohnny Huang 6266f2f8e5SJohnny Huang struct otpstrap_status { 6369d5fd8fSJohnny Huang int value; 6469d5fd8fSJohnny Huang int option_array[7]; 6569d5fd8fSJohnny Huang int remain_times; 6669d5fd8fSJohnny Huang int writeable_option; 6769d5fd8fSJohnny Huang int protected; 6869d5fd8fSJohnny Huang }; 6969d5fd8fSJohnny Huang 7066f2f8e5SJohnny Huang struct otpconf_parse { 7166f2f8e5SJohnny Huang int dw_offset; 7266f2f8e5SJohnny Huang int bit; 7366f2f8e5SJohnny Huang int length; 7466f2f8e5SJohnny Huang int value; 7566f2f8e5SJohnny Huang int keep; 7666f2f8e5SJohnny Huang char status[80]; 7766f2f8e5SJohnny Huang }; 7866f2f8e5SJohnny Huang 79a8bd6d8cSJohnny Huang struct otpstrap_info { 8079e42a59SJoel Stanley int8_t bit_offset; 8179e42a59SJoel Stanley int8_t length; 8279e42a59SJoel Stanley int8_t value; 8379e42a59SJoel Stanley char *information; 84a8bd6d8cSJohnny Huang }; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang struct otpconf_info { 8779e42a59SJoel Stanley int8_t dw_offset; 8879e42a59SJoel Stanley int8_t bit_offset; 8979e42a59SJoel Stanley int8_t length; 9079e42a59SJoel Stanley int8_t value; 9179e42a59SJoel Stanley char *information; 92a8bd6d8cSJohnny Huang }; 93a8bd6d8cSJohnny Huang 949a4fe690SJohnny Huang struct otpkey_type { 959a4fe690SJohnny Huang int value; 969a4fe690SJohnny Huang int key_type; 979a4fe690SJohnny Huang int need_id; 989a4fe690SJohnny Huang char information[110]; 999a4fe690SJohnny Huang }; 1009a4fe690SJohnny Huang 1019a4fe690SJohnny Huang struct otp_info_cb { 1029a4fe690SJohnny Huang int version; 10379e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1049a4fe690SJohnny Huang int strap_info_len; 10579e42a59SJoel Stanley const struct otpconf_info *conf_info; 1069a4fe690SJohnny Huang int conf_info_len; 10779e42a59SJoel Stanley const struct otpkey_type *key_info; 1089a4fe690SJohnny Huang int key_info_len; 1099a4fe690SJohnny Huang }; 1109a4fe690SJohnny Huang 1119a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1129a4fe690SJohnny Huang 11379e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = { 11491448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 11591448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 11691448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 11791448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 11891448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 11991448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 12091448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 12191448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 122541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 12391448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 12491448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 12591448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 12691448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 12791448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 12891448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 12991448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 13091448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 13191448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 13291448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 13391448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 13491448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 13591448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 13691448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 13791448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 13891448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 13991448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 14091448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 14191448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 14291448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 14391448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 14491448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 14591448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 14691448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 14791448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 14891448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 14991448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 15091448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 15191448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 15291448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 15391448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 15491448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 15591448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 15691448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 15791448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 15891448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 15991448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 16091448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 16191448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 16291448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 16391448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 16491448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 16591448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 16691448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 16791448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 16891448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 16991448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 17091448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 17191448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 17291448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 17391448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 17491448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 17591448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 17691448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 17791448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 17891448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 17991448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 18091448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 18191448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 18291448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 18391448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 18491448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 18591448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 18691448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 18791448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 18891448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 18991448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 19091448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 19191448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 19291448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 19391448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 19491448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 19591448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 19691448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 19791448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 19891448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 19991448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 20091448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 20191448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 20291448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 20391448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 20491448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 20591448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 20691448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 20791448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 20891448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 20991448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 21091448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 21191448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 21291448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 21391448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 21491448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 21591448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 21691448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 21791448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 21891448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 21991448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 22091448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 22191448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 22291448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 22376d13988SJohnny Huang }; 2249a4fe690SJohnny Huang 22579e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = { 2263cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2273cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2283cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2293cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2303cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2313cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2323cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2333cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2343cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2353cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2363cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2373cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2383cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2393cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2403cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2413cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2423cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2433cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2443cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2453cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2463cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2473cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2483cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2493cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2503cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2513cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2523cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2533cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2543cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2553cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2563cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2573cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2583cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2593cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2603cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2613cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2623cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2633cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2643cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 2653cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 2663cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 2673cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 2683cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 2693cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 2703cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 2713cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 2723cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 2733cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 2743cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 2753cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 2763cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 2773cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 2783cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 2793cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 2803cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 2813cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 2823cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 2833cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 2843cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 2853cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 2863cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 2873cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 2883cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 2893cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 2903cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 2913cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 2923cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 2933cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 2943cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 2953cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 2963cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 2973cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 2983cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 2993cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3003cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3013cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3023cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3033cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3043cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3053cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3063cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3073cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3083cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3093cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3103cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3113cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3123cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3133cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3143cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3153cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3163cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3173cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3183cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3193cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3203cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3213cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3223cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3233cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3243cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3253cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3263cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3273cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3283cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3293cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3303cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3313cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3323cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3333cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3343cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3353cb28812SJohnny Huang }; 3363cb28812SJohnny Huang 33779e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = { 33891448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 33991448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 34091448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 34191448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 34291448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 34391448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 34491448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 34591448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 34691448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 34791448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 34891448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 34991448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 35091448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 35191448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 35291448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 35391448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 35491448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 355541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 35691448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 35791448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 35891448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 35991448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 36091448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 36191448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 36291448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 36391448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 36491448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 36591448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 36691448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 36791448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 36891448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 36991448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 37091448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 37191448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 37291448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 37391448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 37491448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 37591448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 37691448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 37791448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 37891448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 37991448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 38091448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 38191448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 3823cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 3833cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 3843cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 3853cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 3863cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 3873cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 3883cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 3893cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 3903cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 3913cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 3923cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 3933cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 3943cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 3953cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 3963cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 3973cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 3983cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 3993cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4003cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4013cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4023cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4033cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4043cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4053cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4063cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4073cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4083cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4093cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4103cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4113cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4123cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4133cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4143cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4153cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4163cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4173cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4183cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4193cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4203cb28812SJohnny Huang }; 4213cb28812SJohnny Huang 42279e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = { 4233cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4243cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4253cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4263cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4273cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4283cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4293cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4303cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4313cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4323cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4333cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4343cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4353cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4363cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4373cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4383cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4393cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4403cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4413cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4423cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4433cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4443cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4453cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4463cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4473cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4483cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 4493cb28812SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 4503cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4513cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4523cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4533cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4543cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4553cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4563cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4573cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4583cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4593cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4603cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4613cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4623cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4633cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4643cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4653cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4663cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4673cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4683cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4693cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 47091448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 47191448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 47291448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 47373f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 47473f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 47591448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 47691448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 47791448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 47891448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 47991448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 48091448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 48191448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 48291448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 48391448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 48491448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 48591448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 48691448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 48791448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 48891448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 48991448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 49091448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 49191448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 49291448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 49391448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 49491448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 49591448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 49691448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 49791448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 49891448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 49991448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 50091448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 50191448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 50291448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 50391448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 504b458cd62SJohnny Huang }; 5059a4fe690SJohnny Huang 50679e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 5079a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5089a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5099a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5109a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5119a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5129a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5139a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5149a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5159a4fe690SJohnny Huang }; 5169a4fe690SJohnny Huang 51779e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 5189a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5199a4fe690SJohnny 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"}, 5209a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5219a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5229a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5239a4fe690SJohnny Huang }; 5249a4fe690SJohnny Huang 5259a4fe690SJohnny Huang static uint32_t chip_version(void) 5269a4fe690SJohnny Huang { 5279a4fe690SJohnny Huang uint32_t rev_id; 5289a4fe690SJohnny Huang 5299a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5309a4fe690SJohnny Huang 5319a4fe690SJohnny Huang return rev_id; 5329a4fe690SJohnny Huang } 5339a4fe690SJohnny Huang 5343d3688adSJohnny Huang static void wait_complete(void) 5353d3688adSJohnny Huang { 5363d3688adSJohnny Huang int reg; 5373d3688adSJohnny Huang 5383d3688adSJohnny Huang do { 5393d3688adSJohnny Huang reg = readl(OTP_STATUS); 5403d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5413d3688adSJohnny Huang } 5423d3688adSJohnny Huang 5432a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 54469d5fd8fSJohnny Huang { 5453d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5463d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5473d3688adSJohnny Huang wait_complete(); 5483d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5493d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 55069d5fd8fSJohnny Huang } 55169d5fd8fSJohnny Huang 5522a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 55369d5fd8fSJohnny Huang { 55469d5fd8fSJohnny Huang int config_offset; 55569d5fd8fSJohnny Huang 55669d5fd8fSJohnny Huang config_offset = 0x800; 55769d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 55869d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 55969d5fd8fSJohnny Huang 5603d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 5613d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5623d3688adSJohnny Huang wait_complete(); 5633d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 56469d5fd8fSJohnny Huang } 56569d5fd8fSJohnny Huang 56669d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 56769d5fd8fSJohnny Huang { 56869d5fd8fSJohnny Huang int i; 56969d5fd8fSJohnny Huang uint32_t ret[1]; 57069d5fd8fSJohnny Huang 57169d5fd8fSJohnny Huang if (offset + dw_count > 32) 5722a856b9aSJohnny Huang return OTP_USAGE; 57369d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 57469d5fd8fSJohnny Huang otp_read_config(i, ret); 575a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 57669d5fd8fSJohnny Huang } 57769d5fd8fSJohnny Huang printf("\n"); 5782a856b9aSJohnny Huang return OTP_SUCCESS; 57969d5fd8fSJohnny Huang } 58069d5fd8fSJohnny Huang 58169d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 58269d5fd8fSJohnny Huang { 58369d5fd8fSJohnny Huang int i; 58469d5fd8fSJohnny Huang uint32_t ret[2]; 58569d5fd8fSJohnny Huang 58669d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5872a856b9aSJohnny Huang return OTP_USAGE; 58869d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 58969d5fd8fSJohnny Huang otp_read_data(i, ret); 59069d5fd8fSJohnny Huang if (i % 4 == 0) 59169d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 59269d5fd8fSJohnny Huang else 59369d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 59469d5fd8fSJohnny Huang 59569d5fd8fSJohnny Huang } 59669d5fd8fSJohnny Huang printf("\n"); 5972a856b9aSJohnny Huang return OTP_SUCCESS; 59869d5fd8fSJohnny Huang } 59969d5fd8fSJohnny Huang 60069d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 60169d5fd8fSJohnny Huang { 60269d5fd8fSJohnny Huang uint32_t ret; 60369d5fd8fSJohnny Huang uint32_t *buf; 60469d5fd8fSJohnny Huang 60569d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 60669d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 60769d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 60869d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 60969d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6103d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6113d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6123d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6133d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6143d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6153d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6163d3688adSJohnny Huang wait_complete(); 6173d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 61869d5fd8fSJohnny Huang if (ret & 0x1) 61969d5fd8fSJohnny Huang return 0; 62069d5fd8fSJohnny Huang else 62169d5fd8fSJohnny Huang return -1; 62269d5fd8fSJohnny Huang } 62369d5fd8fSJohnny Huang 62469d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 62569d5fd8fSJohnny Huang { 6263d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6273d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6283d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6293d3688adSJohnny Huang wait_complete(); 63069d5fd8fSJohnny Huang } 63169d5fd8fSJohnny Huang 63269d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 63369d5fd8fSJohnny Huang { 6343d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6353d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6363d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6373d3688adSJohnny Huang wait_complete(); 63869d5fd8fSJohnny Huang } 63969d5fd8fSJohnny Huang 640a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 64169d5fd8fSJohnny Huang { 64230a8c590SJohnny Huang uint32_t ret[2]; 64369d5fd8fSJohnny Huang 64430a8c590SJohnny Huang if (otp_addr % 2 == 0) 6453d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 64630a8c590SJohnny Huang else 6473d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 64830a8c590SJohnny Huang 6493d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6503d3688adSJohnny Huang wait_complete(); 6513d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6523d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 653a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 65430a8c590SJohnny Huang if (otp_addr % 2 == 0) { 65530a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 65669d5fd8fSJohnny Huang return 0; 65769d5fd8fSJohnny Huang else 65869d5fd8fSJohnny Huang return -1; 65930a8c590SJohnny Huang } else { 66030a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 66130a8c590SJohnny Huang return 0; 66230a8c590SJohnny Huang else 66330a8c590SJohnny Huang return -1; 66430a8c590SJohnny Huang } 66530a8c590SJohnny Huang 66669d5fd8fSJohnny Huang } 66769d5fd8fSJohnny Huang 668d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6694c1c9b35SJohnny Huang { 6704c1c9b35SJohnny Huang uint32_t ret[2]; 6714c1c9b35SJohnny Huang 6724c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6734c1c9b35SJohnny Huang 6744c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6753d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 6764c1c9b35SJohnny Huang else 6773d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 6783d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6793d3688adSJohnny Huang wait_complete(); 6803d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6813d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 6824c1c9b35SJohnny Huang if (size == 1) { 6834c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6844c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 685d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6864c1c9b35SJohnny Huang compare[0] = 0; 6874c1c9b35SJohnny Huang return 0; 6884c1c9b35SJohnny Huang } else { 6894c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6904c1c9b35SJohnny Huang return -1; 6914c1c9b35SJohnny Huang } 6924c1c9b35SJohnny Huang 6934c1c9b35SJohnny Huang } else { 6944c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 695d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 6964c1c9b35SJohnny Huang compare[0] = ~0; 6974c1c9b35SJohnny Huang return 0; 6984c1c9b35SJohnny Huang } else { 699d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7004c1c9b35SJohnny Huang return -1; 7014c1c9b35SJohnny Huang } 7024c1c9b35SJohnny Huang } 7034c1c9b35SJohnny Huang } else if (size == 2) { 7044c1c9b35SJohnny Huang // otp_addr should be even 705d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7064c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7074c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7084c1c9b35SJohnny Huang compare[0] = 0; 7094c1c9b35SJohnny Huang compare[1] = ~0; 7104c1c9b35SJohnny Huang return 0; 7114c1c9b35SJohnny Huang } else { 7124c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7134c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7144c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7154c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7164c1c9b35SJohnny Huang return -1; 7174c1c9b35SJohnny Huang } 7184c1c9b35SJohnny Huang } else { 7194c1c9b35SJohnny Huang return -1; 7204c1c9b35SJohnny Huang } 7214c1c9b35SJohnny Huang } 7224c1c9b35SJohnny Huang 7237e22f42dSJohnny Huang static void otp_soak(int soak) 724d90825e2SJohnny Huang { 725de6fbf1cSJohnny Huang switch (soak) { 726de6fbf1cSJohnny Huang case 0: //default 727de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 728de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 729de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 730de6fbf1cSJohnny Huang break; 731de6fbf1cSJohnny Huang case 1: //normal program 732de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 733de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 734de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 735de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 736de6fbf1cSJohnny Huang break; 737de6fbf1cSJohnny Huang case 2: //soak program 738d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 739d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 740d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 741de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 742de6fbf1cSJohnny Huang break; 743d90825e2SJohnny Huang } 744de6fbf1cSJohnny Huang 7453d3688adSJohnny Huang wait_complete(); 746d90825e2SJohnny Huang } 747d90825e2SJohnny Huang 748d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 749d90825e2SJohnny Huang { 750d90825e2SJohnny Huang int j, bit_value, prog_bit; 751d90825e2SJohnny Huang 752d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 753d90825e2SJohnny Huang if ((keep >> j) & 0x1) 754d90825e2SJohnny Huang continue; 755d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 756d90825e2SJohnny Huang if (prog_address % 2 == 0) { 757d90825e2SJohnny Huang if (bit_value) 758d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 759d90825e2SJohnny Huang else 760d90825e2SJohnny Huang continue; 761d90825e2SJohnny Huang } else { 762d90825e2SJohnny Huang prog_address |= 1 << 15; 763d90825e2SJohnny Huang if (bit_value) 764d90825e2SJohnny Huang continue; 765d90825e2SJohnny Huang else 766d90825e2SJohnny Huang prog_bit = 0x1 << j; 767d90825e2SJohnny Huang } 768d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 769d90825e2SJohnny Huang } 770d90825e2SJohnny Huang } 771d90825e2SJohnny Huang 77254552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address) 77354552c69SJohnny Huang { 77454552c69SJohnny Huang int pass; 77554552c69SJohnny Huang int i; 77654552c69SJohnny Huang uint32_t data0_masked; 77754552c69SJohnny Huang uint32_t data1_masked; 77854552c69SJohnny Huang uint32_t buf0_masked; 77954552c69SJohnny Huang uint32_t buf1_masked; 78054552c69SJohnny Huang uint32_t compare[2]; 78154552c69SJohnny Huang 78254552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 78354552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 78454552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 78554552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 78654552c69SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) 78754552c69SJohnny Huang return 0; 78854552c69SJohnny Huang 78954552c69SJohnny Huang otp_soak(1); 79054552c69SJohnny Huang if (data0_masked != buf0_masked) 79154552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 79254552c69SJohnny Huang if (data1_masked != buf1_masked) 79354552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 79454552c69SJohnny Huang 79554552c69SJohnny Huang pass = 0; 79654552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 79754552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 79854552c69SJohnny Huang otp_soak(2); 79954552c69SJohnny Huang if (compare[0] != 0) { 80054552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 80154552c69SJohnny Huang } 80254552c69SJohnny Huang if (compare[1] != ~0) { 80354552c69SJohnny Huang otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1); 80454552c69SJohnny Huang } 80554552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 80654552c69SJohnny Huang otp_soak(1); 80754552c69SJohnny Huang } else { 80854552c69SJohnny Huang pass = 1; 80954552c69SJohnny Huang break; 81054552c69SJohnny Huang } 81154552c69SJohnny Huang } else { 81254552c69SJohnny Huang pass = 1; 81354552c69SJohnny Huang break; 81454552c69SJohnny Huang } 81554552c69SJohnny Huang } 81654552c69SJohnny Huang 81754552c69SJohnny Huang if (!pass) { 81854552c69SJohnny Huang otp_soak(0); 81954552c69SJohnny Huang return OTP_FAILURE; 82054552c69SJohnny Huang } 82154552c69SJohnny Huang return OTP_SUCCESS; 82254552c69SJohnny Huang } 82354552c69SJohnny Huang 82476d13988SJohnny Huang 825541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 82676d13988SJohnny Huang { 82776d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 82876d13988SJohnny Huang int i, j; 82976d13988SJohnny Huang 83076d13988SJohnny Huang for (j = 0; j < 64; j++) { 83176d13988SJohnny Huang otpstrap[j].value = 0; 83276d13988SJohnny Huang otpstrap[j].remain_times = 7; 83376d13988SJohnny Huang otpstrap[j].writeable_option = -1; 83476d13988SJohnny Huang otpstrap[j].protected = 0; 83576d13988SJohnny Huang } 83676d13988SJohnny Huang 83776d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 83876d13988SJohnny Huang int option = (i - 16) / 2; 83976d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 84076d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 84176d13988SJohnny Huang for (j = 0; j < 32; j++) { 84276d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 84376d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 84476d13988SJohnny Huang otpstrap[j].writeable_option = option; 84576d13988SJohnny Huang } 84676d13988SJohnny Huang if (bit_value == 1) 84776d13988SJohnny Huang otpstrap[j].remain_times --; 84876d13988SJohnny Huang otpstrap[j].value ^= bit_value; 84976d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 85076d13988SJohnny Huang } 85176d13988SJohnny Huang for (j = 32; j < 64; j++) { 85276d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 85376d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 85476d13988SJohnny Huang otpstrap[j].writeable_option = option; 85576d13988SJohnny Huang } 85676d13988SJohnny Huang if (bit_value == 1) 85776d13988SJohnny Huang otpstrap[j].remain_times --; 85876d13988SJohnny Huang otpstrap[j].value ^= bit_value; 85976d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 86076d13988SJohnny Huang } 86176d13988SJohnny Huang } 86276d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 86376d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 86476d13988SJohnny Huang for (j = 0; j < 32; j++) { 86576d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 86676d13988SJohnny Huang otpstrap[j].protected = 1; 86776d13988SJohnny Huang } 86876d13988SJohnny Huang for (j = 32; j < 64; j++) { 86976d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 87076d13988SJohnny Huang otpstrap[j].protected = 1; 87176d13988SJohnny Huang } 87276d13988SJohnny Huang } 87376d13988SJohnny Huang 874b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 87569d5fd8fSJohnny Huang { 87679e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 877442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 878b458cd62SJohnny Huang uint32_t mask; 879b458cd62SJohnny Huang uint32_t dw_offset; 880b458cd62SJohnny Huang uint32_t bit_offset; 881b458cd62SJohnny Huang uint32_t otp_value; 882b458cd62SJohnny Huang uint32_t otp_keep; 883b458cd62SJohnny Huang int fail = 0; 88473f11549SJohnny Huang char valid_bit[20]; 88566f2f8e5SJohnny Huang int i; 88673f11549SJohnny Huang int j; 88766f2f8e5SJohnny Huang 888737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 88966f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8903cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8913cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8923cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8933cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 894b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 895b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 896b458cd62SJohnny Huang 897b458cd62SJohnny Huang if (otp_keep == mask) { 898b458cd62SJohnny Huang continue; 899b458cd62SJohnny Huang } else if (otp_keep != 0) { 900b458cd62SJohnny Huang fail = 1; 901b458cd62SJohnny Huang } 902b458cd62SJohnny Huang 9033cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9043cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9053cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9063cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 907b458cd62SJohnny Huang continue; 908b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 909b458cd62SJohnny Huang 9103cb28812SJohnny Huang if (conf_info[i].length == 1) { 9113cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 91266f2f8e5SJohnny Huang } else { 913b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9143cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9153cb28812SJohnny Huang conf_info[i].bit_offset); 91666f2f8e5SJohnny Huang } 917b458cd62SJohnny Huang printf("0x%-10x", otp_value); 918b458cd62SJohnny Huang 919b458cd62SJohnny Huang if (fail) { 920b458cd62SJohnny Huang printf("Keep mask error\n"); 921b458cd62SJohnny Huang } else { 9223cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 923b458cd62SJohnny Huang printf("Reserved\n"); 9243cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9253cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 926b458cd62SJohnny Huang printf("\n"); 9273cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 928b458cd62SJohnny Huang if (otp_value != 0) { 92973f11549SJohnny Huang for (j = 0; j < 7; j++) { 93073f11549SJohnny Huang if (otp_value == (1 << j)) { 93173f11549SJohnny Huang valid_bit[j * 2] = '1'; 932b458cd62SJohnny Huang } else { 93373f11549SJohnny Huang valid_bit[j * 2] = '0'; 93473f11549SJohnny Huang } 93573f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 93673f11549SJohnny Huang } 93773f11549SJohnny Huang valid_bit[15] = 0; 93873f11549SJohnny Huang } else { 93973f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 940b458cd62SJohnny Huang } 9413cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 942b458cd62SJohnny Huang printf("\n"); 943b458cd62SJohnny Huang } else { 9443cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 945b458cd62SJohnny Huang } 946b458cd62SJohnny Huang } 947b458cd62SJohnny Huang } 948b458cd62SJohnny Huang 949b458cd62SJohnny Huang if (fail) 950b458cd62SJohnny Huang return OTP_FAILURE; 951b458cd62SJohnny Huang 95266f2f8e5SJohnny Huang return OTP_SUCCESS; 95366f2f8e5SJohnny Huang } 95466f2f8e5SJohnny Huang 9552d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 95666f2f8e5SJohnny Huang { 95779e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 958b458cd62SJohnny Huang uint32_t OTPCFG[12]; 959b458cd62SJohnny Huang uint32_t mask; 960b458cd62SJohnny Huang uint32_t dw_offset; 961b458cd62SJohnny Huang uint32_t bit_offset; 962b458cd62SJohnny Huang uint32_t otp_value; 96373f11549SJohnny Huang char valid_bit[20]; 96466f2f8e5SJohnny Huang int i; 96573f11549SJohnny Huang int j; 96666f2f8e5SJohnny Huang 96766f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 96866f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 96966f2f8e5SJohnny Huang 97066f2f8e5SJohnny Huang 971b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 972b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9733cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9743cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9752d4b0742SJohnny Huang continue; 9763cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9773cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9783cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 979b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 980b458cd62SJohnny Huang 9813cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9823cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9833cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9843cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 985b458cd62SJohnny Huang continue; 986b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 987b458cd62SJohnny Huang 9883cb28812SJohnny Huang if (conf_info[i].length == 1) { 9893cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 990b458cd62SJohnny Huang } else { 991b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9923cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9933cb28812SJohnny Huang conf_info[i].bit_offset); 994b458cd62SJohnny Huang } 995b458cd62SJohnny Huang printf("0x%-10x", otp_value); 996b458cd62SJohnny Huang 9973cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 998b458cd62SJohnny Huang printf("Reserved\n"); 9993cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10003cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1001b458cd62SJohnny Huang printf("\n"); 10023cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1003b458cd62SJohnny Huang if (otp_value != 0) { 100473f11549SJohnny Huang for (j = 0; j < 7; j++) { 100573f11549SJohnny Huang if (otp_value == (1 << j)) { 100673f11549SJohnny Huang valid_bit[j * 2] = '1'; 1007b458cd62SJohnny Huang } else { 100873f11549SJohnny Huang valid_bit[j * 2] = '0'; 100973f11549SJohnny Huang } 101073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 101173f11549SJohnny Huang } 101273f11549SJohnny Huang valid_bit[15] = 0; 101373f11549SJohnny Huang } else { 101473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1015b458cd62SJohnny Huang } 10163cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1017b458cd62SJohnny Huang printf("\n"); 1018b458cd62SJohnny Huang } else { 10193cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1020b458cd62SJohnny Huang } 1021b458cd62SJohnny Huang } 1022b458cd62SJohnny Huang return OTP_SUCCESS; 102366f2f8e5SJohnny Huang } 102466f2f8e5SJohnny Huang 1025b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 102676d13988SJohnny Huang { 102779e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1028a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 1029a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 103076d13988SJohnny Huang int i; 1031a8bd6d8cSJohnny Huang int fail = 0; 1032a8bd6d8cSJohnny Huang uint32_t bit_offset; 1033a8bd6d8cSJohnny Huang uint32_t dw_offset; 1034a8bd6d8cSJohnny Huang uint32_t mask; 1035a8bd6d8cSJohnny Huang uint32_t otp_value; 1036a8bd6d8cSJohnny Huang uint32_t otp_protect; 1037a8bd6d8cSJohnny Huang uint32_t otp_keep; 103876d13988SJohnny Huang 1039a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1040a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1041b458cd62SJohnny Huang 10423cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 10433cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 1044a8bd6d8cSJohnny Huang dw_offset = 1; 10453cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1046a8bd6d8cSJohnny Huang } else { 1047a8bd6d8cSJohnny Huang dw_offset = 0; 10483cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1049a8bd6d8cSJohnny Huang } 105076d13988SJohnny Huang 10513cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1052a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1053a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1054a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1055a8bd6d8cSJohnny Huang 1056a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1057a8bd6d8cSJohnny Huang continue; 1058a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1059a8bd6d8cSJohnny Huang fail = 1; 1060a8bd6d8cSJohnny Huang } 1061a8bd6d8cSJohnny Huang 10623cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10633cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1064a8bd6d8cSJohnny Huang continue; 1065a8bd6d8cSJohnny Huang 10663cb28812SJohnny Huang if (strap_info[i].length == 1) { 10673cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1068a8bd6d8cSJohnny Huang } else { 1069b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10703cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10713cb28812SJohnny Huang strap_info[i].bit_offset); 1072a8bd6d8cSJohnny Huang } 1073a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1074a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1075a8bd6d8cSJohnny Huang 1076a8bd6d8cSJohnny Huang if (fail) { 1077a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1078a8bd6d8cSJohnny Huang } else { 10793cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10803cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1081a8bd6d8cSJohnny Huang else 1082a8bd6d8cSJohnny Huang printf("Reserved\n"); 1083a8bd6d8cSJohnny Huang } 1084a8bd6d8cSJohnny Huang } 1085a8bd6d8cSJohnny Huang 1086a8bd6d8cSJohnny Huang if (fail) 108776d13988SJohnny Huang return OTP_FAILURE; 108876d13988SJohnny Huang 108976d13988SJohnny Huang return OTP_SUCCESS; 109076d13988SJohnny Huang } 109176d13988SJohnny Huang 1092b458cd62SJohnny Huang static int otp_print_strap_info(int view) 109376d13988SJohnny Huang { 109479e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 109576d13988SJohnny Huang struct otpstrap_status strap_status[64]; 109607baa4e8SJohnny Huang int i, j; 1097b458cd62SJohnny Huang int fail = 0; 1098b458cd62SJohnny Huang uint32_t bit_offset; 1099b458cd62SJohnny Huang uint32_t length; 1100b458cd62SJohnny Huang uint32_t otp_value; 1101b458cd62SJohnny Huang uint32_t otp_protect; 110276d13988SJohnny Huang 1103541eb887SJohnny Huang otp_strap_status(strap_status); 110476d13988SJohnny Huang 1105b458cd62SJohnny Huang if (view) { 110607baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 110707baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 110807baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 110907baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1110b458cd62SJohnny Huang } else { 1111b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1112b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 111376d13988SJohnny Huang } 11143cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1115b458cd62SJohnny Huang otp_value = 0; 11163cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 11173cb28812SJohnny Huang length = strap_info[i].length; 1118b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1119c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1120c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1121b458cd62SJohnny Huang } 11223cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11233cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1124b458cd62SJohnny Huang continue; 1125b458cd62SJohnny Huang if (view) { 1126b458cd62SJohnny Huang for (j = 0; j < length; j++) { 11273cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1128b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 112907baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1130b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 11313cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1132b458cd62SJohnny Huang printf(" Reserved\n"); 1133b458cd62SJohnny Huang continue; 1134b458cd62SJohnny Huang } 1135b458cd62SJohnny Huang if (length == 1) { 11363cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1137b458cd62SJohnny Huang continue; 113876d13988SJohnny Huang } 113976d13988SJohnny Huang 1140b458cd62SJohnny Huang if (j == 0) 11413cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1142b458cd62SJohnny Huang else if (j == length - 1) 1143b458cd62SJohnny Huang printf("\\ \"\n"); 1144b458cd62SJohnny Huang else 1145b458cd62SJohnny Huang printf("| \"\n"); 114676d13988SJohnny Huang } 1147b458cd62SJohnny Huang } else { 1148c947ef08SJohnny Huang if (length == 1) { 11493cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1150b458cd62SJohnny Huang } else { 1151b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1152b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1153b458cd62SJohnny Huang } 1154b458cd62SJohnny Huang 1155b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1156b458cd62SJohnny Huang 11573cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11583cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1159b458cd62SJohnny Huang else 1160b458cd62SJohnny Huang printf("Reserved\n"); 1161b458cd62SJohnny Huang } 1162b458cd62SJohnny Huang } 1163b458cd62SJohnny Huang 1164b458cd62SJohnny Huang if (fail) 1165b458cd62SJohnny Huang return OTP_FAILURE; 1166b458cd62SJohnny Huang 1167b458cd62SJohnny Huang return OTP_SUCCESS; 1168b458cd62SJohnny Huang } 1169b458cd62SJohnny Huang 117069d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 117169d5fd8fSJohnny Huang { 117269d5fd8fSJohnny Huang int i; 117369d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 117469d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 117569d5fd8fSJohnny Huang if (i % 16 == 0) { 117669d5fd8fSJohnny Huang printf("%04X: ", i); 117769d5fd8fSJohnny Huang } 117869d5fd8fSJohnny Huang printf("%02X ", buf[i]); 117969d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 118069d5fd8fSJohnny Huang printf("\n"); 118169d5fd8fSJohnny Huang } 118269d5fd8fSJohnny Huang } 118369d5fd8fSJohnny Huang } 118469d5fd8fSJohnny Huang 11857f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 118669d5fd8fSJohnny Huang { 118769d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 118879e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 11899a4fe690SJohnny Huang struct otpkey_type key_info; 119069d5fd8fSJohnny Huang char *byte_buf; 1191*9d998018SJohnny Huang char empty = 1; 119269d5fd8fSJohnny Huang int i = 0, len = 0; 11939a4fe690SJohnny Huang int j; 119454552c69SJohnny Huang 119569d5fd8fSJohnny Huang byte_buf = (char *)buf; 1196*9d998018SJohnny Huang 1197*9d998018SJohnny Huang for (i = 0; i < 16; i++) { 1198*9d998018SJohnny Huang if (buf[i] != 0) { 1199*9d998018SJohnny Huang empty = 0; 1200*9d998018SJohnny Huang } 1201*9d998018SJohnny Huang } 1202*9d998018SJohnny Huang if (empty) 1203*9d998018SJohnny Huang return 0; 1204*9d998018SJohnny Huang 1205*9d998018SJohnny Huang i = 0; 120669d5fd8fSJohnny Huang while (1) { 120769d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 120869d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 120969d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 121069d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 121169d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 121269d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 12139a4fe690SJohnny Huang 12149a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 12159a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 12169a4fe690SJohnny Huang key_info = key_info_array[j]; 12179a4fe690SJohnny Huang break; 12189a4fe690SJohnny Huang } 12199a4fe690SJohnny Huang } 12209a4fe690SJohnny Huang 12217f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 122269d5fd8fSJohnny Huang printf("Key Type: "); 12239a4fe690SJohnny Huang printf("%s\n", key_info.information); 12249a4fe690SJohnny Huang 12259a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 122669d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 122769d5fd8fSJohnny Huang switch (key_length) { 122869d5fd8fSJohnny Huang case 0: 122969d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 123069d5fd8fSJohnny Huang break; 123169d5fd8fSJohnny Huang case 1: 123269d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 123369d5fd8fSJohnny Huang break; 123469d5fd8fSJohnny Huang case 2: 123569d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 123669d5fd8fSJohnny Huang break; 123769d5fd8fSJohnny Huang case 3: 123869d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 123969d5fd8fSJohnny Huang break; 124069d5fd8fSJohnny Huang } 12419a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 124269d5fd8fSJohnny Huang printf("RSA SHA Type: "); 124369d5fd8fSJohnny Huang switch (key_length) { 124469d5fd8fSJohnny Huang case 0: 124569d5fd8fSJohnny Huang printf("RSA1024\n"); 124669d5fd8fSJohnny Huang len = 0x100; 124769d5fd8fSJohnny Huang break; 124869d5fd8fSJohnny Huang case 1: 124969d5fd8fSJohnny Huang printf("RSA2048\n"); 125069d5fd8fSJohnny Huang len = 0x200; 125169d5fd8fSJohnny Huang break; 125269d5fd8fSJohnny Huang case 2: 125369d5fd8fSJohnny Huang printf("RSA3072\n"); 125469d5fd8fSJohnny Huang len = 0x300; 125569d5fd8fSJohnny Huang break; 125669d5fd8fSJohnny Huang case 3: 125769d5fd8fSJohnny Huang printf("RSA4096\n"); 125869d5fd8fSJohnny Huang len = 0x400; 125969d5fd8fSJohnny Huang break; 126069d5fd8fSJohnny Huang } 126169d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 126269d5fd8fSJohnny Huang } 12639a4fe690SJohnny Huang if (key_info.need_id) 126469d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 126569d5fd8fSJohnny Huang printf("Key Value:\n"); 12669a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 126769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12689a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12699a4fe690SJohnny Huang printf("AES Key:\n"); 12709a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12719a4fe690SJohnny Huang if (info_cb.version == 0) { 12729a4fe690SJohnny Huang printf("AES IV:\n"); 12739a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12749a4fe690SJohnny Huang } 12759a4fe690SJohnny Huang 12769a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12779a4fe690SJohnny Huang if (info_cb.version == 0) { 127869d5fd8fSJohnny Huang printf("AES Key:\n"); 127969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 128069d5fd8fSJohnny Huang printf("AES IV:\n"); 128169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12829a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12839a4fe690SJohnny Huang printf("AES Key 1:\n"); 12849a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12859a4fe690SJohnny Huang printf("AES Key 2:\n"); 12869a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12879a4fe690SJohnny Huang } 128869d5fd8fSJohnny Huang 12899a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 129069d5fd8fSJohnny Huang printf("RSA mod:\n"); 129169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 129269d5fd8fSJohnny Huang printf("RSA exp:\n"); 129369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 129469d5fd8fSJohnny Huang } 129569d5fd8fSJohnny Huang if (last) 129669d5fd8fSJohnny Huang break; 129769d5fd8fSJohnny Huang i++; 129869d5fd8fSJohnny Huang } 129969d5fd8fSJohnny Huang return 0; 130069d5fd8fSJohnny Huang } 130169d5fd8fSJohnny Huang 1302a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 130369d5fd8fSJohnny Huang { 1304a6d0d645SJohnny Huang int i, k; 1305d90825e2SJohnny Huang int pass = 0; 1306a6d0d645SJohnny Huang uint32_t prog_address; 1307a6d0d645SJohnny Huang uint32_t data[12]; 1308a6d0d645SJohnny Huang uint32_t compare[2]; 1309d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1310d90825e2SJohnny Huang uint32_t data_masked; 1311d90825e2SJohnny Huang uint32_t buf_masked; 131269d5fd8fSJohnny Huang 1313a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1314a6d0d645SJohnny Huang 1315a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 131669d5fd8fSJohnny Huang prog_address = 0x800; 1317a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1318a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1319a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1320a6d0d645SJohnny Huang } 1321a6d0d645SJohnny Huang 1322a6d0d645SJohnny Huang printf("Check writable...\n"); 1323a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1324d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1325d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1326d90825e2SJohnny Huang if (data_masked == buf_masked) 132769d5fd8fSJohnny Huang continue; 1328d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1329a6d0d645SJohnny Huang continue; 1330a6d0d645SJohnny Huang } else { 1331a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1332a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1333a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1334a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 13352a856b9aSJohnny Huang return OTP_FAILURE; 1336a6d0d645SJohnny Huang } 1337a6d0d645SJohnny Huang } 1338a6d0d645SJohnny Huang 1339a6d0d645SJohnny Huang printf("Start Programing...\n"); 1340d90825e2SJohnny Huang otp_soak(0); 1341a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1342d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1343d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1344a6d0d645SJohnny Huang prog_address = 0x800; 1345a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1346a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1347a7a389eaSJohnny Huang if (data_masked == buf_masked) 1348a6d0d645SJohnny Huang continue; 1349de6fbf1cSJohnny Huang 1350a6d0d645SJohnny Huang 1351de6fbf1cSJohnny Huang otp_soak(1); 1352d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1353a6d0d645SJohnny Huang 135469d5fd8fSJohnny Huang pass = 0; 135569d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1356d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1357de6fbf1cSJohnny Huang otp_soak(2); 1358a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1359de6fbf1cSJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1360de6fbf1cSJohnny Huang otp_soak(1); 1361de6fbf1cSJohnny Huang } else { 1362de6fbf1cSJohnny Huang pass = 1; 1363de6fbf1cSJohnny Huang break; 1364de6fbf1cSJohnny Huang } 1365a6d0d645SJohnny Huang } else { 136669d5fd8fSJohnny Huang pass = 1; 136769d5fd8fSJohnny Huang break; 136869d5fd8fSJohnny Huang } 136969d5fd8fSJohnny Huang } 1370a6d0d645SJohnny Huang } 1371a6d0d645SJohnny Huang 1372de6fbf1cSJohnny Huang otp_soak(0); 137369d5fd8fSJohnny Huang if (!pass) 13742a856b9aSJohnny Huang return OTP_FAILURE; 1375a6d0d645SJohnny Huang 13762a856b9aSJohnny Huang return OTP_SUCCESS; 1377d90825e2SJohnny Huang 137869d5fd8fSJohnny Huang } 137969d5fd8fSJohnny Huang 138069d5fd8fSJohnny Huang 138176d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 138269d5fd8fSJohnny Huang { 138369d5fd8fSJohnny Huang int i; 138469d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 138569d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 138669d5fd8fSJohnny Huang int bit, pbit, kbit; 138769d5fd8fSJohnny Huang int fail = 0; 1388a6af4a17SJohnny Huang int skip = -1; 138966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 139069d5fd8fSJohnny Huang 1391541eb887SJohnny Huang otp_strap_status(otpstrap); 139269d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 139369d5fd8fSJohnny Huang if (i < 32) { 139469d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 139569d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 139669d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 139769d5fd8fSJohnny Huang } else { 139869d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 139969d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 140069d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 140169d5fd8fSJohnny Huang } 140269d5fd8fSJohnny Huang 140369d5fd8fSJohnny Huang if (kbit == 1) { 140469d5fd8fSJohnny Huang continue; 140569d5fd8fSJohnny Huang } else { 1406a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 140769d5fd8fSJohnny Huang } 140869d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 140969d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1410a6af4a17SJohnny Huang if (skip == -1) 1411a6af4a17SJohnny Huang skip = 1; 141269d5fd8fSJohnny Huang continue; 1413a6af4a17SJohnny Huang } else { 1414a6af4a17SJohnny Huang skip = 0; 141569d5fd8fSJohnny Huang } 141669d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 141769d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 141869d5fd8fSJohnny Huang fail = 1; 141969d5fd8fSJohnny Huang continue; 142069d5fd8fSJohnny Huang } 142169d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1422a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 142369d5fd8fSJohnny Huang fail = 1; 142469d5fd8fSJohnny Huang continue; 142569d5fd8fSJohnny Huang } 142669d5fd8fSJohnny Huang if (pbit == 1) { 142769d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 142869d5fd8fSJohnny Huang } 1429a6af4a17SJohnny Huang printf(" Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1); 143069d5fd8fSJohnny Huang } 143169d5fd8fSJohnny Huang if (fail == 1) 1432a6af4a17SJohnny Huang return OTP_FAILURE; 1433a6af4a17SJohnny Huang else if (skip == 1) 1434a6af4a17SJohnny Huang return OTP_PROG_SKIP; 14357e22f42dSJohnny Huang 14367e22f42dSJohnny Huang return 0; 143769d5fd8fSJohnny Huang } 143869d5fd8fSJohnny Huang 14392a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 144069d5fd8fSJohnny Huang { 144169d5fd8fSJohnny Huang int i, j; 144266f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 144369d5fd8fSJohnny Huang 14442a856b9aSJohnny Huang if (start < 0 || start > 64) 14452a856b9aSJohnny Huang return OTP_USAGE; 14462a856b9aSJohnny Huang 14472a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 14482a856b9aSJohnny Huang return OTP_USAGE; 14492a856b9aSJohnny Huang 1450541eb887SJohnny Huang otp_strap_status(otpstrap); 145169d5fd8fSJohnny Huang 145207baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1453a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1454737ed20bSJohnny Huang 1455cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 145607baa4e8SJohnny Huang printf("0x%-8X", i); 1457737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1458737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1459737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1460737ed20bSJohnny Huang printf(" "); 146169d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1462737ed20bSJohnny Huang printf("protected and not writable"); 146369d5fd8fSJohnny Huang } else { 1464737ed20bSJohnny Huang printf("not protected "); 146569d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1466737ed20bSJohnny Huang printf("and no remaining times to write."); 146769d5fd8fSJohnny Huang } else { 1468737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 146969d5fd8fSJohnny Huang } 147069d5fd8fSJohnny Huang } 1471737ed20bSJohnny Huang printf("\n"); 147269d5fd8fSJohnny Huang } 14732a856b9aSJohnny Huang 14742a856b9aSJohnny Huang return OTP_SUCCESS; 147569d5fd8fSJohnny Huang } 147669d5fd8fSJohnny Huang 147769d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 147869d5fd8fSJohnny Huang { 147969d5fd8fSJohnny Huang int i, j; 148069d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 148169d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 148269d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 148369d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 148469d5fd8fSJohnny Huang int fail = 0; 14857e22f42dSJohnny Huang int pass = 0; 148666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 148769d5fd8fSJohnny Huang 14887f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1489541eb887SJohnny Huang otp_strap_status(otpstrap); 149069d5fd8fSJohnny Huang 14917f795e57SJohnny Huang printf("Check writable...\n"); 14927f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 14937f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14947f795e57SJohnny Huang return OTP_FAILURE; 14957f795e57SJohnny Huang } 14967e22f42dSJohnny Huang 149769d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 149869d5fd8fSJohnny Huang prog_address = 0x800; 149969d5fd8fSJohnny Huang if (i < 32) { 150069d5fd8fSJohnny Huang offset = i; 150169d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 150269d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 150369d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 150469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 150569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 150669d5fd8fSJohnny Huang 150769d5fd8fSJohnny Huang } else { 150869d5fd8fSJohnny Huang offset = (i - 32); 150969d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 151069d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 151169d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 151269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 151369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 151469d5fd8fSJohnny Huang } 151569d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 151669d5fd8fSJohnny Huang 151769d5fd8fSJohnny Huang if (kbit == 1) { 151869d5fd8fSJohnny Huang continue; 151969d5fd8fSJohnny Huang } 152069d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 152169d5fd8fSJohnny Huang continue; 152269d5fd8fSJohnny Huang } 152369d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 152469d5fd8fSJohnny Huang fail = 1; 152569d5fd8fSJohnny Huang continue; 152669d5fd8fSJohnny Huang } 152769d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 152869d5fd8fSJohnny Huang fail = 1; 152969d5fd8fSJohnny Huang continue; 153069d5fd8fSJohnny Huang } 15317e22f42dSJohnny Huang 15327e22f42dSJohnny Huang 1533de6fbf1cSJohnny Huang otp_soak(1); 15347e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15357e22f42dSJohnny Huang 15367e22f42dSJohnny Huang pass = 0; 153769d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1538de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1539de6fbf1cSJohnny Huang otp_soak(2); 1540de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1541de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1542de6fbf1cSJohnny Huang otp_soak(1); 1543de6fbf1cSJohnny Huang } else { 154469d5fd8fSJohnny Huang pass = 1; 154569d5fd8fSJohnny Huang break; 154669d5fd8fSJohnny Huang } 1547de6fbf1cSJohnny Huang } else { 1548de6fbf1cSJohnny Huang pass = 1; 1549de6fbf1cSJohnny Huang break; 15504b65a65dSJohnny Huang } 155169d5fd8fSJohnny Huang } 155269d5fd8fSJohnny Huang if (!pass) 15532a856b9aSJohnny Huang return OTP_FAILURE; 155469d5fd8fSJohnny Huang 155569d5fd8fSJohnny Huang if (pbit == 0) 155669d5fd8fSJohnny Huang continue; 155769d5fd8fSJohnny Huang prog_address = 0x800; 155869d5fd8fSJohnny Huang if (i < 32) 155969d5fd8fSJohnny Huang prog_address |= 0x60c; 156069d5fd8fSJohnny Huang else 156169d5fd8fSJohnny Huang prog_address |= 0x60e; 156269d5fd8fSJohnny Huang 15637e22f42dSJohnny Huang 1564de6fbf1cSJohnny Huang otp_soak(1); 15657e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15667e22f42dSJohnny Huang 15677e22f42dSJohnny Huang pass = 0; 156869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1569de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1570de6fbf1cSJohnny Huang otp_soak(2); 1571de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1572de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1573de6fbf1cSJohnny Huang otp_soak(1); 1574de6fbf1cSJohnny Huang } else { 157569d5fd8fSJohnny Huang pass = 1; 157669d5fd8fSJohnny Huang break; 157769d5fd8fSJohnny Huang } 1578de6fbf1cSJohnny Huang } else { 1579de6fbf1cSJohnny Huang pass = 1; 1580de6fbf1cSJohnny Huang break; 158169d5fd8fSJohnny Huang } 158269d5fd8fSJohnny Huang } 158369d5fd8fSJohnny Huang if (!pass) 15842a856b9aSJohnny Huang return OTP_FAILURE; 158569d5fd8fSJohnny Huang 158669d5fd8fSJohnny Huang } 1587de6fbf1cSJohnny Huang otp_soak(0); 158869d5fd8fSJohnny Huang if (fail == 1) 15892a856b9aSJohnny Huang return OTP_FAILURE; 159069d5fd8fSJohnny Huang else 15912a856b9aSJohnny Huang return OTP_SUCCESS; 159269d5fd8fSJohnny Huang 159369d5fd8fSJohnny Huang } 159469d5fd8fSJohnny Huang 1595de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1596cd1610b4SJohnny Huang { 1597cd1610b4SJohnny Huang int prog_bit; 1598cd1610b4SJohnny Huang 1599cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1600cd1610b4SJohnny Huang if (value) 1601cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1602cd1610b4SJohnny Huang else 1603cd1610b4SJohnny Huang return; 1604cd1610b4SJohnny Huang } else { 1605cd1610b4SJohnny Huang prog_address |= 1 << 15; 1606cd1610b4SJohnny Huang if (!value) 1607cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1608cd1610b4SJohnny Huang else 1609cd1610b4SJohnny Huang return; 1610cd1610b4SJohnny Huang } 1611cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1612cd1610b4SJohnny Huang } 1613cd1610b4SJohnny Huang 1614d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 16154c1c9b35SJohnny Huang { 161654552c69SJohnny Huang int i; 161754552c69SJohnny Huang int ret; 1618d90825e2SJohnny Huang uint32_t data[2048]; 1619d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 16204c1c9b35SJohnny Huang 162154552c69SJohnny Huang uint32_t data_masked; 162254552c69SJohnny Huang uint32_t buf_masked; 16234c1c9b35SJohnny Huang 16244c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 16254c1c9b35SJohnny Huang 1626d6cdf762SJohnny Huang for (i = 0; i < 2046 ; i += 2) { 1627d90825e2SJohnny Huang otp_read_data(i, &data[i]); 16284c1c9b35SJohnny Huang } 1629d90825e2SJohnny Huang 16304c1c9b35SJohnny Huang 16314c1c9b35SJohnny Huang printf("Check writable...\n"); 163254552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1633d6cdf762SJohnny Huang for (i = 0; i < 2046; i++) { 163454552c69SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 163554552c69SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 163654552c69SJohnny Huang if (data_masked == buf_masked) 16374c1c9b35SJohnny Huang continue; 1638d90825e2SJohnny Huang if (i % 2 == 0) { 163954552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 16404c1c9b35SJohnny Huang continue; 16414c1c9b35SJohnny Huang } else { 16424c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1643d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 16444c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1645d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16462a856b9aSJohnny Huang return OTP_FAILURE; 164769d5fd8fSJohnny Huang } 1648d90825e2SJohnny Huang } else { 164954552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1650d90825e2SJohnny Huang continue; 1651d90825e2SJohnny Huang } else { 1652d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1653d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1654d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1655d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16562a856b9aSJohnny Huang return OTP_FAILURE; 1657d90825e2SJohnny Huang } 1658d90825e2SJohnny Huang } 1659d90825e2SJohnny Huang } 166069d5fd8fSJohnny Huang 1661d90825e2SJohnny Huang printf("Start Programing...\n"); 1662d90825e2SJohnny Huang 166354552c69SJohnny Huang // programing ecc region first 166454552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 166554552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 166654552c69SJohnny Huang if (ret != OTP_SUCCESS) { 166754552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 166854552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 166954552c69SJohnny Huang return ret; 1670d90825e2SJohnny Huang } 1671d90825e2SJohnny Huang } 1672d90825e2SJohnny Huang 167354552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 167454552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 167554552c69SJohnny Huang if (ret != OTP_SUCCESS) { 167654552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 167754552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 167854552c69SJohnny Huang return ret; 1679d90825e2SJohnny Huang } 1680de6fbf1cSJohnny Huang } 1681de6fbf1cSJohnny Huang otp_soak(0); 16822a856b9aSJohnny Huang return OTP_SUCCESS; 1683d90825e2SJohnny Huang 1684d90825e2SJohnny Huang } 1685d90825e2SJohnny Huang 1686d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 168769d5fd8fSJohnny Huang { 168869d5fd8fSJohnny Huang int ret; 16897332532cSJohnny Huang int mode = 0; 16909a4fe690SJohnny Huang int image_version = 0; 169169d5fd8fSJohnny Huang uint32_t *buf; 1692d90825e2SJohnny Huang uint32_t *data_region = NULL; 1693d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1694d90825e2SJohnny Huang uint32_t *strap_region = NULL; 169569d5fd8fSJohnny Huang 1696d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 169769d5fd8fSJohnny Huang if (!buf) { 169869d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16992a856b9aSJohnny Huang return OTP_FAILURE; 170069d5fd8fSJohnny Huang } 1701d90825e2SJohnny Huang 17029a4fe690SJohnny Huang image_version = buf[0] & 0x3; 17039a4fe690SJohnny Huang if (image_version != info_cb.version) { 17049a4fe690SJohnny Huang puts("Version is not match\n"); 17059a4fe690SJohnny Huang return OTP_FAILURE; 17069a4fe690SJohnny Huang } 17079a4fe690SJohnny Huang 1708d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 17097332532cSJohnny Huang mode |= OTP_REGION_DATA; 17107332532cSJohnny Huang data_region = &buf[36]; 1711d90825e2SJohnny Huang } 1712d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 17137332532cSJohnny Huang mode |= OTP_REGION_CONF; 17147332532cSJohnny Huang conf_region = &buf[12]; 1715d90825e2SJohnny Huang } 1716d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 17177332532cSJohnny Huang mode |= OTP_REGION_STRAP; 17187332532cSJohnny Huang strap_region = &buf[4]; 1719d90825e2SJohnny Huang } 17207332532cSJohnny Huang 172169d5fd8fSJohnny Huang if (!nconfirm) { 17227332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17237f795e57SJohnny Huang printf("\nOTP data region :\n"); 17247f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 172569d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17262a856b9aSJohnny Huang return OTP_FAILURE; 172769d5fd8fSJohnny Huang } 172869d5fd8fSJohnny Huang } 17297332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17307332532cSJohnny Huang printf("\nOTP strap region :\n"); 17317332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17327332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17337332532cSJohnny Huang return OTP_FAILURE; 17347332532cSJohnny Huang } 17357332532cSJohnny Huang } 17367332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17377332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17387332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17397332532cSJohnny Huang printf("OTP config error, please check.\n"); 17407332532cSJohnny Huang return OTP_FAILURE; 17417332532cSJohnny Huang } 17427332532cSJohnny Huang } 17437332532cSJohnny Huang 174469d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 174569d5fd8fSJohnny Huang if (!confirm_yesno()) { 174669d5fd8fSJohnny Huang printf(" Aborting\n"); 17472a856b9aSJohnny Huang return OTP_FAILURE; 174869d5fd8fSJohnny Huang } 174969d5fd8fSJohnny Huang } 17507332532cSJohnny Huang 17517332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17527332532cSJohnny Huang printf("programing data region ...\n"); 1753d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17542a856b9aSJohnny Huang if (ret != 0) { 175569d5fd8fSJohnny Huang printf("Error\n"); 175669d5fd8fSJohnny Huang return ret; 175769d5fd8fSJohnny Huang } else { 175869d5fd8fSJohnny Huang printf("Done\n"); 175969d5fd8fSJohnny Huang } 17607332532cSJohnny Huang } 17617332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17627332532cSJohnny Huang printf("programing strap region ...\n"); 1763d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17642a856b9aSJohnny Huang if (ret != 0) { 176569d5fd8fSJohnny Huang printf("Error\n"); 176669d5fd8fSJohnny Huang return ret; 176769d5fd8fSJohnny Huang } else { 176869d5fd8fSJohnny Huang printf("Done\n"); 176969d5fd8fSJohnny Huang } 17707332532cSJohnny Huang } 17717332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17727332532cSJohnny Huang printf("programing configuration region ...\n"); 1773d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17742a856b9aSJohnny Huang if (ret != 0) { 177569d5fd8fSJohnny Huang printf("Error\n"); 177669d5fd8fSJohnny Huang return ret; 177769d5fd8fSJohnny Huang } 177869d5fd8fSJohnny Huang printf("Done\n"); 177969d5fd8fSJohnny Huang } 1780cd1610b4SJohnny Huang 17817332532cSJohnny Huang return OTP_SUCCESS; 17822a856b9aSJohnny Huang } 17832a856b9aSJohnny Huang 17842a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1785cd1610b4SJohnny Huang { 1786a6af4a17SJohnny Huang uint32_t read[2]; 1787cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1788d90825e2SJohnny Huang uint32_t prog_address = 0; 178966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1790cd1610b4SJohnny Huang int otp_bit; 1791cd1610b4SJohnny Huang int i; 1792cd1610b4SJohnny Huang int pass; 1793a6af4a17SJohnny Huang int ret; 1794cd1610b4SJohnny Huang 1795cd1610b4SJohnny Huang switch (mode) { 1796a6d0d645SJohnny Huang case OTP_REGION_CONF: 1797a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1798cd1610b4SJohnny Huang prog_address = 0x800; 1799cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1800cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1801a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1802cd1610b4SJohnny Huang if (otp_bit == value) { 1803a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1804cd1610b4SJohnny Huang printf("No need to program\n"); 18052a856b9aSJohnny Huang return OTP_SUCCESS; 1806cd1610b4SJohnny Huang } 1807cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1808a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1809cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 18102a856b9aSJohnny Huang return OTP_FAILURE; 1811cd1610b4SJohnny Huang } 1812a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1813cd1610b4SJohnny Huang break; 1814a6d0d645SJohnny Huang case OTP_REGION_DATA: 1815cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1816cd1610b4SJohnny Huang 1817cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1818a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1819a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1820643b9cfdSJohnny Huang 1821643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1822643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1823643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1824643b9cfdSJohnny Huang return OTP_FAILURE; 1825643b9cfdSJohnny Huang } 1826cd1610b4SJohnny Huang } else { 1827a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1828a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1829643b9cfdSJohnny Huang 1830643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1831643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1832643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1833643b9cfdSJohnny Huang return OTP_FAILURE; 1834643b9cfdSJohnny Huang } 1835cd1610b4SJohnny Huang } 1836cd1610b4SJohnny Huang if (otp_bit == value) { 1837a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1838cd1610b4SJohnny Huang printf("No need to program\n"); 18392a856b9aSJohnny Huang return OTP_SUCCESS; 1840cd1610b4SJohnny Huang } 1841643b9cfdSJohnny Huang 1842a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1843cd1610b4SJohnny Huang break; 1844a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1845541eb887SJohnny Huang otp_strap_status(otpstrap); 1846cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1847cd1610b4SJohnny Huang if (bit_offset < 32) { 1848cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1849cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1850cd1610b4SJohnny Huang strap_buf[3] = ~0; 1851cd1610b4SJohnny Huang strap_buf[5] = 0; 18522a856b9aSJohnny Huang // if (protect) 18532a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 18542a856b9aSJohnny Huang // else 18552a856b9aSJohnny Huang // strap_buf[4] = 0; 1856cd1610b4SJohnny Huang } else { 1857cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1858cd1610b4SJohnny Huang strap_buf[2] = ~0; 1859cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1860cd1610b4SJohnny Huang strap_buf[4] = 0; 18612a856b9aSJohnny Huang // if (protect) 18622a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 18632a856b9aSJohnny Huang // else 18642a856b9aSJohnny Huang // strap_buf[5] = 0; 1865cd1610b4SJohnny Huang } 186676d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1867a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18682a856b9aSJohnny Huang return OTP_FAILURE; 1869a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1870a6af4a17SJohnny Huang return OTP_SUCCESS; 1871a6af4a17SJohnny Huang 1872cd1610b4SJohnny Huang break; 1873cd1610b4SJohnny Huang } 1874cd1610b4SJohnny Huang 1875cd1610b4SJohnny Huang if (!nconfirm) { 1876cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1877cd1610b4SJohnny Huang if (!confirm_yesno()) { 1878cd1610b4SJohnny Huang printf(" Aborting\n"); 18792a856b9aSJohnny Huang return OTP_FAILURE; 1880cd1610b4SJohnny Huang } 1881cd1610b4SJohnny Huang } 1882cd1610b4SJohnny Huang 1883cd1610b4SJohnny Huang switch (mode) { 1884a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1885cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1886a6d0d645SJohnny Huang case OTP_REGION_CONF: 1887a6d0d645SJohnny Huang case OTP_REGION_DATA: 1888de6fbf1cSJohnny Huang otp_soak(1); 1889de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1890de6fbf1cSJohnny Huang pass = 0; 1891de6fbf1cSJohnny Huang 1892cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1893a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1894de6fbf1cSJohnny Huang otp_soak(2); 1895de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1896de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1897de6fbf1cSJohnny Huang otp_soak(1); 1898cd1610b4SJohnny Huang } else { 1899de6fbf1cSJohnny Huang pass = 1; 1900de6fbf1cSJohnny Huang break; 1901de6fbf1cSJohnny Huang } 1902de6fbf1cSJohnny Huang } else { 1903de6fbf1cSJohnny Huang pass = 1; 1904cd1610b4SJohnny Huang break; 1905cd1610b4SJohnny Huang } 1906cd1610b4SJohnny Huang } 1907de6fbf1cSJohnny Huang 1908de6fbf1cSJohnny Huang otp_soak(0); 1909de6fbf1cSJohnny Huang if (pass) { 19109009c25dSJohnny Huang printf("SUCCESS\n"); 19112a856b9aSJohnny Huang return OTP_SUCCESS; 19129009c25dSJohnny Huang } else { 19139009c25dSJohnny Huang printf("OTP cannot be programed\n"); 19149009c25dSJohnny Huang printf("FAILED\n"); 19159009c25dSJohnny Huang return OTP_FAILURE; 19169009c25dSJohnny Huang } 1917cd1610b4SJohnny Huang } 1918cd1610b4SJohnny Huang 19192a856b9aSJohnny Huang return OTP_USAGE; 1920cd1610b4SJohnny Huang } 1921cd1610b4SJohnny Huang 19222a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 192369d5fd8fSJohnny Huang { 19242a856b9aSJohnny Huang uint32_t offset, count; 19252a856b9aSJohnny Huang int ret; 192669d5fd8fSJohnny Huang 19272a856b9aSJohnny Huang if (argc == 4) { 19282a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19292a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19302a856b9aSJohnny Huang } else if (argc == 3) { 19312a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19322a856b9aSJohnny Huang count = 1; 19332a856b9aSJohnny Huang } else { 193469d5fd8fSJohnny Huang return CMD_RET_USAGE; 193569d5fd8fSJohnny Huang } 193669d5fd8fSJohnny Huang 193769d5fd8fSJohnny Huang 19382a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19393d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19402a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19412a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19423d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19432a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19442a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19453d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19462a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19472a856b9aSJohnny Huang } else { 19482a856b9aSJohnny Huang return CMD_RET_USAGE; 194969d5fd8fSJohnny Huang } 195069d5fd8fSJohnny Huang 19512a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19522a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19532a856b9aSJohnny Huang else 19542a856b9aSJohnny Huang return CMD_RET_USAGE; 19552a856b9aSJohnny Huang 19562a856b9aSJohnny Huang } 19572a856b9aSJohnny Huang 19582a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19592a856b9aSJohnny Huang { 19602a856b9aSJohnny Huang phys_addr_t addr; 19612a856b9aSJohnny Huang uint32_t byte_size; 19622a856b9aSJohnny Huang int ret; 19632a856b9aSJohnny Huang 19642a856b9aSJohnny Huang if (argc == 4) { 1965ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19662a856b9aSJohnny Huang return CMD_RET_USAGE; 19672a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19682a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 19693d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19702a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19712a856b9aSJohnny Huang } else if (argc == 3) { 19722a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19732a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 19743d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19752a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19762a856b9aSJohnny Huang } else { 19772a856b9aSJohnny Huang return CMD_RET_USAGE; 19782a856b9aSJohnny Huang } 19792a856b9aSJohnny Huang 19802a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19812a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19822a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19832a856b9aSJohnny Huang return CMD_RET_FAILURE; 19842a856b9aSJohnny Huang else 19852a856b9aSJohnny Huang return CMD_RET_USAGE; 19862a856b9aSJohnny Huang } 19872a856b9aSJohnny Huang 19882a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19892a856b9aSJohnny Huang { 19902a856b9aSJohnny Huang int mode = 0; 19912a856b9aSJohnny Huang int nconfirm = 0; 19922a856b9aSJohnny Huang int otp_addr = 0; 19932a856b9aSJohnny Huang int bit_offset; 19942a856b9aSJohnny Huang int value; 19952a856b9aSJohnny Huang int ret; 19962a856b9aSJohnny Huang 19972a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19982a856b9aSJohnny Huang return CMD_RET_USAGE; 19992a856b9aSJohnny Huang 20002a856b9aSJohnny Huang /* Drop the pb cmd */ 20012a856b9aSJohnny Huang argc--; 20022a856b9aSJohnny Huang argv++; 20032a856b9aSJohnny Huang 20042a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2005a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 20062a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2007a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 20082a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2009a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2010cd1610b4SJohnny Huang else 20112a856b9aSJohnny Huang return CMD_RET_USAGE; 20122a856b9aSJohnny Huang 20132a856b9aSJohnny Huang /* Drop the region cmd */ 20142a856b9aSJohnny Huang argc--; 20152a856b9aSJohnny Huang argv++; 20162a856b9aSJohnny Huang 2017ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2018cd1610b4SJohnny Huang nconfirm = 1; 20192a856b9aSJohnny Huang /* Drop the force option */ 20202a856b9aSJohnny Huang argc--; 20212a856b9aSJohnny Huang argv++; 20222a856b9aSJohnny Huang } 2023cd1610b4SJohnny Huang 2024a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20252a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20262a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20270808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20282a856b9aSJohnny Huang return CMD_RET_USAGE; 2029cd1610b4SJohnny Huang } else { 20302a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20312a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20322a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20330808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20342a856b9aSJohnny Huang return CMD_RET_USAGE; 20350808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 203678855207SJohnny Huang if (otp_addr >= 0x800) 20370808cc55SJohnny Huang return CMD_RET_USAGE; 20380808cc55SJohnny Huang } else { 203978855207SJohnny Huang if (otp_addr >= 0x20) 20400808cc55SJohnny Huang return CMD_RET_USAGE; 20410808cc55SJohnny Huang } 2042cd1610b4SJohnny Huang } 2043cd1610b4SJohnny Huang if (value != 0 && value != 1) 20442a856b9aSJohnny Huang return CMD_RET_USAGE; 2045cd1610b4SJohnny Huang 20463d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20472a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20482a856b9aSJohnny Huang 20492a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20502a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20512a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20522a856b9aSJohnny Huang return CMD_RET_FAILURE; 20532a856b9aSJohnny Huang else 20542a856b9aSJohnny Huang return CMD_RET_USAGE; 20552a856b9aSJohnny Huang } 20562a856b9aSJohnny Huang 20572a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20582a856b9aSJohnny Huang { 20592a856b9aSJohnny Huang phys_addr_t addr; 20602a856b9aSJohnny Huang int otp_addr = 0; 20612a856b9aSJohnny Huang 20622a856b9aSJohnny Huang if (argc != 3) 20632a856b9aSJohnny Huang return CMD_RET_USAGE; 20642a856b9aSJohnny Huang 20653d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20662a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20672a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20682a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 206969d5fd8fSJohnny Huang printf("Compare pass\n"); 20702a856b9aSJohnny Huang return CMD_RET_SUCCESS; 207169d5fd8fSJohnny Huang } else { 207269d5fd8fSJohnny Huang printf("Compare fail\n"); 20732a856b9aSJohnny Huang return CMD_RET_FAILURE; 207469d5fd8fSJohnny Huang } 207569d5fd8fSJohnny Huang } 207669d5fd8fSJohnny Huang 207766f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 207866f2f8e5SJohnny Huang { 2079a8bd6d8cSJohnny Huang int view = 0; 20802d4b0742SJohnny Huang int input; 2081a8bd6d8cSJohnny Huang 2082a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 208366f2f8e5SJohnny Huang return CMD_RET_USAGE; 208466f2f8e5SJohnny Huang 20852d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 208666f2f8e5SJohnny Huang 20873d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20882d4b0742SJohnny Huang if (argc == 3) { 20892d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20902d4b0742SJohnny Huang otp_print_conf_info(input); 20912d4b0742SJohnny Huang } else { 20922d4b0742SJohnny Huang otp_print_conf_info(-1); 20932d4b0742SJohnny Huang } 20942d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20952d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2096a8bd6d8cSJohnny Huang view = 1; 2097a8bd6d8cSJohnny Huang /* Drop the view option */ 2098a8bd6d8cSJohnny Huang argc--; 2099a8bd6d8cSJohnny Huang argv++; 2100a8bd6d8cSJohnny Huang } 21013d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2102b458cd62SJohnny Huang otp_print_strap_info(view); 210366f2f8e5SJohnny Huang } else { 210466f2f8e5SJohnny Huang return CMD_RET_USAGE; 210566f2f8e5SJohnny Huang } 21062d4b0742SJohnny Huang 210766f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 210866f2f8e5SJohnny Huang } 210966f2f8e5SJohnny Huang 2110737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2111737ed20bSJohnny Huang { 2112737ed20bSJohnny Huang int input; 2113737ed20bSJohnny Huang int bit_offset; 2114737ed20bSJohnny Huang int prog_address; 2115737ed20bSJohnny Huang int pass; 2116737ed20bSJohnny Huang int i; 2117737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2118737ed20bSJohnny Huang return CMD_RET_USAGE; 2119737ed20bSJohnny Huang 2120ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2121737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2122737ed20bSJohnny Huang } else { 2123737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2124737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2125737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2126737ed20bSJohnny Huang if (!confirm_yesno()) { 2127737ed20bSJohnny Huang printf(" Aborting\n"); 2128737ed20bSJohnny Huang return CMD_RET_FAILURE; 2129737ed20bSJohnny Huang } 2130737ed20bSJohnny Huang } 2131737ed20bSJohnny Huang 2132737ed20bSJohnny Huang prog_address = 0x800; 2133737ed20bSJohnny Huang if (input < 32) { 2134737ed20bSJohnny Huang bit_offset = input; 2135737ed20bSJohnny Huang prog_address |= 0x60c; 2136737ed20bSJohnny Huang } else if (input < 64) { 2137737ed20bSJohnny Huang bit_offset = input - 32; 2138737ed20bSJohnny Huang prog_address |= 0x60e; 2139737ed20bSJohnny Huang } else { 2140737ed20bSJohnny Huang return CMD_RET_USAGE; 2141737ed20bSJohnny Huang } 2142737ed20bSJohnny Huang 2143737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2144737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2145737ed20bSJohnny Huang } 2146de6fbf1cSJohnny Huang 2147de6fbf1cSJohnny Huang otp_soak(1); 2148de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2149de6fbf1cSJohnny Huang pass = 0; 2150de6fbf1cSJohnny Huang 2151737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2152737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2153de6fbf1cSJohnny Huang otp_soak(2); 2154de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2155de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2156de6fbf1cSJohnny Huang otp_soak(1); 2157737ed20bSJohnny Huang } else { 2158de6fbf1cSJohnny Huang pass = 1; 2159de6fbf1cSJohnny Huang break; 2160de6fbf1cSJohnny Huang } 2161de6fbf1cSJohnny Huang } else { 2162de6fbf1cSJohnny Huang pass = 1; 2163737ed20bSJohnny Huang break; 2164737ed20bSJohnny Huang } 2165737ed20bSJohnny Huang } 2166de6fbf1cSJohnny Huang otp_soak(0); 2167de6fbf1cSJohnny Huang if (pass) { 2168737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2169737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2170737ed20bSJohnny Huang } 2171737ed20bSJohnny Huang 2172737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2173737ed20bSJohnny Huang return CMD_RET_FAILURE; 2174737ed20bSJohnny Huang 2175737ed20bSJohnny Huang } 21769a4fe690SJohnny Huang 21772a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21782a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2179a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21802a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21812a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2182737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21832a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21842a856b9aSJohnny Huang }; 21852a856b9aSJohnny Huang 21862a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21872a856b9aSJohnny Huang { 21882a856b9aSJohnny Huang cmd_tbl_t *cp; 21892a856b9aSJohnny Huang 21902a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21912a856b9aSJohnny Huang 2192737ed20bSJohnny Huang /* Drop the otp command */ 21932a856b9aSJohnny Huang argc--; 21942a856b9aSJohnny Huang argv++; 21952a856b9aSJohnny Huang 21962a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 21972a856b9aSJohnny Huang return CMD_RET_USAGE; 21982a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 21992a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22002a856b9aSJohnny Huang 22019a4fe690SJohnny Huang if (chip_version() == 0) { 22029a4fe690SJohnny Huang info_cb.version = 0; 22039a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 22049a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 22059a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 22069a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 22079a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 22089a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 22099a4fe690SJohnny Huang } else if (chip_version() == 1) { 22109a4fe690SJohnny Huang info_cb.version = 1; 22113cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 22123cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 22133cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 22143cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 22159a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 22169a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 22179a4fe690SJohnny Huang } 22189a4fe690SJohnny Huang 22192a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 222069d5fd8fSJohnny Huang } 222169d5fd8fSJohnny Huang 222269d5fd8fSJohnny Huang U_BOOT_CMD( 222369d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 222469d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 22252a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 22262a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 22272d4b0742SJohnny Huang "otp info strap [v]\n" 22282d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2229ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2230ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2231ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2232ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 22332a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 223469d5fd8fSJohnny Huang ); 2235