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 28a6d0d645SJohnny Huang #define OTP_REGION_STRAP 1 29a6d0d645SJohnny Huang #define OTP_REGION_CONF 2 30a6d0d645SJohnny Huang #define OTP_REGION_DATA 3 31a6d0d645SJohnny Huang #define OTP_REGION_ALL 4 3269d5fd8fSJohnny Huang 332a856b9aSJohnny Huang #define OTP_USAGE -1 342a856b9aSJohnny Huang #define OTP_FAILURE -2 352a856b9aSJohnny Huang #define OTP_SUCCESS 0 362a856b9aSJohnny Huang 37a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 38a6af4a17SJohnny Huang 3966f2f8e5SJohnny Huang #define DISABLE_SECREG_PROG(x) (x & 0x1) 4066f2f8e5SJohnny Huang #define ENABLE_SEC_BOOT(x) ((x >> 1) & 0x1) 4166f2f8e5SJohnny Huang #define INIT_PROG_DONE(x) ((x >> 2) & 0x1) 4266f2f8e5SJohnny Huang #define ENABLE_USERREG_ECC(x) ((x >> 3) & 0x1) 4366f2f8e5SJohnny Huang #define ENABLE_SECREG_ECC(x) ((x >> 4) & 0x1) 4466f2f8e5SJohnny Huang #define DISABLE_LOW_SEC_KEY(x) ((x >> 5) & 0x1) 4566f2f8e5SJohnny Huang #define IGNORE_SEC_BOOT_HWSTRAP(x) ((x >> 6) & 0x1) 4666f2f8e5SJohnny Huang #define SEC_BOOT_MDOES(x) ((x >> 7) & 0x1) 47e1f9e54eSJohnny Huang #define SEC_MODE1 0x0 48e1f9e54eSJohnny Huang #define SEC_MODE2 0x1 49e1f9e54eSJohnny Huang #define OTP_BIT_CELL_MODES(x) ((x >> 8) & 0x3) 50e1f9e54eSJohnny Huang #define SINGLE_CELL_MODE 0x0 51e1f9e54eSJohnny Huang #define DIFFERENTIAL_MODE 0x1 52e1f9e54eSJohnny Huang #define DIFFERENTIAL_REDUDANT_MODE 0x2 53e1f9e54eSJohnny Huang #define CRYPTO_MODES(x) ((x >> 10) & 0x3) 54e1f9e54eSJohnny Huang #define CRYPTO_RSA1024 0x0 55e1f9e54eSJohnny Huang #define CRYPTO_RSA2048 0x1 56e1f9e54eSJohnny Huang #define CRYPTO_RSA3072 0x2 57e1f9e54eSJohnny Huang #define CRYPTO_RSA4096 0x3 58e1f9e54eSJohnny Huang #define HASH_MODES(x) ((x >> 12) & 0x3) 59e1f9e54eSJohnny Huang #define HASH_SAH224 0x0 60e1f9e54eSJohnny Huang #define HASH_SAH256 0x1 61e1f9e54eSJohnny Huang #define HASH_SAH384 0x2 62e1f9e54eSJohnny Huang #define HASH_SAH512 0x3 63e1f9e54eSJohnny Huang #define SECREG_SIZE(x) ((x >> 16) & 0x3f) 6466f2f8e5SJohnny Huang #define WRITE_PROTECT_SECREG(x) ((x >> 22) & 0x1) 6566f2f8e5SJohnny Huang #define WRITE_PROTECT_USERREG(x) ((x >> 23) & 0x1) 6666f2f8e5SJohnny Huang #define WRITE_PROTECT_CONFREG(x) ((x >> 24) & 0x1) 6766f2f8e5SJohnny Huang #define WRITE_PROTECT_STRAPREG(x) ((x >> 25) & 0x1) 6866f2f8e5SJohnny Huang #define ENABLE_COPY_TO_SRAM(x) ((x >> 26) & 0x1) 6966f2f8e5SJohnny Huang #define ENABLE_IMAGE_ENC(x) ((x >> 27) & 0x1) 7066f2f8e5SJohnny Huang #define WRITE_PROTECT_KEY_RETIRE(x) ((x >> 29) & 0x1) 7166f2f8e5SJohnny Huang #define ENABLE_SIPROM_RED(x) ((x >> 30) & 0x1) 7266f2f8e5SJohnny Huang #define ENABLE_SIPROM_MLOCK(x) ((x >> 31) & 0x1) 73e1f9e54eSJohnny Huang 74e1f9e54eSJohnny Huang #define VENDER_ID(x) (x & 0xFFFF) 75e1f9e54eSJohnny Huang #define KEY_REVISION(x) ((x >> 16) & 0xFFFF) 76e1f9e54eSJohnny Huang 77e1f9e54eSJohnny Huang #define SEC_BOOT_HEADER_OFFSET(x) (x & 0xFFFF) 78e1f9e54eSJohnny Huang 79e1f9e54eSJohnny Huang #define KEYS_VALID_BITS(x) (x & 0xff) 80e1f9e54eSJohnny Huang #define KEYS_RETIRE_BITS(x) ((x >> 16) & 0xff) 814c1c9b35SJohnny Huang 82*76d13988SJohnny Huang #define ENABLE_SECURE_BOOT(x) (x & 0x1) 83*76d13988SJohnny Huang #define BOOT_FROM_EMMC(x) ((x >> 1) & 0x1) 84*76d13988SJohnny Huang #define BOOT_FROM_DEBUG_SPI(x) ((x >> 2) & 0x1) 85*76d13988SJohnny Huang #define DISABLE_ARM_CM3(x) ((x >> 3) & 0x1) 86*76d13988SJohnny Huang #define VGA_EXPANSION_ROM(x) ((x >> 4) & 0x1) 87*76d13988SJohnny Huang #define MAC1_RMII_MODE(x) ((x >> 5) & 0x1) 88*76d13988SJohnny Huang #define MAC2_RMII_MODE(x) ((x >> 6) & 0x1) 89*76d13988SJohnny Huang #define CPU_FREQUENCY(x) ((x >> 7) & 0x7) 90*76d13988SJohnny Huang #define HCLK_RATIO(x) ((x >> 10) & 0x3) 91*76d13988SJohnny Huang #define VGA_MEMORY_SIZE(x) ((x >> 12) & 0x3) 92*76d13988SJohnny Huang #define VGA_CLASS_CODE(x) ((x >> 17) & 0x1) 93*76d13988SJohnny Huang #define DISABLE_DEBUG0(x) ((x >> 18) & 0x1) 94*76d13988SJohnny Huang #define BOOT_FROM_EMMC_SPEED_MDOE(x) ((x >> 19) & 0x1) 95*76d13988SJohnny Huang #define DISABLE_PCIE_EHCI(x) ((x >> 20) & 0x1) 96*76d13988SJohnny Huang #define DISABLE_VGA_XDMA(x) ((x >> 21) & 0x1) 97*76d13988SJohnny Huang #define DISABLE_DEDICATED_BMC_FUNCTION(x) ((x >> 22) & 0x1) 98*76d13988SJohnny Huang #define DEDICATE_ROOT_COMPLEX_RELAX(x) ((x >> 23) & 0x1) 99*76d13988SJohnny Huang #define SELECT_DRAM_TYPES(x) ((x >> 24) & 0x1) 100*76d13988SJohnny Huang #define MAC3_RMII_MODE(x) (x & 0x1) 101*76d13988SJohnny Huang #define MAC4_RMII_MODE(x) ((x >> 1) & 0x1) 102*76d13988SJohnny Huang #define SIO_CONF_ADDR(x) ((x >> 2) & 0x1) 103*76d13988SJohnny Huang #define DISABLE_SIO(x) ((x >> 3) & 0x1) 104*76d13988SJohnny Huang #define DISABLE_DEBUG1(x) ((x >> 4) & 0x1) 105*76d13988SJohnny Huang #define ENABLE_ACPI(x) ((x >> 5) & 0x1) 106*76d13988SJohnny Huang #define SELECT_LPC(x) ((x >> 6) & 0x1) 107*76d13988SJohnny Huang #define ENABLE_SAFS(x) ((x >> 7) & 0x1) 108*76d13988SJohnny Huang #define ENABLE_SPI_3B4B_AUTO(x) ((x >> 10) & 0x1) 109*76d13988SJohnny Huang #define ENABLE_BOOT_SPI_ABR(x) ((x >> 11) & 0x1) 110*76d13988SJohnny Huang #define BOOT_SPI_ABR_MODE(x) ((x >> 12) & 0x1) 111*76d13988SJohnny Huang #define BOOT_SPI_FLASH_SIZE(x) ((x >> 13) & 0x7) 112*76d13988SJohnny Huang #define ENABLE_HOST_SPI_ABR(x) ((x >> 16) & 0x1) 113*76d13988SJohnny Huang #define EBABLE_HOST_SPI_ABR_SEL_PIN(x) ((x >> 17) & 0x1) 114*76d13988SJohnny Huang #define HOST_SPI_ABR_MODE(x) ((x >> 18) & 0x1) 115*76d13988SJohnny Huang #define HOST_SPI_FLASH_SIZE(x) ((x >> 19) & 0x7) 116*76d13988SJohnny Huang #define ENABLE_BOOT_SPI_AUX_CONTROL_PIN(x) ((x >> 22) & 0x1) 117*76d13988SJohnny Huang #define BOOT_SPI_CRTM_SIZE(x) ((x >> 23) & 0x3) 118*76d13988SJohnny Huang #define HOST_SPI_CRTM_SIZE(x) ((x >> 25) & 0x3) 119*76d13988SJohnny Huang #define ENABLE_HOST_SPI_AUX_CONTROL_PIN(x) ((x >> 27) & 0x1) 120*76d13988SJohnny Huang #define ENABLE_GPIO_PASS_THROUGH(x) ((x >> 28) & 0x1) 121*76d13988SJohnny Huang #define DISABLE_LOW_SECURITY_KEY(x) ((x >> 29) & 0x1) 122*76d13988SJohnny Huang #define ENABLE_DEDICATE_GPIO_STRAP(x) ((x >> 30) & 0x1) 123*76d13988SJohnny Huang 124*76d13988SJohnny Huang 1254c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 1264c1c9b35SJohnny Huang #define PBWIDTH 60 1274c1c9b35SJohnny Huang 1284c1c9b35SJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 1294c1c9b35SJohnny Huang { 1304c1c9b35SJohnny Huang int val = numerator * 100 / denominator; 1314c1c9b35SJohnny Huang int lpad = numerator * PBWIDTH / denominator; 1324c1c9b35SJohnny Huang int rpad = PBWIDTH - lpad; 1334c1c9b35SJohnny Huang char buffer[256]; 1344c1c9b35SJohnny Huang va_list aptr; 1354c1c9b35SJohnny Huang 1364c1c9b35SJohnny Huang va_start(aptr, format); 1374c1c9b35SJohnny Huang vsprintf(buffer, format, aptr); 1384c1c9b35SJohnny Huang va_end(aptr); 1394c1c9b35SJohnny Huang 1404c1c9b35SJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 1414c1c9b35SJohnny Huang if (numerator == denominator) 1424c1c9b35SJohnny Huang printf("\n"); 1434c1c9b35SJohnny Huang } 1444c1c9b35SJohnny Huang 14566f2f8e5SJohnny Huang struct otpstrap_status { 14669d5fd8fSJohnny Huang int value; 14769d5fd8fSJohnny Huang int option_array[7]; 14869d5fd8fSJohnny Huang int remain_times; 14969d5fd8fSJohnny Huang int writeable_option; 15069d5fd8fSJohnny Huang int protected; 15169d5fd8fSJohnny Huang }; 15269d5fd8fSJohnny Huang 15366f2f8e5SJohnny Huang struct otpconf_parse { 15466f2f8e5SJohnny Huang int dw_offset; 15566f2f8e5SJohnny Huang int bit; 15666f2f8e5SJohnny Huang int length; 15766f2f8e5SJohnny Huang int value; 15866f2f8e5SJohnny Huang int keep; 15966f2f8e5SJohnny Huang char status[80]; 16066f2f8e5SJohnny Huang }; 16166f2f8e5SJohnny Huang 162*76d13988SJohnny Huang struct otpstrap_parse { 163*76d13988SJohnny Huang int bit; 164*76d13988SJohnny Huang int length; 165*76d13988SJohnny Huang int value; 166*76d13988SJohnny Huang int keep; 167*76d13988SJohnny Huang int protect; 168*76d13988SJohnny Huang char status[80]; 169*76d13988SJohnny Huang }; 170*76d13988SJohnny Huang 1712a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 17269d5fd8fSJohnny Huang { 17369d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 17469d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 17569d5fd8fSJohnny Huang udelay(2); 17669d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 17769d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 17869d5fd8fSJohnny Huang } 17969d5fd8fSJohnny Huang 1802a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 18169d5fd8fSJohnny Huang { 18269d5fd8fSJohnny Huang int config_offset; 18369d5fd8fSJohnny Huang 18469d5fd8fSJohnny Huang config_offset = 0x800; 18569d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 18669d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 18769d5fd8fSJohnny Huang 18869d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 18969d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 19069d5fd8fSJohnny Huang udelay(2); 19169d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 19269d5fd8fSJohnny Huang } 19369d5fd8fSJohnny Huang 19469d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 19569d5fd8fSJohnny Huang { 19669d5fd8fSJohnny Huang int i; 19769d5fd8fSJohnny Huang uint32_t ret[1]; 19869d5fd8fSJohnny Huang 19969d5fd8fSJohnny Huang if (offset + dw_count > 32) 2002a856b9aSJohnny Huang return OTP_USAGE; 20169d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 20269d5fd8fSJohnny Huang otp_read_config(i, ret); 203a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 20469d5fd8fSJohnny Huang } 20569d5fd8fSJohnny Huang printf("\n"); 2062a856b9aSJohnny Huang return OTP_SUCCESS; 20769d5fd8fSJohnny Huang } 20869d5fd8fSJohnny Huang 20969d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 21069d5fd8fSJohnny Huang { 21169d5fd8fSJohnny Huang int i; 21269d5fd8fSJohnny Huang uint32_t ret[2]; 21369d5fd8fSJohnny Huang 21469d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 2152a856b9aSJohnny Huang return OTP_USAGE; 21669d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 21769d5fd8fSJohnny Huang otp_read_data(i, ret); 21869d5fd8fSJohnny Huang if (i % 4 == 0) 21969d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 22069d5fd8fSJohnny Huang else 22169d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 22269d5fd8fSJohnny Huang 22369d5fd8fSJohnny Huang } 22469d5fd8fSJohnny Huang printf("\n"); 2252a856b9aSJohnny Huang return OTP_SUCCESS; 22669d5fd8fSJohnny Huang } 22769d5fd8fSJohnny Huang 22869d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 22969d5fd8fSJohnny Huang { 23069d5fd8fSJohnny Huang uint32_t ret; 23169d5fd8fSJohnny Huang uint32_t *buf; 23269d5fd8fSJohnny Huang 23369d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 23469d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 23569d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 23669d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 23769d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 23869d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 23969d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 24069d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 24169d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 24269d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 24369d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 24469d5fd8fSJohnny Huang udelay(10); 24569d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 24669d5fd8fSJohnny Huang if (ret & 0x1) 24769d5fd8fSJohnny Huang return 0; 24869d5fd8fSJohnny Huang else 24969d5fd8fSJohnny Huang return -1; 25069d5fd8fSJohnny Huang } 25169d5fd8fSJohnny Huang 25269d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 25369d5fd8fSJohnny Huang { 25469d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 25569d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 25669d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 25769d5fd8fSJohnny Huang udelay(100); 25869d5fd8fSJohnny Huang } 25969d5fd8fSJohnny Huang 26069d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 26169d5fd8fSJohnny Huang { 26269d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 26369d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 26469d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 26569d5fd8fSJohnny Huang udelay(85); 26669d5fd8fSJohnny Huang } 26769d5fd8fSJohnny Huang 268a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 26969d5fd8fSJohnny Huang { 27069d5fd8fSJohnny Huang int ret; 27169d5fd8fSJohnny Huang 27269d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 27369d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 27469d5fd8fSJohnny Huang udelay(2); 27569d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 276a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 27769d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 27869d5fd8fSJohnny Huang return 0; 27969d5fd8fSJohnny Huang else 28069d5fd8fSJohnny Huang return -1; 28169d5fd8fSJohnny Huang } 28269d5fd8fSJohnny Huang 283d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 2844c1c9b35SJohnny Huang { 2854c1c9b35SJohnny Huang uint32_t ret[2]; 2864c1c9b35SJohnny Huang 2874c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 2884c1c9b35SJohnny Huang 2894c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 2904c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 2914c1c9b35SJohnny Huang else 2924c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 2934c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 2944c1c9b35SJohnny Huang udelay(2); 2954c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 2964c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 2974c1c9b35SJohnny Huang if (size == 1) { 2984c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 2994c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 300d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 3014c1c9b35SJohnny Huang compare[0] = 0; 3024c1c9b35SJohnny Huang return 0; 3034c1c9b35SJohnny Huang } else { 3044c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 3054c1c9b35SJohnny Huang return -1; 3064c1c9b35SJohnny Huang } 3074c1c9b35SJohnny Huang 3084c1c9b35SJohnny Huang } else { 3094c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 310d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 3114c1c9b35SJohnny Huang compare[0] = ~0; 3124c1c9b35SJohnny Huang return 0; 3134c1c9b35SJohnny Huang } else { 314d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 3154c1c9b35SJohnny Huang return -1; 3164c1c9b35SJohnny Huang } 3174c1c9b35SJohnny Huang } 3184c1c9b35SJohnny Huang } else if (size == 2) { 3194c1c9b35SJohnny Huang // otp_addr should be even 320d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 3214c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 3224c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 3234c1c9b35SJohnny Huang compare[0] = 0; 3244c1c9b35SJohnny Huang compare[1] = ~0; 3254c1c9b35SJohnny Huang return 0; 3264c1c9b35SJohnny Huang } else { 3274c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 3284c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 3294c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 3304c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 3314c1c9b35SJohnny Huang return -1; 3324c1c9b35SJohnny Huang } 3334c1c9b35SJohnny Huang } else { 3344c1c9b35SJohnny Huang return -1; 3354c1c9b35SJohnny Huang } 3364c1c9b35SJohnny Huang } 3374c1c9b35SJohnny Huang 3387e22f42dSJohnny Huang static void otp_soak(int soak) 339d90825e2SJohnny Huang { 340d90825e2SJohnny Huang if (soak) { 341d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 342d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 343d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 344d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 345d90825e2SJohnny Huang } else { 346d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 347d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 348d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 349d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 350d90825e2SJohnny Huang } 351d90825e2SJohnny Huang } 352d90825e2SJohnny Huang 353d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 354d90825e2SJohnny Huang { 355d90825e2SJohnny Huang int j, bit_value, prog_bit; 356d90825e2SJohnny Huang 357d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 358d90825e2SJohnny Huang if ((keep >> j) & 0x1) 359d90825e2SJohnny Huang continue; 360d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 361d90825e2SJohnny Huang if (prog_address % 2 == 0) { 362d90825e2SJohnny Huang if (bit_value) 363d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 364d90825e2SJohnny Huang else 365d90825e2SJohnny Huang continue; 366d90825e2SJohnny Huang } else { 367d90825e2SJohnny Huang prog_address |= 1 << 15; 368d90825e2SJohnny Huang if (bit_value) 369d90825e2SJohnny Huang continue; 370d90825e2SJohnny Huang else 371d90825e2SJohnny Huang prog_bit = 0x1 << j; 372d90825e2SJohnny Huang } 373d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 374d90825e2SJohnny Huang } 375d90825e2SJohnny Huang } 376d90825e2SJohnny Huang 377*76d13988SJohnny Huang 378*76d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 379*76d13988SJohnny Huang { 380*76d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 381*76d13988SJohnny Huang int i, j; 382*76d13988SJohnny Huang 383*76d13988SJohnny Huang for (j = 0; j < 64; j++) { 384*76d13988SJohnny Huang otpstrap[j].value = 0; 385*76d13988SJohnny Huang otpstrap[j].remain_times = 7; 386*76d13988SJohnny Huang otpstrap[j].writeable_option = -1; 387*76d13988SJohnny Huang otpstrap[j].protected = 0; 388*76d13988SJohnny Huang } 389*76d13988SJohnny Huang 390*76d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 391*76d13988SJohnny Huang int option = (i - 16) / 2; 392*76d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 393*76d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 394*76d13988SJohnny Huang for (j = 0; j < 32; j++) { 395*76d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 396*76d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 397*76d13988SJohnny Huang otpstrap[j].writeable_option = option; 398*76d13988SJohnny Huang } 399*76d13988SJohnny Huang if (bit_value == 1) 400*76d13988SJohnny Huang otpstrap[j].remain_times --; 401*76d13988SJohnny Huang otpstrap[j].value ^= bit_value; 402*76d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 403*76d13988SJohnny Huang } 404*76d13988SJohnny Huang for (j = 32; j < 64; j++) { 405*76d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 406*76d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 407*76d13988SJohnny Huang otpstrap[j].writeable_option = option; 408*76d13988SJohnny Huang } 409*76d13988SJohnny Huang if (bit_value == 1) 410*76d13988SJohnny Huang otpstrap[j].remain_times --; 411*76d13988SJohnny Huang otpstrap[j].value ^= bit_value; 412*76d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 413*76d13988SJohnny Huang } 414*76d13988SJohnny Huang } 415*76d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 416*76d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 417*76d13988SJohnny Huang for (j = 0; j < 32; j++) { 418*76d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 419*76d13988SJohnny Huang otpstrap[j].protected = 1; 420*76d13988SJohnny Huang } 421*76d13988SJohnny Huang for (j = 32; j < 64; j++) { 422*76d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 423*76d13988SJohnny Huang otpstrap[j].protected = 1; 424*76d13988SJohnny Huang } 425*76d13988SJohnny Huang } 426*76d13988SJohnny Huang 42766f2f8e5SJohnny Huang static int otp_conf_parse(uint32_t *OTPCFG, struct otpconf_parse *conf_parse) 42869d5fd8fSJohnny Huang { 4294c1c9b35SJohnny Huang int tmp, i; 43066f2f8e5SJohnny Huang int k = 0; 4314c1c9b35SJohnny Huang int pass = 0; 432442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 43369d5fd8fSJohnny Huang 43466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 43566f2f8e5SJohnny Huang conf_parse[k].bit = 0; 43666f2f8e5SJohnny Huang conf_parse[k].length = 1; 43766f2f8e5SJohnny Huang conf_parse[k].value = DISABLE_SECREG_PROG(OTPCFG[0]); 43866f2f8e5SJohnny Huang if (DISABLE_SECREG_PROG(OTPCFG_KEEP[0])) { 43966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 44066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 441442839bbSJohnny Huang } else { 44266f2f8e5SJohnny Huang if (DISABLE_SECREG_PROG(OTPCFG[0])) 44366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 44466f2f8e5SJohnny Huang "Disable Secure Region programming"); 44569d5fd8fSJohnny Huang else 44666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 44766f2f8e5SJohnny Huang "Enable Secure Region programming"); 448442839bbSJohnny Huang } 449442839bbSJohnny Huang 45066f2f8e5SJohnny Huang k++; 45166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 45266f2f8e5SJohnny Huang conf_parse[k].bit = 1; 45366f2f8e5SJohnny Huang conf_parse[k].length = 1; 45466f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SEC_BOOT(OTPCFG[0]); 45566f2f8e5SJohnny Huang if (ENABLE_SEC_BOOT(OTPCFG_KEEP[0])) { 45666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 45766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 458442839bbSJohnny Huang } else { 45966f2f8e5SJohnny Huang if (ENABLE_SEC_BOOT(OTPCFG[0])) 46066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 46166f2f8e5SJohnny Huang "Enable Secure Boot"); 46269d5fd8fSJohnny Huang else 46366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 46466f2f8e5SJohnny Huang "Disable Secure Boot"); 465442839bbSJohnny Huang } 466442839bbSJohnny Huang 46766f2f8e5SJohnny Huang k++; 46866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 46966f2f8e5SJohnny Huang conf_parse[k].bit = 3; 47066f2f8e5SJohnny Huang conf_parse[k].length = 1; 47166f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_USERREG_ECC(OTPCFG[0]); 47266f2f8e5SJohnny Huang if (ENABLE_USERREG_ECC(OTPCFG_KEEP[0])) { 47366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 47466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 475442839bbSJohnny Huang } else { 47666f2f8e5SJohnny Huang if (ENABLE_USERREG_ECC(OTPCFG[0])) 47766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 47866f2f8e5SJohnny Huang "User region ECC enable"); 47969d5fd8fSJohnny Huang else 48066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 48166f2f8e5SJohnny Huang "User region ECC disable"); 482442839bbSJohnny Huang } 483442839bbSJohnny Huang 48466f2f8e5SJohnny Huang k++; 48566f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 48666f2f8e5SJohnny Huang conf_parse[k].bit = 4; 48766f2f8e5SJohnny Huang conf_parse[k].length = 1; 48866f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SECREG_ECC(OTPCFG[0]); 48966f2f8e5SJohnny Huang if (ENABLE_SECREG_ECC(OTPCFG_KEEP[0])) { 49066f2f8e5SJohnny Huang conf_parse[k].keep = 1; 49166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 492442839bbSJohnny Huang } else { 49366f2f8e5SJohnny Huang if (ENABLE_SECREG_ECC(OTPCFG[0])) 49466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 49566f2f8e5SJohnny Huang "Secure Region ECC enable"); 49669d5fd8fSJohnny Huang else 49766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 49866f2f8e5SJohnny Huang "Secure Region ECC disable"); 499442839bbSJohnny Huang } 500442839bbSJohnny Huang 50166f2f8e5SJohnny Huang k++; 50266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 50366f2f8e5SJohnny Huang conf_parse[k].bit = 5; 50466f2f8e5SJohnny Huang conf_parse[k].length = 1; 50566f2f8e5SJohnny Huang conf_parse[k].value = DISABLE_LOW_SEC_KEY(OTPCFG[0]); 50666f2f8e5SJohnny Huang if (DISABLE_LOW_SEC_KEY(OTPCFG_KEEP[0])) { 50766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 50866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 509442839bbSJohnny Huang } else { 51066f2f8e5SJohnny Huang if (DISABLE_LOW_SEC_KEY(OTPCFG[0])) 51166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 51266f2f8e5SJohnny Huang "Disable low security key"); 51369d5fd8fSJohnny Huang else 51466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 51566f2f8e5SJohnny Huang "Enable low security key"); 516442839bbSJohnny Huang } 517442839bbSJohnny Huang 51866f2f8e5SJohnny Huang k++; 51966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 52066f2f8e5SJohnny Huang conf_parse[k].bit = 6; 52166f2f8e5SJohnny Huang conf_parse[k].length = 1; 52266f2f8e5SJohnny Huang conf_parse[k].value = IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0]); 52366f2f8e5SJohnny Huang if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG_KEEP[0])) { 52466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 52566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 526442839bbSJohnny Huang } else { 52766f2f8e5SJohnny Huang if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0])) 52866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 52966f2f8e5SJohnny Huang "Ignore Secure Boot hardware strap"); 53069d5fd8fSJohnny Huang else 53166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 53266f2f8e5SJohnny Huang "Do not ignore Secure Boot hardware strap"); 533442839bbSJohnny Huang } 534442839bbSJohnny Huang 53566f2f8e5SJohnny Huang k++; 53666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 53766f2f8e5SJohnny Huang conf_parse[k].bit = 7; 53866f2f8e5SJohnny Huang conf_parse[k].length = 1; 53966f2f8e5SJohnny Huang conf_parse[k].value = SEC_BOOT_MDOES(OTPCFG[0]); 54066f2f8e5SJohnny Huang if (SEC_BOOT_MDOES(OTPCFG_KEEP[0])) { 54166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 54266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 543442839bbSJohnny Huang } else { 54466f2f8e5SJohnny Huang if (SEC_BOOT_MDOES(OTPCFG[0])) 54566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 54666f2f8e5SJohnny Huang "Secure Boot Mode: 1"); 547e1f9e54eSJohnny Huang else 54866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 54966f2f8e5SJohnny Huang "Secure Boot Mode: 2"); 550442839bbSJohnny Huang } 551442839bbSJohnny Huang 55266f2f8e5SJohnny Huang k++; 55366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 55466f2f8e5SJohnny Huang conf_parse[k].bit = 8; 55566f2f8e5SJohnny Huang conf_parse[k].length = 2; 55666f2f8e5SJohnny Huang conf_parse[k].value = OTP_BIT_CELL_MODES(OTPCFG[0]); 557442839bbSJohnny Huang if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0x3) { 55866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 55966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 56066f2f8e5SJohnny Huang } else if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0) { 56166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "OTP bit cell mode : "); 56266f2f8e5SJohnny Huang if (conf_parse[k].value == SINGLE_CELL_MODE) { 56366f2f8e5SJohnny Huang strcat(conf_parse[k].status, 56466f2f8e5SJohnny Huang "Single cell mode (recommended)"); 56566f2f8e5SJohnny Huang } else if (conf_parse[k].value == DIFFERENTIAL_MODE) { 56666f2f8e5SJohnny Huang strcat(conf_parse[k].status, 56766f2f8e5SJohnny Huang "Differnetial mode"); 56866f2f8e5SJohnny Huang } else if (conf_parse[k].value == DIFFERENTIAL_REDUDANT_MODE) { 56966f2f8e5SJohnny Huang strcat(conf_parse[k].status, 57066f2f8e5SJohnny Huang "Differential-redundant mode"); 571442839bbSJohnny Huang } else { 57266f2f8e5SJohnny Huang strcat(conf_parse[k].status, 57366f2f8e5SJohnny Huang "Value error"); 57469d5fd8fSJohnny Huang return -1; 57569d5fd8fSJohnny Huang } 57666f2f8e5SJohnny Huang } else { 57766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 57866f2f8e5SJohnny Huang return -1; 579442839bbSJohnny Huang } 58066f2f8e5SJohnny Huang 58166f2f8e5SJohnny Huang k++; 58266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 58366f2f8e5SJohnny Huang conf_parse[k].bit = 10; 58466f2f8e5SJohnny Huang conf_parse[k].length = 2; 58566f2f8e5SJohnny Huang conf_parse[k].value = CRYPTO_MODES(OTPCFG[0]); 586442839bbSJohnny Huang if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0x3) { 58766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 58866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 58966f2f8e5SJohnny Huang } else if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0) { 59066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "RSA mode : "); 59166f2f8e5SJohnny Huang if (conf_parse[k].value == CRYPTO_RSA1024) { 59266f2f8e5SJohnny Huang strcat(conf_parse[k].status, 59366f2f8e5SJohnny Huang "RSA1024"); 59466f2f8e5SJohnny Huang } else if (conf_parse[k].value == CRYPTO_RSA2048) { 59566f2f8e5SJohnny Huang strcat(conf_parse[k].status, 59666f2f8e5SJohnny Huang "RSA2048"); 59766f2f8e5SJohnny Huang } else if (conf_parse[k].value == CRYPTO_RSA3072) { 59866f2f8e5SJohnny Huang strcat(conf_parse[k].status, 59966f2f8e5SJohnny Huang "RSA3072"); 600442839bbSJohnny Huang } else { 60166f2f8e5SJohnny Huang strcat(conf_parse[k].status, 60266f2f8e5SJohnny Huang "RSA4096"); 60366f2f8e5SJohnny Huang } 60469d5fd8fSJohnny Huang } else { 60566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 60666f2f8e5SJohnny Huang return -1; 60769d5fd8fSJohnny Huang } 60866f2f8e5SJohnny Huang 60966f2f8e5SJohnny Huang k++; 61066f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 61166f2f8e5SJohnny Huang conf_parse[k].bit = 12; 61266f2f8e5SJohnny Huang conf_parse[k].length = 2; 61366f2f8e5SJohnny Huang conf_parse[k].value = HASH_MODES(OTPCFG[0]); 614442839bbSJohnny Huang if (HASH_MODES(OTPCFG_KEEP[0]) == 0x3) { 61566f2f8e5SJohnny Huang conf_parse[k].keep = 1; 61666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 61766f2f8e5SJohnny Huang } else if (HASH_MODES(OTPCFG_KEEP[0]) == 0) { 61866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "SHA mode : "); 61966f2f8e5SJohnny Huang if (conf_parse[k].value == HASH_SAH224) { 62066f2f8e5SJohnny Huang strcat(conf_parse[k].status, 62166f2f8e5SJohnny Huang "SHA224"); 62266f2f8e5SJohnny Huang } else if (conf_parse[k].value == HASH_SAH256) { 62366f2f8e5SJohnny Huang strcat(conf_parse[k].status, 62466f2f8e5SJohnny Huang "SHA256"); 62566f2f8e5SJohnny Huang } else if (conf_parse[k].value == HASH_SAH384) { 62666f2f8e5SJohnny Huang strcat(conf_parse[k].status, 62766f2f8e5SJohnny Huang "SHA384"); 628442839bbSJohnny Huang } else { 62966f2f8e5SJohnny Huang strcat(conf_parse[k].status, 63066f2f8e5SJohnny Huang "SHA512"); 63169d5fd8fSJohnny Huang } 63266f2f8e5SJohnny Huang } else { 63366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 63466f2f8e5SJohnny Huang return -1; 635442839bbSJohnny Huang } 63669d5fd8fSJohnny Huang 63766f2f8e5SJohnny Huang k++; 63866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 63966f2f8e5SJohnny Huang conf_parse[k].bit = 16; 64066f2f8e5SJohnny Huang conf_parse[k].length = 6; 64166f2f8e5SJohnny Huang conf_parse[k].value = SECREG_SIZE(OTPCFG[0]); 642442839bbSJohnny Huang if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0x3f) { 64366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 64466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 64566f2f8e5SJohnny Huang } else if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0) { 64666f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 64766f2f8e5SJohnny Huang "Secure Region size (DW): 0x%x", SECREG_SIZE(OTPCFG[0])); 648442839bbSJohnny Huang } else { 64966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 65066f2f8e5SJohnny Huang return -1; 651442839bbSJohnny Huang } 65269d5fd8fSJohnny Huang 65366f2f8e5SJohnny Huang k++; 65466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 65566f2f8e5SJohnny Huang conf_parse[k].bit = 22; 65666f2f8e5SJohnny Huang conf_parse[k].length = 1; 65766f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_SECREG(OTPCFG[0]); 65866f2f8e5SJohnny Huang if (WRITE_PROTECT_SECREG(OTPCFG_KEEP[0])) { 65966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 66066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 661442839bbSJohnny Huang } else { 66266f2f8e5SJohnny Huang if (WRITE_PROTECT_SECREG(OTPCFG[0])) 66366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 66466f2f8e5SJohnny Huang "Secure Region : Write Protect"); 66569d5fd8fSJohnny Huang else 66666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 66766f2f8e5SJohnny Huang "Secure Region : Writable"); 668442839bbSJohnny Huang } 669442839bbSJohnny Huang 67066f2f8e5SJohnny Huang k++; 67166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 67266f2f8e5SJohnny Huang conf_parse[k].bit = 23; 67366f2f8e5SJohnny Huang conf_parse[k].length = 1; 67466f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_USERREG(OTPCFG[0]); 67566f2f8e5SJohnny Huang if (WRITE_PROTECT_USERREG(OTPCFG_KEEP[0])) { 67666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 67766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 678442839bbSJohnny Huang } else { 67966f2f8e5SJohnny Huang if (WRITE_PROTECT_USERREG(OTPCFG[0])) 68066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 68166f2f8e5SJohnny Huang "User Region : Write Protect"); 68269d5fd8fSJohnny Huang else 68366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 68466f2f8e5SJohnny Huang "User Region : Writable"); 685442839bbSJohnny Huang } 686442839bbSJohnny Huang 68766f2f8e5SJohnny Huang k++; 68866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 68966f2f8e5SJohnny Huang conf_parse[k].bit = 24; 69066f2f8e5SJohnny Huang conf_parse[k].length = 1; 69166f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_CONFREG(OTPCFG[0]); 69266f2f8e5SJohnny Huang if (WRITE_PROTECT_CONFREG(OTPCFG_KEEP[0])) { 69366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 69466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 695442839bbSJohnny Huang } else { 69666f2f8e5SJohnny Huang if (WRITE_PROTECT_CONFREG(OTPCFG[0])) 69766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 69866f2f8e5SJohnny Huang "Configure Region : Write Protect"); 69969d5fd8fSJohnny Huang else 70066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 70166f2f8e5SJohnny Huang "Configure Region : Writable"); 702442839bbSJohnny Huang } 703442839bbSJohnny Huang 70466f2f8e5SJohnny Huang k++; 70566f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 70666f2f8e5SJohnny Huang conf_parse[k].bit = 25; 70766f2f8e5SJohnny Huang conf_parse[k].length = 1; 70866f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_STRAPREG(OTPCFG[0]); 70966f2f8e5SJohnny Huang if (WRITE_PROTECT_STRAPREG(OTPCFG_KEEP[0])) { 71066f2f8e5SJohnny Huang conf_parse[k].keep = 1; 71166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 712442839bbSJohnny Huang } else { 71366f2f8e5SJohnny Huang if (WRITE_PROTECT_STRAPREG(OTPCFG[0])) 71466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 71566f2f8e5SJohnny Huang "OTP strap Region : Write Protect"); 71669d5fd8fSJohnny Huang else 71766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 71866f2f8e5SJohnny Huang "OTP strap Region : Writable"); 719442839bbSJohnny Huang } 720442839bbSJohnny Huang 72166f2f8e5SJohnny Huang k++; 72266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 72366f2f8e5SJohnny Huang conf_parse[k].bit = 26; 72466f2f8e5SJohnny Huang conf_parse[k].length = 1; 72566f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_COPY_TO_SRAM(OTPCFG[0]); 72666f2f8e5SJohnny Huang if (ENABLE_COPY_TO_SRAM(OTPCFG_KEEP[0])) { 72766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 72866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 729442839bbSJohnny Huang } else { 73066f2f8e5SJohnny Huang if (ENABLE_COPY_TO_SRAM(OTPCFG[0])) 73166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 73266f2f8e5SJohnny Huang "Copy Boot Image to Internal SRAM"); 73369d5fd8fSJohnny Huang else 73466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 73566f2f8e5SJohnny Huang "Disable Copy Boot Image to Internal SRAM"); 736442839bbSJohnny Huang } 73766f2f8e5SJohnny Huang 73866f2f8e5SJohnny Huang k++; 73966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 74066f2f8e5SJohnny Huang conf_parse[k].bit = 27; 74166f2f8e5SJohnny Huang conf_parse[k].length = 1; 74266f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_IMAGE_ENC(OTPCFG[0]); 74366f2f8e5SJohnny Huang if (ENABLE_IMAGE_ENC(OTPCFG_KEEP[0])) { 74466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 74566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 746442839bbSJohnny Huang } else { 74766f2f8e5SJohnny Huang if (ENABLE_IMAGE_ENC(OTPCFG[0])) 74866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 74966f2f8e5SJohnny Huang "Enable image encryption"); 75069d5fd8fSJohnny Huang else 75166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 75266f2f8e5SJohnny Huang "Disable image encryption"); 753442839bbSJohnny Huang } 754442839bbSJohnny Huang 75566f2f8e5SJohnny Huang k++; 75666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 75766f2f8e5SJohnny Huang conf_parse[k].bit = 29; 75866f2f8e5SJohnny Huang conf_parse[k].length = 1; 75966f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_KEY_RETIRE(OTPCFG[0]); 76066f2f8e5SJohnny Huang if (WRITE_PROTECT_KEY_RETIRE(OTPCFG_KEEP[0])) { 76166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 76266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 763442839bbSJohnny Huang } else { 76466f2f8e5SJohnny Huang if (WRITE_PROTECT_KEY_RETIRE(OTPCFG[0])) 76566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 76666f2f8e5SJohnny Huang "OTP key retire Region : Write Protect"); 76769d5fd8fSJohnny Huang else 76866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 76966f2f8e5SJohnny Huang "OTP key retire Region : Writable"); 770442839bbSJohnny Huang } 771442839bbSJohnny Huang 77266f2f8e5SJohnny Huang k++; 77366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 77466f2f8e5SJohnny Huang conf_parse[k].bit = 30; 77566f2f8e5SJohnny Huang conf_parse[k].length = 1; 77666f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SIPROM_RED(OTPCFG[0]); 77766f2f8e5SJohnny Huang if (ENABLE_SIPROM_RED(OTPCFG_KEEP[0])) { 77866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 77966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 780442839bbSJohnny Huang } else { 78166f2f8e5SJohnny Huang if (ENABLE_SIPROM_RED(OTPCFG[0])) 78266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 78366f2f8e5SJohnny Huang "SIPROM RED_EN redundancy repair enable"); 78469d5fd8fSJohnny Huang else 78566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 78666f2f8e5SJohnny Huang "SIPROM RED_EN redundancy repair disable"); 787442839bbSJohnny Huang } 788442839bbSJohnny Huang 78966f2f8e5SJohnny Huang k++; 79066f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 79166f2f8e5SJohnny Huang conf_parse[k].bit = 31; 79266f2f8e5SJohnny Huang conf_parse[k].length = 1; 79366f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SIPROM_MLOCK(OTPCFG[0]); 79466f2f8e5SJohnny Huang if (ENABLE_SIPROM_MLOCK(OTPCFG_KEEP[0])) { 79566f2f8e5SJohnny Huang conf_parse[k].keep = 1; 79666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 797442839bbSJohnny Huang } else { 79866f2f8e5SJohnny Huang if (ENABLE_SIPROM_MLOCK(OTPCFG[0])) 79966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 80066f2f8e5SJohnny Huang "SIPROM Mlock memory lock enable"); 80169d5fd8fSJohnny Huang else 80266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 80366f2f8e5SJohnny Huang "SIPROM Mlock memory lock disable"); 804442839bbSJohnny Huang } 80569d5fd8fSJohnny Huang 80666f2f8e5SJohnny Huang k++; 80766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 2; 80866f2f8e5SJohnny Huang conf_parse[k].bit = 0; 80966f2f8e5SJohnny Huang conf_parse[k].length = 16; 81066f2f8e5SJohnny Huang conf_parse[k].value = VENDER_ID(OTPCFG[2]); 81166f2f8e5SJohnny Huang if (VENDER_ID(OTPCFG_KEEP[2]) == 0xffff) { 81266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 81366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 81466f2f8e5SJohnny Huang } else if (VENDER_ID(OTPCFG_KEEP[2]) == 0) { 81566f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 81666f2f8e5SJohnny Huang "Vender ID : 0x%x", VENDER_ID(OTPCFG[2])); 817442839bbSJohnny Huang } else { 81866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 81966f2f8e5SJohnny Huang return -1; 820442839bbSJohnny Huang } 82169d5fd8fSJohnny Huang 82266f2f8e5SJohnny Huang k++; 82366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 2; 82466f2f8e5SJohnny Huang conf_parse[k].bit = 16; 82566f2f8e5SJohnny Huang conf_parse[k].length = 16; 82666f2f8e5SJohnny Huang conf_parse[k].value = KEY_REVISION(OTPCFG[2]); 82766f2f8e5SJohnny Huang if (KEY_REVISION(OTPCFG_KEEP[2]) == 0xffff) { 82866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 82966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 83066f2f8e5SJohnny Huang } else if (KEY_REVISION(OTPCFG_KEEP[2]) == 0) { 83166f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 83266f2f8e5SJohnny Huang "Key Revision : 0x%x", KEY_REVISION(OTPCFG[2])); 833442839bbSJohnny Huang } else { 83466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 83566f2f8e5SJohnny Huang return -1; 83666f2f8e5SJohnny Huang } 83766f2f8e5SJohnny Huang 83866f2f8e5SJohnny Huang k++; 83966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 3; 84066f2f8e5SJohnny Huang conf_parse[k].bit = 0; 84166f2f8e5SJohnny Huang conf_parse[k].length = 16; 84266f2f8e5SJohnny Huang conf_parse[k].value = SEC_BOOT_HEADER_OFFSET(OTPCFG[3]); 84366f2f8e5SJohnny Huang if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0xffff) { 84466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 84566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 84666f2f8e5SJohnny Huang } else if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0) { 84766f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 84866f2f8e5SJohnny Huang "Secure boot header offset : 0x%x", 849e1f9e54eSJohnny Huang SEC_BOOT_HEADER_OFFSET(OTPCFG[3])); 85066f2f8e5SJohnny Huang } else { 85166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 85266f2f8e5SJohnny Huang return -1; 853442839bbSJohnny Huang } 85469d5fd8fSJohnny Huang 85566f2f8e5SJohnny Huang k++; 85666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 4; 85766f2f8e5SJohnny Huang conf_parse[k].bit = 0; 85866f2f8e5SJohnny Huang conf_parse[k].length = 8; 85966f2f8e5SJohnny Huang conf_parse[k].value = KEYS_VALID_BITS(OTPCFG[4]); 86066f2f8e5SJohnny Huang if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0xff) { 86166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 86266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 86366f2f8e5SJohnny Huang } else if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0) { 864e1f9e54eSJohnny Huang tmp = KEYS_VALID_BITS(OTPCFG[4]); 865e1f9e54eSJohnny Huang if (tmp != 0) { 86669d5fd8fSJohnny Huang for (i = 0; i < 7; i++) { 86769d5fd8fSJohnny Huang if (tmp == (1 << i)) { 868e1f9e54eSJohnny Huang pass = i + 1; 86969d5fd8fSJohnny Huang } 87069d5fd8fSJohnny Huang } 871e1f9e54eSJohnny Huang } else { 872e1f9e54eSJohnny Huang pass = 0; 873e1f9e54eSJohnny Huang } 87466f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 87566f2f8e5SJohnny Huang "Keys valid : %d", pass); 876442839bbSJohnny Huang } else { 87766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 87866f2f8e5SJohnny Huang return -1; 87966f2f8e5SJohnny Huang } 88066f2f8e5SJohnny Huang 88166f2f8e5SJohnny Huang k++; 88266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 4; 88366f2f8e5SJohnny Huang conf_parse[k].bit = 16; 88466f2f8e5SJohnny Huang conf_parse[k].length = 8; 88566f2f8e5SJohnny Huang conf_parse[k].value = KEYS_RETIRE_BITS(OTPCFG[4]); 88666f2f8e5SJohnny Huang if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0xff) { 88766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 88866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 88966f2f8e5SJohnny Huang } else if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0) { 890e1f9e54eSJohnny Huang tmp = KEYS_RETIRE_BITS(OTPCFG[4]); 891e1f9e54eSJohnny Huang if (tmp != 0) { 89269d5fd8fSJohnny Huang for (i = 0; i < 7; i++) { 89369d5fd8fSJohnny Huang if (tmp == (1 << i)) { 894e1f9e54eSJohnny Huang pass = i + 1; 89569d5fd8fSJohnny Huang } 89669d5fd8fSJohnny Huang } 897e1f9e54eSJohnny Huang } else { 898e1f9e54eSJohnny Huang pass = 0; 89969d5fd8fSJohnny Huang } 90066f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 90166f2f8e5SJohnny Huang "Keys Retire ID : %d", pass); 90266f2f8e5SJohnny Huang } else { 90366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 90466f2f8e5SJohnny Huang return -1; 905442839bbSJohnny Huang } 90666f2f8e5SJohnny Huang 90766f2f8e5SJohnny Huang k++; 90866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 5; 90966f2f8e5SJohnny Huang conf_parse[k].bit = 0; 91066f2f8e5SJohnny Huang conf_parse[k].length = 32; 91166f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[5]; 912442839bbSJohnny Huang if (OTPCFG_KEEP[5] == 0xFFFFFFFF) { 91366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 91466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 91566f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[5] == 0) { 91666f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 91766f2f8e5SJohnny Huang "User define data, random number low : 0x%x", OTPCFG[5]); 918442839bbSJohnny Huang } else { 91966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 92066f2f8e5SJohnny Huang return -1; 921442839bbSJohnny Huang } 92269d5fd8fSJohnny Huang 92366f2f8e5SJohnny Huang k++; 92466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 6; 92566f2f8e5SJohnny Huang conf_parse[k].bit = 0; 92666f2f8e5SJohnny Huang conf_parse[k].length = 32; 92766f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[6]; 928442839bbSJohnny Huang if (OTPCFG_KEEP[6] == 0xFFFFFFFF) { 92966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 93066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 93166f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[6] == 0) { 93266f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 93366f2f8e5SJohnny Huang "User define data, random number high : 0x%x", OTPCFG[6]); 934442839bbSJohnny Huang } else { 93566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 93666f2f8e5SJohnny Huang return -1; 937442839bbSJohnny Huang } 93869d5fd8fSJohnny Huang 93966f2f8e5SJohnny Huang k++; 94066f2f8e5SJohnny Huang conf_parse[k].dw_offset = 8; 94166f2f8e5SJohnny Huang conf_parse[k].bit = 0; 94266f2f8e5SJohnny Huang conf_parse[k].length = 32; 94366f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[8]; 944442839bbSJohnny Huang if (OTPCFG_KEEP[8] == 0xFFFFFFFF) { 94566f2f8e5SJohnny Huang conf_parse[k].keep = 1; 94666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 94766f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[8] == 0) { 94866f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 94966f2f8e5SJohnny Huang "Redundancy Repair : 0x%x", OTPCFG[8]); 950442839bbSJohnny Huang } else { 95166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 95266f2f8e5SJohnny Huang return -1; 953442839bbSJohnny Huang } 95469d5fd8fSJohnny Huang 95566f2f8e5SJohnny Huang k++; 95666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 10; 95766f2f8e5SJohnny Huang conf_parse[k].bit = 0; 95866f2f8e5SJohnny Huang conf_parse[k].length = 32; 95966f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[10]; 960442839bbSJohnny Huang if (OTPCFG_KEEP[10] == 0xFFFFFFFF) { 96166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 96266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 96366f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[10] == 0) { 96466f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 96566f2f8e5SJohnny Huang "Manifest ID low : 0x%x", OTPCFG[10]); 966442839bbSJohnny Huang } else { 96766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 96866f2f8e5SJohnny Huang return -1; 969442839bbSJohnny Huang } 97069d5fd8fSJohnny Huang 97166f2f8e5SJohnny Huang k++; 97266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 11; 97366f2f8e5SJohnny Huang conf_parse[k].bit = 0; 97466f2f8e5SJohnny Huang conf_parse[k].length = 32; 97566f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[11]; 976442839bbSJohnny Huang if (OTPCFG_KEEP[11] == 0xFFFFFFFF) { 97766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 97866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 97966f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[11] == 0) { 98066f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 98166f2f8e5SJohnny Huang "Manifest ID high : 0x%x", OTPCFG[11]); 982442839bbSJohnny Huang } else { 98366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 98466f2f8e5SJohnny Huang return -1; 985442839bbSJohnny Huang } 986442839bbSJohnny Huang 98766f2f8e5SJohnny Huang return k + 1; 98869d5fd8fSJohnny Huang 98969d5fd8fSJohnny Huang } 99069d5fd8fSJohnny Huang 991*76d13988SJohnny Huang static int otp_strap_parse(uint32_t *OTPSTRAP, 992*76d13988SJohnny Huang struct otpstrap_parse *strap_parse) 993*76d13988SJohnny Huang { 994*76d13988SJohnny Huang int k = 0; 995*76d13988SJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 996*76d13988SJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 997*76d13988SJohnny Huang 998*76d13988SJohnny Huang strap_parse[k].bit = 0; 999*76d13988SJohnny Huang strap_parse[k].length = 1; 1000*76d13988SJohnny Huang strap_parse[k].value = ENABLE_SECURE_BOOT(OTPSTRAP[0]); 1001*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_SECURE_BOOT(OTPSTRAP_PRO[0]); 1002*76d13988SJohnny Huang if (ENABLE_SECURE_BOOT(OTPSTRAP_KEEP[0])) { 1003*76d13988SJohnny Huang strap_parse[k].keep = 1; 1004*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1005*76d13988SJohnny Huang } else { 1006*76d13988SJohnny Huang if (ENABLE_SECURE_BOOT(OTPSTRAP[0])) 1007*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1008*76d13988SJohnny Huang "Enable secure boot"); 1009*76d13988SJohnny Huang else 1010*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1011*76d13988SJohnny Huang "Disable secure boot"); 1012*76d13988SJohnny Huang } 1013*76d13988SJohnny Huang 1014*76d13988SJohnny Huang k++; 1015*76d13988SJohnny Huang strap_parse[k].bit = 1; 1016*76d13988SJohnny Huang strap_parse[k].length = 1; 1017*76d13988SJohnny Huang strap_parse[k].value = BOOT_FROM_EMMC(OTPSTRAP[0]); 1018*76d13988SJohnny Huang strap_parse[k].protect = BOOT_FROM_EMMC(OTPSTRAP_PRO[0]); 1019*76d13988SJohnny Huang if (BOOT_FROM_EMMC(OTPSTRAP_KEEP[0])) { 1020*76d13988SJohnny Huang strap_parse[k].keep = 1; 1021*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1022*76d13988SJohnny Huang } else { 1023*76d13988SJohnny Huang if (BOOT_FROM_EMMC(OTPSTRAP[0])) 1024*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1025*76d13988SJohnny Huang "Enable boot from eMMC"); 1026*76d13988SJohnny Huang else 1027*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1028*76d13988SJohnny Huang "Disable boot from eMMC"); 1029*76d13988SJohnny Huang } 1030*76d13988SJohnny Huang 1031*76d13988SJohnny Huang k++; 1032*76d13988SJohnny Huang strap_parse[k].bit = 2; 1033*76d13988SJohnny Huang strap_parse[k].length = 1; 1034*76d13988SJohnny Huang strap_parse[k].value = BOOT_FROM_DEBUG_SPI(OTPSTRAP[0]); 1035*76d13988SJohnny Huang strap_parse[k].protect = BOOT_FROM_DEBUG_SPI(OTPSTRAP_PRO[0]); 1036*76d13988SJohnny Huang if (BOOT_FROM_DEBUG_SPI(OTPSTRAP_KEEP[0])) { 1037*76d13988SJohnny Huang strap_parse[k].keep = 1; 1038*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1039*76d13988SJohnny Huang } else { 1040*76d13988SJohnny Huang if (BOOT_FROM_DEBUG_SPI(OTPSTRAP[0])) 1041*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1042*76d13988SJohnny Huang "Enable Boot from debug SPI"); 1043*76d13988SJohnny Huang else 1044*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1045*76d13988SJohnny Huang "Disable Boot from debug SPI"); 1046*76d13988SJohnny Huang } 1047*76d13988SJohnny Huang 1048*76d13988SJohnny Huang k++; 1049*76d13988SJohnny Huang strap_parse[k].bit = 3; 1050*76d13988SJohnny Huang strap_parse[k].length = 1; 1051*76d13988SJohnny Huang strap_parse[k].value = DISABLE_ARM_CM3(OTPSTRAP[0]); 1052*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_ARM_CM3(OTPSTRAP_PRO[0]); 1053*76d13988SJohnny Huang if (DISABLE_ARM_CM3(OTPSTRAP_KEEP[0])) { 1054*76d13988SJohnny Huang strap_parse[k].keep = 1; 1055*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1056*76d13988SJohnny Huang } else { 1057*76d13988SJohnny Huang if (DISABLE_ARM_CM3(OTPSTRAP[0])) 1058*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1059*76d13988SJohnny Huang "Disable ARM CM3"); 1060*76d13988SJohnny Huang else 1061*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1062*76d13988SJohnny Huang "Enable ARM CM3"); 1063*76d13988SJohnny Huang } 1064*76d13988SJohnny Huang 1065*76d13988SJohnny Huang k++; 1066*76d13988SJohnny Huang strap_parse[k].bit = 4; 1067*76d13988SJohnny Huang strap_parse[k].length = 1; 1068*76d13988SJohnny Huang strap_parse[k].value = VGA_EXPANSION_ROM(OTPSTRAP[0]); 1069*76d13988SJohnny Huang strap_parse[k].protect = VGA_EXPANSION_ROM(OTPSTRAP_PRO[0]); 1070*76d13988SJohnny Huang if (VGA_EXPANSION_ROM(OTPSTRAP_KEEP[0])) { 1071*76d13988SJohnny Huang strap_parse[k].keep = 1; 1072*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1073*76d13988SJohnny Huang } else { 1074*76d13988SJohnny Huang if (VGA_EXPANSION_ROM(OTPSTRAP[0])) 1075*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1076*76d13988SJohnny Huang "Enable dedicated VGA BIOS ROM"); 1077*76d13988SJohnny Huang else 1078*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1079*76d13988SJohnny Huang "No VGA BISO ROM, VGA BIOS is merged in the system BIOS"); 1080*76d13988SJohnny Huang } 1081*76d13988SJohnny Huang 1082*76d13988SJohnny Huang k++; 1083*76d13988SJohnny Huang strap_parse[k].bit = 5; 1084*76d13988SJohnny Huang strap_parse[k].length = 1; 1085*76d13988SJohnny Huang strap_parse[k].value = MAC1_RMII_MODE(OTPSTRAP[0]); 1086*76d13988SJohnny Huang strap_parse[k].protect = MAC1_RMII_MODE(OTPSTRAP_PRO[0]); 1087*76d13988SJohnny Huang if (MAC1_RMII_MODE(OTPSTRAP_KEEP[0])) { 1088*76d13988SJohnny Huang strap_parse[k].keep = 1; 1089*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1090*76d13988SJohnny Huang } else { 1091*76d13988SJohnny Huang if (MAC1_RMII_MODE(OTPSTRAP[0])) 1092*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1093*76d13988SJohnny Huang "MAC 1 : RGMII"); 1094*76d13988SJohnny Huang else 1095*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1096*76d13988SJohnny Huang "MAC 1 : RMII/NCSI"); 1097*76d13988SJohnny Huang } 1098*76d13988SJohnny Huang 1099*76d13988SJohnny Huang k++; 1100*76d13988SJohnny Huang strap_parse[k].bit = 6; 1101*76d13988SJohnny Huang strap_parse[k].length = 1; 1102*76d13988SJohnny Huang strap_parse[k].value = MAC2_RMII_MODE(OTPSTRAP[0]); 1103*76d13988SJohnny Huang strap_parse[k].protect = MAC2_RMII_MODE(OTPSTRAP_PRO[0]); 1104*76d13988SJohnny Huang if (MAC2_RMII_MODE(OTPSTRAP_KEEP[0])) { 1105*76d13988SJohnny Huang strap_parse[k].keep = 1; 1106*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1107*76d13988SJohnny Huang } else { 1108*76d13988SJohnny Huang if (MAC2_RMII_MODE(OTPSTRAP[0])) 1109*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1110*76d13988SJohnny Huang "MAC 2 : RGMII"); 1111*76d13988SJohnny Huang else 1112*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1113*76d13988SJohnny Huang "MAC 2 : RMII/NCSI"); 1114*76d13988SJohnny Huang } 1115*76d13988SJohnny Huang 1116*76d13988SJohnny Huang k++; 1117*76d13988SJohnny Huang strap_parse[k].bit = 7; 1118*76d13988SJohnny Huang strap_parse[k].length = 3; 1119*76d13988SJohnny Huang strap_parse[k].value = CPU_FREQUENCY(OTPSTRAP[0]); 1120*76d13988SJohnny Huang strap_parse[k].protect = CPU_FREQUENCY(OTPSTRAP_PRO[0]); 1121*76d13988SJohnny Huang if (CPU_FREQUENCY(OTPSTRAP_KEEP[0]) == 0x7) { 1122*76d13988SJohnny Huang strap_parse[k].keep = 1; 1123*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1124*76d13988SJohnny Huang } else if (CPU_FREQUENCY(OTPSTRAP_KEEP[0]) == 0) { 1125*76d13988SJohnny Huang if (CPU_FREQUENCY(OTPSTRAP[0]) == 0) { 1126*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1127*76d13988SJohnny Huang "CPU Frequency : 1GHz"); 1128*76d13988SJohnny Huang } else if (CPU_FREQUENCY(OTPSTRAP[0]) == 1) { 1129*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1130*76d13988SJohnny Huang "CPU Frequency : 800MHz"); 1131*76d13988SJohnny Huang } else if (CPU_FREQUENCY(OTPSTRAP[0]) == 2) { 1132*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1133*76d13988SJohnny Huang "CPU Frequency : 1.2GHz"); 1134*76d13988SJohnny Huang } else if (CPU_FREQUENCY(OTPSTRAP[0]) == 3) { 1135*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1136*76d13988SJohnny Huang "CPU Frequency : 1.4GHz"); 1137*76d13988SJohnny Huang } else { 1138*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1139*76d13988SJohnny Huang "CPU Frequency : error"); 1140*76d13988SJohnny Huang return -1; 1141*76d13988SJohnny Huang } 1142*76d13988SJohnny Huang } else { 1143*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1144*76d13988SJohnny Huang return -1; 1145*76d13988SJohnny Huang } 1146*76d13988SJohnny Huang 1147*76d13988SJohnny Huang k++; 1148*76d13988SJohnny Huang strap_parse[k].bit = 10; 1149*76d13988SJohnny Huang strap_parse[k].length = 2; 1150*76d13988SJohnny Huang strap_parse[k].value = HCLK_RATIO(OTPSTRAP[0]); 1151*76d13988SJohnny Huang strap_parse[k].protect = HCLK_RATIO(OTPSTRAP_PRO[0]); 1152*76d13988SJohnny Huang if (HCLK_RATIO(OTPSTRAP_KEEP[0]) == 0x3) { 1153*76d13988SJohnny Huang strap_parse[k].keep = 1; 1154*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1155*76d13988SJohnny Huang } else if (HCLK_RATIO(OTPSTRAP_KEEP[0]) == 0) { 1156*76d13988SJohnny Huang if (HCLK_RATIO(OTPSTRAP[0]) == 0) { 1157*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1158*76d13988SJohnny Huang "HCLK ratio AXI:AHB = 2:1"); 1159*76d13988SJohnny Huang } else if (HCLK_RATIO(OTPSTRAP[0]) == 1) { 1160*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1161*76d13988SJohnny Huang "HCLK ratio AXI:AHB = 2:1"); 1162*76d13988SJohnny Huang } else if (HCLK_RATIO(OTPSTRAP[0]) == 2) { 1163*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1164*76d13988SJohnny Huang "HCLK ratio AXI:AHB = 3:1"); 1165*76d13988SJohnny Huang } else if (HCLK_RATIO(OTPSTRAP[0]) == 3) { 1166*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1167*76d13988SJohnny Huang "HCLK ratio AXI:AHB = 4:1"); 1168*76d13988SJohnny Huang } 1169*76d13988SJohnny Huang } else { 1170*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1171*76d13988SJohnny Huang return -1; 1172*76d13988SJohnny Huang } 1173*76d13988SJohnny Huang 1174*76d13988SJohnny Huang k++; 1175*76d13988SJohnny Huang strap_parse[k].bit = 12; 1176*76d13988SJohnny Huang strap_parse[k].length = 2; 1177*76d13988SJohnny Huang strap_parse[k].value = VGA_MEMORY_SIZE(OTPSTRAP[0]); 1178*76d13988SJohnny Huang strap_parse[k].protect = VGA_MEMORY_SIZE(OTPSTRAP_PRO[0]); 1179*76d13988SJohnny Huang if (VGA_MEMORY_SIZE(OTPSTRAP_KEEP[0]) == 0x3) { 1180*76d13988SJohnny Huang strap_parse[k].keep = 1; 1181*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1182*76d13988SJohnny Huang } else if (VGA_MEMORY_SIZE(OTPSTRAP_KEEP[0]) == 0) { 1183*76d13988SJohnny Huang if (VGA_MEMORY_SIZE(OTPSTRAP[0]) == 0) { 1184*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1185*76d13988SJohnny Huang "VGA memory size : 8MB"); 1186*76d13988SJohnny Huang } else if (VGA_MEMORY_SIZE(OTPSTRAP[0]) == 1) { 1187*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1188*76d13988SJohnny Huang "VGA memory size : 16MB"); 1189*76d13988SJohnny Huang } else if (VGA_MEMORY_SIZE(OTPSTRAP[0]) == 2) { 1190*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1191*76d13988SJohnny Huang "VGA memory size : 32MB"); 1192*76d13988SJohnny Huang } else if (VGA_MEMORY_SIZE(OTPSTRAP[0]) == 3) { 1193*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1194*76d13988SJohnny Huang "VGA memory size : 64MB"); 1195*76d13988SJohnny Huang } 1196*76d13988SJohnny Huang } else { 1197*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1198*76d13988SJohnny Huang return -1; 1199*76d13988SJohnny Huang } 1200*76d13988SJohnny Huang 1201*76d13988SJohnny Huang k++; 1202*76d13988SJohnny Huang strap_parse[k].bit = 17; 1203*76d13988SJohnny Huang strap_parse[k].length = 1; 1204*76d13988SJohnny Huang strap_parse[k].value = VGA_CLASS_CODE(OTPSTRAP[0]); 1205*76d13988SJohnny Huang strap_parse[k].protect = VGA_CLASS_CODE(OTPSTRAP_PRO[0]); 1206*76d13988SJohnny Huang if (VGA_CLASS_CODE(OTPSTRAP_KEEP[0])) { 1207*76d13988SJohnny Huang strap_parse[k].keep = 1; 1208*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1209*76d13988SJohnny Huang } else { 1210*76d13988SJohnny Huang if (VGA_CLASS_CODE(OTPSTRAP[0])) 1211*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1212*76d13988SJohnny Huang "VGA class code : Class Code for VGA device"); 1213*76d13988SJohnny Huang else 1214*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1215*76d13988SJohnny Huang "VGA class code : Class Code for video device"); 1216*76d13988SJohnny Huang } 1217*76d13988SJohnny Huang 1218*76d13988SJohnny Huang k++; 1219*76d13988SJohnny Huang strap_parse[k].bit = 18; 1220*76d13988SJohnny Huang strap_parse[k].length = 1; 1221*76d13988SJohnny Huang strap_parse[k].value = DISABLE_DEBUG0(OTPSTRAP[0]); 1222*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_DEBUG0(OTPSTRAP_PRO[0]); 1223*76d13988SJohnny Huang if (DISABLE_DEBUG0(OTPSTRAP_KEEP[0])) { 1224*76d13988SJohnny Huang strap_parse[k].keep = 1; 1225*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1226*76d13988SJohnny Huang } else { 1227*76d13988SJohnny Huang if (DISABLE_DEBUG0(OTPSTRAP[0])) 1228*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1229*76d13988SJohnny Huang "Disable debug interfaces 0"); 1230*76d13988SJohnny Huang else 1231*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1232*76d13988SJohnny Huang "Enable debug interfaces 0"); 1233*76d13988SJohnny Huang } 1234*76d13988SJohnny Huang 1235*76d13988SJohnny Huang k++; 1236*76d13988SJohnny Huang strap_parse[k].bit = 19; 1237*76d13988SJohnny Huang strap_parse[k].length = 1; 1238*76d13988SJohnny Huang strap_parse[k].value = BOOT_FROM_EMMC_SPEED_MDOE(OTPSTRAP[0]); 1239*76d13988SJohnny Huang strap_parse[k].protect = BOOT_FROM_EMMC_SPEED_MDOE(OTPSTRAP_PRO[0]); 1240*76d13988SJohnny Huang if (BOOT_FROM_EMMC_SPEED_MDOE(OTPSTRAP_KEEP[0])) { 1241*76d13988SJohnny Huang strap_parse[k].keep = 1; 1242*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1243*76d13988SJohnny Huang } else { 1244*76d13988SJohnny Huang if (BOOT_FROM_EMMC_SPEED_MDOE(OTPSTRAP[0])) 1245*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1246*76d13988SJohnny Huang "Boot from emmc mode : Normal eMMC speed"); 1247*76d13988SJohnny Huang else 1248*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1249*76d13988SJohnny Huang "Boot from emmc mode : High eMMC speed"); 1250*76d13988SJohnny Huang } 1251*76d13988SJohnny Huang 1252*76d13988SJohnny Huang k++; 1253*76d13988SJohnny Huang strap_parse[k].bit = 20; 1254*76d13988SJohnny Huang strap_parse[k].length = 1; 1255*76d13988SJohnny Huang strap_parse[k].value = DISABLE_PCIE_EHCI(OTPSTRAP[0]); 1256*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_PCIE_EHCI(OTPSTRAP_PRO[0]); 1257*76d13988SJohnny Huang if (DISABLE_PCIE_EHCI(OTPSTRAP_KEEP[0])) { 1258*76d13988SJohnny Huang strap_parse[k].keep = 1; 1259*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1260*76d13988SJohnny Huang } else { 1261*76d13988SJohnny Huang if (DISABLE_PCIE_EHCI(OTPSTRAP[0])) 1262*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1263*76d13988SJohnny Huang "Disable Pcie EHCI device"); 1264*76d13988SJohnny Huang else 1265*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1266*76d13988SJohnny Huang "Enable Pcie EHCI device"); 1267*76d13988SJohnny Huang } 1268*76d13988SJohnny Huang 1269*76d13988SJohnny Huang k++; 1270*76d13988SJohnny Huang strap_parse[k].bit = 21; 1271*76d13988SJohnny Huang strap_parse[k].length = 1; 1272*76d13988SJohnny Huang strap_parse[k].value = DISABLE_VGA_XDMA(OTPSTRAP[0]); 1273*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_VGA_XDMA(OTPSTRAP_PRO[0]); 1274*76d13988SJohnny Huang if (DISABLE_VGA_XDMA(OTPSTRAP_KEEP[0])) { 1275*76d13988SJohnny Huang strap_parse[k].keep = 1; 1276*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1277*76d13988SJohnny Huang } else { 1278*76d13988SJohnny Huang if (DISABLE_VGA_XDMA(OTPSTRAP[0])) 1279*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1280*76d13988SJohnny Huang "Disable VGA XDMA function"); 1281*76d13988SJohnny Huang else 1282*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1283*76d13988SJohnny Huang "Enable VGA XDMA function"); 1284*76d13988SJohnny Huang } 1285*76d13988SJohnny Huang 1286*76d13988SJohnny Huang k++; 1287*76d13988SJohnny Huang strap_parse[k].bit = 22; 1288*76d13988SJohnny Huang strap_parse[k].length = 1; 1289*76d13988SJohnny Huang strap_parse[k].value = DISABLE_DEDICATED_BMC_FUNCTION(OTPSTRAP[0]); 1290*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_DEDICATED_BMC_FUNCTION(OTPSTRAP_PRO[0]); 1291*76d13988SJohnny Huang if (DISABLE_DEDICATED_BMC_FUNCTION(OTPSTRAP_KEEP[0])) { 1292*76d13988SJohnny Huang strap_parse[k].keep = 1; 1293*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1294*76d13988SJohnny Huang } else { 1295*76d13988SJohnny Huang if (DISABLE_DEDICATED_BMC_FUNCTION(OTPSTRAP[0])) 1296*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1297*76d13988SJohnny Huang "Disable dedicated BMC functions for non-BMC application"); 1298*76d13988SJohnny Huang else 1299*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1300*76d13988SJohnny Huang "Normal BMC mode"); 1301*76d13988SJohnny Huang } 1302*76d13988SJohnny Huang 1303*76d13988SJohnny Huang k++; 1304*76d13988SJohnny Huang strap_parse[k].bit = 23; 1305*76d13988SJohnny Huang strap_parse[k].length = 1; 1306*76d13988SJohnny Huang strap_parse[k].value = DEDICATE_ROOT_COMPLEX_RELAX(OTPSTRAP[0]); 1307*76d13988SJohnny Huang strap_parse[k].protect = DEDICATE_ROOT_COMPLEX_RELAX(OTPSTRAP_PRO[0]); 1308*76d13988SJohnny Huang if (DEDICATE_ROOT_COMPLEX_RELAX(OTPSTRAP_KEEP[0])) { 1309*76d13988SJohnny Huang strap_parse[k].keep = 1; 1310*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1311*76d13988SJohnny Huang } else { 1312*76d13988SJohnny Huang if (DEDICATE_ROOT_COMPLEX_RELAX(OTPSTRAP[0])) 1313*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1314*76d13988SJohnny Huang "SSPRST# pin is for PCIE root complex dedicated reset pin"); 1315*76d13988SJohnny Huang else 1316*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1317*76d13988SJohnny Huang "SSPRST# pin is for secondary processor dedicated reset pin"); 1318*76d13988SJohnny Huang } 1319*76d13988SJohnny Huang 1320*76d13988SJohnny Huang k++; 1321*76d13988SJohnny Huang strap_parse[k].bit = 24; 1322*76d13988SJohnny Huang strap_parse[k].length = 1; 1323*76d13988SJohnny Huang strap_parse[k].value = SELECT_DRAM_TYPES(OTPSTRAP[0]); 1324*76d13988SJohnny Huang strap_parse[k].protect = SELECT_DRAM_TYPES(OTPSTRAP_PRO[0]); 1325*76d13988SJohnny Huang if (SELECT_DRAM_TYPES(OTPSTRAP_KEEP[0])) { 1326*76d13988SJohnny Huang strap_parse[k].keep = 1; 1327*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1328*76d13988SJohnny Huang } else { 1329*76d13988SJohnny Huang if (SELECT_DRAM_TYPES(OTPSTRAP[0])) 1330*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1331*76d13988SJohnny Huang "DRAM types : DDR4"); 1332*76d13988SJohnny Huang else 1333*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1334*76d13988SJohnny Huang "DRAM types : DDR3"); 1335*76d13988SJohnny Huang } 1336*76d13988SJohnny Huang 1337*76d13988SJohnny Huang k++; 1338*76d13988SJohnny Huang strap_parse[k].bit = 32; 1339*76d13988SJohnny Huang strap_parse[k].length = 1; 1340*76d13988SJohnny Huang strap_parse[k].value = MAC3_RMII_MODE(OTPSTRAP[1]); 1341*76d13988SJohnny Huang strap_parse[k].protect = MAC3_RMII_MODE(OTPSTRAP_PRO[1]); 1342*76d13988SJohnny Huang if (MAC3_RMII_MODE(OTPSTRAP_KEEP[1])) { 1343*76d13988SJohnny Huang strap_parse[k].keep = 1; 1344*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1345*76d13988SJohnny Huang } else { 1346*76d13988SJohnny Huang if (MAC3_RMII_MODE(OTPSTRAP[1])) 1347*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1348*76d13988SJohnny Huang "MAC 3 : RGMII"); 1349*76d13988SJohnny Huang else 1350*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1351*76d13988SJohnny Huang "MAC 3 : RMII/NCSI"); 1352*76d13988SJohnny Huang } 1353*76d13988SJohnny Huang 1354*76d13988SJohnny Huang k++; 1355*76d13988SJohnny Huang strap_parse[k].bit = 33; 1356*76d13988SJohnny Huang strap_parse[k].length = 1; 1357*76d13988SJohnny Huang strap_parse[k].value = MAC4_RMII_MODE(OTPSTRAP[1]); 1358*76d13988SJohnny Huang strap_parse[k].protect = MAC4_RMII_MODE(OTPSTRAP_PRO[1]); 1359*76d13988SJohnny Huang if (MAC4_RMII_MODE(OTPSTRAP_KEEP[1])) { 1360*76d13988SJohnny Huang strap_parse[k].keep = 1; 1361*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1362*76d13988SJohnny Huang } else { 1363*76d13988SJohnny Huang if (MAC4_RMII_MODE(OTPSTRAP[1])) 1364*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1365*76d13988SJohnny Huang "MAC 4 : RGMII"); 1366*76d13988SJohnny Huang else 1367*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1368*76d13988SJohnny Huang "MAC 4 : RMII/NCSI"); 1369*76d13988SJohnny Huang } 1370*76d13988SJohnny Huang 1371*76d13988SJohnny Huang k++; 1372*76d13988SJohnny Huang strap_parse[k].bit = 34; 1373*76d13988SJohnny Huang strap_parse[k].length = 1; 1374*76d13988SJohnny Huang strap_parse[k].value = SIO_CONF_ADDR(OTPSTRAP[1]); 1375*76d13988SJohnny Huang strap_parse[k].protect = SIO_CONF_ADDR(OTPSTRAP_PRO[1]); 1376*76d13988SJohnny Huang if (SIO_CONF_ADDR(OTPSTRAP_KEEP[1])) { 1377*76d13988SJohnny Huang strap_parse[k].keep = 1; 1378*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1379*76d13988SJohnny Huang } else { 1380*76d13988SJohnny Huang if (SIO_CONF_ADDR(OTPSTRAP[1])) 1381*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1382*76d13988SJohnny Huang "SuperIO configuration address : 0x4E"); 1383*76d13988SJohnny Huang else 1384*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1385*76d13988SJohnny Huang "SuperIO configuration address : 0x2E"); 1386*76d13988SJohnny Huang } 1387*76d13988SJohnny Huang 1388*76d13988SJohnny Huang k++; 1389*76d13988SJohnny Huang strap_parse[k].bit = 35; 1390*76d13988SJohnny Huang strap_parse[k].length = 1; 1391*76d13988SJohnny Huang strap_parse[k].value = DISABLE_SIO(OTPSTRAP[1]); 1392*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_SIO(OTPSTRAP_PRO[1]); 1393*76d13988SJohnny Huang if (DISABLE_SIO(OTPSTRAP_KEEP[1])) { 1394*76d13988SJohnny Huang strap_parse[k].keep = 1; 1395*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1396*76d13988SJohnny Huang } else { 1397*76d13988SJohnny Huang if (DISABLE_SIO(OTPSTRAP[1])) 1398*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1399*76d13988SJohnny Huang "Disable LPC to decode SuperIO"); 1400*76d13988SJohnny Huang else 1401*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1402*76d13988SJohnny Huang "Enable LPC to decode SuperIO"); 1403*76d13988SJohnny Huang } 1404*76d13988SJohnny Huang 1405*76d13988SJohnny Huang k++; 1406*76d13988SJohnny Huang strap_parse[k].bit = 36; 1407*76d13988SJohnny Huang strap_parse[k].length = 1; 1408*76d13988SJohnny Huang strap_parse[k].value = DISABLE_DEBUG1(OTPSTRAP[1]); 1409*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_DEBUG1(OTPSTRAP_PRO[1]); 1410*76d13988SJohnny Huang if (DISABLE_DEBUG1(OTPSTRAP_KEEP[1])) { 1411*76d13988SJohnny Huang strap_parse[k].keep = 1; 1412*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1413*76d13988SJohnny Huang } else { 1414*76d13988SJohnny Huang if (DISABLE_DEBUG1(OTPSTRAP[1])) 1415*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1416*76d13988SJohnny Huang "Disable debug interfaces 1"); 1417*76d13988SJohnny Huang else 1418*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1419*76d13988SJohnny Huang "Enable debug interfaces 1"); 1420*76d13988SJohnny Huang } 1421*76d13988SJohnny Huang 1422*76d13988SJohnny Huang k++; 1423*76d13988SJohnny Huang strap_parse[k].bit = 37; 1424*76d13988SJohnny Huang strap_parse[k].length = 1; 1425*76d13988SJohnny Huang strap_parse[k].value = ENABLE_ACPI(OTPSTRAP[1]); 1426*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_ACPI(OTPSTRAP_PRO[1]); 1427*76d13988SJohnny Huang if (ENABLE_ACPI(OTPSTRAP_KEEP[1])) { 1428*76d13988SJohnny Huang strap_parse[k].keep = 1; 1429*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1430*76d13988SJohnny Huang } else { 1431*76d13988SJohnny Huang if (ENABLE_ACPI(OTPSTRAP[1])) 1432*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1433*76d13988SJohnny Huang "Enable ACPI function"); 1434*76d13988SJohnny Huang else 1435*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1436*76d13988SJohnny Huang "Disable ACPI function"); 1437*76d13988SJohnny Huang } 1438*76d13988SJohnny Huang 1439*76d13988SJohnny Huang k++; 1440*76d13988SJohnny Huang strap_parse[k].bit = 38; 1441*76d13988SJohnny Huang strap_parse[k].length = 1; 1442*76d13988SJohnny Huang strap_parse[k].value = SELECT_LPC(OTPSTRAP[1]); 1443*76d13988SJohnny Huang strap_parse[k].protect = SELECT_LPC(OTPSTRAP_PRO[1]); 1444*76d13988SJohnny Huang if (SELECT_LPC(OTPSTRAP_KEEP[1])) { 1445*76d13988SJohnny Huang strap_parse[k].keep = 1; 1446*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1447*76d13988SJohnny Huang } else { 1448*76d13988SJohnny Huang if (SELECT_LPC(OTPSTRAP[1])) 1449*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1450*76d13988SJohnny Huang "Enable LPC mode"); 1451*76d13988SJohnny Huang else 1452*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1453*76d13988SJohnny Huang "Enable eSPI mode"); 1454*76d13988SJohnny Huang } 1455*76d13988SJohnny Huang 1456*76d13988SJohnny Huang k++; 1457*76d13988SJohnny Huang strap_parse[k].bit = 39; 1458*76d13988SJohnny Huang strap_parse[k].length = 1; 1459*76d13988SJohnny Huang strap_parse[k].value = ENABLE_SAFS(OTPSTRAP[1]); 1460*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_SAFS(OTPSTRAP_PRO[1]); 1461*76d13988SJohnny Huang if (ENABLE_SAFS(OTPSTRAP_KEEP[1])) { 1462*76d13988SJohnny Huang strap_parse[k].keep = 1; 1463*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1464*76d13988SJohnny Huang } else { 1465*76d13988SJohnny Huang if (ENABLE_SAFS(OTPSTRAP[1])) 1466*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1467*76d13988SJohnny Huang "Enable SAFS mode"); 1468*76d13988SJohnny Huang else 1469*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1470*76d13988SJohnny Huang "Enable SAFS mode"); 1471*76d13988SJohnny Huang } 1472*76d13988SJohnny Huang 1473*76d13988SJohnny Huang k++; 1474*76d13988SJohnny Huang strap_parse[k].bit = 42; 1475*76d13988SJohnny Huang strap_parse[k].length = 1; 1476*76d13988SJohnny Huang strap_parse[k].value = ENABLE_SPI_3B4B_AUTO(OTPSTRAP[1]); 1477*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_SPI_3B4B_AUTO(OTPSTRAP_PRO[1]); 1478*76d13988SJohnny Huang if (ENABLE_SPI_3B4B_AUTO(OTPSTRAP_KEEP[1])) { 1479*76d13988SJohnny Huang strap_parse[k].keep = 1; 1480*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1481*76d13988SJohnny Huang } else { 1482*76d13988SJohnny Huang if (ENABLE_SPI_3B4B_AUTO(OTPSTRAP[1])) 1483*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1484*76d13988SJohnny Huang "Enable boot SPI 3B/4B address mode auto detection"); 1485*76d13988SJohnny Huang else 1486*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1487*76d13988SJohnny Huang "Disable boot SPI 3B/4B address mode auto detection"); 1488*76d13988SJohnny Huang } 1489*76d13988SJohnny Huang 1490*76d13988SJohnny Huang k++; 1491*76d13988SJohnny Huang strap_parse[k].bit = 43; 1492*76d13988SJohnny Huang strap_parse[k].length = 1; 1493*76d13988SJohnny Huang strap_parse[k].value = ENABLE_BOOT_SPI_ABR(OTPSTRAP[1]); 1494*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_BOOT_SPI_ABR(OTPSTRAP_PRO[1]); 1495*76d13988SJohnny Huang if (ENABLE_BOOT_SPI_ABR(OTPSTRAP_KEEP[1])) { 1496*76d13988SJohnny Huang strap_parse[k].keep = 1; 1497*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1498*76d13988SJohnny Huang } else { 1499*76d13988SJohnny Huang if (ENABLE_BOOT_SPI_ABR(OTPSTRAP[1])) 1500*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1501*76d13988SJohnny Huang "Enable boot SPI ABR"); 1502*76d13988SJohnny Huang else 1503*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1504*76d13988SJohnny Huang "Disable boot SPI ABR"); 1505*76d13988SJohnny Huang } 1506*76d13988SJohnny Huang 1507*76d13988SJohnny Huang k++; 1508*76d13988SJohnny Huang strap_parse[k].bit = 44; 1509*76d13988SJohnny Huang strap_parse[k].length = 1; 1510*76d13988SJohnny Huang strap_parse[k].value = BOOT_SPI_ABR_MODE(OTPSTRAP[1]); 1511*76d13988SJohnny Huang strap_parse[k].protect = BOOT_SPI_ABR_MODE(OTPSTRAP_PRO[1]); 1512*76d13988SJohnny Huang if (BOOT_SPI_ABR_MODE(OTPSTRAP_KEEP[1])) { 1513*76d13988SJohnny Huang strap_parse[k].keep = 1; 1514*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1515*76d13988SJohnny Huang } else { 1516*76d13988SJohnny Huang if (BOOT_SPI_ABR_MODE(OTPSTRAP[1])) 1517*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1518*76d13988SJohnny Huang "Boot SPI ABR mode : single SPI flash"); 1519*76d13988SJohnny Huang else 1520*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1521*76d13988SJohnny Huang "Boot SPI ABR mode : dual SPI flash"); 1522*76d13988SJohnny Huang } 1523*76d13988SJohnny Huang 1524*76d13988SJohnny Huang k++; 1525*76d13988SJohnny Huang strap_parse[k].bit = 45; 1526*76d13988SJohnny Huang strap_parse[k].length = 3; 1527*76d13988SJohnny Huang strap_parse[k].value = BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]); 1528*76d13988SJohnny Huang strap_parse[k].protect = BOOT_SPI_FLASH_SIZE(OTPSTRAP_PRO[1]); 1529*76d13988SJohnny Huang if (BOOT_SPI_FLASH_SIZE(OTPSTRAP_KEEP[1]) == 0x7) { 1530*76d13988SJohnny Huang strap_parse[k].keep = 1; 1531*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1532*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP_KEEP[1]) == 0) { 1533*76d13988SJohnny Huang if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 0) { 1534*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1535*76d13988SJohnny Huang "Boot SPI flash size : no define size"); 1536*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 1) { 1537*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1538*76d13988SJohnny Huang "Boot SPI flash size : 2MB"); 1539*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 2) { 1540*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1541*76d13988SJohnny Huang "Boot SPI flash size : 4MB"); 1542*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 3) { 1543*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1544*76d13988SJohnny Huang "Boot SPI flash size : 8MB"); 1545*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 4) { 1546*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1547*76d13988SJohnny Huang "Boot SPI flash size : 16MB"); 1548*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 5) { 1549*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1550*76d13988SJohnny Huang "Boot SPI flash size : 32MB"); 1551*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 6) { 1552*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1553*76d13988SJohnny Huang "Boot SPI flash size : 64MB"); 1554*76d13988SJohnny Huang } else if (BOOT_SPI_FLASH_SIZE(OTPSTRAP[1]) == 7) { 1555*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1556*76d13988SJohnny Huang "Boot SPI flash size : 128MB"); 1557*76d13988SJohnny Huang } 1558*76d13988SJohnny Huang } else { 1559*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1560*76d13988SJohnny Huang return -1; 1561*76d13988SJohnny Huang } 1562*76d13988SJohnny Huang 1563*76d13988SJohnny Huang k++; 1564*76d13988SJohnny Huang strap_parse[k].bit = 48; 1565*76d13988SJohnny Huang strap_parse[k].length = 1; 1566*76d13988SJohnny Huang strap_parse[k].value = ENABLE_HOST_SPI_ABR(OTPSTRAP[1]); 1567*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_HOST_SPI_ABR(OTPSTRAP_PRO[1]); 1568*76d13988SJohnny Huang if (ENABLE_HOST_SPI_ABR(OTPSTRAP_KEEP[1])) { 1569*76d13988SJohnny Huang strap_parse[k].keep = 1; 1570*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1571*76d13988SJohnny Huang } else { 1572*76d13988SJohnny Huang if (ENABLE_HOST_SPI_ABR(OTPSTRAP[1])) 1573*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1574*76d13988SJohnny Huang "Enable host SPI ABR"); 1575*76d13988SJohnny Huang else 1576*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1577*76d13988SJohnny Huang "Disable host SPI ABR"); 1578*76d13988SJohnny Huang } 1579*76d13988SJohnny Huang 1580*76d13988SJohnny Huang k++; 1581*76d13988SJohnny Huang strap_parse[k].bit = 49; 1582*76d13988SJohnny Huang strap_parse[k].length = 1; 1583*76d13988SJohnny Huang strap_parse[k].value = EBABLE_HOST_SPI_ABR_SEL_PIN(OTPSTRAP[1]); 1584*76d13988SJohnny Huang strap_parse[k].protect = EBABLE_HOST_SPI_ABR_SEL_PIN(OTPSTRAP_PRO[1]); 1585*76d13988SJohnny Huang if (EBABLE_HOST_SPI_ABR_SEL_PIN(OTPSTRAP_KEEP[1])) { 1586*76d13988SJohnny Huang strap_parse[k].keep = 1; 1587*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1588*76d13988SJohnny Huang } else { 1589*76d13988SJohnny Huang if (EBABLE_HOST_SPI_ABR_SEL_PIN(OTPSTRAP[1])) 1590*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1591*76d13988SJohnny Huang "Enable host SPI ABR mode select pin"); 1592*76d13988SJohnny Huang else 1593*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1594*76d13988SJohnny Huang "Disable host SPI ABR mode select pin"); 1595*76d13988SJohnny Huang } 1596*76d13988SJohnny Huang 1597*76d13988SJohnny Huang k++; 1598*76d13988SJohnny Huang strap_parse[k].bit = 50; 1599*76d13988SJohnny Huang strap_parse[k].length = 1; 1600*76d13988SJohnny Huang strap_parse[k].value = HOST_SPI_ABR_MODE(OTPSTRAP[1]); 1601*76d13988SJohnny Huang strap_parse[k].protect = HOST_SPI_ABR_MODE(OTPSTRAP_PRO[1]); 1602*76d13988SJohnny Huang if (HOST_SPI_ABR_MODE(OTPSTRAP_KEEP[1])) { 1603*76d13988SJohnny Huang strap_parse[k].keep = 1; 1604*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1605*76d13988SJohnny Huang } else { 1606*76d13988SJohnny Huang if (HOST_SPI_ABR_MODE(OTPSTRAP[1])) 1607*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1608*76d13988SJohnny Huang "Host SPI ABR mode : single SPI flash"); 1609*76d13988SJohnny Huang else 1610*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1611*76d13988SJohnny Huang "Host SPI ABR mode : dual SPI flash"); 1612*76d13988SJohnny Huang } 1613*76d13988SJohnny Huang 1614*76d13988SJohnny Huang k++; 1615*76d13988SJohnny Huang strap_parse[k].bit = 51; 1616*76d13988SJohnny Huang strap_parse[k].length = 3; 1617*76d13988SJohnny Huang strap_parse[k].value = HOST_SPI_FLASH_SIZE(OTPSTRAP[1]); 1618*76d13988SJohnny Huang strap_parse[k].protect = HOST_SPI_FLASH_SIZE(OTPSTRAP_PRO[1]); 1619*76d13988SJohnny Huang if (HOST_SPI_FLASH_SIZE(OTPSTRAP_KEEP[1]) == 0x7) { 1620*76d13988SJohnny Huang strap_parse[k].keep = 1; 1621*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1622*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP_KEEP[1]) == 0) { 1623*76d13988SJohnny Huang if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 0) { 1624*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1625*76d13988SJohnny Huang "Host SPI flash size : no define size"); 1626*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 1) { 1627*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1628*76d13988SJohnny Huang "Host SPI flash size : 2MB"); 1629*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 2) { 1630*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1631*76d13988SJohnny Huang "Host SPI flash size : 4MB"); 1632*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 3) { 1633*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1634*76d13988SJohnny Huang "Host SPI flash size : 8MB"); 1635*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 4) { 1636*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1637*76d13988SJohnny Huang "Host SPI flash size : 16MB"); 1638*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 5) { 1639*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1640*76d13988SJohnny Huang "Host SPI flash size : 32MB"); 1641*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 6) { 1642*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1643*76d13988SJohnny Huang "Host SPI flash size : 64MB"); 1644*76d13988SJohnny Huang } else if (HOST_SPI_FLASH_SIZE(OTPSTRAP[1]) == 7) { 1645*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1646*76d13988SJohnny Huang "Host SPI flash size : 128MB"); 1647*76d13988SJohnny Huang } 1648*76d13988SJohnny Huang } else { 1649*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1650*76d13988SJohnny Huang return -1; 1651*76d13988SJohnny Huang } 1652*76d13988SJohnny Huang 1653*76d13988SJohnny Huang k++; 1654*76d13988SJohnny Huang strap_parse[k].bit = 54; 1655*76d13988SJohnny Huang strap_parse[k].length = 1; 1656*76d13988SJohnny Huang strap_parse[k].value = ENABLE_BOOT_SPI_AUX_CONTROL_PIN(OTPSTRAP[1]); 1657*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_BOOT_SPI_AUX_CONTROL_PIN(OTPSTRAP_PRO[1]); 1658*76d13988SJohnny Huang if (ENABLE_BOOT_SPI_AUX_CONTROL_PIN(OTPSTRAP_KEEP[1])) { 1659*76d13988SJohnny Huang strap_parse[k].keep = 1; 1660*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1661*76d13988SJohnny Huang } else { 1662*76d13988SJohnny Huang if (ENABLE_BOOT_SPI_AUX_CONTROL_PIN(OTPSTRAP[1])) 1663*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1664*76d13988SJohnny Huang "Enable boot SPI auxiliary control pins"); 1665*76d13988SJohnny Huang else 1666*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1667*76d13988SJohnny Huang "Disable boot SPI auxiliary control pins"); 1668*76d13988SJohnny Huang } 1669*76d13988SJohnny Huang 1670*76d13988SJohnny Huang k++; 1671*76d13988SJohnny Huang strap_parse[k].bit = 55; 1672*76d13988SJohnny Huang strap_parse[k].length = 2; 1673*76d13988SJohnny Huang strap_parse[k].value = BOOT_SPI_CRTM_SIZE(OTPSTRAP[1]); 1674*76d13988SJohnny Huang strap_parse[k].protect = BOOT_SPI_CRTM_SIZE(OTPSTRAP_PRO[1]); 1675*76d13988SJohnny Huang if (BOOT_SPI_CRTM_SIZE(OTPSTRAP_KEEP[0]) == 0x3) { 1676*76d13988SJohnny Huang strap_parse[k].keep = 1; 1677*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1678*76d13988SJohnny Huang } else if (BOOT_SPI_CRTM_SIZE(OTPSTRAP_KEEP[0]) == 0) { 1679*76d13988SJohnny Huang if (BOOT_SPI_CRTM_SIZE(OTPSTRAP[0]) == 0) { 1680*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1681*76d13988SJohnny Huang "Boot SPI CRTM size : disable CRTM"); 1682*76d13988SJohnny Huang } else if (BOOT_SPI_CRTM_SIZE(OTPSTRAP[0]) == 1) { 1683*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1684*76d13988SJohnny Huang "Boot SPI CRTM size : 256KB"); 1685*76d13988SJohnny Huang } else if (BOOT_SPI_CRTM_SIZE(OTPSTRAP[0]) == 2) { 1686*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1687*76d13988SJohnny Huang "Boot SPI CRTM size : 512KB"); 1688*76d13988SJohnny Huang } else if (BOOT_SPI_CRTM_SIZE(OTPSTRAP[0]) == 3) { 1689*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1690*76d13988SJohnny Huang "Boot SPI CRTM size : 1MB"); 1691*76d13988SJohnny Huang } 1692*76d13988SJohnny Huang } else { 1693*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1694*76d13988SJohnny Huang return -1; 1695*76d13988SJohnny Huang } 1696*76d13988SJohnny Huang 1697*76d13988SJohnny Huang k++; 1698*76d13988SJohnny Huang strap_parse[k].bit = 57; 1699*76d13988SJohnny Huang strap_parse[k].length = 2; 1700*76d13988SJohnny Huang strap_parse[k].value = HOST_SPI_CRTM_SIZE(OTPSTRAP[1]); 1701*76d13988SJohnny Huang strap_parse[k].protect = HOST_SPI_CRTM_SIZE(OTPSTRAP_PRO[1]); 1702*76d13988SJohnny Huang if (HOST_SPI_CRTM_SIZE(OTPSTRAP_KEEP[0]) == 0x3) { 1703*76d13988SJohnny Huang strap_parse[k].keep = 1; 1704*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1705*76d13988SJohnny Huang } else if (HOST_SPI_CRTM_SIZE(OTPSTRAP_KEEP[0]) == 0) { 1706*76d13988SJohnny Huang if (HOST_SPI_CRTM_SIZE(OTPSTRAP[0]) == 0) { 1707*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1708*76d13988SJohnny Huang "Host SPI CRTM size : disable CRTM"); 1709*76d13988SJohnny Huang } else if (HOST_SPI_CRTM_SIZE(OTPSTRAP[0]) == 1) { 1710*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1711*76d13988SJohnny Huang "Host SPI CRTM size : 256KB"); 1712*76d13988SJohnny Huang } else if (HOST_SPI_CRTM_SIZE(OTPSTRAP[0]) == 2) { 1713*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1714*76d13988SJohnny Huang "Host SPI CRTM size : 512KB"); 1715*76d13988SJohnny Huang } else if (HOST_SPI_CRTM_SIZE(OTPSTRAP[0]) == 3) { 1716*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1717*76d13988SJohnny Huang "Host SPI CRTM size : 1MB"); 1718*76d13988SJohnny Huang } 1719*76d13988SJohnny Huang } else { 1720*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Keep mask error!"); 1721*76d13988SJohnny Huang return -1; 1722*76d13988SJohnny Huang } 1723*76d13988SJohnny Huang 1724*76d13988SJohnny Huang k++; 1725*76d13988SJohnny Huang strap_parse[k].bit = 59; 1726*76d13988SJohnny Huang strap_parse[k].length = 1; 1727*76d13988SJohnny Huang strap_parse[k].value = ENABLE_HOST_SPI_AUX_CONTROL_PIN(OTPSTRAP[1]); 1728*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_HOST_SPI_AUX_CONTROL_PIN(OTPSTRAP_PRO[1]); 1729*76d13988SJohnny Huang if (ENABLE_HOST_SPI_AUX_CONTROL_PIN(OTPSTRAP_KEEP[1])) { 1730*76d13988SJohnny Huang strap_parse[k].keep = 1; 1731*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1732*76d13988SJohnny Huang } else { 1733*76d13988SJohnny Huang if (ENABLE_HOST_SPI_AUX_CONTROL_PIN(OTPSTRAP[1])) 1734*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1735*76d13988SJohnny Huang "Enable host SPI auxiliary control pins"); 1736*76d13988SJohnny Huang else 1737*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1738*76d13988SJohnny Huang "Disable host SPI auxiliary control pins"); 1739*76d13988SJohnny Huang } 1740*76d13988SJohnny Huang 1741*76d13988SJohnny Huang k++; 1742*76d13988SJohnny Huang strap_parse[k].bit = 60; 1743*76d13988SJohnny Huang strap_parse[k].length = 1; 1744*76d13988SJohnny Huang strap_parse[k].value = ENABLE_GPIO_PASS_THROUGH(OTPSTRAP[1]); 1745*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_GPIO_PASS_THROUGH(OTPSTRAP_PRO[1]); 1746*76d13988SJohnny Huang if (ENABLE_GPIO_PASS_THROUGH(OTPSTRAP_KEEP[1])) { 1747*76d13988SJohnny Huang strap_parse[k].keep = 1; 1748*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1749*76d13988SJohnny Huang } else { 1750*76d13988SJohnny Huang if (ENABLE_GPIO_PASS_THROUGH(OTPSTRAP[1])) 1751*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1752*76d13988SJohnny Huang "Enable GPIO pass through"); 1753*76d13988SJohnny Huang else 1754*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1755*76d13988SJohnny Huang "Disable GPIO pass through"); 1756*76d13988SJohnny Huang } 1757*76d13988SJohnny Huang 1758*76d13988SJohnny Huang k++; 1759*76d13988SJohnny Huang strap_parse[k].bit = 61; 1760*76d13988SJohnny Huang strap_parse[k].length = 1; 1761*76d13988SJohnny Huang strap_parse[k].value = DISABLE_LOW_SECURITY_KEY(OTPSTRAP[1]); 1762*76d13988SJohnny Huang strap_parse[k].protect = DISABLE_LOW_SECURITY_KEY(OTPSTRAP_PRO[1]); 1763*76d13988SJohnny Huang if (DISABLE_LOW_SECURITY_KEY(OTPSTRAP_KEEP[1])) { 1764*76d13988SJohnny Huang strap_parse[k].keep = 1; 1765*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1766*76d13988SJohnny Huang } else { 1767*76d13988SJohnny Huang if (DISABLE_LOW_SECURITY_KEY(OTPSTRAP[1])) 1768*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1769*76d13988SJohnny Huang "Disable low security secure boot key"); 1770*76d13988SJohnny Huang else 1771*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1772*76d13988SJohnny Huang "Enable low security secure boot key"); 1773*76d13988SJohnny Huang } 1774*76d13988SJohnny Huang 1775*76d13988SJohnny Huang k++; 1776*76d13988SJohnny Huang strap_parse[k].bit = 62; 1777*76d13988SJohnny Huang strap_parse[k].length = 1; 1778*76d13988SJohnny Huang strap_parse[k].value = ENABLE_DEDICATE_GPIO_STRAP(OTPSTRAP[1]); 1779*76d13988SJohnny Huang strap_parse[k].protect = ENABLE_DEDICATE_GPIO_STRAP(OTPSTRAP_PRO[1]); 1780*76d13988SJohnny Huang if (ENABLE_DEDICATE_GPIO_STRAP(OTPSTRAP_KEEP[1])) { 1781*76d13988SJohnny Huang strap_parse[k].keep = 1; 1782*76d13988SJohnny Huang strcpy(strap_parse[k].status, "Skip"); 1783*76d13988SJohnny Huang } else { 1784*76d13988SJohnny Huang if (ENABLE_DEDICATE_GPIO_STRAP(OTPSTRAP[1])) 1785*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1786*76d13988SJohnny Huang "Enable dedicate GPIO strap pins"); 1787*76d13988SJohnny Huang else 1788*76d13988SJohnny Huang strcpy(strap_parse[k].status, 1789*76d13988SJohnny Huang "Disable dedicate GPIO strap pins"); 1790*76d13988SJohnny Huang } 1791*76d13988SJohnny Huang 1792*76d13988SJohnny Huang return k + 1; 1793*76d13988SJohnny Huang } 179466f2f8e5SJohnny Huang 179566f2f8e5SJohnny Huang static int otp_print_conf_info(uint32_t *OTPCFG) 179666f2f8e5SJohnny Huang { 179766f2f8e5SJohnny Huang struct otpconf_parse conf_parse[60]; 179866f2f8e5SJohnny Huang int length; 179966f2f8e5SJohnny Huang int i; 180066f2f8e5SJohnny Huang 180166f2f8e5SJohnny Huang length = otp_conf_parse(OTPCFG, conf_parse); 180266f2f8e5SJohnny Huang 180366f2f8e5SJohnny Huang if (length <= 0) 180466f2f8e5SJohnny Huang return OTP_FAILURE; 180566f2f8e5SJohnny Huang 180666f2f8e5SJohnny Huang printf("DW BIT Value Status\n"); 180766f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 180866f2f8e5SJohnny Huang for (i = 0; i < length; i++) { 180966f2f8e5SJohnny Huang printf("%-4d", conf_parse[i].dw_offset); 181066f2f8e5SJohnny Huang if (conf_parse[i].length == 1) { 181166f2f8e5SJohnny Huang printf("%-8d", conf_parse[i].bit); 181266f2f8e5SJohnny Huang } else { 181366f2f8e5SJohnny Huang printf("%-2d:%-5d", 181466f2f8e5SJohnny Huang conf_parse[i].bit + conf_parse[i].length - 1, 181566f2f8e5SJohnny Huang conf_parse[i].bit); 181666f2f8e5SJohnny Huang } 181766f2f8e5SJohnny Huang printf("0x%-10x", conf_parse[i].value); 181866f2f8e5SJohnny Huang printf("%s\n", conf_parse[i].status); 181966f2f8e5SJohnny Huang } 182066f2f8e5SJohnny Huang return OTP_SUCCESS; 182166f2f8e5SJohnny Huang } 182266f2f8e5SJohnny Huang 182366f2f8e5SJohnny Huang static void otp_info_config(void) 182466f2f8e5SJohnny Huang { 182566f2f8e5SJohnny Huang uint32_t OTPCFG[24]; 182666f2f8e5SJohnny Huang int i; 182766f2f8e5SJohnny Huang 182866f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 182966f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 183066f2f8e5SJohnny Huang 183166f2f8e5SJohnny Huang for (i = 12; i < 24; i++) 183266f2f8e5SJohnny Huang OTPCFG[i] = 0; 183366f2f8e5SJohnny Huang 183466f2f8e5SJohnny Huang otp_print_conf_info(OTPCFG); 183566f2f8e5SJohnny Huang } 183666f2f8e5SJohnny Huang 1837*76d13988SJohnny Huang static int otp_print_strap_info(uint32_t *OTPSTRAP) 1838*76d13988SJohnny Huang { 1839*76d13988SJohnny Huang struct otpstrap_parse strap_parse[60]; 1840*76d13988SJohnny Huang int length; 1841*76d13988SJohnny Huang int i; 1842*76d13988SJohnny Huang 1843*76d13988SJohnny Huang length = otp_strap_parse(OTPSTRAP, strap_parse); 1844*76d13988SJohnny Huang 1845*76d13988SJohnny Huang if (length <= 0) 1846*76d13988SJohnny Huang return OTP_FAILURE; 1847*76d13988SJohnny Huang 1848*76d13988SJohnny Huang printf("BIT Value Protect Status\n"); 1849*76d13988SJohnny Huang printf("__________________________________________________________________________________________\n"); 1850*76d13988SJohnny Huang for (i = 0; i < length; i++) { 1851*76d13988SJohnny Huang if (strap_parse[i].length == 1) { 1852*76d13988SJohnny Huang printf("%-8d", strap_parse[i].bit); 1853*76d13988SJohnny Huang } else { 1854*76d13988SJohnny Huang printf("%-2d:%-5d", 1855*76d13988SJohnny Huang strap_parse[i].bit + strap_parse[i].length - 1, 1856*76d13988SJohnny Huang strap_parse[i].bit); 1857*76d13988SJohnny Huang } 1858*76d13988SJohnny Huang printf("0x%-10x", strap_parse[i].value); 1859*76d13988SJohnny Huang printf("0x%-10x", strap_parse[i].protect); 1860*76d13988SJohnny Huang printf("%s\n", strap_parse[i].status); 1861*76d13988SJohnny Huang } 1862*76d13988SJohnny Huang return OTP_SUCCESS; 1863*76d13988SJohnny Huang } 1864*76d13988SJohnny Huang 1865*76d13988SJohnny Huang static void otp_info_strap(void) 1866*76d13988SJohnny Huang { 1867*76d13988SJohnny Huang struct otpstrap_status strap_status[64]; 1868*76d13988SJohnny Huang uint32_t OTPSTRAP[6]; 1869*76d13988SJohnny Huang int i; 1870*76d13988SJohnny Huang 1871*76d13988SJohnny Huang 1872*76d13988SJohnny Huang otp_strp_status(strap_status); 1873*76d13988SJohnny Huang 1874*76d13988SJohnny Huang for (i = 0; i < 6; i++) 1875*76d13988SJohnny Huang OTPSTRAP[i] = 0; 1876*76d13988SJohnny Huang for (i = 0; i < 32; i++) { 1877*76d13988SJohnny Huang OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i; 1878*76d13988SJohnny Huang OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i; 1879*76d13988SJohnny Huang } 1880*76d13988SJohnny Huang for (i = 0; i < 32; i++) { 1881*76d13988SJohnny Huang OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i; 1882*76d13988SJohnny Huang OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i; 1883*76d13988SJohnny Huang } 1884*76d13988SJohnny Huang 1885*76d13988SJohnny Huang otp_print_strap_info(OTPSTRAP); 1886*76d13988SJohnny Huang } 1887*76d13988SJohnny Huang 188869d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 188969d5fd8fSJohnny Huang { 189069d5fd8fSJohnny Huang int i; 189169d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 189269d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 189369d5fd8fSJohnny Huang if (i % 16 == 0) { 189469d5fd8fSJohnny Huang printf("%04X: ", i); 189569d5fd8fSJohnny Huang } 189669d5fd8fSJohnny Huang printf("%02X ", buf[i]); 189769d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 189869d5fd8fSJohnny Huang printf("\n"); 189969d5fd8fSJohnny Huang } 190069d5fd8fSJohnny Huang } 190169d5fd8fSJohnny Huang } 190269d5fd8fSJohnny Huang 1903d90825e2SJohnny Huang static int otp_data_parse(uint32_t *buf) 190469d5fd8fSJohnny Huang { 190569d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 190669d5fd8fSJohnny Huang char *byte_buf; 190769d5fd8fSJohnny Huang int i = 0, len = 0; 190869d5fd8fSJohnny Huang byte_buf = (char *)buf; 190969d5fd8fSJohnny Huang while (1) { 191069d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 191169d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 191269d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 191369d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 191469d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 191569d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 191669d5fd8fSJohnny Huang printf("Key[%d]:\n", i); 191769d5fd8fSJohnny Huang printf("Key Type: "); 191869d5fd8fSJohnny Huang switch (key_type) { 191969d5fd8fSJohnny Huang case 0: 192069d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 192169d5fd8fSJohnny Huang break; 192269d5fd8fSJohnny Huang case 1: 192369d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 192469d5fd8fSJohnny Huang break; 192569d5fd8fSJohnny Huang case 4: 192669d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 192769d5fd8fSJohnny Huang break; 192869d5fd8fSJohnny Huang case 8: 192969d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 193069d5fd8fSJohnny Huang break; 193169d5fd8fSJohnny Huang case 9: 193269d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 193369d5fd8fSJohnny Huang break; 193469d5fd8fSJohnny Huang case 10: 193569d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 193669d5fd8fSJohnny Huang break; 193769d5fd8fSJohnny Huang case 13: 193869d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 193969d5fd8fSJohnny Huang break; 194069d5fd8fSJohnny Huang case 14: 194169d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 194269d5fd8fSJohnny Huang break; 194369d5fd8fSJohnny Huang default: 194469d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 194569d5fd8fSJohnny Huang return -1; 194669d5fd8fSJohnny Huang } 194769d5fd8fSJohnny Huang if (key_type == 4) { 194869d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 194969d5fd8fSJohnny Huang switch (key_length) { 195069d5fd8fSJohnny Huang case 0: 195169d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 195269d5fd8fSJohnny Huang break; 195369d5fd8fSJohnny Huang case 1: 195469d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 195569d5fd8fSJohnny Huang break; 195669d5fd8fSJohnny Huang case 2: 195769d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 195869d5fd8fSJohnny Huang break; 195969d5fd8fSJohnny Huang case 3: 196069d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 196169d5fd8fSJohnny Huang break; 196269d5fd8fSJohnny Huang } 1963cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 196469d5fd8fSJohnny Huang printf("RSA SHA Type: "); 196569d5fd8fSJohnny Huang switch (key_length) { 196669d5fd8fSJohnny Huang case 0: 196769d5fd8fSJohnny Huang printf("RSA1024\n"); 196869d5fd8fSJohnny Huang len = 0x100; 196969d5fd8fSJohnny Huang break; 197069d5fd8fSJohnny Huang case 1: 197169d5fd8fSJohnny Huang printf("RSA2048\n"); 197269d5fd8fSJohnny Huang len = 0x200; 197369d5fd8fSJohnny Huang break; 197469d5fd8fSJohnny Huang case 2: 197569d5fd8fSJohnny Huang printf("RSA3072\n"); 197669d5fd8fSJohnny Huang len = 0x300; 197769d5fd8fSJohnny Huang break; 197869d5fd8fSJohnny Huang case 3: 197969d5fd8fSJohnny Huang printf("RSA4096\n"); 198069d5fd8fSJohnny Huang len = 0x400; 198169d5fd8fSJohnny Huang break; 198269d5fd8fSJohnny Huang } 198369d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 198469d5fd8fSJohnny Huang } 198569d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 198669d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 198769d5fd8fSJohnny Huang printf("Key Value:\n"); 198869d5fd8fSJohnny Huang if (key_type == 4) { 198969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 199069d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 199169d5fd8fSJohnny Huang printf("AES Key:\n"); 199269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 199369d5fd8fSJohnny Huang printf("AES IV:\n"); 199469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 199569d5fd8fSJohnny Huang 199669d5fd8fSJohnny Huang } else { 199769d5fd8fSJohnny Huang printf("RSA mod:\n"); 199869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 199969d5fd8fSJohnny Huang printf("RSA exp:\n"); 200069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 200169d5fd8fSJohnny Huang } 200269d5fd8fSJohnny Huang if (last) 200369d5fd8fSJohnny Huang break; 200469d5fd8fSJohnny Huang i++; 200569d5fd8fSJohnny Huang } 200669d5fd8fSJohnny Huang return 0; 200769d5fd8fSJohnny Huang } 200869d5fd8fSJohnny Huang 2009a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 201069d5fd8fSJohnny Huang { 2011a6d0d645SJohnny Huang int i, k; 2012d90825e2SJohnny Huang int pass = 0; 2013d90825e2SJohnny Huang int soak = 0; 2014a6d0d645SJohnny Huang uint32_t prog_address; 2015a6d0d645SJohnny Huang uint32_t data[12]; 2016a6d0d645SJohnny Huang uint32_t compare[2]; 2017d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 2018d90825e2SJohnny Huang uint32_t data_masked; 2019d90825e2SJohnny Huang uint32_t buf_masked; 202069d5fd8fSJohnny Huang 2021a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 2022a6d0d645SJohnny Huang 2023a6d0d645SJohnny Huang printProgress(0, 12, ""); 2024a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 2025a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 202669d5fd8fSJohnny Huang prog_address = 0x800; 2027a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 2028a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 2029a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 2030a6d0d645SJohnny Huang } 2031a6d0d645SJohnny Huang 2032a6d0d645SJohnny Huang printf("Check writable...\n"); 2033a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 2034d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 2035d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 2036d90825e2SJohnny Huang if (data_masked == buf_masked) 203769d5fd8fSJohnny Huang continue; 2038d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 2039a6d0d645SJohnny Huang continue; 2040a6d0d645SJohnny Huang } else { 2041a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 2042a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 2043a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 2044a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 20452a856b9aSJohnny Huang return OTP_FAILURE; 2046a6d0d645SJohnny Huang } 2047a6d0d645SJohnny Huang } 2048a6d0d645SJohnny Huang 2049a6d0d645SJohnny Huang printf("Start Programing...\n"); 2050a6d0d645SJohnny Huang printProgress(0, 12, ""); 2051d90825e2SJohnny Huang otp_soak(0); 2052a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 2053d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 2054d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 2055a6d0d645SJohnny Huang prog_address = 0x800; 2056a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 2057a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 2058d90825e2SJohnny Huang if (data_masked == buf_masked) { 2059a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 2060a6d0d645SJohnny Huang continue; 2061a6d0d645SJohnny Huang } 2062d90825e2SJohnny Huang if (soak) { 2063d90825e2SJohnny Huang soak = 0; 2064d90825e2SJohnny Huang otp_soak(0); 2065d90825e2SJohnny Huang } 2066a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 2067a6d0d645SJohnny Huang 2068d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 2069a6d0d645SJohnny Huang 207069d5fd8fSJohnny Huang pass = 0; 207169d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 2072d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 2073d90825e2SJohnny Huang if (soak == 0) { 2074d90825e2SJohnny Huang soak = 1; 2075d90825e2SJohnny Huang otp_soak(1); 2076d90825e2SJohnny Huang } 2077a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 2078a6d0d645SJohnny Huang } else { 207969d5fd8fSJohnny Huang pass = 1; 208069d5fd8fSJohnny Huang break; 208169d5fd8fSJohnny Huang } 208269d5fd8fSJohnny Huang } 2083a6d0d645SJohnny Huang } 2084a6d0d645SJohnny Huang 208569d5fd8fSJohnny Huang if (!pass) 20862a856b9aSJohnny Huang return OTP_FAILURE; 2087a6d0d645SJohnny Huang 20882a856b9aSJohnny Huang return OTP_SUCCESS; 2089d90825e2SJohnny Huang 209069d5fd8fSJohnny Huang } 209169d5fd8fSJohnny Huang 209269d5fd8fSJohnny Huang 2093*76d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 209469d5fd8fSJohnny Huang { 209569d5fd8fSJohnny Huang int i; 209669d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 209769d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 209869d5fd8fSJohnny Huang int bit, pbit, kbit; 209969d5fd8fSJohnny Huang int fail = 0; 2100a6af4a17SJohnny Huang int skip = -1; 210166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 210269d5fd8fSJohnny Huang 210369d5fd8fSJohnny Huang otp_strp_status(otpstrap); 210469d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 210569d5fd8fSJohnny Huang if (i < 32) { 210669d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 210769d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 210869d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 210969d5fd8fSJohnny Huang } else { 211069d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 211169d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 211269d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 211369d5fd8fSJohnny Huang } 211469d5fd8fSJohnny Huang 211569d5fd8fSJohnny Huang if (kbit == 1) { 211669d5fd8fSJohnny Huang continue; 211769d5fd8fSJohnny Huang } else { 2118a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 211969d5fd8fSJohnny Huang } 212069d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 212169d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 2122a6af4a17SJohnny Huang if (skip == -1) 2123a6af4a17SJohnny Huang skip = 1; 212469d5fd8fSJohnny Huang continue; 2125a6af4a17SJohnny Huang } else { 2126a6af4a17SJohnny Huang skip = 0; 212769d5fd8fSJohnny Huang } 212869d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 212969d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 213069d5fd8fSJohnny Huang fail = 1; 213169d5fd8fSJohnny Huang continue; 213269d5fd8fSJohnny Huang } 213369d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 2134a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 213569d5fd8fSJohnny Huang fail = 1; 213669d5fd8fSJohnny Huang continue; 213769d5fd8fSJohnny Huang } 213869d5fd8fSJohnny Huang if (pbit == 1) { 213969d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 214069d5fd8fSJohnny Huang } 2141a6af4a17SJohnny 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); 214269d5fd8fSJohnny Huang } 214369d5fd8fSJohnny Huang if (fail == 1) 2144a6af4a17SJohnny Huang return OTP_FAILURE; 2145a6af4a17SJohnny Huang else if (skip == 1) 2146a6af4a17SJohnny Huang return OTP_PROG_SKIP; 21477e22f42dSJohnny Huang 21487e22f42dSJohnny Huang return 0; 214969d5fd8fSJohnny Huang } 215069d5fd8fSJohnny Huang 21512a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 215269d5fd8fSJohnny Huang { 215369d5fd8fSJohnny Huang int i, j; 215466f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 215569d5fd8fSJohnny Huang 21562a856b9aSJohnny Huang if (start < 0 || start > 64) 21572a856b9aSJohnny Huang return OTP_USAGE; 21582a856b9aSJohnny Huang 21592a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 21602a856b9aSJohnny Huang return OTP_USAGE; 21612a856b9aSJohnny Huang 216269d5fd8fSJohnny Huang otp_strp_status(otpstrap); 216369d5fd8fSJohnny Huang 2164cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 2165a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 216669d5fd8fSJohnny Huang printf(" OTP Option value: "); 216769d5fd8fSJohnny Huang for (j = 1; j <= 7; j++) 2168a6af4a17SJohnny Huang printf("[%X]:%X ", j, otpstrap[i].option_array[j - 1]); 216969d5fd8fSJohnny Huang printf("\n"); 2170a6af4a17SJohnny Huang printf(" OTP Value: %X\n", otpstrap[i].value); 217169d5fd8fSJohnny Huang printf(" Status:\n"); 217269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 2173a6af4a17SJohnny Huang printf(" OTPSTRAP[%X] is protected and is not writable\n", i); 217469d5fd8fSJohnny Huang } else { 2175a6af4a17SJohnny Huang printf(" OTPSTRAP[%X] is not protected ", i); 217669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 2177a6af4a17SJohnny Huang printf("and no remaining times to write.\n"); 217869d5fd8fSJohnny Huang } else { 2179a6af4a17SJohnny Huang printf("and still can write %d times\n", otpstrap[i].remain_times); 218069d5fd8fSJohnny Huang } 218169d5fd8fSJohnny Huang } 218269d5fd8fSJohnny Huang } 21832a856b9aSJohnny Huang 21842a856b9aSJohnny Huang return OTP_SUCCESS; 218569d5fd8fSJohnny Huang } 218669d5fd8fSJohnny Huang 218769d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 218869d5fd8fSJohnny Huang { 218969d5fd8fSJohnny Huang int i, j; 219069d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 219169d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 219269d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 219369d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 219469d5fd8fSJohnny Huang int fail = 0; 21957e22f42dSJohnny Huang int pass = 0; 21967e22f42dSJohnny Huang int soak = 0; 219766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 219869d5fd8fSJohnny Huang 219969d5fd8fSJohnny Huang otp_strp_status(otpstrap); 220069d5fd8fSJohnny Huang 22017e22f42dSJohnny Huang otp_soak(0); 22027e22f42dSJohnny Huang 220369d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 22044c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 220569d5fd8fSJohnny Huang prog_address = 0x800; 220669d5fd8fSJohnny Huang if (i < 32) { 220769d5fd8fSJohnny Huang offset = i; 220869d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 220969d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 221069d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 221169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 221269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 221369d5fd8fSJohnny Huang 221469d5fd8fSJohnny Huang } else { 221569d5fd8fSJohnny Huang offset = (i - 32); 221669d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 221769d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 221869d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 221969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 222069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 222169d5fd8fSJohnny Huang } 222269d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 222369d5fd8fSJohnny Huang 222469d5fd8fSJohnny Huang if (kbit == 1) { 222569d5fd8fSJohnny Huang continue; 222669d5fd8fSJohnny Huang } 222769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 222869d5fd8fSJohnny Huang continue; 222969d5fd8fSJohnny Huang } 223069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 223169d5fd8fSJohnny Huang fail = 1; 223269d5fd8fSJohnny Huang continue; 223369d5fd8fSJohnny Huang } 223469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 223569d5fd8fSJohnny Huang fail = 1; 223669d5fd8fSJohnny Huang continue; 223769d5fd8fSJohnny Huang } 22387e22f42dSJohnny Huang 22397e22f42dSJohnny Huang if (soak) { 224069d5fd8fSJohnny Huang soak = 0; 22417e22f42dSJohnny Huang otp_soak(0); 22427e22f42dSJohnny Huang } 22437e22f42dSJohnny Huang 22447e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 22457e22f42dSJohnny Huang 22467e22f42dSJohnny Huang pass = 0; 22477e22f42dSJohnny Huang 224869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 2249a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 225069d5fd8fSJohnny Huang pass = 1; 225169d5fd8fSJohnny Huang break; 225269d5fd8fSJohnny Huang } 22537e22f42dSJohnny Huang if (soak == 0) { 225469d5fd8fSJohnny Huang soak = 1; 22557e22f42dSJohnny Huang otp_soak(1); 22564b65a65dSJohnny Huang } 225769d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 225869d5fd8fSJohnny Huang } 225969d5fd8fSJohnny Huang if (!pass) 22602a856b9aSJohnny Huang return OTP_FAILURE; 226169d5fd8fSJohnny Huang 226269d5fd8fSJohnny Huang if (pbit == 0) 226369d5fd8fSJohnny Huang continue; 226469d5fd8fSJohnny Huang prog_address = 0x800; 226569d5fd8fSJohnny Huang if (i < 32) 226669d5fd8fSJohnny Huang prog_address |= 0x60c; 226769d5fd8fSJohnny Huang else 226869d5fd8fSJohnny Huang prog_address |= 0x60e; 226969d5fd8fSJohnny Huang 22707e22f42dSJohnny Huang 22717e22f42dSJohnny Huang if (soak) { 22727e22f42dSJohnny Huang soak = 0; 22737e22f42dSJohnny Huang otp_soak(0); 22747e22f42dSJohnny Huang } 22757e22f42dSJohnny Huang 22767e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 22777e22f42dSJohnny Huang 22787e22f42dSJohnny Huang pass = 0; 22797e22f42dSJohnny Huang 228069d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 22817e22f42dSJohnny Huang 2282a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 228369d5fd8fSJohnny Huang pass = 1; 228469d5fd8fSJohnny Huang break; 228569d5fd8fSJohnny Huang } 22867e22f42dSJohnny Huang if (soak == 0) { 228769d5fd8fSJohnny Huang soak = 1; 22887e22f42dSJohnny Huang otp_soak(1); 228969d5fd8fSJohnny Huang } 229069d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 229169d5fd8fSJohnny Huang } 229269d5fd8fSJohnny Huang if (!pass) 22932a856b9aSJohnny Huang return OTP_FAILURE; 229469d5fd8fSJohnny Huang 229569d5fd8fSJohnny Huang } 229669d5fd8fSJohnny Huang if (fail == 1) 22972a856b9aSJohnny Huang return OTP_FAILURE; 229869d5fd8fSJohnny Huang else 22992a856b9aSJohnny Huang return OTP_SUCCESS; 230069d5fd8fSJohnny Huang 230169d5fd8fSJohnny Huang } 230269d5fd8fSJohnny Huang 2303cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 2304cd1610b4SJohnny Huang { 2305cd1610b4SJohnny Huang int prog_bit; 2306cd1610b4SJohnny Huang 23077e22f42dSJohnny Huang otp_soak(soak); 23087e22f42dSJohnny Huang 2309cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 2310cd1610b4SJohnny Huang if (value) 2311cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 2312cd1610b4SJohnny Huang else 2313cd1610b4SJohnny Huang return; 2314cd1610b4SJohnny Huang } else { 2315cd1610b4SJohnny Huang prog_address |= 1 << 15; 2316cd1610b4SJohnny Huang if (!value) 2317cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 2318cd1610b4SJohnny Huang else 2319cd1610b4SJohnny Huang return; 2320cd1610b4SJohnny Huang } 2321cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 2322cd1610b4SJohnny Huang } 2323cd1610b4SJohnny Huang 2324d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 23254c1c9b35SJohnny Huang { 23264c1c9b35SJohnny Huang int i, k; 23274c1c9b35SJohnny Huang int pass; 2328d90825e2SJohnny Huang int soak = 0; 23294c1c9b35SJohnny Huang uint32_t prog_address; 2330d90825e2SJohnny Huang uint32_t data[2048]; 23314c1c9b35SJohnny Huang uint32_t compare[2]; 2332d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 23334c1c9b35SJohnny Huang 2334d90825e2SJohnny Huang uint32_t data0_masked; 2335d90825e2SJohnny Huang uint32_t data1_masked; 2336d90825e2SJohnny Huang uint32_t buf0_masked; 2337d90825e2SJohnny Huang uint32_t buf1_masked; 23384c1c9b35SJohnny Huang 23394c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 23404c1c9b35SJohnny Huang 2341d90825e2SJohnny Huang printProgress(0, 2048, ""); 2342d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 2343d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 2344d90825e2SJohnny Huang otp_read_data(i, &data[i]); 23454c1c9b35SJohnny Huang } 2346d90825e2SJohnny Huang 23474c1c9b35SJohnny Huang 23484c1c9b35SJohnny Huang printf("Check writable...\n"); 2349d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 2350d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 2351d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 2352d90825e2SJohnny Huang if (data0_masked == buf0_masked) 23534c1c9b35SJohnny Huang continue; 2354d90825e2SJohnny Huang if (i % 2 == 0) { 2355d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 23564c1c9b35SJohnny Huang continue; 23574c1c9b35SJohnny Huang } else { 23584c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 2359d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 23604c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 2361d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 23622a856b9aSJohnny Huang return OTP_FAILURE; 236369d5fd8fSJohnny Huang } 2364d90825e2SJohnny Huang } else { 2365d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 2366d90825e2SJohnny Huang continue; 2367d90825e2SJohnny Huang } else { 2368d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 2369d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 2370d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 2371d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 23722a856b9aSJohnny Huang return OTP_FAILURE; 2373d90825e2SJohnny Huang } 2374d90825e2SJohnny Huang } 2375d90825e2SJohnny Huang } 237669d5fd8fSJohnny Huang 2377d90825e2SJohnny Huang printf("Start Programing...\n"); 2378d90825e2SJohnny Huang printProgress(0, 2048, ""); 2379d90825e2SJohnny Huang 2380d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 2381d90825e2SJohnny Huang prog_address = i; 2382d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 2383d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 2384d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 2385d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 2386d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 2387d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 2388d90825e2SJohnny Huang continue; 2389d90825e2SJohnny Huang } 2390d90825e2SJohnny Huang if (soak) { 2391d90825e2SJohnny Huang soak = 0; 2392d90825e2SJohnny Huang otp_soak(0); 2393d90825e2SJohnny Huang } 2394d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 2395d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 2396d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 2397d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 2398d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 2399d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 2400d90825e2SJohnny Huang } else { 2401d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 2402d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 2403d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 2404d90825e2SJohnny Huang } 2405d90825e2SJohnny Huang 2406d90825e2SJohnny Huang pass = 0; 2407d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 2408d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 2409d90825e2SJohnny Huang if (soak == 0) { 2410d90825e2SJohnny Huang soak = 1; 2411d90825e2SJohnny Huang otp_soak(1); 2412d90825e2SJohnny Huang } 2413d90825e2SJohnny Huang if (compare[0] != 0) { 2414d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 2415d90825e2SJohnny Huang } 2416d90825e2SJohnny Huang if (compare[1] != ~0) { 2417d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 2418d90825e2SJohnny Huang } 2419d90825e2SJohnny Huang } else { 2420d90825e2SJohnny Huang pass = 1; 2421d90825e2SJohnny Huang break; 2422d90825e2SJohnny Huang } 2423d90825e2SJohnny Huang } 2424d90825e2SJohnny Huang 2425d90825e2SJohnny Huang if (!pass) 24262a856b9aSJohnny Huang return OTP_FAILURE; 2427d90825e2SJohnny Huang } 24282a856b9aSJohnny Huang return OTP_SUCCESS; 2429d90825e2SJohnny Huang 2430d90825e2SJohnny Huang } 2431d90825e2SJohnny Huang 2432d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 243369d5fd8fSJohnny Huang { 243469d5fd8fSJohnny Huang int ret; 2435d90825e2SJohnny Huang int mode; 243669d5fd8fSJohnny Huang uint32_t *buf; 2437d90825e2SJohnny Huang uint32_t *data_region = NULL; 2438d90825e2SJohnny Huang uint32_t *conf_region = NULL; 2439d90825e2SJohnny Huang uint32_t *strap_region = NULL; 244069d5fd8fSJohnny Huang 2441d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 244269d5fd8fSJohnny Huang if (!buf) { 244369d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 24442a856b9aSJohnny Huang return OTP_FAILURE; 244569d5fd8fSJohnny Huang } 2446d90825e2SJohnny Huang 2447d90825e2SJohnny Huang if (((buf[0] >> 29) & 0x7) == 0x7) { 2448d90825e2SJohnny Huang mode = OTP_REGION_ALL; 2449d90825e2SJohnny Huang conf_region = &buf[1]; 2450d90825e2SJohnny Huang strap_region = &buf[25]; 2451d90825e2SJohnny Huang data_region = &buf[31]; 2452d90825e2SJohnny Huang } else { 2453d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 2454d90825e2SJohnny Huang mode = OTP_REGION_DATA; 2455d90825e2SJohnny Huang data_region = &buf[31]; 2456d90825e2SJohnny Huang } 2457d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 2458d90825e2SJohnny Huang mode = OTP_REGION_CONF; 2459d90825e2SJohnny Huang strap_region = &buf[25]; 2460d90825e2SJohnny Huang } 2461d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 2462d90825e2SJohnny Huang mode = OTP_REGION_STRAP; 2463d90825e2SJohnny Huang conf_region = &buf[1]; 2464d90825e2SJohnny Huang } 2465d90825e2SJohnny Huang } 246669d5fd8fSJohnny Huang if (!nconfirm) { 2467a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 246866f2f8e5SJohnny Huang if (otp_print_conf_info(conf_region) < 0) { 246969d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 24702a856b9aSJohnny Huang return OTP_FAILURE; 247169d5fd8fSJohnny Huang } 2472a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 2473d90825e2SJohnny Huang if (otp_data_parse(data_region) < 0) { 247469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 24752a856b9aSJohnny Huang return OTP_FAILURE; 247669d5fd8fSJohnny Huang } 2477a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 2478*76d13988SJohnny Huang ret = otp_strap_image_confirm(strap_region); 2479a6af4a17SJohnny Huang if (ret == OTP_FAILURE) { 248069d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 24812a856b9aSJohnny Huang return OTP_FAILURE; 2482a6af4a17SJohnny Huang } else if (ret == OTP_PROG_SKIP) { 2483a6af4a17SJohnny Huang printf("OTP strap skip all\n"); 2484a6af4a17SJohnny Huang return OTP_SUCCESS; 248569d5fd8fSJohnny Huang } 2486a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 248766f2f8e5SJohnny Huang if (otp_print_conf_info(conf_region) < 0) { 248869d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 24892a856b9aSJohnny Huang return OTP_FAILURE; 249069d5fd8fSJohnny Huang } 2491*76d13988SJohnny Huang if (otp_strap_image_confirm(strap_region) == OTP_FAILURE) { 249269d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 24932a856b9aSJohnny Huang return OTP_FAILURE; 249469d5fd8fSJohnny Huang } 2495d90825e2SJohnny Huang if (otp_data_parse(data_region) < 0) { 249669d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 24972a856b9aSJohnny Huang return OTP_FAILURE; 249869d5fd8fSJohnny Huang } 249969d5fd8fSJohnny Huang } 250069d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 250169d5fd8fSJohnny Huang if (!confirm_yesno()) { 250269d5fd8fSJohnny Huang printf(" Aborting\n"); 25032a856b9aSJohnny Huang return OTP_FAILURE; 250469d5fd8fSJohnny Huang } 250569d5fd8fSJohnny Huang } 2506a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 2507d90825e2SJohnny Huang return otp_prog_conf(conf_region); 2508a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 2509d90825e2SJohnny Huang return otp_prog_strap(strap_region); 2510a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 2511d90825e2SJohnny Huang return otp_prog_data(data_region); 2512a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 251369d5fd8fSJohnny Huang printf("programing data region ... "); 2514d90825e2SJohnny Huang ret = otp_prog_data(data_region); 25152a856b9aSJohnny Huang if (ret != 0) { 251669d5fd8fSJohnny Huang printf("Error\n"); 251769d5fd8fSJohnny Huang return ret; 251869d5fd8fSJohnny Huang } else { 251969d5fd8fSJohnny Huang printf("Done\n"); 252069d5fd8fSJohnny Huang } 252169d5fd8fSJohnny Huang printf("programing strap region ... "); 2522d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 25232a856b9aSJohnny Huang if (ret != 0) { 252469d5fd8fSJohnny Huang printf("Error\n"); 252569d5fd8fSJohnny Huang return ret; 252669d5fd8fSJohnny Huang } else { 252769d5fd8fSJohnny Huang printf("Done\n"); 252869d5fd8fSJohnny Huang } 252969d5fd8fSJohnny Huang printf("programing configuration region ... "); 2530d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 25312a856b9aSJohnny Huang if (ret != 0) { 253269d5fd8fSJohnny Huang printf("Error\n"); 253369d5fd8fSJohnny Huang return ret; 253469d5fd8fSJohnny Huang } 253569d5fd8fSJohnny Huang printf("Done\n"); 25362a856b9aSJohnny Huang return OTP_SUCCESS; 253769d5fd8fSJohnny Huang } 2538cd1610b4SJohnny Huang 25392a856b9aSJohnny Huang return OTP_USAGE; 25402a856b9aSJohnny Huang } 25412a856b9aSJohnny Huang 25422a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 2543cd1610b4SJohnny Huang { 2544a6af4a17SJohnny Huang uint32_t read[2]; 2545cd1610b4SJohnny Huang uint32_t strap_buf[6]; 2546d90825e2SJohnny Huang uint32_t prog_address = 0; 254766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 2548cd1610b4SJohnny Huang int otp_bit; 2549cd1610b4SJohnny Huang int i; 2550cd1610b4SJohnny Huang int pass; 2551a6af4a17SJohnny Huang int ret; 2552cd1610b4SJohnny Huang 2553cd1610b4SJohnny Huang switch (mode) { 2554a6d0d645SJohnny Huang case OTP_REGION_CONF: 2555a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 2556cd1610b4SJohnny Huang prog_address = 0x800; 2557cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 2558cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 2559a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2560cd1610b4SJohnny Huang if (otp_bit == value) { 2561a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 2562cd1610b4SJohnny Huang printf("No need to program\n"); 25632a856b9aSJohnny Huang return OTP_SUCCESS; 2564cd1610b4SJohnny Huang } 2565cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2566a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 2567cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 25682a856b9aSJohnny Huang return OTP_FAILURE; 2569cd1610b4SJohnny Huang } 2570a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 2571cd1610b4SJohnny Huang break; 2572a6d0d645SJohnny Huang case OTP_REGION_DATA: 2573cd1610b4SJohnny Huang prog_address = otp_dw_offset; 2574cd1610b4SJohnny Huang 2575cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 2576a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 2577a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2578cd1610b4SJohnny Huang } else { 2579a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 2580a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 2581cd1610b4SJohnny Huang } 2582cd1610b4SJohnny Huang if (otp_bit == value) { 2583a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 2584cd1610b4SJohnny Huang printf("No need to program\n"); 25852a856b9aSJohnny Huang return OTP_SUCCESS; 2586cd1610b4SJohnny Huang } 2587cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2588a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 2589cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 25902a856b9aSJohnny Huang return OTP_FAILURE; 2591cd1610b4SJohnny Huang } 2592a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 2593cd1610b4SJohnny Huang break; 2594a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2595cd1610b4SJohnny Huang otp_strp_status(otpstrap); 2596cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 2597cd1610b4SJohnny Huang if (bit_offset < 32) { 2598cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 2599cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 2600cd1610b4SJohnny Huang strap_buf[3] = ~0; 2601cd1610b4SJohnny Huang strap_buf[5] = 0; 26022a856b9aSJohnny Huang // if (protect) 26032a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 26042a856b9aSJohnny Huang // else 26052a856b9aSJohnny Huang // strap_buf[4] = 0; 2606cd1610b4SJohnny Huang } else { 2607cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 2608cd1610b4SJohnny Huang strap_buf[2] = ~0; 2609cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 2610cd1610b4SJohnny Huang strap_buf[4] = 0; 26112a856b9aSJohnny Huang // if (protect) 26122a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 26132a856b9aSJohnny Huang // else 26142a856b9aSJohnny Huang // strap_buf[5] = 0; 2615cd1610b4SJohnny Huang } 2616*76d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 2617a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 26182a856b9aSJohnny Huang return OTP_FAILURE; 2619a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 2620a6af4a17SJohnny Huang return OTP_SUCCESS; 2621a6af4a17SJohnny Huang 2622cd1610b4SJohnny Huang break; 2623cd1610b4SJohnny Huang } 2624cd1610b4SJohnny Huang 2625cd1610b4SJohnny Huang if (!nconfirm) { 2626cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2627cd1610b4SJohnny Huang if (!confirm_yesno()) { 2628cd1610b4SJohnny Huang printf(" Aborting\n"); 26292a856b9aSJohnny Huang return OTP_FAILURE; 2630cd1610b4SJohnny Huang } 2631cd1610b4SJohnny Huang } 2632cd1610b4SJohnny Huang 2633cd1610b4SJohnny Huang switch (mode) { 2634a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2635cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 2636a6d0d645SJohnny Huang case OTP_REGION_CONF: 2637a6d0d645SJohnny Huang case OTP_REGION_DATA: 2638cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 2639cd1610b4SJohnny Huang pass = -1; 2640cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 2641a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2642cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 2643cd1610b4SJohnny Huang } else { 2644cd1610b4SJohnny Huang pass = 0; 2645cd1610b4SJohnny Huang break; 2646cd1610b4SJohnny Huang } 2647cd1610b4SJohnny Huang } 26482a856b9aSJohnny Huang if (pass == 0) 26492a856b9aSJohnny Huang return OTP_SUCCESS; 2650cd1610b4SJohnny Huang } 2651cd1610b4SJohnny Huang 26522a856b9aSJohnny Huang return OTP_USAGE; 2653cd1610b4SJohnny Huang } 2654cd1610b4SJohnny Huang 26552a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 265669d5fd8fSJohnny Huang { 26572a856b9aSJohnny Huang uint32_t offset, count; 26582a856b9aSJohnny Huang int ret; 265969d5fd8fSJohnny Huang 26602a856b9aSJohnny Huang if (argc == 4) { 26612a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 26622a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 26632a856b9aSJohnny Huang } else if (argc == 3) { 26642a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 26652a856b9aSJohnny Huang count = 1; 26662a856b9aSJohnny Huang } else { 266769d5fd8fSJohnny Huang return CMD_RET_USAGE; 266869d5fd8fSJohnny Huang } 266969d5fd8fSJohnny Huang 267069d5fd8fSJohnny Huang 26712a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 267269d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 26732a856b9aSJohnny Huang ret = otp_print_config(offset, count); 26742a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 26752a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 26762a856b9aSJohnny Huang ret = otp_print_data(offset, count); 26772a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 26782a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 26792a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 26802a856b9aSJohnny Huang } else { 26812a856b9aSJohnny Huang return CMD_RET_USAGE; 268269d5fd8fSJohnny Huang } 268369d5fd8fSJohnny Huang 26842a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 26852a856b9aSJohnny Huang return CMD_RET_SUCCESS; 26862a856b9aSJohnny Huang else 26872a856b9aSJohnny Huang return CMD_RET_USAGE; 26882a856b9aSJohnny Huang 26892a856b9aSJohnny Huang } 26902a856b9aSJohnny Huang 26912a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 26922a856b9aSJohnny Huang { 26932a856b9aSJohnny Huang phys_addr_t addr; 26942a856b9aSJohnny Huang uint32_t byte_size; 26952a856b9aSJohnny Huang int ret; 26962a856b9aSJohnny Huang 26972a856b9aSJohnny Huang if (argc == 4) { 26982a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 26992a856b9aSJohnny Huang return CMD_RET_USAGE; 27002a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 27012a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 270269d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 27032a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 27042a856b9aSJohnny Huang } else if (argc == 3) { 27052a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 27062a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 27072a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 27082a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 27092a856b9aSJohnny Huang } else { 27102a856b9aSJohnny Huang return CMD_RET_USAGE; 27112a856b9aSJohnny Huang } 27122a856b9aSJohnny Huang 27132a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 27142a856b9aSJohnny Huang return CMD_RET_SUCCESS; 27152a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 27162a856b9aSJohnny Huang return CMD_RET_FAILURE; 27172a856b9aSJohnny Huang else 27182a856b9aSJohnny Huang return CMD_RET_USAGE; 27192a856b9aSJohnny Huang } 27202a856b9aSJohnny Huang 27212a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 27222a856b9aSJohnny Huang { 27232a856b9aSJohnny Huang int mode = 0; 27242a856b9aSJohnny Huang int nconfirm = 0; 27252a856b9aSJohnny Huang int otp_addr = 0; 27262a856b9aSJohnny Huang int bit_offset; 27272a856b9aSJohnny Huang int value; 27282a856b9aSJohnny Huang int ret; 27292a856b9aSJohnny Huang 27302a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 27312a856b9aSJohnny Huang return CMD_RET_USAGE; 27322a856b9aSJohnny Huang 27332a856b9aSJohnny Huang /* Drop the pb cmd */ 27342a856b9aSJohnny Huang argc--; 27352a856b9aSJohnny Huang argv++; 27362a856b9aSJohnny Huang 27372a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2738a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 27392a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2740a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 27412a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2742a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2743cd1610b4SJohnny Huang else 27442a856b9aSJohnny Huang return CMD_RET_USAGE; 27452a856b9aSJohnny Huang 27462a856b9aSJohnny Huang /* Drop the region cmd */ 27472a856b9aSJohnny Huang argc--; 27482a856b9aSJohnny Huang argv++; 27492a856b9aSJohnny Huang 27502a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 2751cd1610b4SJohnny Huang nconfirm = 1; 27522a856b9aSJohnny Huang /* Drop the force option */ 27532a856b9aSJohnny Huang argc--; 27542a856b9aSJohnny Huang argv++; 27552a856b9aSJohnny Huang } 2756cd1610b4SJohnny Huang 2757a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 27582a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 27592a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 2760cd1610b4SJohnny Huang if (bit_offset >= 64) 27612a856b9aSJohnny Huang return CMD_RET_USAGE; 2762cd1610b4SJohnny Huang } else { 27632a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 27642a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 27652a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 2766cd1610b4SJohnny Huang if (bit_offset >= 32) 27672a856b9aSJohnny Huang return CMD_RET_USAGE; 2768cd1610b4SJohnny Huang } 2769cd1610b4SJohnny Huang if (value != 0 && value != 1) 27702a856b9aSJohnny Huang return CMD_RET_USAGE; 2771cd1610b4SJohnny Huang 2772cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 27732a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 27742a856b9aSJohnny Huang 27752a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 27762a856b9aSJohnny Huang return CMD_RET_SUCCESS; 27772a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 27782a856b9aSJohnny Huang return CMD_RET_FAILURE; 27792a856b9aSJohnny Huang else 27802a856b9aSJohnny Huang return CMD_RET_USAGE; 27812a856b9aSJohnny Huang } 27822a856b9aSJohnny Huang 27832a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 27842a856b9aSJohnny Huang { 27852a856b9aSJohnny Huang phys_addr_t addr; 27862a856b9aSJohnny Huang int otp_addr = 0; 27872a856b9aSJohnny Huang 27882a856b9aSJohnny Huang if (argc != 3) 27892a856b9aSJohnny Huang return CMD_RET_USAGE; 27902a856b9aSJohnny Huang 279169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 27922a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 27932a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 27942a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 279569d5fd8fSJohnny Huang printf("Compare pass\n"); 27962a856b9aSJohnny Huang return CMD_RET_SUCCESS; 279769d5fd8fSJohnny Huang } else { 279869d5fd8fSJohnny Huang printf("Compare fail\n"); 27992a856b9aSJohnny Huang return CMD_RET_FAILURE; 280069d5fd8fSJohnny Huang } 280169d5fd8fSJohnny Huang } 280269d5fd8fSJohnny Huang 280366f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 280466f2f8e5SJohnny Huang { 280566f2f8e5SJohnny Huang if (argc != 2) 280666f2f8e5SJohnny Huang return CMD_RET_USAGE; 280766f2f8e5SJohnny Huang 280866f2f8e5SJohnny Huang 280966f2f8e5SJohnny Huang if (!strcmp(argv[1], "conf")) { 281066f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 281166f2f8e5SJohnny Huang otp_info_config(); 281266f2f8e5SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 281366f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 2814*76d13988SJohnny Huang otp_info_strap(); 281566f2f8e5SJohnny Huang } else { 281666f2f8e5SJohnny Huang return CMD_RET_USAGE; 281766f2f8e5SJohnny Huang } 281866f2f8e5SJohnny Huang 281966f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 282066f2f8e5SJohnny Huang } 282166f2f8e5SJohnny Huang 28222a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 28232a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 28242a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 28252a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 28262a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 282766f2f8e5SJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 282869d5fd8fSJohnny Huang 28292a856b9aSJohnny Huang }; 28302a856b9aSJohnny Huang 28312a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 28322a856b9aSJohnny Huang { 28332a856b9aSJohnny Huang cmd_tbl_t *cp; 28342a856b9aSJohnny Huang 28352a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 28362a856b9aSJohnny Huang 28372a856b9aSJohnny Huang /* Drop the mmc command */ 28382a856b9aSJohnny Huang argc--; 28392a856b9aSJohnny Huang argv++; 28402a856b9aSJohnny Huang 28412a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 28422a856b9aSJohnny Huang return CMD_RET_USAGE; 28432a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 28442a856b9aSJohnny Huang return CMD_RET_SUCCESS; 28452a856b9aSJohnny Huang 28462a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 284769d5fd8fSJohnny Huang } 284869d5fd8fSJohnny Huang 284969d5fd8fSJohnny Huang U_BOOT_CMD( 285069d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 285169d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 28522a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 28532a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 2854*76d13988SJohnny Huang "otp info conf|strap\n" 2855d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2856cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2857cd1610b4SJohnny Huang "otp pb strap [f] <bit_offset> <value> <protect>\n" 28582a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 285969d5fd8fSJohnny Huang ); 2860