169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 389a4fe690SJohnny Huang #define OTP_KEY_TYPE_RSA 1 399a4fe690SJohnny Huang #define OTP_KEY_TYPE_AES 2 409a4fe690SJohnny Huang #define OTP_KEY_TYPE_VAULT 3 419a4fe690SJohnny Huang #define OTP_KEY_TYPE_HMAC 4 429a4fe690SJohnny Huang 439a4fe690SJohnny Huang 44a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 45b458cd62SJohnny Huang #define OTP_REG_VALUE -2 46b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4776d13988SJohnny Huang 484c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 494c1c9b35SJohnny Huang #define PBWIDTH 60 504c1c9b35SJohnny Huang 513d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 523d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 533d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 543d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 553d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 563d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 573d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 583d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 593d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 603d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 613d3688adSJohnny Huang 6266f2f8e5SJohnny Huang struct otpstrap_status { 6369d5fd8fSJohnny Huang int value; 6469d5fd8fSJohnny Huang int option_array[7]; 6569d5fd8fSJohnny Huang int remain_times; 6669d5fd8fSJohnny Huang int writeable_option; 6769d5fd8fSJohnny Huang int protected; 6869d5fd8fSJohnny Huang }; 6969d5fd8fSJohnny Huang 7066f2f8e5SJohnny Huang struct otpconf_parse { 7166f2f8e5SJohnny Huang int dw_offset; 7266f2f8e5SJohnny Huang int bit; 7366f2f8e5SJohnny Huang int length; 7466f2f8e5SJohnny Huang int value; 7566f2f8e5SJohnny Huang int keep; 7666f2f8e5SJohnny Huang char status[80]; 7766f2f8e5SJohnny Huang }; 7866f2f8e5SJohnny Huang 79a8bd6d8cSJohnny Huang struct otpstrap_info { 8079e42a59SJoel Stanley int8_t bit_offset; 8179e42a59SJoel Stanley int8_t length; 8279e42a59SJoel Stanley int8_t value; 8379e42a59SJoel Stanley char *information; 84a8bd6d8cSJohnny Huang }; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang struct otpconf_info { 8779e42a59SJoel Stanley int8_t dw_offset; 8879e42a59SJoel Stanley int8_t bit_offset; 8979e42a59SJoel Stanley int8_t length; 9079e42a59SJoel Stanley int8_t value; 9179e42a59SJoel Stanley char *information; 92a8bd6d8cSJohnny Huang }; 93a8bd6d8cSJohnny Huang 949a4fe690SJohnny Huang struct otpkey_type { 959a4fe690SJohnny Huang int value; 969a4fe690SJohnny Huang int key_type; 979a4fe690SJohnny Huang int need_id; 989a4fe690SJohnny Huang char information[110]; 999a4fe690SJohnny Huang }; 1009a4fe690SJohnny Huang 1019a4fe690SJohnny Huang struct otp_info_cb { 1029a4fe690SJohnny Huang int version; 10379e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1049a4fe690SJohnny Huang int strap_info_len; 10579e42a59SJoel Stanley const struct otpconf_info *conf_info; 1069a4fe690SJohnny Huang int conf_info_len; 10779e42a59SJoel Stanley const struct otpkey_type *key_info; 1089a4fe690SJohnny Huang int key_info_len; 1099a4fe690SJohnny Huang }; 1109a4fe690SJohnny Huang 1119a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1129a4fe690SJohnny Huang 11379e42a59SJoel Stanley static const struct otpstrap_info a0_strap_info[] = { 11491448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 11591448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 11691448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 11791448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 11891448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 11991448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 12091448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 12191448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 122541eb887SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 12391448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 12491448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 12591448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 12691448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 12791448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 12891448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 12991448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 13091448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 13191448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 13291448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 13391448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 13491448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 13591448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 13691448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 13791448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 13891448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 13991448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 14091448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 14191448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 14291448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 14391448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 14491448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 14591448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 14691448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 14791448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 14891448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 14991448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 15091448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 15191448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 15291448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 15391448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 15491448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 15591448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 15691448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 15791448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 15891448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 15991448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 16091448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 16191448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 16291448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 16391448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 16491448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 16591448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 16691448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 16791448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 16891448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 16991448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 17091448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 17191448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 17291448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 17391448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 17491448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 17591448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 17691448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 17791448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 17891448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 17991448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 18091448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 18191448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 18291448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 18391448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 18491448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 18591448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 18691448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 18791448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 18891448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 18991448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 19091448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 19191448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 19291448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 19391448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 19491448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 19591448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 19691448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 19791448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 19891448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 19991448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 20091448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 20191448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 20291448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 20391448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 20491448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 20591448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 20691448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 20791448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 20891448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 20991448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 21091448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 21191448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 21291448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 21391448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 21491448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 21591448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 21691448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 21791448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 21891448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 21991448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 22091448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 22191448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 22291448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 22376d13988SJohnny Huang }; 2249a4fe690SJohnny Huang 22579e42a59SJoel Stanley static const struct otpstrap_info a1_strap_info[] = { 2263cb28812SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 2273cb28812SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 2283cb28812SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 2293cb28812SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 2303cb28812SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 2313cb28812SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 2323cb28812SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 2333cb28812SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 2343cb28812SJohnny Huang { 4, 1, 0, "No VGA BIOS ROM, VGA BIOS is merged in the system BIOS" }, 2353cb28812SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 2363cb28812SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 2373cb28812SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 2383cb28812SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 2393cb28812SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 2403cb28812SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 2413cb28812SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 2423cb28812SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 2433cb28812SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 2443cb28812SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 2453cb28812SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 2463cb28812SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 2473cb28812SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 2483cb28812SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 2493cb28812SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 2503cb28812SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 2513cb28812SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 2523cb28812SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 2533cb28812SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 2543cb28812SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 2553cb28812SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 2563cb28812SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 2573cb28812SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 2583cb28812SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 2593cb28812SJohnny Huang { 20, 1, 0, "Disable Pcie EHCI device" }, 2603cb28812SJohnny Huang { 20, 1, 1, "Enable Pcie EHCI device" }, 2613cb28812SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 2623cb28812SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 2633cb28812SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 2643cb28812SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 2653cb28812SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 2663cb28812SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 2673cb28812SJohnny Huang { 24, 1, 0, "Enable watchdog to reset full chip" }, 2683cb28812SJohnny Huang { 24, 1, 1, "Disable watchdog to reset full chip" }, 2693cb28812SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 2703cb28812SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 2713cb28812SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 2723cb28812SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 2733cb28812SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 2743cb28812SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 2753cb28812SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 2763cb28812SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 2773cb28812SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 2783cb28812SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 2793cb28812SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 2803cb28812SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 2813cb28812SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 2823cb28812SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 2833cb28812SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 2843cb28812SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 2853cb28812SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 2863cb28812SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 2873cb28812SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 2883cb28812SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 2893cb28812SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 2903cb28812SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 2913cb28812SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 2923cb28812SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 2933cb28812SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 2943cb28812SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 2953cb28812SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 2963cb28812SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 2973cb28812SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 2983cb28812SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 2993cb28812SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 3003cb28812SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 3013cb28812SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 3023cb28812SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 3033cb28812SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 3043cb28812SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 3053cb28812SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 3063cb28812SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 3073cb28812SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 3083cb28812SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 3093cb28812SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 3103cb28812SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 3113cb28812SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 3123cb28812SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 3133cb28812SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 3143cb28812SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 3153cb28812SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 3163cb28812SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 3173cb28812SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 3183cb28812SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 3193cb28812SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 3203cb28812SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 3213cb28812SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 3223cb28812SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 3233cb28812SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 3243cb28812SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 3253cb28812SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 3263cb28812SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 3273cb28812SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 3283cb28812SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 3293cb28812SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 3303cb28812SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 3313cb28812SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 3323cb28812SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 3333cb28812SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 3343cb28812SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 3353cb28812SJohnny Huang }; 3363cb28812SJohnny Huang 33779e42a59SJoel Stanley static const struct otpconf_info a0_conf_info[] = { 33891448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 33991448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 34091448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 34191448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 34291448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 34391448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 34491448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 34591448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 34691448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 34791448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 34891448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 34991448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 35091448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 35191448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 35291448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 35391448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 35491448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 355541eb887SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 35691448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 35791448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 35891448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 35991448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 36091448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 36191448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 36291448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 36391448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 36491448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 36591448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 36691448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 36791448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 36891448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 36991448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 37091448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 37191448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 37291448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 37391448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 37491448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 37591448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 37691448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 37791448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 37891448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 37991448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 38091448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 38191448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 3823cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 3833cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 3843cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 3853cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 3863cb28812SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 3873cb28812SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 3883cb28812SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 3893cb28812SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 3903cb28812SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 3913cb28812SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 3923cb28812SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 3933cb28812SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 3943cb28812SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 3953cb28812SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 3963cb28812SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 3973cb28812SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 3983cb28812SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 3993cb28812SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 4003cb28812SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 4013cb28812SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 4023cb28812SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 4033cb28812SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 4043cb28812SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 4053cb28812SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 4063cb28812SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 4073cb28812SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 4083cb28812SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 4093cb28812SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 4103cb28812SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 4113cb28812SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 4123cb28812SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 4133cb28812SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 4143cb28812SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 4153cb28812SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 4163cb28812SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 4173cb28812SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 4183cb28812SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 4193cb28812SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 4203cb28812SJohnny Huang }; 4213cb28812SJohnny Huang 42279e42a59SJoel Stanley static const struct otpconf_info a1_conf_info[] = { 4233cb28812SJohnny Huang { 0, 0, 1, OTP_REG_RESERVED, "" }, 4243cb28812SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 4253cb28812SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 4263cb28812SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 4273cb28812SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 4283cb28812SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 4293cb28812SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 4303cb28812SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 4313cb28812SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 4323cb28812SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 4333cb28812SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 4343cb28812SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 4353cb28812SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 4363cb28812SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: GCM" }, 4373cb28812SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 4383cb28812SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 4393cb28812SJohnny Huang { 0, 8, 2, 1, "Differential mode" }, 4403cb28812SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 4413cb28812SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 4423cb28812SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 4433cb28812SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 4443cb28812SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 4453cb28812SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 4463cb28812SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 4473cb28812SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 4483cb28812SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 4493cb28812SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 4503cb28812SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 4513cb28812SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 4523cb28812SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 4533cb28812SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 4543cb28812SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 4553cb28812SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 4563cb28812SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 4573cb28812SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 4583cb28812SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 4593cb28812SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 4603cb28812SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 4613cb28812SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 4623cb28812SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 4633cb28812SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 4643cb28812SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 4653cb28812SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 4663cb28812SJohnny Huang { 0, 30, 1, 0, "Data region redundancy repair disable" }, 4673cb28812SJohnny Huang { 0, 30, 1, 1, "Data region redundancy repair enable" }, 4683cb28812SJohnny Huang { 0, 31, 1, 0, "OTP memory lock disable" }, 4693cb28812SJohnny Huang { 0, 31, 1, 1, "OTP memory lock enable" }, 47091448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 47191448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 47291448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 47373f11549SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %s" }, 47473f11549SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %s" }, 47591448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 47691448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 47791448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 47891448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 47991448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 48091448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 48191448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 48291448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 48391448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 48491448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 48591448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 48691448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 48791448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 48891448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 48991448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 49091448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 49191448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 49291448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 49391448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 49491448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 49591448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 49691448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 49791448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 49891448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 49991448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 50091448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 50191448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 50291448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 50391448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 504b458cd62SJohnny Huang }; 5059a4fe690SJohnny Huang 50679e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 5079a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 5089a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5099a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 5109a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5119a4fe690SJohnny Huang {9, OTP_KEY_TYPE_RSA, 0, "RSA-public as SOC public key"}, 5129a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5139a4fe690SJohnny Huang {13, OTP_KEY_TYPE_RSA, 0, "RSA-private as SOC private key"}, 5149a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5159a4fe690SJohnny Huang }; 5169a4fe690SJohnny Huang 51779e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 5189a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 5199a4fe690SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 5209a4fe690SJohnny Huang {8, OTP_KEY_TYPE_RSA, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 5219a4fe690SJohnny Huang {10, OTP_KEY_TYPE_RSA, 0, "RSA-public as AES key decryption key"}, 5229a4fe690SJohnny Huang {14, OTP_KEY_TYPE_RSA, 0, "RSA-private as AES key decryption key"}, 5239a4fe690SJohnny Huang }; 5249a4fe690SJohnny Huang 5259a4fe690SJohnny Huang static uint32_t chip_version(void) 5269a4fe690SJohnny Huang { 5279a4fe690SJohnny Huang uint32_t rev_id; 5289a4fe690SJohnny Huang 5299a4fe690SJohnny Huang rev_id = (readl(0x1e6e2004) >> 16) & 0xff ; 5309a4fe690SJohnny Huang 5319a4fe690SJohnny Huang return rev_id; 5329a4fe690SJohnny Huang } 5339a4fe690SJohnny Huang 5343d3688adSJohnny Huang static void wait_complete(void) 5353d3688adSJohnny Huang { 5363d3688adSJohnny Huang int reg; 5373d3688adSJohnny Huang 5383d3688adSJohnny Huang do { 5393d3688adSJohnny Huang reg = readl(OTP_STATUS); 5403d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 5413d3688adSJohnny Huang } 5423d3688adSJohnny Huang 5432a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 54469d5fd8fSJohnny Huang { 5453d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 5463d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5473d3688adSJohnny Huang wait_complete(); 5483d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 5493d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 55069d5fd8fSJohnny Huang } 55169d5fd8fSJohnny Huang 5522a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 55369d5fd8fSJohnny Huang { 55469d5fd8fSJohnny Huang int config_offset; 55569d5fd8fSJohnny Huang 55669d5fd8fSJohnny Huang config_offset = 0x800; 55769d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 55869d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 55969d5fd8fSJohnny Huang 5603d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 5613d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 5623d3688adSJohnny Huang wait_complete(); 5633d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 56469d5fd8fSJohnny Huang } 56569d5fd8fSJohnny Huang 56669d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 56769d5fd8fSJohnny Huang { 56869d5fd8fSJohnny Huang int i; 56969d5fd8fSJohnny Huang uint32_t ret[1]; 57069d5fd8fSJohnny Huang 57169d5fd8fSJohnny Huang if (offset + dw_count > 32) 5722a856b9aSJohnny Huang return OTP_USAGE; 57369d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 57469d5fd8fSJohnny Huang otp_read_config(i, ret); 575a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 57669d5fd8fSJohnny Huang } 57769d5fd8fSJohnny Huang printf("\n"); 5782a856b9aSJohnny Huang return OTP_SUCCESS; 57969d5fd8fSJohnny Huang } 58069d5fd8fSJohnny Huang 58169d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 58269d5fd8fSJohnny Huang { 58369d5fd8fSJohnny Huang int i; 58469d5fd8fSJohnny Huang uint32_t ret[2]; 58569d5fd8fSJohnny Huang 58669d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5872a856b9aSJohnny Huang return OTP_USAGE; 58869d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 58969d5fd8fSJohnny Huang otp_read_data(i, ret); 59069d5fd8fSJohnny Huang if (i % 4 == 0) 59169d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 59269d5fd8fSJohnny Huang else 59369d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 59469d5fd8fSJohnny Huang 59569d5fd8fSJohnny Huang } 59669d5fd8fSJohnny Huang printf("\n"); 5972a856b9aSJohnny Huang return OTP_SUCCESS; 59869d5fd8fSJohnny Huang } 59969d5fd8fSJohnny Huang 60069d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 60169d5fd8fSJohnny Huang { 60269d5fd8fSJohnny Huang uint32_t ret; 60369d5fd8fSJohnny Huang uint32_t *buf; 60469d5fd8fSJohnny Huang 60569d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 60669d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 60769d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 60869d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 60969d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 6103d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 6113d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 6123d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 6133d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 6143d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 6153d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 6163d3688adSJohnny Huang wait_complete(); 6173d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 61869d5fd8fSJohnny Huang if (ret & 0x1) 61969d5fd8fSJohnny Huang return 0; 62069d5fd8fSJohnny Huang else 62169d5fd8fSJohnny Huang return -1; 62269d5fd8fSJohnny Huang } 62369d5fd8fSJohnny Huang 62469d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 62569d5fd8fSJohnny Huang { 6263d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6273d3688adSJohnny Huang writel(data, OTP_COMPARE_1); //write data 6283d3688adSJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 6293d3688adSJohnny Huang wait_complete(); 63069d5fd8fSJohnny Huang } 63169d5fd8fSJohnny Huang 63269d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 63369d5fd8fSJohnny Huang { 6343d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //write address 6353d3688adSJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 6363d3688adSJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 6373d3688adSJohnny Huang wait_complete(); 63869d5fd8fSJohnny Huang } 63969d5fd8fSJohnny Huang 640a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 64169d5fd8fSJohnny Huang { 64230a8c590SJohnny Huang uint32_t ret[2]; 64369d5fd8fSJohnny Huang 64430a8c590SJohnny Huang if (otp_addr % 2 == 0) 6453d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 64630a8c590SJohnny Huang else 6473d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 64830a8c590SJohnny Huang 6493d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6503d3688adSJohnny Huang wait_complete(); 6513d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6523d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 653a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 65430a8c590SJohnny Huang if (otp_addr % 2 == 0) { 65530a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 65669d5fd8fSJohnny Huang return 0; 65769d5fd8fSJohnny Huang else 65869d5fd8fSJohnny Huang return -1; 65930a8c590SJohnny Huang } else { 66030a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 66130a8c590SJohnny Huang return 0; 66230a8c590SJohnny Huang else 66330a8c590SJohnny Huang return -1; 66430a8c590SJohnny Huang } 66530a8c590SJohnny Huang 66669d5fd8fSJohnny Huang } 66769d5fd8fSJohnny Huang 668d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 6694c1c9b35SJohnny Huang { 6704c1c9b35SJohnny Huang uint32_t ret[2]; 6714c1c9b35SJohnny Huang 6724c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6734c1c9b35SJohnny Huang 6744c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6753d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 6764c1c9b35SJohnny Huang else 6773d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 6783d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 6793d3688adSJohnny Huang wait_complete(); 6803d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 6813d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 6824c1c9b35SJohnny Huang if (size == 1) { 6834c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6844c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 685d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6864c1c9b35SJohnny Huang compare[0] = 0; 6874c1c9b35SJohnny Huang return 0; 6884c1c9b35SJohnny Huang } else { 6894c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6904c1c9b35SJohnny Huang return -1; 6914c1c9b35SJohnny Huang } 6924c1c9b35SJohnny Huang 6934c1c9b35SJohnny Huang } else { 6944c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 695d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 6964c1c9b35SJohnny Huang compare[0] = ~0; 6974c1c9b35SJohnny Huang return 0; 6984c1c9b35SJohnny Huang } else { 699d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 7004c1c9b35SJohnny Huang return -1; 7014c1c9b35SJohnny Huang } 7024c1c9b35SJohnny Huang } 7034c1c9b35SJohnny Huang } else if (size == 2) { 7044c1c9b35SJohnny Huang // otp_addr should be even 705d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 7064c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7074c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7084c1c9b35SJohnny Huang compare[0] = 0; 7094c1c9b35SJohnny Huang compare[1] = ~0; 7104c1c9b35SJohnny Huang return 0; 7114c1c9b35SJohnny Huang } else { 7124c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 7134c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 7144c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 7154c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 7164c1c9b35SJohnny Huang return -1; 7174c1c9b35SJohnny Huang } 7184c1c9b35SJohnny Huang } else { 7194c1c9b35SJohnny Huang return -1; 7204c1c9b35SJohnny Huang } 7214c1c9b35SJohnny Huang } 7224c1c9b35SJohnny Huang 7237e22f42dSJohnny Huang static void otp_soak(int soak) 724d90825e2SJohnny Huang { 725de6fbf1cSJohnny Huang switch (soak) { 726de6fbf1cSJohnny Huang case 0: //default 727de6fbf1cSJohnny Huang otp_write(0x3000, 0x0); // Write MRA 728de6fbf1cSJohnny Huang otp_write(0x5000, 0x0); // Write MRB 729de6fbf1cSJohnny Huang otp_write(0x1000, 0x0); // Write MR 730de6fbf1cSJohnny Huang break; 731de6fbf1cSJohnny Huang case 1: //normal program 732de6fbf1cSJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 733de6fbf1cSJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 734de6fbf1cSJohnny Huang otp_write(0x1000, 0x4020); // Write MR 735de6fbf1cSJohnny Huang writel(0x04190760, OTP_TIMING); 736de6fbf1cSJohnny Huang break; 737de6fbf1cSJohnny Huang case 2: //soak program 738d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 739d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 740d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 741de6fbf1cSJohnny Huang writel(0x041930d4, OTP_TIMING); 742de6fbf1cSJohnny Huang break; 743d90825e2SJohnny Huang } 744de6fbf1cSJohnny Huang 7453d3688adSJohnny Huang wait_complete(); 746d90825e2SJohnny Huang } 747d90825e2SJohnny Huang 748d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 749d90825e2SJohnny Huang { 750d90825e2SJohnny Huang int j, bit_value, prog_bit; 751d90825e2SJohnny Huang 752d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 753d90825e2SJohnny Huang if ((keep >> j) & 0x1) 754d90825e2SJohnny Huang continue; 755d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 756d90825e2SJohnny Huang if (prog_address % 2 == 0) { 757d90825e2SJohnny Huang if (bit_value) 758d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 759d90825e2SJohnny Huang else 760d90825e2SJohnny Huang continue; 761d90825e2SJohnny Huang } else { 762d90825e2SJohnny Huang prog_address |= 1 << 15; 763d90825e2SJohnny Huang if (bit_value) 764d90825e2SJohnny Huang continue; 765d90825e2SJohnny Huang else 766d90825e2SJohnny Huang prog_bit = 0x1 << j; 767d90825e2SJohnny Huang } 768d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 769d90825e2SJohnny Huang } 770d90825e2SJohnny Huang } 771d90825e2SJohnny Huang 772*54552c69SJohnny Huang static int otp_prog_verify_2dw(uint32_t *data, uint32_t *buf, uint32_t *ignore_mask, uint32_t prog_address) 773*54552c69SJohnny Huang { 774*54552c69SJohnny Huang int pass; 775*54552c69SJohnny Huang int i; 776*54552c69SJohnny Huang uint32_t data0_masked; 777*54552c69SJohnny Huang uint32_t data1_masked; 778*54552c69SJohnny Huang uint32_t buf0_masked; 779*54552c69SJohnny Huang uint32_t buf1_masked; 780*54552c69SJohnny Huang uint32_t compare[2]; 781*54552c69SJohnny Huang 782*54552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 783*54552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 784*54552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 785*54552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 786*54552c69SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) 787*54552c69SJohnny Huang return 0; 788*54552c69SJohnny Huang 789*54552c69SJohnny Huang otp_soak(1); 790*54552c69SJohnny Huang if (data0_masked != buf0_masked) 791*54552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 792*54552c69SJohnny Huang if (data1_masked != buf1_masked) 793*54552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 794*54552c69SJohnny Huang 795*54552c69SJohnny Huang pass = 0; 796*54552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 797*54552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 798*54552c69SJohnny Huang otp_soak(2); 799*54552c69SJohnny Huang if (compare[0] != 0) { 800*54552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 801*54552c69SJohnny Huang } 802*54552c69SJohnny Huang if (compare[1] != ~0) { 803*54552c69SJohnny Huang otp_prog_dw(compare[1], ignore_mask[0], prog_address + 1); 804*54552c69SJohnny Huang } 805*54552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 806*54552c69SJohnny Huang otp_soak(1); 807*54552c69SJohnny Huang } else { 808*54552c69SJohnny Huang pass = 1; 809*54552c69SJohnny Huang break; 810*54552c69SJohnny Huang } 811*54552c69SJohnny Huang } else { 812*54552c69SJohnny Huang pass = 1; 813*54552c69SJohnny Huang break; 814*54552c69SJohnny Huang } 815*54552c69SJohnny Huang } 816*54552c69SJohnny Huang 817*54552c69SJohnny Huang if (!pass) { 818*54552c69SJohnny Huang otp_soak(0); 819*54552c69SJohnny Huang return OTP_FAILURE; 820*54552c69SJohnny Huang } 821*54552c69SJohnny Huang return OTP_SUCCESS; 822*54552c69SJohnny Huang } 823*54552c69SJohnny Huang 82476d13988SJohnny Huang 825541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 82676d13988SJohnny Huang { 82776d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 82876d13988SJohnny Huang int i, j; 82976d13988SJohnny Huang 83076d13988SJohnny Huang for (j = 0; j < 64; j++) { 83176d13988SJohnny Huang otpstrap[j].value = 0; 83276d13988SJohnny Huang otpstrap[j].remain_times = 7; 83376d13988SJohnny Huang otpstrap[j].writeable_option = -1; 83476d13988SJohnny Huang otpstrap[j].protected = 0; 83576d13988SJohnny Huang } 83676d13988SJohnny Huang 83776d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 83876d13988SJohnny Huang int option = (i - 16) / 2; 83976d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 84076d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 84176d13988SJohnny Huang for (j = 0; j < 32; j++) { 84276d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 84376d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 84476d13988SJohnny Huang otpstrap[j].writeable_option = option; 84576d13988SJohnny Huang } 84676d13988SJohnny Huang if (bit_value == 1) 84776d13988SJohnny Huang otpstrap[j].remain_times --; 84876d13988SJohnny Huang otpstrap[j].value ^= bit_value; 84976d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 85076d13988SJohnny Huang } 85176d13988SJohnny Huang for (j = 32; j < 64; j++) { 85276d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 85376d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 85476d13988SJohnny Huang otpstrap[j].writeable_option = option; 85576d13988SJohnny Huang } 85676d13988SJohnny Huang if (bit_value == 1) 85776d13988SJohnny Huang otpstrap[j].remain_times --; 85876d13988SJohnny Huang otpstrap[j].value ^= bit_value; 85976d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 86076d13988SJohnny Huang } 86176d13988SJohnny Huang } 86276d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 86376d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 86476d13988SJohnny Huang for (j = 0; j < 32; j++) { 86576d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 86676d13988SJohnny Huang otpstrap[j].protected = 1; 86776d13988SJohnny Huang } 86876d13988SJohnny Huang for (j = 32; j < 64; j++) { 86976d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 87076d13988SJohnny Huang otpstrap[j].protected = 1; 87176d13988SJohnny Huang } 87276d13988SJohnny Huang } 87376d13988SJohnny Huang 874b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 87569d5fd8fSJohnny Huang { 87679e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 877442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 878b458cd62SJohnny Huang uint32_t mask; 879b458cd62SJohnny Huang uint32_t dw_offset; 880b458cd62SJohnny Huang uint32_t bit_offset; 881b458cd62SJohnny Huang uint32_t otp_value; 882b458cd62SJohnny Huang uint32_t otp_keep; 883b458cd62SJohnny Huang int fail = 0; 88473f11549SJohnny Huang char valid_bit[20]; 88566f2f8e5SJohnny Huang int i; 88673f11549SJohnny Huang int j; 88766f2f8e5SJohnny Huang 888737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 88966f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8903cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8913cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8923cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8933cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 894b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 895b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 896b458cd62SJohnny Huang 897b458cd62SJohnny Huang if (otp_keep == mask) { 898b458cd62SJohnny Huang continue; 899b458cd62SJohnny Huang } else if (otp_keep != 0) { 900b458cd62SJohnny Huang fail = 1; 901b458cd62SJohnny Huang } 902b458cd62SJohnny Huang 9033cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9043cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9053cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9063cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 907b458cd62SJohnny Huang continue; 908b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 909b458cd62SJohnny Huang 9103cb28812SJohnny Huang if (conf_info[i].length == 1) { 9113cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 91266f2f8e5SJohnny Huang } else { 913b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9143cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9153cb28812SJohnny Huang conf_info[i].bit_offset); 91666f2f8e5SJohnny Huang } 917b458cd62SJohnny Huang printf("0x%-10x", otp_value); 918b458cd62SJohnny Huang 919b458cd62SJohnny Huang if (fail) { 920b458cd62SJohnny Huang printf("Keep mask error\n"); 921b458cd62SJohnny Huang } else { 9223cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 923b458cd62SJohnny Huang printf("Reserved\n"); 9243cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9253cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 926b458cd62SJohnny Huang printf("\n"); 9273cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 928b458cd62SJohnny Huang if (otp_value != 0) { 92973f11549SJohnny Huang for (j = 0; j < 7; j++) { 93073f11549SJohnny Huang if (otp_value == (1 << j)) { 93173f11549SJohnny Huang valid_bit[j * 2] = '1'; 932b458cd62SJohnny Huang } else { 93373f11549SJohnny Huang valid_bit[j * 2] = '0'; 93473f11549SJohnny Huang } 93573f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 93673f11549SJohnny Huang } 93773f11549SJohnny Huang valid_bit[15] = 0; 93873f11549SJohnny Huang } else { 93973f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 940b458cd62SJohnny Huang } 9413cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 942b458cd62SJohnny Huang printf("\n"); 943b458cd62SJohnny Huang } else { 9443cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 945b458cd62SJohnny Huang } 946b458cd62SJohnny Huang } 947b458cd62SJohnny Huang } 948b458cd62SJohnny Huang 949b458cd62SJohnny Huang if (fail) 950b458cd62SJohnny Huang return OTP_FAILURE; 951b458cd62SJohnny Huang 95266f2f8e5SJohnny Huang return OTP_SUCCESS; 95366f2f8e5SJohnny Huang } 95466f2f8e5SJohnny Huang 9552d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 95666f2f8e5SJohnny Huang { 95779e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 958b458cd62SJohnny Huang uint32_t OTPCFG[12]; 959b458cd62SJohnny Huang uint32_t mask; 960b458cd62SJohnny Huang uint32_t dw_offset; 961b458cd62SJohnny Huang uint32_t bit_offset; 962b458cd62SJohnny Huang uint32_t otp_value; 96373f11549SJohnny Huang char valid_bit[20]; 96466f2f8e5SJohnny Huang int i; 96573f11549SJohnny Huang int j; 96666f2f8e5SJohnny Huang 96766f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 96866f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 96966f2f8e5SJohnny Huang 97066f2f8e5SJohnny Huang 971b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 972b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9733cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9743cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9752d4b0742SJohnny Huang continue; 9763cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9773cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9783cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 979b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 980b458cd62SJohnny Huang 9813cb28812SJohnny Huang if ((otp_value != conf_info[i].value) && 9823cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9833cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9843cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 985b458cd62SJohnny Huang continue; 986b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 987b458cd62SJohnny Huang 9883cb28812SJohnny Huang if (conf_info[i].length == 1) { 9893cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 990b458cd62SJohnny Huang } else { 991b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9923cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 9933cb28812SJohnny Huang conf_info[i].bit_offset); 994b458cd62SJohnny Huang } 995b458cd62SJohnny Huang printf("0x%-10x", otp_value); 996b458cd62SJohnny Huang 9973cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 998b458cd62SJohnny Huang printf("Reserved\n"); 9993cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10003cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1001b458cd62SJohnny Huang printf("\n"); 10023cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1003b458cd62SJohnny Huang if (otp_value != 0) { 100473f11549SJohnny Huang for (j = 0; j < 7; j++) { 100573f11549SJohnny Huang if (otp_value == (1 << j)) { 100673f11549SJohnny Huang valid_bit[j * 2] = '1'; 1007b458cd62SJohnny Huang } else { 100873f11549SJohnny Huang valid_bit[j * 2] = '0'; 100973f11549SJohnny Huang } 101073f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 101173f11549SJohnny Huang } 101273f11549SJohnny Huang valid_bit[15] = 0; 101373f11549SJohnny Huang } else { 101473f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1015b458cd62SJohnny Huang } 10163cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1017b458cd62SJohnny Huang printf("\n"); 1018b458cd62SJohnny Huang } else { 10193cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1020b458cd62SJohnny Huang } 1021b458cd62SJohnny Huang } 1022b458cd62SJohnny Huang return OTP_SUCCESS; 102366f2f8e5SJohnny Huang } 102466f2f8e5SJohnny Huang 1025b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 102676d13988SJohnny Huang { 102779e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1028a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 1029a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 103076d13988SJohnny Huang int i; 1031a8bd6d8cSJohnny Huang int fail = 0; 1032a8bd6d8cSJohnny Huang uint32_t bit_offset; 1033a8bd6d8cSJohnny Huang uint32_t dw_offset; 1034a8bd6d8cSJohnny Huang uint32_t mask; 1035a8bd6d8cSJohnny Huang uint32_t otp_value; 1036a8bd6d8cSJohnny Huang uint32_t otp_protect; 1037a8bd6d8cSJohnny Huang uint32_t otp_keep; 103876d13988SJohnny Huang 1039a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1040a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1041b458cd62SJohnny Huang 10423cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 10433cb28812SJohnny Huang if (strap_info[i].bit_offset > 32) { 1044a8bd6d8cSJohnny Huang dw_offset = 1; 10453cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1046a8bd6d8cSJohnny Huang } else { 1047a8bd6d8cSJohnny Huang dw_offset = 0; 10483cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1049a8bd6d8cSJohnny Huang } 105076d13988SJohnny Huang 10513cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1052a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1053a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1054a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1055a8bd6d8cSJohnny Huang 1056a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1057a8bd6d8cSJohnny Huang continue; 1058a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1059a8bd6d8cSJohnny Huang fail = 1; 1060a8bd6d8cSJohnny Huang } 1061a8bd6d8cSJohnny Huang 10623cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 10633cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1064a8bd6d8cSJohnny Huang continue; 1065a8bd6d8cSJohnny Huang 10663cb28812SJohnny Huang if (strap_info[i].length == 1) { 10673cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1068a8bd6d8cSJohnny Huang } else { 1069b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10703cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10713cb28812SJohnny Huang strap_info[i].bit_offset); 1072a8bd6d8cSJohnny Huang } 1073a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1074a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1075a8bd6d8cSJohnny Huang 1076a8bd6d8cSJohnny Huang if (fail) { 1077a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1078a8bd6d8cSJohnny Huang } else { 10793cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10803cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1081a8bd6d8cSJohnny Huang else 1082a8bd6d8cSJohnny Huang printf("Reserved\n"); 1083a8bd6d8cSJohnny Huang } 1084a8bd6d8cSJohnny Huang } 1085a8bd6d8cSJohnny Huang 1086a8bd6d8cSJohnny Huang if (fail) 108776d13988SJohnny Huang return OTP_FAILURE; 108876d13988SJohnny Huang 108976d13988SJohnny Huang return OTP_SUCCESS; 109076d13988SJohnny Huang } 109176d13988SJohnny Huang 1092b458cd62SJohnny Huang static int otp_print_strap_info(int view) 109376d13988SJohnny Huang { 109479e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 109576d13988SJohnny Huang struct otpstrap_status strap_status[64]; 109607baa4e8SJohnny Huang int i, j; 1097b458cd62SJohnny Huang int fail = 0; 1098b458cd62SJohnny Huang uint32_t bit_offset; 1099b458cd62SJohnny Huang uint32_t length; 1100b458cd62SJohnny Huang uint32_t otp_value; 1101b458cd62SJohnny Huang uint32_t otp_protect; 110276d13988SJohnny Huang 1103541eb887SJohnny Huang otp_strap_status(strap_status); 110476d13988SJohnny Huang 1105b458cd62SJohnny Huang if (view) { 110607baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 110707baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 110807baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 110907baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1110b458cd62SJohnny Huang } else { 1111b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1112b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 111376d13988SJohnny Huang } 11143cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1115b458cd62SJohnny Huang otp_value = 0; 11163cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 11173cb28812SJohnny Huang length = strap_info[i].length; 1118b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1119c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1120c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1121b458cd62SJohnny Huang } 11223cb28812SJohnny Huang if ((otp_value != strap_info[i].value) && 11233cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1124b458cd62SJohnny Huang continue; 1125b458cd62SJohnny Huang if (view) { 1126b458cd62SJohnny Huang for (j = 0; j < length; j++) { 11273cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1128b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 112907baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1130b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 11313cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1132b458cd62SJohnny Huang printf(" Reserved\n"); 1133b458cd62SJohnny Huang continue; 1134b458cd62SJohnny Huang } 1135b458cd62SJohnny Huang if (length == 1) { 11363cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1137b458cd62SJohnny Huang continue; 113876d13988SJohnny Huang } 113976d13988SJohnny Huang 1140b458cd62SJohnny Huang if (j == 0) 11413cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1142b458cd62SJohnny Huang else if (j == length - 1) 1143b458cd62SJohnny Huang printf("\\ \"\n"); 1144b458cd62SJohnny Huang else 1145b458cd62SJohnny Huang printf("| \"\n"); 114676d13988SJohnny Huang } 1147b458cd62SJohnny Huang } else { 1148c947ef08SJohnny Huang if (length == 1) { 11493cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1150b458cd62SJohnny Huang } else { 1151b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1152b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1153b458cd62SJohnny Huang } 1154b458cd62SJohnny Huang 1155b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1156b458cd62SJohnny Huang 11573cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11583cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1159b458cd62SJohnny Huang else 1160b458cd62SJohnny Huang printf("Reserved\n"); 1161b458cd62SJohnny Huang } 1162b458cd62SJohnny Huang } 1163b458cd62SJohnny Huang 1164b458cd62SJohnny Huang if (fail) 1165b458cd62SJohnny Huang return OTP_FAILURE; 1166b458cd62SJohnny Huang 1167b458cd62SJohnny Huang return OTP_SUCCESS; 1168b458cd62SJohnny Huang } 1169b458cd62SJohnny Huang 117069d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 117169d5fd8fSJohnny Huang { 117269d5fd8fSJohnny Huang int i; 117369d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 117469d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 117569d5fd8fSJohnny Huang if (i % 16 == 0) { 117669d5fd8fSJohnny Huang printf("%04X: ", i); 117769d5fd8fSJohnny Huang } 117869d5fd8fSJohnny Huang printf("%02X ", buf[i]); 117969d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 118069d5fd8fSJohnny Huang printf("\n"); 118169d5fd8fSJohnny Huang } 118269d5fd8fSJohnny Huang } 118369d5fd8fSJohnny Huang } 118469d5fd8fSJohnny Huang 11857f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 118669d5fd8fSJohnny Huang { 118769d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 118879e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 11899a4fe690SJohnny Huang struct otpkey_type key_info; 119069d5fd8fSJohnny Huang char *byte_buf; 119169d5fd8fSJohnny Huang int i = 0, len = 0; 11929a4fe690SJohnny Huang int j; 1193*54552c69SJohnny Huang 119469d5fd8fSJohnny Huang byte_buf = (char *)buf; 119569d5fd8fSJohnny Huang while (1) { 119669d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 119769d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 119869d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 119969d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 120069d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 120169d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 12029a4fe690SJohnny Huang 12039a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 12049a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 12059a4fe690SJohnny Huang key_info = key_info_array[j]; 12069a4fe690SJohnny Huang break; 12079a4fe690SJohnny Huang } 12089a4fe690SJohnny Huang } 12099a4fe690SJohnny Huang 12107f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 121169d5fd8fSJohnny Huang printf("Key Type: "); 12129a4fe690SJohnny Huang printf("%s\n", key_info.information); 12139a4fe690SJohnny Huang 12149a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 121569d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 121669d5fd8fSJohnny Huang switch (key_length) { 121769d5fd8fSJohnny Huang case 0: 121869d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 121969d5fd8fSJohnny Huang break; 122069d5fd8fSJohnny Huang case 1: 122169d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 122269d5fd8fSJohnny Huang break; 122369d5fd8fSJohnny Huang case 2: 122469d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 122569d5fd8fSJohnny Huang break; 122669d5fd8fSJohnny Huang case 3: 122769d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 122869d5fd8fSJohnny Huang break; 122969d5fd8fSJohnny Huang } 12309a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 123169d5fd8fSJohnny Huang printf("RSA SHA Type: "); 123269d5fd8fSJohnny Huang switch (key_length) { 123369d5fd8fSJohnny Huang case 0: 123469d5fd8fSJohnny Huang printf("RSA1024\n"); 123569d5fd8fSJohnny Huang len = 0x100; 123669d5fd8fSJohnny Huang break; 123769d5fd8fSJohnny Huang case 1: 123869d5fd8fSJohnny Huang printf("RSA2048\n"); 123969d5fd8fSJohnny Huang len = 0x200; 124069d5fd8fSJohnny Huang break; 124169d5fd8fSJohnny Huang case 2: 124269d5fd8fSJohnny Huang printf("RSA3072\n"); 124369d5fd8fSJohnny Huang len = 0x300; 124469d5fd8fSJohnny Huang break; 124569d5fd8fSJohnny Huang case 3: 124669d5fd8fSJohnny Huang printf("RSA4096\n"); 124769d5fd8fSJohnny Huang len = 0x400; 124869d5fd8fSJohnny Huang break; 124969d5fd8fSJohnny Huang } 125069d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 125169d5fd8fSJohnny Huang } 12529a4fe690SJohnny Huang if (key_info.need_id) 125369d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 125469d5fd8fSJohnny Huang printf("Key Value:\n"); 12559a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 125669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12579a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12589a4fe690SJohnny Huang printf("AES Key:\n"); 12599a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12609a4fe690SJohnny Huang if (info_cb.version == 0) { 12619a4fe690SJohnny Huang printf("AES IV:\n"); 12629a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12639a4fe690SJohnny Huang } 12649a4fe690SJohnny Huang 12659a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 12669a4fe690SJohnny Huang if (info_cb.version == 0) { 126769d5fd8fSJohnny Huang printf("AES Key:\n"); 126869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 126969d5fd8fSJohnny Huang printf("AES IV:\n"); 127069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12719a4fe690SJohnny Huang } else if (info_cb.version == 1) { 12729a4fe690SJohnny Huang printf("AES Key 1:\n"); 12739a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12749a4fe690SJohnny Huang printf("AES Key 2:\n"); 12759a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12769a4fe690SJohnny Huang } 127769d5fd8fSJohnny Huang 12789a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA) { 127969d5fd8fSJohnny Huang printf("RSA mod:\n"); 128069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 128169d5fd8fSJohnny Huang printf("RSA exp:\n"); 128269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 128369d5fd8fSJohnny Huang } 128469d5fd8fSJohnny Huang if (last) 128569d5fd8fSJohnny Huang break; 128669d5fd8fSJohnny Huang i++; 128769d5fd8fSJohnny Huang } 128869d5fd8fSJohnny Huang return 0; 128969d5fd8fSJohnny Huang } 129069d5fd8fSJohnny Huang 1291a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 129269d5fd8fSJohnny Huang { 1293a6d0d645SJohnny Huang int i, k; 1294d90825e2SJohnny Huang int pass = 0; 1295a6d0d645SJohnny Huang uint32_t prog_address; 1296a6d0d645SJohnny Huang uint32_t data[12]; 1297a6d0d645SJohnny Huang uint32_t compare[2]; 1298d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1299d90825e2SJohnny Huang uint32_t data_masked; 1300d90825e2SJohnny Huang uint32_t buf_masked; 130169d5fd8fSJohnny Huang 1302a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1303a6d0d645SJohnny Huang 1304a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 130569d5fd8fSJohnny Huang prog_address = 0x800; 1306a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1307a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1308a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1309a6d0d645SJohnny Huang } 1310a6d0d645SJohnny Huang 1311a6d0d645SJohnny Huang printf("Check writable...\n"); 1312a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1313d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1314d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1315d90825e2SJohnny Huang if (data_masked == buf_masked) 131669d5fd8fSJohnny Huang continue; 1317d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1318a6d0d645SJohnny Huang continue; 1319a6d0d645SJohnny Huang } else { 1320a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1321a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1322a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1323a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 13242a856b9aSJohnny Huang return OTP_FAILURE; 1325a6d0d645SJohnny Huang } 1326a6d0d645SJohnny Huang } 1327a6d0d645SJohnny Huang 1328a6d0d645SJohnny Huang printf("Start Programing...\n"); 1329d90825e2SJohnny Huang otp_soak(0); 1330a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1331d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1332d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1333a6d0d645SJohnny Huang prog_address = 0x800; 1334a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1335a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1336a7a389eaSJohnny Huang if (data_masked == buf_masked) 1337a6d0d645SJohnny Huang continue; 1338de6fbf1cSJohnny Huang 1339a6d0d645SJohnny Huang 1340de6fbf1cSJohnny Huang otp_soak(1); 1341d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1342a6d0d645SJohnny Huang 134369d5fd8fSJohnny Huang pass = 0; 134469d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1345d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1346de6fbf1cSJohnny Huang otp_soak(2); 1347a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1348de6fbf1cSJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1349de6fbf1cSJohnny Huang otp_soak(1); 1350de6fbf1cSJohnny Huang } else { 1351de6fbf1cSJohnny Huang pass = 1; 1352de6fbf1cSJohnny Huang break; 1353de6fbf1cSJohnny Huang } 1354a6d0d645SJohnny Huang } else { 135569d5fd8fSJohnny Huang pass = 1; 135669d5fd8fSJohnny Huang break; 135769d5fd8fSJohnny Huang } 135869d5fd8fSJohnny Huang } 1359a6d0d645SJohnny Huang } 1360a6d0d645SJohnny Huang 1361de6fbf1cSJohnny Huang otp_soak(0); 136269d5fd8fSJohnny Huang if (!pass) 13632a856b9aSJohnny Huang return OTP_FAILURE; 1364a6d0d645SJohnny Huang 13652a856b9aSJohnny Huang return OTP_SUCCESS; 1366d90825e2SJohnny Huang 136769d5fd8fSJohnny Huang } 136869d5fd8fSJohnny Huang 136969d5fd8fSJohnny Huang 137076d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 137169d5fd8fSJohnny Huang { 137269d5fd8fSJohnny Huang int i; 137369d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 137469d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 137569d5fd8fSJohnny Huang int bit, pbit, kbit; 137669d5fd8fSJohnny Huang int fail = 0; 1377a6af4a17SJohnny Huang int skip = -1; 137866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 137969d5fd8fSJohnny Huang 1380541eb887SJohnny Huang otp_strap_status(otpstrap); 138169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 138269d5fd8fSJohnny Huang if (i < 32) { 138369d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 138469d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 138569d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 138669d5fd8fSJohnny Huang } else { 138769d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 138869d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 138969d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 139069d5fd8fSJohnny Huang } 139169d5fd8fSJohnny Huang 139269d5fd8fSJohnny Huang if (kbit == 1) { 139369d5fd8fSJohnny Huang continue; 139469d5fd8fSJohnny Huang } else { 1395a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 139669d5fd8fSJohnny Huang } 139769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 139869d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1399a6af4a17SJohnny Huang if (skip == -1) 1400a6af4a17SJohnny Huang skip = 1; 140169d5fd8fSJohnny Huang continue; 1402a6af4a17SJohnny Huang } else { 1403a6af4a17SJohnny Huang skip = 0; 140469d5fd8fSJohnny Huang } 140569d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 140669d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 140769d5fd8fSJohnny Huang fail = 1; 140869d5fd8fSJohnny Huang continue; 140969d5fd8fSJohnny Huang } 141069d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1411a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 141269d5fd8fSJohnny Huang fail = 1; 141369d5fd8fSJohnny Huang continue; 141469d5fd8fSJohnny Huang } 141569d5fd8fSJohnny Huang if (pbit == 1) { 141669d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 141769d5fd8fSJohnny Huang } 1418a6af4a17SJohnny 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); 141969d5fd8fSJohnny Huang } 142069d5fd8fSJohnny Huang if (fail == 1) 1421a6af4a17SJohnny Huang return OTP_FAILURE; 1422a6af4a17SJohnny Huang else if (skip == 1) 1423a6af4a17SJohnny Huang return OTP_PROG_SKIP; 14247e22f42dSJohnny Huang 14257e22f42dSJohnny Huang return 0; 142669d5fd8fSJohnny Huang } 142769d5fd8fSJohnny Huang 14282a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 142969d5fd8fSJohnny Huang { 143069d5fd8fSJohnny Huang int i, j; 143166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 143269d5fd8fSJohnny Huang 14332a856b9aSJohnny Huang if (start < 0 || start > 64) 14342a856b9aSJohnny Huang return OTP_USAGE; 14352a856b9aSJohnny Huang 14362a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 14372a856b9aSJohnny Huang return OTP_USAGE; 14382a856b9aSJohnny Huang 1439541eb887SJohnny Huang otp_strap_status(otpstrap); 144069d5fd8fSJohnny Huang 144107baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1442a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1443737ed20bSJohnny Huang 1444cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 144507baa4e8SJohnny Huang printf("0x%-8X", i); 1446737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1447737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1448737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1449737ed20bSJohnny Huang printf(" "); 145069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1451737ed20bSJohnny Huang printf("protected and not writable"); 145269d5fd8fSJohnny Huang } else { 1453737ed20bSJohnny Huang printf("not protected "); 145469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1455737ed20bSJohnny Huang printf("and no remaining times to write."); 145669d5fd8fSJohnny Huang } else { 1457737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 145869d5fd8fSJohnny Huang } 145969d5fd8fSJohnny Huang } 1460737ed20bSJohnny Huang printf("\n"); 146169d5fd8fSJohnny Huang } 14622a856b9aSJohnny Huang 14632a856b9aSJohnny Huang return OTP_SUCCESS; 146469d5fd8fSJohnny Huang } 146569d5fd8fSJohnny Huang 146669d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 146769d5fd8fSJohnny Huang { 146869d5fd8fSJohnny Huang int i, j; 146969d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 147069d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 147169d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 147269d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 147369d5fd8fSJohnny Huang int fail = 0; 14747e22f42dSJohnny Huang int pass = 0; 147566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 147669d5fd8fSJohnny Huang 14777f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1478541eb887SJohnny Huang otp_strap_status(otpstrap); 147969d5fd8fSJohnny Huang 14807f795e57SJohnny Huang printf("Check writable...\n"); 14817f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 14827f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14837f795e57SJohnny Huang return OTP_FAILURE; 14847f795e57SJohnny Huang } 14857e22f42dSJohnny Huang 148669d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 148769d5fd8fSJohnny Huang prog_address = 0x800; 148869d5fd8fSJohnny Huang if (i < 32) { 148969d5fd8fSJohnny Huang offset = i; 149069d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 149169d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 149269d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 149369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 149469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 149569d5fd8fSJohnny Huang 149669d5fd8fSJohnny Huang } else { 149769d5fd8fSJohnny Huang offset = (i - 32); 149869d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 149969d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 150069d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 150169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 150269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 150369d5fd8fSJohnny Huang } 150469d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 150569d5fd8fSJohnny Huang 150669d5fd8fSJohnny Huang if (kbit == 1) { 150769d5fd8fSJohnny Huang continue; 150869d5fd8fSJohnny Huang } 150969d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 151069d5fd8fSJohnny Huang continue; 151169d5fd8fSJohnny Huang } 151269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 151369d5fd8fSJohnny Huang fail = 1; 151469d5fd8fSJohnny Huang continue; 151569d5fd8fSJohnny Huang } 151669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 151769d5fd8fSJohnny Huang fail = 1; 151869d5fd8fSJohnny Huang continue; 151969d5fd8fSJohnny Huang } 15207e22f42dSJohnny Huang 15217e22f42dSJohnny Huang 1522de6fbf1cSJohnny Huang otp_soak(1); 15237e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15247e22f42dSJohnny Huang 15257e22f42dSJohnny Huang pass = 0; 152669d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1527de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1528de6fbf1cSJohnny Huang otp_soak(2); 1529de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1530de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1531de6fbf1cSJohnny Huang otp_soak(1); 1532de6fbf1cSJohnny Huang } else { 153369d5fd8fSJohnny Huang pass = 1; 153469d5fd8fSJohnny Huang break; 153569d5fd8fSJohnny Huang } 1536de6fbf1cSJohnny Huang } else { 1537de6fbf1cSJohnny Huang pass = 1; 1538de6fbf1cSJohnny Huang break; 15394b65a65dSJohnny Huang } 154069d5fd8fSJohnny Huang } 154169d5fd8fSJohnny Huang if (!pass) 15422a856b9aSJohnny Huang return OTP_FAILURE; 154369d5fd8fSJohnny Huang 154469d5fd8fSJohnny Huang if (pbit == 0) 154569d5fd8fSJohnny Huang continue; 154669d5fd8fSJohnny Huang prog_address = 0x800; 154769d5fd8fSJohnny Huang if (i < 32) 154869d5fd8fSJohnny Huang prog_address |= 0x60c; 154969d5fd8fSJohnny Huang else 155069d5fd8fSJohnny Huang prog_address |= 0x60e; 155169d5fd8fSJohnny Huang 15527e22f42dSJohnny Huang 1553de6fbf1cSJohnny Huang otp_soak(1); 15547e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 15557e22f42dSJohnny Huang 15567e22f42dSJohnny Huang pass = 0; 155769d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1558de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1559de6fbf1cSJohnny Huang otp_soak(2); 1560de6fbf1cSJohnny Huang otp_prog(prog_address, prog_bit); 1561de6fbf1cSJohnny Huang if (verify_bit(prog_address, offset, 1) != 0) { 1562de6fbf1cSJohnny Huang otp_soak(1); 1563de6fbf1cSJohnny Huang } else { 156469d5fd8fSJohnny Huang pass = 1; 156569d5fd8fSJohnny Huang break; 156669d5fd8fSJohnny Huang } 1567de6fbf1cSJohnny Huang } else { 1568de6fbf1cSJohnny Huang pass = 1; 1569de6fbf1cSJohnny Huang break; 157069d5fd8fSJohnny Huang } 157169d5fd8fSJohnny Huang } 157269d5fd8fSJohnny Huang if (!pass) 15732a856b9aSJohnny Huang return OTP_FAILURE; 157469d5fd8fSJohnny Huang 157569d5fd8fSJohnny Huang } 1576de6fbf1cSJohnny Huang otp_soak(0); 157769d5fd8fSJohnny Huang if (fail == 1) 15782a856b9aSJohnny Huang return OTP_FAILURE; 157969d5fd8fSJohnny Huang else 15802a856b9aSJohnny Huang return OTP_SUCCESS; 158169d5fd8fSJohnny Huang 158269d5fd8fSJohnny Huang } 158369d5fd8fSJohnny Huang 1584de6fbf1cSJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset) 1585cd1610b4SJohnny Huang { 1586cd1610b4SJohnny Huang int prog_bit; 1587cd1610b4SJohnny Huang 1588cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1589cd1610b4SJohnny Huang if (value) 1590cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1591cd1610b4SJohnny Huang else 1592cd1610b4SJohnny Huang return; 1593cd1610b4SJohnny Huang } else { 1594cd1610b4SJohnny Huang prog_address |= 1 << 15; 1595cd1610b4SJohnny Huang if (!value) 1596cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1597cd1610b4SJohnny Huang else 1598cd1610b4SJohnny Huang return; 1599cd1610b4SJohnny Huang } 1600cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1601cd1610b4SJohnny Huang } 1602cd1610b4SJohnny Huang 1603d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 16044c1c9b35SJohnny Huang { 1605*54552c69SJohnny Huang int i; 1606*54552c69SJohnny Huang int ret; 1607d90825e2SJohnny Huang uint32_t data[2048]; 1608d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 16094c1c9b35SJohnny Huang 1610*54552c69SJohnny Huang uint32_t data_masked; 1611*54552c69SJohnny Huang uint32_t buf_masked; 16124c1c9b35SJohnny Huang 16134c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 16144c1c9b35SJohnny Huang 1615d6cdf762SJohnny Huang for (i = 0; i < 2046 ; i += 2) { 1616d90825e2SJohnny Huang otp_read_data(i, &data[i]); 16174c1c9b35SJohnny Huang } 1618d90825e2SJohnny Huang 16194c1c9b35SJohnny Huang 16204c1c9b35SJohnny Huang printf("Check writable...\n"); 1621*54552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1622d6cdf762SJohnny Huang for (i = 0; i < 2046; i++) { 1623*54552c69SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1624*54552c69SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1625*54552c69SJohnny Huang if (data_masked == buf_masked) 16264c1c9b35SJohnny Huang continue; 1627d90825e2SJohnny Huang if (i % 2 == 0) { 1628*54552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 16294c1c9b35SJohnny Huang continue; 16304c1c9b35SJohnny Huang } else { 16314c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1632d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 16334c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1634d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16352a856b9aSJohnny Huang return OTP_FAILURE; 163669d5fd8fSJohnny Huang } 1637d90825e2SJohnny Huang } else { 1638*54552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1639d90825e2SJohnny Huang continue; 1640d90825e2SJohnny Huang } else { 1641d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1642d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1643d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1644d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 16452a856b9aSJohnny Huang return OTP_FAILURE; 1646d90825e2SJohnny Huang } 1647d90825e2SJohnny Huang } 1648d90825e2SJohnny Huang } 164969d5fd8fSJohnny Huang 1650d90825e2SJohnny Huang printf("Start Programing...\n"); 1651d90825e2SJohnny Huang 1652*54552c69SJohnny Huang // programing ecc region first 1653*54552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1654*54552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 1655*54552c69SJohnny Huang if (ret != OTP_SUCCESS) { 1656*54552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1657*54552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 1658*54552c69SJohnny Huang return ret; 1659d90825e2SJohnny Huang } 1660d90825e2SJohnny Huang } 1661d90825e2SJohnny Huang 1662*54552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 1663*54552c69SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_keep[i], i); 1664*54552c69SJohnny Huang if (ret != OTP_SUCCESS) { 1665*54552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1666*54552c69SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_keep[i], buf_keep[i + 1]); 1667*54552c69SJohnny Huang return ret; 1668d90825e2SJohnny Huang } 1669de6fbf1cSJohnny Huang } 1670de6fbf1cSJohnny Huang otp_soak(0); 16712a856b9aSJohnny Huang return OTP_SUCCESS; 1672d90825e2SJohnny Huang 1673d90825e2SJohnny Huang } 1674d90825e2SJohnny Huang 1675d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 167669d5fd8fSJohnny Huang { 167769d5fd8fSJohnny Huang int ret; 16787332532cSJohnny Huang int mode = 0; 16799a4fe690SJohnny Huang int image_version = 0; 168069d5fd8fSJohnny Huang uint32_t *buf; 1681d90825e2SJohnny Huang uint32_t *data_region = NULL; 1682d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1683d90825e2SJohnny Huang uint32_t *strap_region = NULL; 168469d5fd8fSJohnny Huang 1685d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 168669d5fd8fSJohnny Huang if (!buf) { 168769d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16882a856b9aSJohnny Huang return OTP_FAILURE; 168969d5fd8fSJohnny Huang } 1690d90825e2SJohnny Huang 16919a4fe690SJohnny Huang image_version = buf[0] & 0x3; 16929a4fe690SJohnny Huang if (image_version != info_cb.version) { 16939a4fe690SJohnny Huang puts("Version is not match\n"); 16949a4fe690SJohnny Huang return OTP_FAILURE; 16959a4fe690SJohnny Huang } 16969a4fe690SJohnny Huang 1697d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 16987332532cSJohnny Huang mode |= OTP_REGION_DATA; 16997332532cSJohnny Huang data_region = &buf[36]; 1700d90825e2SJohnny Huang } 1701d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 17027332532cSJohnny Huang mode |= OTP_REGION_CONF; 17037332532cSJohnny Huang conf_region = &buf[12]; 1704d90825e2SJohnny Huang } 1705d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 17067332532cSJohnny Huang mode |= OTP_REGION_STRAP; 17077332532cSJohnny Huang strap_region = &buf[4]; 1708d90825e2SJohnny Huang } 17097332532cSJohnny Huang 171069d5fd8fSJohnny Huang if (!nconfirm) { 17117332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17127f795e57SJohnny Huang printf("\nOTP data region :\n"); 17137f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 171469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17152a856b9aSJohnny Huang return OTP_FAILURE; 171669d5fd8fSJohnny Huang } 171769d5fd8fSJohnny Huang } 17187332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17197332532cSJohnny Huang printf("\nOTP strap region :\n"); 17207332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 17217332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17227332532cSJohnny Huang return OTP_FAILURE; 17237332532cSJohnny Huang } 17247332532cSJohnny Huang } 17257332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17267332532cSJohnny Huang printf("\nOTP configuration region :\n"); 17277332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 17287332532cSJohnny Huang printf("OTP config error, please check.\n"); 17297332532cSJohnny Huang return OTP_FAILURE; 17307332532cSJohnny Huang } 17317332532cSJohnny Huang } 17327332532cSJohnny Huang 173369d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 173469d5fd8fSJohnny Huang if (!confirm_yesno()) { 173569d5fd8fSJohnny Huang printf(" Aborting\n"); 17362a856b9aSJohnny Huang return OTP_FAILURE; 173769d5fd8fSJohnny Huang } 173869d5fd8fSJohnny Huang } 17397332532cSJohnny Huang 17407332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 17417332532cSJohnny Huang printf("programing data region ...\n"); 1742d90825e2SJohnny Huang ret = otp_prog_data(data_region); 17432a856b9aSJohnny Huang if (ret != 0) { 174469d5fd8fSJohnny Huang printf("Error\n"); 174569d5fd8fSJohnny Huang return ret; 174669d5fd8fSJohnny Huang } else { 174769d5fd8fSJohnny Huang printf("Done\n"); 174869d5fd8fSJohnny Huang } 17497332532cSJohnny Huang } 17507332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 17517332532cSJohnny Huang printf("programing strap region ...\n"); 1752d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 17532a856b9aSJohnny Huang if (ret != 0) { 175469d5fd8fSJohnny Huang printf("Error\n"); 175569d5fd8fSJohnny Huang return ret; 175669d5fd8fSJohnny Huang } else { 175769d5fd8fSJohnny Huang printf("Done\n"); 175869d5fd8fSJohnny Huang } 17597332532cSJohnny Huang } 17607332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 17617332532cSJohnny Huang printf("programing configuration region ...\n"); 1762d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17632a856b9aSJohnny Huang if (ret != 0) { 176469d5fd8fSJohnny Huang printf("Error\n"); 176569d5fd8fSJohnny Huang return ret; 176669d5fd8fSJohnny Huang } 176769d5fd8fSJohnny Huang printf("Done\n"); 176869d5fd8fSJohnny Huang } 1769cd1610b4SJohnny Huang 17707332532cSJohnny Huang return OTP_SUCCESS; 17712a856b9aSJohnny Huang } 17722a856b9aSJohnny Huang 17732a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1774cd1610b4SJohnny Huang { 1775a6af4a17SJohnny Huang uint32_t read[2]; 1776cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1777d90825e2SJohnny Huang uint32_t prog_address = 0; 177866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1779cd1610b4SJohnny Huang int otp_bit; 1780cd1610b4SJohnny Huang int i; 1781cd1610b4SJohnny Huang int pass; 1782a6af4a17SJohnny Huang int ret; 1783cd1610b4SJohnny Huang 1784cd1610b4SJohnny Huang switch (mode) { 1785a6d0d645SJohnny Huang case OTP_REGION_CONF: 1786a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1787cd1610b4SJohnny Huang prog_address = 0x800; 1788cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1789cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1790a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1791cd1610b4SJohnny Huang if (otp_bit == value) { 1792a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1793cd1610b4SJohnny Huang printf("No need to program\n"); 17942a856b9aSJohnny Huang return OTP_SUCCESS; 1795cd1610b4SJohnny Huang } 1796cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1797a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1798cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17992a856b9aSJohnny Huang return OTP_FAILURE; 1800cd1610b4SJohnny Huang } 1801a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1802cd1610b4SJohnny Huang break; 1803a6d0d645SJohnny Huang case OTP_REGION_DATA: 1804cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1805cd1610b4SJohnny Huang 1806cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1807a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1808a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1809643b9cfdSJohnny Huang 1810643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1811643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1812643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1813643b9cfdSJohnny Huang return OTP_FAILURE; 1814643b9cfdSJohnny Huang } 1815cd1610b4SJohnny Huang } else { 1816a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1817a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1818643b9cfdSJohnny Huang 1819643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1820643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1821643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1822643b9cfdSJohnny Huang return OTP_FAILURE; 1823643b9cfdSJohnny Huang } 1824cd1610b4SJohnny Huang } 1825cd1610b4SJohnny Huang if (otp_bit == value) { 1826a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1827cd1610b4SJohnny Huang printf("No need to program\n"); 18282a856b9aSJohnny Huang return OTP_SUCCESS; 1829cd1610b4SJohnny Huang } 1830643b9cfdSJohnny Huang 1831a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1832cd1610b4SJohnny Huang break; 1833a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1834541eb887SJohnny Huang otp_strap_status(otpstrap); 1835cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1836cd1610b4SJohnny Huang if (bit_offset < 32) { 1837cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1838cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1839cd1610b4SJohnny Huang strap_buf[3] = ~0; 1840cd1610b4SJohnny Huang strap_buf[5] = 0; 18412a856b9aSJohnny Huang // if (protect) 18422a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 18432a856b9aSJohnny Huang // else 18442a856b9aSJohnny Huang // strap_buf[4] = 0; 1845cd1610b4SJohnny Huang } else { 1846cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1847cd1610b4SJohnny Huang strap_buf[2] = ~0; 1848cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1849cd1610b4SJohnny Huang strap_buf[4] = 0; 18502a856b9aSJohnny Huang // if (protect) 18512a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 18522a856b9aSJohnny Huang // else 18532a856b9aSJohnny Huang // strap_buf[5] = 0; 1854cd1610b4SJohnny Huang } 185576d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1856a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 18572a856b9aSJohnny Huang return OTP_FAILURE; 1858a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1859a6af4a17SJohnny Huang return OTP_SUCCESS; 1860a6af4a17SJohnny Huang 1861cd1610b4SJohnny Huang break; 1862cd1610b4SJohnny Huang } 1863cd1610b4SJohnny Huang 1864cd1610b4SJohnny Huang if (!nconfirm) { 1865cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1866cd1610b4SJohnny Huang if (!confirm_yesno()) { 1867cd1610b4SJohnny Huang printf(" Aborting\n"); 18682a856b9aSJohnny Huang return OTP_FAILURE; 1869cd1610b4SJohnny Huang } 1870cd1610b4SJohnny Huang } 1871cd1610b4SJohnny Huang 1872cd1610b4SJohnny Huang switch (mode) { 1873a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1874cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1875a6d0d645SJohnny Huang case OTP_REGION_CONF: 1876a6d0d645SJohnny Huang case OTP_REGION_DATA: 1877de6fbf1cSJohnny Huang otp_soak(1); 1878de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1879de6fbf1cSJohnny Huang pass = 0; 1880de6fbf1cSJohnny Huang 1881cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1882a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1883de6fbf1cSJohnny Huang otp_soak(2); 1884de6fbf1cSJohnny Huang otp_prog_bit(value, prog_address, bit_offset); 1885de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1886de6fbf1cSJohnny Huang otp_soak(1); 1887cd1610b4SJohnny Huang } else { 1888de6fbf1cSJohnny Huang pass = 1; 1889de6fbf1cSJohnny Huang break; 1890de6fbf1cSJohnny Huang } 1891de6fbf1cSJohnny Huang } else { 1892de6fbf1cSJohnny Huang pass = 1; 1893cd1610b4SJohnny Huang break; 1894cd1610b4SJohnny Huang } 1895cd1610b4SJohnny Huang } 1896de6fbf1cSJohnny Huang 1897de6fbf1cSJohnny Huang otp_soak(0); 1898de6fbf1cSJohnny Huang if (pass) { 18999009c25dSJohnny Huang printf("SUCCESS\n"); 19002a856b9aSJohnny Huang return OTP_SUCCESS; 19019009c25dSJohnny Huang } else { 19029009c25dSJohnny Huang printf("OTP cannot be programed\n"); 19039009c25dSJohnny Huang printf("FAILED\n"); 19049009c25dSJohnny Huang return OTP_FAILURE; 19059009c25dSJohnny Huang } 1906cd1610b4SJohnny Huang } 1907cd1610b4SJohnny Huang 19082a856b9aSJohnny Huang return OTP_USAGE; 1909cd1610b4SJohnny Huang } 1910cd1610b4SJohnny Huang 19112a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 191269d5fd8fSJohnny Huang { 19132a856b9aSJohnny Huang uint32_t offset, count; 19142a856b9aSJohnny Huang int ret; 191569d5fd8fSJohnny Huang 19162a856b9aSJohnny Huang if (argc == 4) { 19172a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19182a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19192a856b9aSJohnny Huang } else if (argc == 3) { 19202a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19212a856b9aSJohnny Huang count = 1; 19222a856b9aSJohnny Huang } else { 192369d5fd8fSJohnny Huang return CMD_RET_USAGE; 192469d5fd8fSJohnny Huang } 192569d5fd8fSJohnny Huang 192669d5fd8fSJohnny Huang 19272a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19283d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19292a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19302a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19313d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19322a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19332a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19343d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19352a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19362a856b9aSJohnny Huang } else { 19372a856b9aSJohnny Huang return CMD_RET_USAGE; 193869d5fd8fSJohnny Huang } 193969d5fd8fSJohnny Huang 19402a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19412a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19422a856b9aSJohnny Huang else 19432a856b9aSJohnny Huang return CMD_RET_USAGE; 19442a856b9aSJohnny Huang 19452a856b9aSJohnny Huang } 19462a856b9aSJohnny Huang 19472a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19482a856b9aSJohnny Huang { 19492a856b9aSJohnny Huang phys_addr_t addr; 19502a856b9aSJohnny Huang uint32_t byte_size; 19512a856b9aSJohnny Huang int ret; 19522a856b9aSJohnny Huang 19532a856b9aSJohnny Huang if (argc == 4) { 1954ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19552a856b9aSJohnny Huang return CMD_RET_USAGE; 19562a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19572a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 19583d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19592a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 19602a856b9aSJohnny Huang } else if (argc == 3) { 19612a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19622a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 19633d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19642a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 19652a856b9aSJohnny Huang } else { 19662a856b9aSJohnny Huang return CMD_RET_USAGE; 19672a856b9aSJohnny Huang } 19682a856b9aSJohnny Huang 19692a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19702a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19712a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19722a856b9aSJohnny Huang return CMD_RET_FAILURE; 19732a856b9aSJohnny Huang else 19742a856b9aSJohnny Huang return CMD_RET_USAGE; 19752a856b9aSJohnny Huang } 19762a856b9aSJohnny Huang 19772a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19782a856b9aSJohnny Huang { 19792a856b9aSJohnny Huang int mode = 0; 19802a856b9aSJohnny Huang int nconfirm = 0; 19812a856b9aSJohnny Huang int otp_addr = 0; 19822a856b9aSJohnny Huang int bit_offset; 19832a856b9aSJohnny Huang int value; 19842a856b9aSJohnny Huang int ret; 19852a856b9aSJohnny Huang 19862a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19872a856b9aSJohnny Huang return CMD_RET_USAGE; 19882a856b9aSJohnny Huang 19892a856b9aSJohnny Huang /* Drop the pb cmd */ 19902a856b9aSJohnny Huang argc--; 19912a856b9aSJohnny Huang argv++; 19922a856b9aSJohnny Huang 19932a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1994a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 19952a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1996a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 19972a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1998a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1999cd1610b4SJohnny Huang else 20002a856b9aSJohnny Huang return CMD_RET_USAGE; 20012a856b9aSJohnny Huang 20022a856b9aSJohnny Huang /* Drop the region cmd */ 20032a856b9aSJohnny Huang argc--; 20042a856b9aSJohnny Huang argv++; 20052a856b9aSJohnny Huang 2006ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2007cd1610b4SJohnny Huang nconfirm = 1; 20082a856b9aSJohnny Huang /* Drop the force option */ 20092a856b9aSJohnny Huang argc--; 20102a856b9aSJohnny Huang argv++; 20112a856b9aSJohnny Huang } 2012cd1610b4SJohnny Huang 2013a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20142a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20152a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20160808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20172a856b9aSJohnny Huang return CMD_RET_USAGE; 2018cd1610b4SJohnny Huang } else { 20192a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20202a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20212a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20220808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20232a856b9aSJohnny Huang return CMD_RET_USAGE; 20240808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 202578855207SJohnny Huang if (otp_addr >= 0x800) 20260808cc55SJohnny Huang return CMD_RET_USAGE; 20270808cc55SJohnny Huang } else { 202878855207SJohnny Huang if (otp_addr >= 0x20) 20290808cc55SJohnny Huang return CMD_RET_USAGE; 20300808cc55SJohnny Huang } 2031cd1610b4SJohnny Huang } 2032cd1610b4SJohnny Huang if (value != 0 && value != 1) 20332a856b9aSJohnny Huang return CMD_RET_USAGE; 2034cd1610b4SJohnny Huang 20353d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20362a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20372a856b9aSJohnny Huang 20382a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20392a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20402a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20412a856b9aSJohnny Huang return CMD_RET_FAILURE; 20422a856b9aSJohnny Huang else 20432a856b9aSJohnny Huang return CMD_RET_USAGE; 20442a856b9aSJohnny Huang } 20452a856b9aSJohnny Huang 20462a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20472a856b9aSJohnny Huang { 20482a856b9aSJohnny Huang phys_addr_t addr; 20492a856b9aSJohnny Huang int otp_addr = 0; 20502a856b9aSJohnny Huang 20512a856b9aSJohnny Huang if (argc != 3) 20522a856b9aSJohnny Huang return CMD_RET_USAGE; 20532a856b9aSJohnny Huang 20543d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20552a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20562a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20572a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 205869d5fd8fSJohnny Huang printf("Compare pass\n"); 20592a856b9aSJohnny Huang return CMD_RET_SUCCESS; 206069d5fd8fSJohnny Huang } else { 206169d5fd8fSJohnny Huang printf("Compare fail\n"); 20622a856b9aSJohnny Huang return CMD_RET_FAILURE; 206369d5fd8fSJohnny Huang } 206469d5fd8fSJohnny Huang } 206569d5fd8fSJohnny Huang 206666f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 206766f2f8e5SJohnny Huang { 2068a8bd6d8cSJohnny Huang int view = 0; 20692d4b0742SJohnny Huang int input; 2070a8bd6d8cSJohnny Huang 2071a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 207266f2f8e5SJohnny Huang return CMD_RET_USAGE; 207366f2f8e5SJohnny Huang 20742d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 207566f2f8e5SJohnny Huang 20763d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20772d4b0742SJohnny Huang if (argc == 3) { 20782d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20792d4b0742SJohnny Huang otp_print_conf_info(input); 20802d4b0742SJohnny Huang } else { 20812d4b0742SJohnny Huang otp_print_conf_info(-1); 20822d4b0742SJohnny Huang } 20832d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 20842d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2085a8bd6d8cSJohnny Huang view = 1; 2086a8bd6d8cSJohnny Huang /* Drop the view option */ 2087a8bd6d8cSJohnny Huang argc--; 2088a8bd6d8cSJohnny Huang argv++; 2089a8bd6d8cSJohnny Huang } 20903d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2091b458cd62SJohnny Huang otp_print_strap_info(view); 209266f2f8e5SJohnny Huang } else { 209366f2f8e5SJohnny Huang return CMD_RET_USAGE; 209466f2f8e5SJohnny Huang } 20952d4b0742SJohnny Huang 209666f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 209766f2f8e5SJohnny Huang } 209866f2f8e5SJohnny Huang 2099737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2100737ed20bSJohnny Huang { 2101737ed20bSJohnny Huang int input; 2102737ed20bSJohnny Huang int bit_offset; 2103737ed20bSJohnny Huang int prog_address; 2104737ed20bSJohnny Huang int pass; 2105737ed20bSJohnny Huang int i; 2106737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2107737ed20bSJohnny Huang return CMD_RET_USAGE; 2108737ed20bSJohnny Huang 2109ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2110737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2111737ed20bSJohnny Huang } else { 2112737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2113737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2114737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2115737ed20bSJohnny Huang if (!confirm_yesno()) { 2116737ed20bSJohnny Huang printf(" Aborting\n"); 2117737ed20bSJohnny Huang return CMD_RET_FAILURE; 2118737ed20bSJohnny Huang } 2119737ed20bSJohnny Huang } 2120737ed20bSJohnny Huang 2121737ed20bSJohnny Huang prog_address = 0x800; 2122737ed20bSJohnny Huang if (input < 32) { 2123737ed20bSJohnny Huang bit_offset = input; 2124737ed20bSJohnny Huang prog_address |= 0x60c; 2125737ed20bSJohnny Huang } else if (input < 64) { 2126737ed20bSJohnny Huang bit_offset = input - 32; 2127737ed20bSJohnny Huang prog_address |= 0x60e; 2128737ed20bSJohnny Huang } else { 2129737ed20bSJohnny Huang return CMD_RET_USAGE; 2130737ed20bSJohnny Huang } 2131737ed20bSJohnny Huang 2132737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2133737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2134737ed20bSJohnny Huang } 2135de6fbf1cSJohnny Huang 2136de6fbf1cSJohnny Huang otp_soak(1); 2137de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2138de6fbf1cSJohnny Huang pass = 0; 2139de6fbf1cSJohnny Huang 2140737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2141737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2142de6fbf1cSJohnny Huang otp_soak(2); 2143de6fbf1cSJohnny Huang otp_prog_bit(1, prog_address, bit_offset); 2144de6fbf1cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2145de6fbf1cSJohnny Huang otp_soak(1); 2146737ed20bSJohnny Huang } else { 2147de6fbf1cSJohnny Huang pass = 1; 2148de6fbf1cSJohnny Huang break; 2149de6fbf1cSJohnny Huang } 2150de6fbf1cSJohnny Huang } else { 2151de6fbf1cSJohnny Huang pass = 1; 2152737ed20bSJohnny Huang break; 2153737ed20bSJohnny Huang } 2154737ed20bSJohnny Huang } 2155de6fbf1cSJohnny Huang otp_soak(0); 2156de6fbf1cSJohnny Huang if (pass) { 2157737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2158737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2159737ed20bSJohnny Huang } 2160737ed20bSJohnny Huang 2161737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2162737ed20bSJohnny Huang return CMD_RET_FAILURE; 2163737ed20bSJohnny Huang 2164737ed20bSJohnny Huang } 21659a4fe690SJohnny Huang 21662a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 21672a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2168a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 21692a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 21702a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2171737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 21722a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 21732a856b9aSJohnny Huang }; 21742a856b9aSJohnny Huang 21752a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21762a856b9aSJohnny Huang { 21772a856b9aSJohnny Huang cmd_tbl_t *cp; 21782a856b9aSJohnny Huang 21792a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 21802a856b9aSJohnny Huang 2181737ed20bSJohnny Huang /* Drop the otp command */ 21822a856b9aSJohnny Huang argc--; 21832a856b9aSJohnny Huang argv++; 21842a856b9aSJohnny Huang 21852a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 21862a856b9aSJohnny Huang return CMD_RET_USAGE; 21872a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 21882a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21892a856b9aSJohnny Huang 21909a4fe690SJohnny Huang if (chip_version() == 0) { 21919a4fe690SJohnny Huang info_cb.version = 0; 21929a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 21939a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 21949a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 21959a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 21969a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 21979a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 21989a4fe690SJohnny Huang } else if (chip_version() == 1) { 21999a4fe690SJohnny Huang info_cb.version = 1; 22003cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 22013cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 22023cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 22033cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 22049a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 22059a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 22069a4fe690SJohnny Huang } 22079a4fe690SJohnny Huang 22082a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 220969d5fd8fSJohnny Huang } 221069d5fd8fSJohnny Huang 221169d5fd8fSJohnny Huang U_BOOT_CMD( 221269d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 221369d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 22142a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 22152a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 22162d4b0742SJohnny Huang "otp info strap [v]\n" 22172d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2218ed071a2bSJohnny Huang "otp prog [o] <addr> <byte_size>\n" 2219ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2220ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2221ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 22222a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 222369d5fd8fSJohnny Huang ); 2224