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" }, 449*bb34a7bfSJohnny Huang { 0, 14, 1, 0, "Disable Patch code" }, 450*bb34a7bfSJohnny Huang { 0, 14, 1, 1, "Enable Patch code" }, 451*bb34a7bfSJohnny Huang { 0, 15, 1, OTP_REG_RESERVED, "" }, 4523cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4533cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4543cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4553cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4563cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4573cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4583cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4593cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4603cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4613cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4623cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4633cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4643cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4653cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4663cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4673cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4683cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4693cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4703cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4713cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 47291448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 47391448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 47491448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 47573f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 47673f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 47791448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 47891448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 47991448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 48091448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 48191448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 48291448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 48391448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 48491448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 48591448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 48691448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 48791448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 48891448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 48991448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 49091448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 49191448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 49291448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 49391448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 49491448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 49591448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 49691448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 49791448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 49891448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 49991448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 50091448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 50191448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 50291448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 50391448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 50491448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 505*bb34a7bfSJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" }, 506*bb34a7bfSJohnny Huang { 14, 0, 11, OTP_REG_VALUE, "Patch code location (DW): 0x%x" }, 507*bb34a7bfSJohnny Huang { 14, 11, 6, OTP_REG_VALUE, "Patch code size (DW): 0x%x" } 508b458cd62SJohnny Huang }; 5099a4fe690SJohnny Huang 51079e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 5119a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5129a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5139a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5149a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5159a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5169a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5179a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5189a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5199a4fe690SJohnny Huang }; 5209a4fe690SJohnny Huang 52179e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 5229a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5239a4fe690SJohnny 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"}, 5249a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5259a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5269a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5279a4fe690SJohnny Huang }; 5289a4fe690SJohnny Huang 5299a4fe690SJohnny Huang static uint32_t chip_version(void) 5309a4fe690SJohnny Huang { 5319a4fe690SJohnny Huang uint32_t rev_id; 5329a4fe690SJohnny Huang 5339a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5349a4fe690SJohnny Huang 5359a4fe690SJohnny Huang return rev_id; 5369a4fe690SJohnny Huang } 5379a4fe690SJohnny Huang 5383d3688adSJohnny Huang static void wait_complete(void) 5393d3688adSJohnny Huang { 5403d3688adSJohnny Huang int reg; 5413d3688adSJohnny Huang 5423d3688adSJohnny Huang do { 5433d3688adSJohnny Huang reg = readl(OTP_STATUS); 5443d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5453d3688adSJohnny Huang } 5463d3688adSJohnny Huang 5472a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 54869d5fd8fSJohnny Huang { 5493d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5503d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5513d3688adSJohnny Huang wait_complete(); 5523d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5533d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 55469d5fd8fSJohnny Huang } 55569d5fd8fSJohnny Huang 5562a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 55769d5fd8fSJohnny Huang { 55869d5fd8fSJohnny Huang int config_offset; 55969d5fd8fSJohnny Huang 56069d5fd8fSJohnny Huang config_offset = 0x800; 56169d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 56269d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 56369d5fd8fSJohnny Huang 5643d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 5653d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5663d3688adSJohnny Huang wait_complete(); 5673d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 56869d5fd8fSJohnny Huang } 56969d5fd8fSJohnny Huang 57069d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 57169d5fd8fSJohnny Huang { 57269d5fd8fSJohnny Huang int i; 57369d5fd8fSJohnny Huang uint32_t ret[1]; 57469d5fd8fSJohnny Huang 57569d5fd8fSJohnny Huang if (offset + dw_count > 32) 5762a856b9aSJohnny Huang return OTP_USAGE; 57769d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 57869d5fd8fSJohnny Huang otp_read_config(i, ret); 579a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 58069d5fd8fSJohnny Huang } 58169d5fd8fSJohnny Huang printf("\n"); 5822a856b9aSJohnny Huang return OTP_SUCCESS; 58369d5fd8fSJohnny Huang } 58469d5fd8fSJohnny Huang 58569d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 58669d5fd8fSJohnny Huang { 58769d5fd8fSJohnny Huang int i; 58869d5fd8fSJohnny Huang uint32_t ret[2]; 58969d5fd8fSJohnny Huang 59069d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5912a856b9aSJohnny Huang return OTP_USAGE; 59269d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 59369d5fd8fSJohnny Huang otp_read_data(i, ret); 59469d5fd8fSJohnny Huang if (i % 4 == 0) 59569d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 59669d5fd8fSJohnny Huang else 59769d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 59869d5fd8fSJohnny Huang 59969d5fd8fSJohnny Huang } 60069d5fd8fSJohnny Huang printf("\n"); 6012a856b9aSJohnny Huang return OTP_SUCCESS; 60269d5fd8fSJohnny Huang } 60369d5fd8fSJohnny Huang 60469d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 60569d5fd8fSJohnny Huang { 60669d5fd8fSJohnny Huang uint32_t ret; 60769d5fd8fSJohnny Huang uint32_t *buf; 60869d5fd8fSJohnny Huang 60969d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 61069d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 61169d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 61269d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 61369d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6143d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6153d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6163d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6173d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6183d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6193d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6203d3688adSJohnny Huang wait_complete(); 6213d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 62269d5fd8fSJohnny Huang if (ret & 0x1) 62369d5fd8fSJohnny Huang return 0; 62469d5fd8fSJohnny Huang else 62569d5fd8fSJohnny Huang return -1; 62669d5fd8fSJohnny Huang } 62769d5fd8fSJohnny Huang 62869d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 62969d5fd8fSJohnny Huang { 6303d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6313d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6323d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6333d3688adSJohnny Huang wait_complete(); 63469d5fd8fSJohnny Huang } 63569d5fd8fSJohnny Huang 63669d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 63769d5fd8fSJohnny Huang { 6383d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6393d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6403d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6413d3688adSJohnny Huang wait_complete(); 64269d5fd8fSJohnny Huang } 64369d5fd8fSJohnny Huang 644a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 64569d5fd8fSJohnny Huang { 64630a8c590SJohnny Huang uint32_t ret[2]; 64769d5fd8fSJohnny Huang 64830a8c590SJohnny Huang if (otp_addr % 2 == 0) 6493d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 65030a8c590SJohnny Huang else 6513d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 65230a8c590SJohnny Huang 6533d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6543d3688adSJohnny Huang wait_complete(); 6553d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6563d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 657a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 65830a8c590SJohnny Huang if (otp_addr % 2 == 0) { 65930a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 66069d5fd8fSJohnny Huang return 0; 66169d5fd8fSJohnny Huang else 66269d5fd8fSJohnny Huang return -1; 66330a8c590SJohnny Huang } else { 66430a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 66530a8c590SJohnny Huang return 0; 66630a8c590SJohnny Huang else 66730a8c590SJohnny Huang return -1; 66830a8c590SJohnny Huang } 66930a8c590SJohnny Huang 67069d5fd8fSJohnny Huang } 67169d5fd8fSJohnny Huang 672d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6734c1c9b35SJohnny Huang { 6744c1c9b35SJohnny Huang uint32_t ret[2]; 6754c1c9b35SJohnny Huang 6764c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6774c1c9b35SJohnny Huang 6784c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6793d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 6804c1c9b35SJohnny Huang else 6813d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 6823d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6833d3688adSJohnny Huang wait_complete(); 6843d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6853d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 6864c1c9b35SJohnny Huang if (size == 1) { 6874c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6884c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 689d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6904c1c9b35SJohnny Huang compare[0] = 0; 6914c1c9b35SJohnny Huang return 0; 6924c1c9b35SJohnny Huang } else { 6934c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6944c1c9b35SJohnny Huang return -1; 6954c1c9b35SJohnny Huang } 6964c1c9b35SJohnny Huang 6974c1c9b35SJohnny Huang } else { 6984c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 699d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 7004c1c9b35SJohnny Huang compare[0] = ~0; 7014c1c9b35SJohnny Huang return 0; 7024c1c9b35SJohnny Huang } else { 703d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7044c1c9b35SJohnny Huang return -1; 7054c1c9b35SJohnny Huang } 7064c1c9b35SJohnny Huang } 7074c1c9b35SJohnny Huang } else if (size == 2) { 7084c1c9b35SJohnny Huang // otp_addr should be even 709d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7104c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7114c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7124c1c9b35SJohnny Huang compare[0] = 0; 7134c1c9b35SJohnny Huang compare[1] = ~0; 7144c1c9b35SJohnny Huang return 0; 7154c1c9b35SJohnny Huang } else { 7164c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7174c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7184c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7194c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7204c1c9b35SJohnny Huang return -1; 7214c1c9b35SJohnny Huang } 7224c1c9b35SJohnny Huang } else { 7234c1c9b35SJohnny Huang return -1; 7244c1c9b35SJohnny Huang } 7254c1c9b35SJohnny Huang } 7264c1c9b35SJohnny Huang 7277e22f42dSJohnny Huang static void otp_soak(int soak) 728d90825e2SJohnny Huang { 729de6fbf1cSJohnny Huang switch (soak) { 730de6fbf1cSJohnny Huang case 0: //default 731de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 732de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 733de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 734de6fbf1cSJohnny Huang break; 735de6fbf1cSJohnny Huang case 1: //normal program 736de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 737de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 738de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 739de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 740de6fbf1cSJohnny Huang break; 741de6fbf1cSJohnny Huang case 2: //soak program 742d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 743d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 744d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 745de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 746de6fbf1cSJohnny Huang break; 747d90825e2SJohnny Huang } 748de6fbf1cSJohnny Huang 7493d3688adSJohnny Huang wait_complete(); 750d90825e2SJohnny Huang } 751d90825e2SJohnny Huang 752d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 753d90825e2SJohnny Huang { 754d90825e2SJohnny Huang int j, bit_value, prog_bit; 755d90825e2SJohnny Huang 756d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 757d90825e2SJohnny Huang if ((keep >> j) & 0x1) 758d90825e2SJohnny Huang continue; 759d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 760d90825e2SJohnny Huang if (prog_address % 2 == 0) { 761d90825e2SJohnny Huang if (bit_value) 762d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 763d90825e2SJohnny Huang else 764d90825e2SJohnny Huang continue; 765d90825e2SJohnny Huang } else { 766d90825e2SJohnny Huang prog_address |= 1 << 15; 767d90825e2SJohnny Huang if (bit_value) 768d90825e2SJohnny Huang continue; 769d90825e2SJohnny Huang else 770d90825e2SJohnny Huang prog_bit = 0x1 << j; 771d90825e2SJohnny Huang } 772d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 773d90825e2SJohnny Huang } 774d90825e2SJohnny Huang } 775d90825e2SJohnny Huang 77654552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address) 77754552c69SJohnny Huang { 77854552c69SJohnny Huang int pass; 77954552c69SJohnny Huang int i; 78054552c69SJohnny Huang uint32_t data0_masked; 78154552c69SJohnny Huang uint32_t data1_masked; 78254552c69SJohnny Huang uint32_t buf0_masked; 78354552c69SJohnny Huang uint32_t buf1_masked; 78454552c69SJohnny Huang uint32_t compare[2]; 78554552c69SJohnny Huang 78654552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 78754552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 78854552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 78954552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 79054552c69SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) 79154552c69SJohnny Huang return 0; 79254552c69SJohnny Huang 79354552c69SJohnny Huang otp_soak(1); 79454552c69SJohnny Huang if (data0_masked != buf0_masked) 79554552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 79654552c69SJohnny Huang if (data1_masked != buf1_masked) 79754552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 79854552c69SJohnny Huang 79954552c69SJohnny Huang pass = 0; 80054552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 80154552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 80254552c69SJohnny Huang otp_soak(2); 80354552c69SJohnny Huang if (compare[0] != 0) { 80454552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 80554552c69SJohnny Huang } 80654552c69SJohnny Huang if (compare[1] != ~0) { 80754552c69SJohnny Huang otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1); 80854552c69SJohnny Huang } 80954552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 81054552c69SJohnny Huang otp_soak(1); 81154552c69SJohnny Huang } else { 81254552c69SJohnny Huang pass = 1; 81354552c69SJohnny Huang break; 81454552c69SJohnny Huang } 81554552c69SJohnny Huang } else { 81654552c69SJohnny Huang pass = 1; 81754552c69SJohnny Huang break; 81854552c69SJohnny Huang } 81954552c69SJohnny Huang } 82054552c69SJohnny Huang 82154552c69SJohnny Huang if (!pass) { 82254552c69SJohnny Huang otp_soak(0); 82354552c69SJohnny Huang return OTP_FAILURE; 82454552c69SJohnny Huang } 82554552c69SJohnny Huang return OTP_SUCCESS; 82654552c69SJohnny Huang } 82754552c69SJohnny Huang 82876d13988SJohnny Huang 829541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 83076d13988SJohnny Huang { 83176d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 83276d13988SJohnny Huang int i, j; 83376d13988SJohnny Huang 83476d13988SJohnny Huang for (j = 0; j < 64; j++) { 83576d13988SJohnny Huang otpstrap[j].value = 0; 83676d13988SJohnny Huang otpstrap[j].remain_times = 7; 83776d13988SJohnny Huang otpstrap[j].writeable_option = -1; 83876d13988SJohnny Huang otpstrap[j].protected = 0; 83976d13988SJohnny Huang } 84076d13988SJohnny Huang 84176d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 84276d13988SJohnny Huang int option = (i - 16) / 2; 84376d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 84476d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 84576d13988SJohnny Huang for (j = 0; j < 32; j++) { 84676d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 84776d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 84876d13988SJohnny Huang otpstrap[j].writeable_option = option; 84976d13988SJohnny Huang } 85076d13988SJohnny Huang if (bit_value == 1) 85176d13988SJohnny Huang otpstrap[j].remain_times --; 85276d13988SJohnny Huang otpstrap[j].value ^= bit_value; 85376d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 85476d13988SJohnny Huang } 85576d13988SJohnny Huang for (j = 32; j < 64; j++) { 85676d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 85776d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 85876d13988SJohnny Huang otpstrap[j].writeable_option = option; 85976d13988SJohnny Huang } 86076d13988SJohnny Huang if (bit_value == 1) 86176d13988SJohnny Huang otpstrap[j].remain_times --; 86276d13988SJohnny Huang otpstrap[j].value ^= bit_value; 86376d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 86476d13988SJohnny Huang } 86576d13988SJohnny Huang } 86676d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 86776d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 86876d13988SJohnny Huang for (j = 0; j < 32; j++) { 86976d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 87076d13988SJohnny Huang otpstrap[j].protected = 1; 87176d13988SJohnny Huang } 87276d13988SJohnny Huang for (j = 32; j < 64; j++) { 87376d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 87476d13988SJohnny Huang otpstrap[j].protected = 1; 87576d13988SJohnny Huang } 87676d13988SJohnny Huang } 87776d13988SJohnny Huang 878b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 87969d5fd8fSJohnny Huang { 88079e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 881*bb34a7bfSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[16]; 882b458cd62SJohnny Huang uint32_t mask; 883b458cd62SJohnny Huang uint32_t dw_offset; 884b458cd62SJohnny Huang uint32_t bit_offset; 885b458cd62SJohnny Huang uint32_t otp_value; 886b458cd62SJohnny Huang uint32_t otp_keep; 887b458cd62SJohnny Huang int fail = 0; 88873f11549SJohnny Huang char valid_bit[20]; 88966f2f8e5SJohnny Huang int i; 89073f11549SJohnny Huang int j; 89166f2f8e5SJohnny Huang 892737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 89366f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8943cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8953cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8963cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8973cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 898b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 899b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 900b458cd62SJohnny Huang 901b458cd62SJohnny Huang if (otp_keep == mask) { 902b458cd62SJohnny Huang continue; 903b458cd62SJohnny Huang } else if (otp_keep != 0) { 904b458cd62SJohnny Huang fail = 1; 905b458cd62SJohnny Huang } 906b458cd62SJohnny Huang 9073cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9083cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9093cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9103cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 911b458cd62SJohnny Huang continue; 912b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 913b458cd62SJohnny Huang 9143cb28812SJohnny Huang if (conf_info[i].length == 1) { 9153cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 91666f2f8e5SJohnny Huang } else { 917b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9183cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9193cb28812SJohnny Huang conf_info[i].bit_offset); 92066f2f8e5SJohnny Huang } 921b458cd62SJohnny Huang printf("0x%-10x", otp_value); 922b458cd62SJohnny Huang 923b458cd62SJohnny Huang if (fail) { 924b458cd62SJohnny Huang printf("Keep mask error\n"); 925b458cd62SJohnny Huang } else { 9263cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 927b458cd62SJohnny Huang printf("Reserved\n"); 9283cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9293cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 930b458cd62SJohnny Huang printf("\n"); 9313cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 932b458cd62SJohnny Huang if (otp_value != 0) { 93373f11549SJohnny Huang for (j = 0; j < 7; j++) { 93473f11549SJohnny Huang if (otp_value == (1 << j)) { 93573f11549SJohnny Huang valid_bit[j * 2] = '1'; 936b458cd62SJohnny Huang } else { 93773f11549SJohnny Huang valid_bit[j * 2] = '0'; 93873f11549SJohnny Huang } 93973f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 94073f11549SJohnny Huang } 94173f11549SJohnny Huang valid_bit[15] = 0; 94273f11549SJohnny Huang } else { 94373f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 944b458cd62SJohnny Huang } 9453cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 946b458cd62SJohnny Huang printf("\n"); 947b458cd62SJohnny Huang } else { 9483cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 949b458cd62SJohnny Huang } 950b458cd62SJohnny Huang } 951b458cd62SJohnny Huang } 952b458cd62SJohnny Huang 953b458cd62SJohnny Huang if (fail) 954b458cd62SJohnny Huang return OTP_FAILURE; 955b458cd62SJohnny Huang 95666f2f8e5SJohnny Huang return OTP_SUCCESS; 95766f2f8e5SJohnny Huang } 95866f2f8e5SJohnny Huang 9592d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 96066f2f8e5SJohnny Huang { 96179e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 962*bb34a7bfSJohnny Huang uint32_t OTPCFG[16]; 963b458cd62SJohnny Huang uint32_t mask; 964b458cd62SJohnny Huang uint32_t dw_offset; 965b458cd62SJohnny Huang uint32_t bit_offset; 966b458cd62SJohnny Huang uint32_t otp_value; 96773f11549SJohnny Huang char valid_bit[20]; 96866f2f8e5SJohnny Huang int i; 96973f11549SJohnny Huang int j; 97066f2f8e5SJohnny Huang 971*bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 97266f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 97366f2f8e5SJohnny Huang 97466f2f8e5SJohnny Huang 975b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 976b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9773cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9783cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9792d4b0742SJohnny Huang continue; 9803cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9813cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9823cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 983b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 984b458cd62SJohnny Huang 9853cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9863cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9873cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9883cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 989b458cd62SJohnny Huang continue; 990b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 991b458cd62SJohnny Huang 9923cb28812SJohnny Huang if (conf_info[i].length == 1) { 9933cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 994b458cd62SJohnny Huang } else { 995b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9963cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9973cb28812SJohnny Huang conf_info[i].bit_offset); 998b458cd62SJohnny Huang } 999b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1000b458cd62SJohnny Huang 10013cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1002b458cd62SJohnny Huang printf("Reserved\n"); 10033cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10043cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1005b458cd62SJohnny Huang printf("\n"); 10063cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1007b458cd62SJohnny Huang if (otp_value != 0) { 100873f11549SJohnny Huang for (j = 0; j < 7; j++) { 100973f11549SJohnny Huang if (otp_value == (1 << j)) { 101073f11549SJohnny Huang valid_bit[j * 2] = '1'; 1011b458cd62SJohnny Huang } else { 101273f11549SJohnny Huang valid_bit[j * 2] = '0'; 101373f11549SJohnny Huang } 101473f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 101573f11549SJohnny Huang } 101673f11549SJohnny Huang valid_bit[15] = 0; 101773f11549SJohnny Huang } else { 101873f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1019b458cd62SJohnny Huang } 10203cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1021b458cd62SJohnny Huang printf("\n"); 1022b458cd62SJohnny Huang } else { 10233cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1024b458cd62SJohnny Huang } 1025b458cd62SJohnny Huang } 1026b458cd62SJohnny Huang return OTP_SUCCESS; 102766f2f8e5SJohnny Huang } 102866f2f8e5SJohnny Huang 1029b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 103076d13988SJohnny Huang { 103179e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1032a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 1033a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 103476d13988SJohnny Huang int i; 1035a8bd6d8cSJohnny Huang int fail = 0; 1036a8bd6d8cSJohnny Huang uint32_t bit_offset; 1037a8bd6d8cSJohnny Huang uint32_t dw_offset; 1038a8bd6d8cSJohnny Huang uint32_t mask; 1039a8bd6d8cSJohnny Huang uint32_t otp_value; 1040a8bd6d8cSJohnny Huang uint32_t otp_protect; 1041a8bd6d8cSJohnny Huang uint32_t otp_keep; 104276d13988SJohnny Huang 1043a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1044a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1045b458cd62SJohnny Huang 10463cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 10473cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 1048a8bd6d8cSJohnny Huang dw_offset = 1; 10493cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1050a8bd6d8cSJohnny Huang } else { 1051a8bd6d8cSJohnny Huang dw_offset = 0; 10523cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1053a8bd6d8cSJohnny Huang } 105476d13988SJohnny Huang 10553cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1056a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1057a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1058a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1059a8bd6d8cSJohnny Huang 1060a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1061a8bd6d8cSJohnny Huang continue; 1062a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1063a8bd6d8cSJohnny Huang fail = 1; 1064a8bd6d8cSJohnny Huang } 1065a8bd6d8cSJohnny Huang 10663cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10673cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1068a8bd6d8cSJohnny Huang continue; 1069a8bd6d8cSJohnny Huang 10703cb28812SJohnny Huang if (strap_info[i].length == 1) { 10713cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1072a8bd6d8cSJohnny Huang } else { 1073b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10743cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10753cb28812SJohnny Huang strap_info[i].bit_offset); 1076a8bd6d8cSJohnny Huang } 1077a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1078a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1079a8bd6d8cSJohnny Huang 1080a8bd6d8cSJohnny Huang if (fail) { 1081a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1082a8bd6d8cSJohnny Huang } else { 10833cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10843cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1085a8bd6d8cSJohnny Huang else 1086a8bd6d8cSJohnny Huang printf("Reserved\n"); 1087a8bd6d8cSJohnny Huang } 1088a8bd6d8cSJohnny Huang } 1089a8bd6d8cSJohnny Huang 1090a8bd6d8cSJohnny Huang if (fail) 109176d13988SJohnny Huang return OTP_FAILURE; 109276d13988SJohnny Huang 109376d13988SJohnny Huang return OTP_SUCCESS; 109476d13988SJohnny Huang } 109576d13988SJohnny Huang 1096b458cd62SJohnny Huang static int otp_print_strap_info(int view) 109776d13988SJohnny Huang { 109879e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 109976d13988SJohnny Huang struct otpstrap_status strap_status[64]; 110007baa4e8SJohnny Huang int i, j; 1101b458cd62SJohnny Huang int fail = 0; 1102b458cd62SJohnny Huang uint32_t bit_offset; 1103b458cd62SJohnny Huang uint32_t length; 1104b458cd62SJohnny Huang uint32_t otp_value; 1105b458cd62SJohnny Huang uint32_t otp_protect; 110676d13988SJohnny Huang 1107541eb887SJohnny Huang otp_strap_status(strap_status); 110876d13988SJohnny Huang 1109b458cd62SJohnny Huang if (view) { 111007baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 111107baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 111207baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 111307baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1114b458cd62SJohnny Huang } else { 1115b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1116b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 111776d13988SJohnny Huang } 11183cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1119b458cd62SJohnny Huang otp_value = 0; 11203cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 11213cb28812SJohnny Huang length = strap_info[i].length; 1122b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1123c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1124c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1125b458cd62SJohnny Huang } 11263cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11273cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1128b458cd62SJohnny Huang continue; 1129b458cd62SJohnny Huang if (view) { 1130b458cd62SJohnny Huang for (j = 0; j < length; j++) { 11313cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1132b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 113307baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1134b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 11353cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1136b458cd62SJohnny Huang printf(" Reserved\n"); 1137b458cd62SJohnny Huang continue; 1138b458cd62SJohnny Huang } 1139b458cd62SJohnny Huang if (length == 1) { 11403cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1141b458cd62SJohnny Huang continue; 114276d13988SJohnny Huang } 114376d13988SJohnny Huang 1144b458cd62SJohnny Huang if (j == 0) 11453cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1146b458cd62SJohnny Huang else if (j == length - 1) 1147b458cd62SJohnny Huang printf("\\ \"\n"); 1148b458cd62SJohnny Huang else 1149b458cd62SJohnny Huang printf("| \"\n"); 115076d13988SJohnny Huang } 1151b458cd62SJohnny Huang } else { 1152c947ef08SJohnny Huang if (length == 1) { 11533cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1154b458cd62SJohnny Huang } else { 1155b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1156b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1157b458cd62SJohnny Huang } 1158b458cd62SJohnny Huang 1159b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1160b458cd62SJohnny Huang 11613cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11623cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1163b458cd62SJohnny Huang else 1164b458cd62SJohnny Huang printf("Reserved\n"); 1165b458cd62SJohnny Huang } 1166b458cd62SJohnny Huang } 1167b458cd62SJohnny Huang 1168b458cd62SJohnny Huang if (fail) 1169b458cd62SJohnny Huang return OTP_FAILURE; 1170b458cd62SJohnny Huang 1171b458cd62SJohnny Huang return OTP_SUCCESS; 1172b458cd62SJohnny Huang } 1173b458cd62SJohnny Huang 117469d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 117569d5fd8fSJohnny Huang { 117669d5fd8fSJohnny Huang int i; 117769d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 117869d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 117969d5fd8fSJohnny Huang if (i % 16 == 0) { 118069d5fd8fSJohnny Huang printf("%04X: ", i); 118169d5fd8fSJohnny Huang } 118269d5fd8fSJohnny Huang printf("%02X ", buf[i]); 118369d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 118469d5fd8fSJohnny Huang printf("\n"); 118569d5fd8fSJohnny Huang } 118669d5fd8fSJohnny Huang } 118769d5fd8fSJohnny Huang } 118869d5fd8fSJohnny Huang 11897f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 119069d5fd8fSJohnny Huang { 119169d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 119279e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 11939a4fe690SJohnny Huang struct otpkey_type key_info; 119469d5fd8fSJohnny Huang char *byte_buf; 11959d998018SJohnny Huang char empty = 1; 119669d5fd8fSJohnny Huang int i = 0, len = 0; 11979a4fe690SJohnny Huang int j; 119854552c69SJohnny Huang 119969d5fd8fSJohnny Huang byte_buf = (char *)buf; 12009d998018SJohnny Huang 12019d998018SJohnny Huang for (i = 0; i < 16; i++) { 12029d998018SJohnny Huang if (buf[i] != 0) { 12039d998018SJohnny Huang empty = 0; 12049d998018SJohnny Huang } 12059d998018SJohnny Huang } 12069d998018SJohnny Huang if (empty) 12079d998018SJohnny Huang return 0; 12089d998018SJohnny Huang 12099d998018SJohnny Huang i = 0; 121069d5fd8fSJohnny Huang while (1) { 121169d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 121269d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 121369d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 121469d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 121569d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 121669d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 12179a4fe690SJohnny Huang 12189a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 12199a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 12209a4fe690SJohnny Huang key_info = key_info_array[j]; 12219a4fe690SJohnny Huang break; 12229a4fe690SJohnny Huang } 12239a4fe690SJohnny Huang } 12249a4fe690SJohnny Huang 12257f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 122669d5fd8fSJohnny Huang printf("Key Type: "); 12279a4fe690SJohnny Huang printf("%s\n", key_info.information); 12289a4fe690SJohnny Huang 12299a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 123069d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 123169d5fd8fSJohnny Huang switch (key_length) { 123269d5fd8fSJohnny Huang case 0: 123369d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 123469d5fd8fSJohnny Huang break; 123569d5fd8fSJohnny Huang case 1: 123669d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 123769d5fd8fSJohnny Huang break; 123869d5fd8fSJohnny Huang case 2: 123969d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 124069d5fd8fSJohnny Huang break; 124169d5fd8fSJohnny Huang case 3: 124269d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 124369d5fd8fSJohnny Huang break; 124469d5fd8fSJohnny Huang } 12459a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 124669d5fd8fSJohnny Huang printf("RSA SHA Type: "); 124769d5fd8fSJohnny Huang switch (key_length) { 124869d5fd8fSJohnny Huang case 0: 124969d5fd8fSJohnny Huang printf("RSA1024\n"); 125069d5fd8fSJohnny Huang len = 0x100; 125169d5fd8fSJohnny Huang break; 125269d5fd8fSJohnny Huang case 1: 125369d5fd8fSJohnny Huang printf("RSA2048\n"); 125469d5fd8fSJohnny Huang len = 0x200; 125569d5fd8fSJohnny Huang break; 125669d5fd8fSJohnny Huang case 2: 125769d5fd8fSJohnny Huang printf("RSA3072\n"); 125869d5fd8fSJohnny Huang len = 0x300; 125969d5fd8fSJohnny Huang break; 126069d5fd8fSJohnny Huang case 3: 126169d5fd8fSJohnny Huang printf("RSA4096\n"); 126269d5fd8fSJohnny Huang len = 0x400; 126369d5fd8fSJohnny Huang break; 126469d5fd8fSJohnny Huang } 126569d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 126669d5fd8fSJohnny Huang } 12679a4fe690SJohnny Huang if (key_info.need_id) 126869d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 126969d5fd8fSJohnny Huang printf("Key Value:\n"); 12709a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 127169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12729a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12739a4fe690SJohnny Huang printf("AES Key:\n"); 12749a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12759a4fe690SJohnny Huang if (info_cb.version == 0) { 12769a4fe690SJohnny Huang printf("AES IV:\n"); 12779a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12789a4fe690SJohnny Huang } 12799a4fe690SJohnny Huang 12809a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12819a4fe690SJohnny Huang if (info_cb.version == 0) { 128269d5fd8fSJohnny Huang printf("AES Key:\n"); 128369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 128469d5fd8fSJohnny Huang printf("AES IV:\n"); 128569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12869a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12879a4fe690SJohnny Huang printf("AES Key 1:\n"); 12889a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12899a4fe690SJohnny Huang printf("AES Key 2:\n"); 12909a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12919a4fe690SJohnny Huang } 129269d5fd8fSJohnny Huang 12939a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 129469d5fd8fSJohnny Huang printf("RSA mod:\n"); 129569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 129669d5fd8fSJohnny Huang printf("RSA exp:\n"); 129769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 129869d5fd8fSJohnny Huang } 129969d5fd8fSJohnny Huang if (last) 130069d5fd8fSJohnny Huang break; 130169d5fd8fSJohnny Huang i++; 130269d5fd8fSJohnny Huang } 130369d5fd8fSJohnny Huang return 0; 130469d5fd8fSJohnny Huang } 130569d5fd8fSJohnny Huang 1306a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 130769d5fd8fSJohnny Huang { 1308a6d0d645SJohnny Huang int i, k; 1309d90825e2SJohnny Huang int pass = 0; 1310a6d0d645SJohnny Huang uint32_t prog_address; 1311*bb34a7bfSJohnny Huang uint32_t data[16]; 1312a6d0d645SJohnny Huang uint32_t compare[2]; 1313*bb34a7bfSJohnny Huang uint32_t *buf_keep = &buf[16]; 1314d90825e2SJohnny Huang uint32_t data_masked; 1315d90825e2SJohnny Huang uint32_t buf_masked; 131669d5fd8fSJohnny Huang 1317a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1318a6d0d645SJohnny Huang 1319*bb34a7bfSJohnny Huang for (i = 0; i < 16 ; i ++) { 132069d5fd8fSJohnny Huang prog_address = 0x800; 1321a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1322a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1323a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1324a6d0d645SJohnny Huang } 1325a6d0d645SJohnny Huang 1326a6d0d645SJohnny Huang printf("Check writable...\n"); 1327*bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 1328d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1329d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1330d90825e2SJohnny Huang if (data_masked == buf_masked) 133169d5fd8fSJohnny Huang continue; 1332d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1333a6d0d645SJohnny Huang continue; 1334a6d0d645SJohnny Huang } else { 1335a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1336a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1337a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1338a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 13392a856b9aSJohnny Huang return OTP_FAILURE; 1340a6d0d645SJohnny Huang } 1341a6d0d645SJohnny Huang } 1342a6d0d645SJohnny Huang 1343a6d0d645SJohnny Huang printf("Start Programing...\n"); 1344d90825e2SJohnny Huang otp_soak(0); 1345*bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 1346d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1347d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1348a6d0d645SJohnny Huang prog_address = 0x800; 1349a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1350a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1351*bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1352*bb34a7bfSJohnny Huang pass = 1; 1353a6d0d645SJohnny Huang continue; 1354*bb34a7bfSJohnny Huang } 1355de6fbf1cSJohnny Huang 1356a6d0d645SJohnny Huang 1357de6fbf1cSJohnny Huang otp_soak(1); 1358d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1359a6d0d645SJohnny Huang 136069d5fd8fSJohnny Huang pass = 0; 136169d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1362d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1363de6fbf1cSJohnny Huang otp_soak(2); 1364a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1365de6fbf1cSJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1366de6fbf1cSJohnny Huang otp_soak(1); 1367de6fbf1cSJohnny Huang } else { 1368de6fbf1cSJohnny Huang pass = 1; 1369de6fbf1cSJohnny Huang break; 1370de6fbf1cSJohnny Huang } 1371a6d0d645SJohnny Huang } else { 137269d5fd8fSJohnny Huang pass = 1; 137369d5fd8fSJohnny Huang break; 137469d5fd8fSJohnny Huang } 137569d5fd8fSJohnny Huang } 1376*bb34a7bfSJohnny Huang if (pass == 0) { 1377*bb34a7bfSJohnny Huang printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n", 1378*bb34a7bfSJohnny Huang i, data[i], buf[i], buf_keep[i]); 1379*bb34a7bfSJohnny Huang break; 1380*bb34a7bfSJohnny Huang } 1381a6d0d645SJohnny Huang } 1382a6d0d645SJohnny Huang 1383de6fbf1cSJohnny Huang otp_soak(0); 138469d5fd8fSJohnny Huang if (!pass) 13852a856b9aSJohnny Huang return OTP_FAILURE; 1386a6d0d645SJohnny Huang 13872a856b9aSJohnny Huang return OTP_SUCCESS; 1388d90825e2SJohnny Huang 138969d5fd8fSJohnny Huang } 139069d5fd8fSJohnny Huang 139169d5fd8fSJohnny Huang 139276d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 139369d5fd8fSJohnny Huang { 139469d5fd8fSJohnny Huang int i; 139569d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 139669d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 139769d5fd8fSJohnny Huang int bit, pbit, kbit; 139869d5fd8fSJohnny Huang int fail = 0; 1399a6af4a17SJohnny Huang int skip = -1; 140066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 140169d5fd8fSJohnny Huang 1402541eb887SJohnny Huang otp_strap_status(otpstrap); 140369d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 140469d5fd8fSJohnny Huang if (i < 32) { 140569d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 140669d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 140769d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 140869d5fd8fSJohnny Huang } else { 140969d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 141069d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 141169d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 141269d5fd8fSJohnny Huang } 141369d5fd8fSJohnny Huang 141469d5fd8fSJohnny Huang if (kbit == 1) { 141569d5fd8fSJohnny Huang continue; 141669d5fd8fSJohnny Huang } else { 1417a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 141869d5fd8fSJohnny Huang } 141969d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 142069d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1421a6af4a17SJohnny Huang if (skip == -1) 1422a6af4a17SJohnny Huang skip = 1; 142369d5fd8fSJohnny Huang continue; 1424a6af4a17SJohnny Huang } else { 1425a6af4a17SJohnny Huang skip = 0; 142669d5fd8fSJohnny Huang } 142769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 142869d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 142969d5fd8fSJohnny Huang fail = 1; 143069d5fd8fSJohnny Huang continue; 143169d5fd8fSJohnny Huang } 143269d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1433a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 143469d5fd8fSJohnny Huang fail = 1; 143569d5fd8fSJohnny Huang continue; 143669d5fd8fSJohnny Huang } 143769d5fd8fSJohnny Huang if (pbit == 1) { 143869d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 143969d5fd8fSJohnny Huang } 1440a6af4a17SJohnny 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); 144169d5fd8fSJohnny Huang } 144269d5fd8fSJohnny Huang if (fail == 1) 1443a6af4a17SJohnny Huang return OTP_FAILURE; 1444a6af4a17SJohnny Huang else if (skip == 1) 1445a6af4a17SJohnny Huang return OTP_PROG_SKIP; 14467e22f42dSJohnny Huang 14477e22f42dSJohnny Huang return 0; 144869d5fd8fSJohnny Huang } 144969d5fd8fSJohnny Huang 14502a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 145169d5fd8fSJohnny Huang { 145269d5fd8fSJohnny Huang int i, j; 145366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 145469d5fd8fSJohnny Huang 14552a856b9aSJohnny Huang if (start < 0 || start > 64) 14562a856b9aSJohnny Huang return OTP_USAGE; 14572a856b9aSJohnny Huang 14582a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 14592a856b9aSJohnny Huang return OTP_USAGE; 14602a856b9aSJohnny Huang 1461541eb887SJohnny Huang otp_strap_status(otpstrap); 146269d5fd8fSJohnny Huang 146307baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1464a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1465737ed20bSJohnny Huang 1466cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 146707baa4e8SJohnny Huang printf("0x%-8X", i); 1468737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1469737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1470737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1471737ed20bSJohnny Huang printf(" "); 147269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1473737ed20bSJohnny Huang printf("protected and not writable"); 147469d5fd8fSJohnny Huang } else { 1475737ed20bSJohnny Huang printf("not protected "); 147669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1477737ed20bSJohnny Huang printf("and no remaining times to write."); 147869d5fd8fSJohnny Huang } else { 1479737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 148069d5fd8fSJohnny Huang } 148169d5fd8fSJohnny Huang } 1482737ed20bSJohnny Huang printf("\n"); 148369d5fd8fSJohnny Huang } 14842a856b9aSJohnny Huang 14852a856b9aSJohnny Huang return OTP_SUCCESS; 148669d5fd8fSJohnny Huang } 148769d5fd8fSJohnny Huang 148869d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 148969d5fd8fSJohnny Huang { 149069d5fd8fSJohnny Huang int i, j; 149169d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 149269d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 149369d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 149469d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 149569d5fd8fSJohnny Huang int fail = 0; 14967e22f42dSJohnny Huang int pass = 0; 149766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 149869d5fd8fSJohnny Huang 14997f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1500541eb887SJohnny Huang otp_strap_status(otpstrap); 150169d5fd8fSJohnny Huang 15027f795e57SJohnny Huang printf("Check writable...\n"); 15037f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 15047f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 15057f795e57SJohnny Huang return OTP_FAILURE; 15067f795e57SJohnny Huang } 15077e22f42dSJohnny Huang 150869d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 150969d5fd8fSJohnny Huang prog_address = 0x800; 151069d5fd8fSJohnny Huang if (i < 32) { 151169d5fd8fSJohnny Huang offset = i; 151269d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 151369d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 151469d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 151569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 151669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 151769d5fd8fSJohnny Huang 151869d5fd8fSJohnny Huang } else { 151969d5fd8fSJohnny Huang offset = (i - 32); 152069d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 152169d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 152269d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 152369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 152469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 152569d5fd8fSJohnny Huang } 152669d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 152769d5fd8fSJohnny Huang 152869d5fd8fSJohnny Huang if (kbit == 1) { 152969d5fd8fSJohnny Huang continue; 153069d5fd8fSJohnny Huang } 153169d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 153269d5fd8fSJohnny Huang continue; 153369d5fd8fSJohnny Huang } 153469d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 153569d5fd8fSJohnny Huang fail = 1; 153669d5fd8fSJohnny Huang continue; 153769d5fd8fSJohnny Huang } 153869d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 153969d5fd8fSJohnny Huang fail = 1; 154069d5fd8fSJohnny Huang continue; 154169d5fd8fSJohnny Huang } 15427e22f42dSJohnny Huang 15437e22f42dSJohnny Huang 1544de6fbf1cSJohnny Huang otp_soak(1); 15457e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15467e22f42dSJohnny Huang 15477e22f42dSJohnny Huang pass = 0; 154869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1549de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1550de6fbf1cSJohnny Huang otp_soak(2); 1551de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1552de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1553de6fbf1cSJohnny Huang otp_soak(1); 1554de6fbf1cSJohnny Huang } else { 155569d5fd8fSJohnny Huang pass = 1; 155669d5fd8fSJohnny Huang break; 155769d5fd8fSJohnny Huang } 1558de6fbf1cSJohnny Huang } else { 1559de6fbf1cSJohnny Huang pass = 1; 1560de6fbf1cSJohnny Huang break; 15614b65a65dSJohnny Huang } 156269d5fd8fSJohnny Huang } 156369d5fd8fSJohnny Huang if (!pass) 15642a856b9aSJohnny Huang return OTP_FAILURE; 156569d5fd8fSJohnny Huang 156669d5fd8fSJohnny Huang if (pbit == 0) 156769d5fd8fSJohnny Huang continue; 156869d5fd8fSJohnny Huang prog_address = 0x800; 156969d5fd8fSJohnny Huang if (i < 32) 157069d5fd8fSJohnny Huang prog_address |= 0x60c; 157169d5fd8fSJohnny Huang else 157269d5fd8fSJohnny Huang prog_address |= 0x60e; 157369d5fd8fSJohnny Huang 15747e22f42dSJohnny Huang 1575de6fbf1cSJohnny Huang otp_soak(1); 15767e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15777e22f42dSJohnny Huang 15787e22f42dSJohnny Huang pass = 0; 157969d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1580de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1581de6fbf1cSJohnny Huang otp_soak(2); 1582de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1583de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1584de6fbf1cSJohnny Huang otp_soak(1); 1585de6fbf1cSJohnny Huang } else { 158669d5fd8fSJohnny Huang pass = 1; 158769d5fd8fSJohnny Huang break; 158869d5fd8fSJohnny Huang } 1589de6fbf1cSJohnny Huang } else { 1590de6fbf1cSJohnny Huang pass = 1; 1591de6fbf1cSJohnny Huang break; 159269d5fd8fSJohnny Huang } 159369d5fd8fSJohnny Huang } 159469d5fd8fSJohnny Huang if (!pass) 15952a856b9aSJohnny Huang return OTP_FAILURE; 159669d5fd8fSJohnny Huang 159769d5fd8fSJohnny Huang } 1598de6fbf1cSJohnny Huang otp_soak(0); 159969d5fd8fSJohnny Huang if (fail == 1) 16002a856b9aSJohnny Huang return OTP_FAILURE; 160169d5fd8fSJohnny Huang else 16022a856b9aSJohnny Huang return OTP_SUCCESS; 160369d5fd8fSJohnny Huang 160469d5fd8fSJohnny Huang } 160569d5fd8fSJohnny Huang 1606de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1607cd1610b4SJohnny Huang { 1608cd1610b4SJohnny Huang int prog_bit; 1609cd1610b4SJohnny Huang 1610cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1611cd1610b4SJohnny Huang if (value) 1612cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1613cd1610b4SJohnny Huang else 1614cd1610b4SJohnny Huang return; 1615cd1610b4SJohnny Huang } else { 1616cd1610b4SJohnny Huang prog_address |= 1 << 15; 1617cd1610b4SJohnny Huang if (!value) 1618cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1619cd1610b4SJohnny Huang else 1620cd1610b4SJohnny Huang return; 1621cd1610b4SJohnny Huang } 1622cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1623cd1610b4SJohnny Huang } 1624cd1610b4SJohnny Huang 1625d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 16264c1c9b35SJohnny Huang { 162754552c69SJohnny Huang int i; 162854552c69SJohnny Huang int ret; 1629d90825e2SJohnny Huang uint32_t data[2048]; 1630d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 16314c1c9b35SJohnny Huang 163254552c69SJohnny Huang uint32_t data_masked; 163354552c69SJohnny Huang uint32_t buf_masked; 16344c1c9b35SJohnny Huang 16354c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 16364c1c9b35SJohnny Huang 1637d6cdf762SJohnny Huang for (i = 0; i < 2046 ; i += 2) { 1638d90825e2SJohnny Huang otp_read_data(i, &data[i]); 16394c1c9b35SJohnny Huang } 1640d90825e2SJohnny Huang 16414c1c9b35SJohnny Huang 16424c1c9b35SJohnny Huang printf("Check writable...\n"); 164354552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1644d6cdf762SJohnny Huang for (i = 0; i < 2046; i++) { 164554552c69SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 164654552c69SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 164754552c69SJohnny Huang if (data_masked == buf_masked) 16484c1c9b35SJohnny Huang continue; 1649d90825e2SJohnny Huang if (i % 2 == 0) { 165054552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 16514c1c9b35SJohnny Huang continue; 16524c1c9b35SJohnny Huang } else { 16534c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1654d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 16554c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1656d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16572a856b9aSJohnny Huang return OTP_FAILURE; 165869d5fd8fSJohnny Huang } 1659d90825e2SJohnny Huang } else { 166054552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1661d90825e2SJohnny Huang continue; 1662d90825e2SJohnny Huang } else { 1663d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1664d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1665d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1666d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16672a856b9aSJohnny Huang return OTP_FAILURE; 1668d90825e2SJohnny Huang } 1669d90825e2SJohnny Huang } 1670d90825e2SJohnny Huang } 167169d5fd8fSJohnny Huang 1672d90825e2SJohnny Huang printf("Start Programing...\n"); 1673d90825e2SJohnny Huang 167454552c69SJohnny Huang // programing ecc region first 167554552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 167654552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 167754552c69SJohnny Huang if (ret != OTP_SUCCESS) { 167854552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 167954552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 168054552c69SJohnny Huang return ret; 1681d90825e2SJohnny Huang } 1682d90825e2SJohnny Huang } 1683d90825e2SJohnny Huang 168454552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 168554552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 168654552c69SJohnny Huang if (ret != OTP_SUCCESS) { 168754552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 168854552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 168954552c69SJohnny Huang return ret; 1690d90825e2SJohnny Huang } 1691de6fbf1cSJohnny Huang } 1692de6fbf1cSJohnny Huang otp_soak(0); 16932a856b9aSJohnny Huang return OTP_SUCCESS; 1694d90825e2SJohnny Huang 1695d90825e2SJohnny Huang } 1696d90825e2SJohnny Huang 1697d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 169869d5fd8fSJohnny Huang { 169969d5fd8fSJohnny Huang int ret; 17007332532cSJohnny Huang int mode = 0; 17019a4fe690SJohnny Huang int image_version = 0; 170269d5fd8fSJohnny Huang uint32_t *buf; 1703d90825e2SJohnny Huang uint32_t *data_region = NULL; 1704d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1705d90825e2SJohnny Huang uint32_t *strap_region = NULL; 170669d5fd8fSJohnny Huang 1707d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 170869d5fd8fSJohnny Huang if (!buf) { 170969d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 17102a856b9aSJohnny Huang return OTP_FAILURE; 171169d5fd8fSJohnny Huang } 1712d90825e2SJohnny Huang 17139a4fe690SJohnny Huang image_version = buf[0] & 0x3; 17149a4fe690SJohnny Huang if (image_version != info_cb.version) { 17159a4fe690SJohnny Huang puts("Version is not match\n"); 17169a4fe690SJohnny Huang return OTP_FAILURE; 17179a4fe690SJohnny Huang } 17189a4fe690SJohnny Huang 1719d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 17207332532cSJohnny Huang mode |= OTP_REGION_DATA; 1721*bb34a7bfSJohnny Huang data_region = &buf[44]; 1722d90825e2SJohnny Huang } 1723d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 17247332532cSJohnny Huang mode |= OTP_REGION_CONF; 17257332532cSJohnny Huang conf_region = &buf[12]; 1726d90825e2SJohnny Huang } 1727d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 17287332532cSJohnny Huang mode |= OTP_REGION_STRAP; 17297332532cSJohnny Huang strap_region = &buf[4]; 1730d90825e2SJohnny Huang } 17317332532cSJohnny Huang 173269d5fd8fSJohnny Huang if (!nconfirm) { 17337332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17347f795e57SJohnny Huang printf("\nOTP data region :\n"); 17357f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 173669d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17372a856b9aSJohnny Huang return OTP_FAILURE; 173869d5fd8fSJohnny Huang } 173969d5fd8fSJohnny Huang } 17407332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17417332532cSJohnny Huang printf("\nOTP strap region :\n"); 17427332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17437332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17447332532cSJohnny Huang return OTP_FAILURE; 17457332532cSJohnny Huang } 17467332532cSJohnny Huang } 17477332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17487332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17497332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17507332532cSJohnny Huang printf("OTP config error, please check.\n"); 17517332532cSJohnny Huang return OTP_FAILURE; 17527332532cSJohnny Huang } 17537332532cSJohnny Huang } 17547332532cSJohnny Huang 175569d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 175669d5fd8fSJohnny Huang if (!confirm_yesno()) { 175769d5fd8fSJohnny Huang printf(" Aborting\n"); 17582a856b9aSJohnny Huang return OTP_FAILURE; 175969d5fd8fSJohnny Huang } 176069d5fd8fSJohnny Huang } 17617332532cSJohnny Huang 17627332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17637332532cSJohnny Huang printf("programing data region ...\n"); 1764d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17652a856b9aSJohnny Huang if (ret != 0) { 176669d5fd8fSJohnny Huang printf("Error\n"); 176769d5fd8fSJohnny Huang return ret; 176869d5fd8fSJohnny Huang } else { 176969d5fd8fSJohnny Huang printf("Done\n"); 177069d5fd8fSJohnny Huang } 17717332532cSJohnny Huang } 17727332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17737332532cSJohnny Huang printf("programing strap region ...\n"); 1774d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17752a856b9aSJohnny Huang if (ret != 0) { 177669d5fd8fSJohnny Huang printf("Error\n"); 177769d5fd8fSJohnny Huang return ret; 177869d5fd8fSJohnny Huang } else { 177969d5fd8fSJohnny Huang printf("Done\n"); 178069d5fd8fSJohnny Huang } 17817332532cSJohnny Huang } 17827332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17837332532cSJohnny Huang printf("programing configuration region ...\n"); 1784d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17852a856b9aSJohnny Huang if (ret != 0) { 178669d5fd8fSJohnny Huang printf("Error\n"); 178769d5fd8fSJohnny Huang return ret; 178869d5fd8fSJohnny Huang } 178969d5fd8fSJohnny Huang printf("Done\n"); 179069d5fd8fSJohnny Huang } 1791cd1610b4SJohnny Huang 17927332532cSJohnny Huang return OTP_SUCCESS; 17932a856b9aSJohnny Huang } 17942a856b9aSJohnny Huang 17952a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1796cd1610b4SJohnny Huang { 1797a6af4a17SJohnny Huang uint32_t read[2]; 1798cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1799d90825e2SJohnny Huang uint32_t prog_address = 0; 180066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1801cd1610b4SJohnny Huang int otp_bit; 1802cd1610b4SJohnny Huang int i; 1803cd1610b4SJohnny Huang int pass; 1804a6af4a17SJohnny Huang int ret; 1805cd1610b4SJohnny Huang 1806cd1610b4SJohnny Huang switch (mode) { 1807a6d0d645SJohnny Huang case OTP_REGION_CONF: 1808a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1809cd1610b4SJohnny Huang prog_address = 0x800; 1810cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1811cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1812a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1813cd1610b4SJohnny Huang if (otp_bit == value) { 1814a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1815cd1610b4SJohnny Huang printf("No need to program\n"); 18162a856b9aSJohnny Huang return OTP_SUCCESS; 1817cd1610b4SJohnny Huang } 1818cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1819a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1820cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 18212a856b9aSJohnny Huang return OTP_FAILURE; 1822cd1610b4SJohnny Huang } 1823a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1824cd1610b4SJohnny Huang break; 1825a6d0d645SJohnny Huang case OTP_REGION_DATA: 1826cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1827cd1610b4SJohnny Huang 1828cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1829a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1830a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1831643b9cfdSJohnny Huang 1832643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1833643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1834643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1835643b9cfdSJohnny Huang return OTP_FAILURE; 1836643b9cfdSJohnny Huang } 1837cd1610b4SJohnny Huang } else { 1838a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1839a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1840643b9cfdSJohnny Huang 1841643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1842643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1843643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1844643b9cfdSJohnny Huang return OTP_FAILURE; 1845643b9cfdSJohnny Huang } 1846cd1610b4SJohnny Huang } 1847cd1610b4SJohnny Huang if (otp_bit == value) { 1848a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1849cd1610b4SJohnny Huang printf("No need to program\n"); 18502a856b9aSJohnny Huang return OTP_SUCCESS; 1851cd1610b4SJohnny Huang } 1852643b9cfdSJohnny Huang 1853a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1854cd1610b4SJohnny Huang break; 1855a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1856541eb887SJohnny Huang otp_strap_status(otpstrap); 1857cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1858cd1610b4SJohnny Huang if (bit_offset < 32) { 1859cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 18603d1cbeb0SJohnny Huang strap_buf[1] = 0; 1861cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1862cd1610b4SJohnny Huang strap_buf[3] = ~0; 18633d1cbeb0SJohnny Huang strap_buf[4] = 0; 1864cd1610b4SJohnny Huang strap_buf[5] = 0; 1865cd1610b4SJohnny Huang } else { 18663d1cbeb0SJohnny Huang strap_buf[0] = 0; 1867cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1868cd1610b4SJohnny Huang strap_buf[2] = ~0; 1869cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1870cd1610b4SJohnny Huang strap_buf[4] = 0; 18713d1cbeb0SJohnny Huang strap_buf[5] = 0; 1872cd1610b4SJohnny Huang } 187376d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1874a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18752a856b9aSJohnny Huang return OTP_FAILURE; 1876a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1877a6af4a17SJohnny Huang return OTP_SUCCESS; 1878a6af4a17SJohnny Huang 1879cd1610b4SJohnny Huang break; 1880cd1610b4SJohnny Huang } 1881cd1610b4SJohnny Huang 1882cd1610b4SJohnny Huang if (!nconfirm) { 1883cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1884cd1610b4SJohnny Huang if (!confirm_yesno()) { 1885cd1610b4SJohnny Huang printf(" Aborting\n"); 18862a856b9aSJohnny Huang return OTP_FAILURE; 1887cd1610b4SJohnny Huang } 1888cd1610b4SJohnny Huang } 1889cd1610b4SJohnny Huang 1890cd1610b4SJohnny Huang switch (mode) { 1891a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1892cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1893a6d0d645SJohnny Huang case OTP_REGION_CONF: 1894a6d0d645SJohnny Huang case OTP_REGION_DATA: 1895de6fbf1cSJohnny Huang otp_soak(1); 1896de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1897de6fbf1cSJohnny Huang pass = 0; 1898de6fbf1cSJohnny Huang 1899cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1900a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1901de6fbf1cSJohnny Huang otp_soak(2); 1902de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1903de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1904de6fbf1cSJohnny Huang otp_soak(1); 1905cd1610b4SJohnny Huang } else { 1906de6fbf1cSJohnny Huang pass = 1; 1907de6fbf1cSJohnny Huang break; 1908de6fbf1cSJohnny Huang } 1909de6fbf1cSJohnny Huang } else { 1910de6fbf1cSJohnny Huang pass = 1; 1911cd1610b4SJohnny Huang break; 1912cd1610b4SJohnny Huang } 1913cd1610b4SJohnny Huang } 1914de6fbf1cSJohnny Huang 1915de6fbf1cSJohnny Huang otp_soak(0); 1916de6fbf1cSJohnny Huang if (pass) { 19179009c25dSJohnny Huang printf("SUCCESS\n"); 19182a856b9aSJohnny Huang return OTP_SUCCESS; 19199009c25dSJohnny Huang } else { 19209009c25dSJohnny Huang printf("OTP cannot be programed\n"); 19219009c25dSJohnny Huang printf("FAILED\n"); 19229009c25dSJohnny Huang return OTP_FAILURE; 19239009c25dSJohnny Huang } 1924cd1610b4SJohnny Huang } 1925cd1610b4SJohnny Huang 19262a856b9aSJohnny Huang return OTP_USAGE; 1927cd1610b4SJohnny Huang } 1928cd1610b4SJohnny Huang 19292a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 193069d5fd8fSJohnny Huang { 19312a856b9aSJohnny Huang uint32_t offset, count; 19322a856b9aSJohnny Huang int ret; 193369d5fd8fSJohnny Huang 19342a856b9aSJohnny Huang if (argc == 4) { 19352a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19362a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19372a856b9aSJohnny Huang } else if (argc == 3) { 19382a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19392a856b9aSJohnny Huang count = 1; 19402a856b9aSJohnny Huang } else { 194169d5fd8fSJohnny Huang return CMD_RET_USAGE; 194269d5fd8fSJohnny Huang } 194369d5fd8fSJohnny Huang 194469d5fd8fSJohnny Huang 19452a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19463d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19472a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19482a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19493d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19502a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19512a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19523d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19532a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19542a856b9aSJohnny Huang } else { 19552a856b9aSJohnny Huang return CMD_RET_USAGE; 195669d5fd8fSJohnny Huang } 195769d5fd8fSJohnny Huang 19582a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19592a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19602a856b9aSJohnny Huang else 19612a856b9aSJohnny Huang return CMD_RET_USAGE; 19622a856b9aSJohnny Huang 19632a856b9aSJohnny Huang } 19642a856b9aSJohnny Huang 19652a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19662a856b9aSJohnny Huang { 19672a856b9aSJohnny Huang phys_addr_t addr; 19682a856b9aSJohnny Huang uint32_t byte_size; 19692a856b9aSJohnny Huang int ret; 19702a856b9aSJohnny Huang 19712a856b9aSJohnny Huang if (argc == 4) { 1972ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19732a856b9aSJohnny Huang return CMD_RET_USAGE; 19742a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19752a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 19763d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19772a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19782a856b9aSJohnny Huang } else if (argc == 3) { 19792a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19802a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 19813d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19822a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19832a856b9aSJohnny Huang } else { 19842a856b9aSJohnny Huang return CMD_RET_USAGE; 19852a856b9aSJohnny Huang } 19862a856b9aSJohnny Huang 19872a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19882a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19892a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19902a856b9aSJohnny Huang return CMD_RET_FAILURE; 19912a856b9aSJohnny Huang else 19922a856b9aSJohnny Huang return CMD_RET_USAGE; 19932a856b9aSJohnny Huang } 19942a856b9aSJohnny Huang 19952a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19962a856b9aSJohnny Huang { 19972a856b9aSJohnny Huang int mode = 0; 19982a856b9aSJohnny Huang int nconfirm = 0; 19992a856b9aSJohnny Huang int otp_addr = 0; 20002a856b9aSJohnny Huang int bit_offset; 20012a856b9aSJohnny Huang int value; 20022a856b9aSJohnny Huang int ret; 20032a856b9aSJohnny Huang 20042a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 20052a856b9aSJohnny Huang return CMD_RET_USAGE; 20062a856b9aSJohnny Huang 20072a856b9aSJohnny Huang /* Drop the pb cmd */ 20082a856b9aSJohnny Huang argc--; 20092a856b9aSJohnny Huang argv++; 20102a856b9aSJohnny Huang 20112a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2012a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 20132a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2014a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 20152a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2016a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2017cd1610b4SJohnny Huang else 20182a856b9aSJohnny Huang return CMD_RET_USAGE; 20192a856b9aSJohnny Huang 20202a856b9aSJohnny Huang /* Drop the region cmd */ 20212a856b9aSJohnny Huang argc--; 20222a856b9aSJohnny Huang argv++; 20232a856b9aSJohnny Huang 2024ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2025cd1610b4SJohnny Huang nconfirm = 1; 20262a856b9aSJohnny Huang /* Drop the force option */ 20272a856b9aSJohnny Huang argc--; 20282a856b9aSJohnny Huang argv++; 20292a856b9aSJohnny Huang } 2030cd1610b4SJohnny Huang 2031a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20322a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20332a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20340808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20352a856b9aSJohnny Huang return CMD_RET_USAGE; 2036cd1610b4SJohnny Huang } else { 20372a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20382a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20392a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20400808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20412a856b9aSJohnny Huang return CMD_RET_USAGE; 20420808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 204378855207SJohnny Huang if (otp_addr >= 0x800) 20440808cc55SJohnny Huang return CMD_RET_USAGE; 20450808cc55SJohnny Huang } else { 204678855207SJohnny Huang if (otp_addr >= 0x20) 20470808cc55SJohnny Huang return CMD_RET_USAGE; 20480808cc55SJohnny Huang } 2049cd1610b4SJohnny Huang } 2050cd1610b4SJohnny Huang if (value != 0 && value != 1) 20512a856b9aSJohnny Huang return CMD_RET_USAGE; 2052cd1610b4SJohnny Huang 20533d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20542a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20552a856b9aSJohnny Huang 20562a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20572a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20582a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20592a856b9aSJohnny Huang return CMD_RET_FAILURE; 20602a856b9aSJohnny Huang else 20612a856b9aSJohnny Huang return CMD_RET_USAGE; 20622a856b9aSJohnny Huang } 20632a856b9aSJohnny Huang 20642a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20652a856b9aSJohnny Huang { 20662a856b9aSJohnny Huang phys_addr_t addr; 20672a856b9aSJohnny Huang int otp_addr = 0; 20682a856b9aSJohnny Huang 20692a856b9aSJohnny Huang if (argc != 3) 20702a856b9aSJohnny Huang return CMD_RET_USAGE; 20712a856b9aSJohnny Huang 20723d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20732a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20742a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20752a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 207669d5fd8fSJohnny Huang printf("Compare pass\n"); 20772a856b9aSJohnny Huang return CMD_RET_SUCCESS; 207869d5fd8fSJohnny Huang } else { 207969d5fd8fSJohnny Huang printf("Compare fail\n"); 20802a856b9aSJohnny Huang return CMD_RET_FAILURE; 208169d5fd8fSJohnny Huang } 208269d5fd8fSJohnny Huang } 208369d5fd8fSJohnny Huang 208466f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 208566f2f8e5SJohnny Huang { 2086a8bd6d8cSJohnny Huang int view = 0; 20872d4b0742SJohnny Huang int input; 2088a8bd6d8cSJohnny Huang 2089a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 209066f2f8e5SJohnny Huang return CMD_RET_USAGE; 209166f2f8e5SJohnny Huang 20922d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 209366f2f8e5SJohnny Huang 20943d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20952d4b0742SJohnny Huang if (argc == 3) { 20962d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20972d4b0742SJohnny Huang otp_print_conf_info(input); 20982d4b0742SJohnny Huang } else { 20992d4b0742SJohnny Huang otp_print_conf_info(-1); 21002d4b0742SJohnny Huang } 21012d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 21022d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2103a8bd6d8cSJohnny Huang view = 1; 2104a8bd6d8cSJohnny Huang /* Drop the view option */ 2105a8bd6d8cSJohnny Huang argc--; 2106a8bd6d8cSJohnny Huang argv++; 2107a8bd6d8cSJohnny Huang } 21083d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2109b458cd62SJohnny Huang otp_print_strap_info(view); 211066f2f8e5SJohnny Huang } else { 211166f2f8e5SJohnny Huang return CMD_RET_USAGE; 211266f2f8e5SJohnny Huang } 21132d4b0742SJohnny Huang 211466f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 211566f2f8e5SJohnny Huang } 211666f2f8e5SJohnny Huang 2117737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2118737ed20bSJohnny Huang { 2119737ed20bSJohnny Huang int input; 2120737ed20bSJohnny Huang int bit_offset; 2121737ed20bSJohnny Huang int prog_address; 2122737ed20bSJohnny Huang int pass; 2123737ed20bSJohnny Huang int i; 2124737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2125737ed20bSJohnny Huang return CMD_RET_USAGE; 2126737ed20bSJohnny Huang 2127ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2128737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2129737ed20bSJohnny Huang } else { 2130737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2131737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2132737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2133737ed20bSJohnny Huang if (!confirm_yesno()) { 2134737ed20bSJohnny Huang printf(" Aborting\n"); 2135737ed20bSJohnny Huang return CMD_RET_FAILURE; 2136737ed20bSJohnny Huang } 2137737ed20bSJohnny Huang } 2138737ed20bSJohnny Huang 2139737ed20bSJohnny Huang prog_address = 0x800; 2140737ed20bSJohnny Huang if (input < 32) { 2141737ed20bSJohnny Huang bit_offset = input; 2142737ed20bSJohnny Huang prog_address |= 0x60c; 2143737ed20bSJohnny Huang } else if (input < 64) { 2144737ed20bSJohnny Huang bit_offset = input - 32; 2145737ed20bSJohnny Huang prog_address |= 0x60e; 2146737ed20bSJohnny Huang } else { 2147737ed20bSJohnny Huang return CMD_RET_USAGE; 2148737ed20bSJohnny Huang } 2149737ed20bSJohnny Huang 2150737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2151737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2152737ed20bSJohnny Huang } 2153de6fbf1cSJohnny Huang 2154de6fbf1cSJohnny Huang otp_soak(1); 2155de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2156de6fbf1cSJohnny Huang pass = 0; 2157de6fbf1cSJohnny Huang 2158737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2159737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2160de6fbf1cSJohnny Huang otp_soak(2); 2161de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2162de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2163de6fbf1cSJohnny Huang otp_soak(1); 2164737ed20bSJohnny Huang } else { 2165de6fbf1cSJohnny Huang pass = 1; 2166de6fbf1cSJohnny Huang break; 2167de6fbf1cSJohnny Huang } 2168de6fbf1cSJohnny Huang } else { 2169de6fbf1cSJohnny Huang pass = 1; 2170737ed20bSJohnny Huang break; 2171737ed20bSJohnny Huang } 2172737ed20bSJohnny Huang } 2173de6fbf1cSJohnny Huang otp_soak(0); 2174de6fbf1cSJohnny Huang if (pass) { 2175737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2176737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2177737ed20bSJohnny Huang } 2178737ed20bSJohnny Huang 2179737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2180737ed20bSJohnny Huang return CMD_RET_FAILURE; 2181737ed20bSJohnny Huang 2182737ed20bSJohnny Huang } 21839a4fe690SJohnny Huang 21842a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21852a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2186a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21872a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21882a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2189737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21902a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21912a856b9aSJohnny Huang }; 21922a856b9aSJohnny Huang 21932a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21942a856b9aSJohnny Huang { 21952a856b9aSJohnny Huang cmd_tbl_t *cp; 21962a856b9aSJohnny Huang 21972a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21982a856b9aSJohnny Huang 2199737ed20bSJohnny Huang /* Drop the otp command */ 22002a856b9aSJohnny Huang argc--; 22012a856b9aSJohnny Huang argv++; 22022a856b9aSJohnny Huang 22032a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 22042a856b9aSJohnny Huang return CMD_RET_USAGE; 22052a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 22062a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22072a856b9aSJohnny Huang 22089a4fe690SJohnny Huang if (chip_version() == 0) { 22099a4fe690SJohnny Huang info_cb.version = 0; 22109a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 22119a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 22129a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 22139a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 22149a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 22159a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 22169a4fe690SJohnny Huang } else if (chip_version() == 1) { 22179a4fe690SJohnny Huang info_cb.version = 1; 22183cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 22193cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 22203cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 22213cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 22229a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 22239a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 22249a4fe690SJohnny Huang } 22259a4fe690SJohnny Huang 22262a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 222769d5fd8fSJohnny Huang } 222869d5fd8fSJohnny Huang 222969d5fd8fSJohnny Huang U_BOOT_CMD( 223069d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 223169d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 22322a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 22332a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 22342d4b0742SJohnny Huang "otp info strap [v]\n" 22352d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2236ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2237ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2238ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2239ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 22402a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 224169d5fd8fSJohnny Huang ); 2242