1a219f6deSJohnny Huang // SPDX-License-Identifier: GPL-2.0+ 269d5fd8fSJohnny Huang /* 3a219f6deSJohnny Huang * Copyright 2021 Aspeed Technology Inc. 469d5fd8fSJohnny Huang */ 5e417205bSJohnny Huang 64c1c9b35SJohnny Huang #include <stdlib.h> 769d5fd8fSJohnny Huang #include <common.h> 869d5fd8fSJohnny Huang #include <console.h> 969d5fd8fSJohnny Huang #include <bootretry.h> 1069d5fd8fSJohnny Huang #include <cli.h> 1169d5fd8fSJohnny Huang #include <command.h> 1269d5fd8fSJohnny Huang #include <console.h> 134c1c9b35SJohnny Huang #include <malloc.h> 1469d5fd8fSJohnny Huang #include <inttypes.h> 1569d5fd8fSJohnny Huang #include <mapmem.h> 1669d5fd8fSJohnny Huang #include <asm/io.h> 1769d5fd8fSJohnny Huang #include <linux/compiler.h> 182031a123SJohnny Huang #include <linux/iopoll.h> 19*a3dcef30SJohnny Huang #include <u-boot/sha512.h> 200cee9a95SJohnny Huang #include "otp_info.h" 2169d5fd8fSJohnny Huang 2269d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2369d5fd8fSJohnny Huang 24*a3dcef30SJohnny Huang #define OTP_VER "2.0.0" 25f67375f7SJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 27dacbba92SJohnny Huang #define RETRY 20 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 38181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PUB 1 39181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PRIV 2 40181f72d8SJohnny Huang #define OTP_KEY_TYPE_AES 3 41181f72d8SJohnny Huang #define OTP_KEY_TYPE_VAULT 4 42181f72d8SJohnny Huang #define OTP_KEY_TYPE_HMAC 5 439a4fe690SJohnny Huang 443d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 453d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 463d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 473d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 483d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 493d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 503d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 513d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 523d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 533d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 54a8789b47SJohnny Huang #define SW_REV_ID0 OTP_BASE + 0x68 55a8789b47SJohnny Huang #define SW_REV_ID1 OTP_BASE + 0x6c 56030cb4a7SJohnny Huang #define SEC_KEY_NUM OTP_BASE + 0x78 573d3688adSJohnny Huang 58696656c6SJohnny Huang #define OTP_MAGIC "SOCOTP" 59696656c6SJohnny Huang #define CHECKSUM_LEN 32 60a219f6deSJohnny Huang #define OTP_INC_DATA BIT(31) 61a219f6deSJohnny Huang #define OTP_INC_CONFIG BIT(30) 62a219f6deSJohnny Huang #define OTP_INC_STRAP BIT(29) 63a219f6deSJohnny Huang #define OTP_ECC_EN BIT(28) 64b25f02d2SJohnny Huang #define OTP_INC_SCU_PRO BIT(25) 65696656c6SJohnny Huang #define OTP_REGION_SIZE(info) ((info >> 16) & 0xffff) 66696656c6SJohnny Huang #define OTP_REGION_OFFSET(info) (info & 0xffff) 67696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info) (info & 0xffff) 68696656c6SJohnny Huang 69e417205bSJohnny Huang #define OTP_A0 0 70e417205bSJohnny Huang #define OTP_A1 1 71e417205bSJohnny Huang #define OTP_A2 2 72e417205bSJohnny Huang #define OTP_A3 3 73e417205bSJohnny Huang 74e417205bSJohnny Huang #define ID0_AST2600A0 0x05000303 75e417205bSJohnny Huang #define ID1_AST2600A0 0x05000303 76e417205bSJohnny Huang #define ID0_AST2600A1 0x05010303 7721a8cfceSJohnny Huang #define ID1_AST2600A1 0x05010303 78e417205bSJohnny Huang #define ID0_AST2600A2 0x05010303 79e417205bSJohnny Huang #define ID1_AST2600A2 0x05020303 80e417205bSJohnny Huang #define ID0_AST2600A3 0x05030303 81e417205bSJohnny Huang #define ID1_AST2600A3 0x05030303 82e417205bSJohnny Huang #define ID0_AST2620A1 0x05010203 83e417205bSJohnny Huang #define ID1_AST2620A1 0x05010203 84e417205bSJohnny Huang #define ID0_AST2620A2 0x05010203 85e417205bSJohnny Huang #define ID1_AST2620A2 0x05020203 86e417205bSJohnny Huang #define ID0_AST2620A3 0x05030203 87e417205bSJohnny Huang #define ID1_AST2620A3 0x05030203 88e417205bSJohnny Huang #define ID0_AST2620A3 0x05030203 89e417205bSJohnny Huang #define ID1_AST2620A3 0x05030203 90e417205bSJohnny Huang #define ID0_AST2605A2 0x05010103 91e417205bSJohnny Huang #define ID1_AST2605A2 0x05020103 92e417205bSJohnny Huang #define ID0_AST2605A3 0x05030103 93e417205bSJohnny Huang #define ID1_AST2605A3 0x05030103 94e417205bSJohnny Huang #define ID0_AST2625A3 0x05030403 95e417205bSJohnny Huang #define ID1_AST2625A3 0x05030403 96696656c6SJohnny Huang 9761a6cda7SJohnny Huang #define SOC_AST2600A0 0 9861a6cda7SJohnny Huang #define SOC_AST2600A1 1 9961a6cda7SJohnny Huang #define SOC_AST2600A2 2 10061a6cda7SJohnny Huang #define SOC_AST2600A3 3 10161a6cda7SJohnny Huang 10261a6cda7SJohnny Huang #define OTPTOOL_VERSION(a, b, c) (((a) << 24) + ((b) << 12) + (c)) 1035e096f11SJohnny Huang #define OTPTOOL_VERSION_MAJOR(x) (((x) >> 24) & 0xff) 1045e096f11SJohnny Huang #define OTPTOOL_VERSION_PATCHLEVEL(x) (((x) >> 12) & 0xfff) 1055e096f11SJohnny Huang #define OTPTOOL_VERSION_SUBLEVEL(x) ((x) & 0xfff) 106*a3dcef30SJohnny Huang #define OTPTOOL_COMPT_VERSION 2 10761a6cda7SJohnny Huang 108696656c6SJohnny Huang struct otp_header { 109696656c6SJohnny Huang u8 otp_magic[8]; 11061a6cda7SJohnny Huang u32 soc_ver; 11161a6cda7SJohnny Huang u32 otptool_ver; 112696656c6SJohnny Huang u32 image_info; 113696656c6SJohnny Huang u32 data_info; 114696656c6SJohnny Huang u32 config_info; 115696656c6SJohnny Huang u32 strap_info; 1167e523e3bSJohnny Huang u32 scu_protect_info; 117696656c6SJohnny Huang u32 checksum_offset; 118a219f6deSJohnny Huang } __packed; 119696656c6SJohnny Huang 12066f2f8e5SJohnny Huang struct otpstrap_status { 12169d5fd8fSJohnny Huang int value; 12269d5fd8fSJohnny Huang int option_array[7]; 12369d5fd8fSJohnny Huang int remain_times; 12469d5fd8fSJohnny Huang int writeable_option; 12569d5fd8fSJohnny Huang int protected; 12669d5fd8fSJohnny Huang }; 12769d5fd8fSJohnny Huang 1289a4fe690SJohnny Huang struct otpkey_type { 1299a4fe690SJohnny Huang int value; 1309a4fe690SJohnny Huang int key_type; 1319a4fe690SJohnny Huang int need_id; 1329a4fe690SJohnny Huang char information[110]; 1339a4fe690SJohnny Huang }; 1349a4fe690SJohnny Huang 135030cb4a7SJohnny Huang struct otp_pro_sts { 136030cb4a7SJohnny Huang char mem_lock; 137030cb4a7SJohnny Huang char pro_key_ret; 138030cb4a7SJohnny Huang char pro_strap; 139030cb4a7SJohnny Huang char pro_conf; 140030cb4a7SJohnny Huang char pro_data; 141030cb4a7SJohnny Huang char pro_sec; 142030cb4a7SJohnny Huang u32 sec_size; 143030cb4a7SJohnny Huang }; 144030cb4a7SJohnny Huang 1459a4fe690SJohnny Huang struct otp_info_cb { 1469a4fe690SJohnny Huang int version; 147e417205bSJohnny Huang char ver_name[3]; 14879e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1499a4fe690SJohnny Huang int strap_info_len; 15079e42a59SJoel Stanley const struct otpconf_info *conf_info; 1519a4fe690SJohnny Huang int conf_info_len; 15279e42a59SJoel Stanley const struct otpkey_type *key_info; 1539a4fe690SJohnny Huang int key_info_len; 1540dc9a440SJohnny Huang const struct scu_info *scu_info; 1550dc9a440SJohnny Huang int scu_info_len; 156030cb4a7SJohnny Huang struct otp_pro_sts pro_sts; 1579a4fe690SJohnny Huang }; 1589a4fe690SJohnny Huang 159696656c6SJohnny Huang struct otp_image_layout { 1605010032bSJohnny Huang int data_length; 1615010032bSJohnny Huang int conf_length; 1625010032bSJohnny Huang int strap_length; 163b25f02d2SJohnny Huang int scu_pro_length; 164a219f6deSJohnny Huang u8 *data; 165a219f6deSJohnny Huang u8 *data_ignore; 166a219f6deSJohnny Huang u8 *conf; 167a219f6deSJohnny Huang u8 *conf_ignore; 168a219f6deSJohnny Huang u8 *strap; 169a219f6deSJohnny Huang u8 *strap_pro; 170a219f6deSJohnny Huang u8 *strap_ignore; 171b25f02d2SJohnny Huang u8 *scu_pro; 172b25f02d2SJohnny Huang u8 *scu_pro_ignore; 173696656c6SJohnny Huang }; 174696656c6SJohnny Huang 1759a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1769a4fe690SJohnny Huang 17779e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 1789a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 1799a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1809a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 181181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 182181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as SOC public key"}, 183181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 184181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as SOC private key"}, 185181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1869a4fe690SJohnny Huang }; 1879a4fe690SJohnny Huang 18879e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 1899a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1909a4fe690SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 191181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 192181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 193181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1949a4fe690SJohnny Huang }; 1959a4fe690SJohnny Huang 1965fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = { 1975fdde29fSJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1985fdde29fSJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 199181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 200181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 201181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 202181f72d8SJohnny Huang }; 203181f72d8SJohnny Huang 204181f72d8SJohnny Huang static const struct otpkey_type a3_key_type[] = { 205181f72d8SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 206181f72d8SJohnny Huang {2, OTP_KEY_TYPE_AES, 1, "AES-256 as OEM platform key for image encryption/decryption in Mode 2 or AES-256 as OEM DSS keys for Mode GCM"}, 207181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 208181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2(big endian)"}, 209181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 210181f72d8SJohnny Huang {11, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key(big endian)"}, 211181f72d8SJohnny Huang {12, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 212181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key(big endian)"}, 2135fdde29fSJohnny Huang }; 2145fdde29fSJohnny Huang 215f347c284SJohnny Huang static void buf_print(u8 *buf, int len) 216f347c284SJohnny Huang { 217f347c284SJohnny Huang int i; 218f347c284SJohnny Huang 219f347c284SJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 220f347c284SJohnny Huang for (i = 0; i < len; i++) { 221f347c284SJohnny Huang if (i % 16 == 0) 222f347c284SJohnny Huang printf("%04X: ", i); 223f347c284SJohnny Huang printf("%02X ", buf[i]); 224f347c284SJohnny Huang if ((i + 1) % 16 == 0) 225f347c284SJohnny Huang printf("\n"); 226f347c284SJohnny Huang } 22788bd7d58SJohnny Huang printf("\n"); 228f347c284SJohnny Huang } 229f347c284SJohnny Huang 230794e27ecSJohnny Huang static int get_dw_bit(u32 *rid, int offset) 231794e27ecSJohnny Huang { 232794e27ecSJohnny Huang int bit_offset; 233794e27ecSJohnny Huang int i; 234794e27ecSJohnny Huang 235794e27ecSJohnny Huang if (offset < 32) { 236794e27ecSJohnny Huang i = 0; 237794e27ecSJohnny Huang bit_offset = offset; 238794e27ecSJohnny Huang } else { 239794e27ecSJohnny Huang i = 1; 240794e27ecSJohnny Huang bit_offset = offset - 32; 241794e27ecSJohnny Huang } 242794e27ecSJohnny Huang if ((rid[i] >> bit_offset) & 0x1) 243794e27ecSJohnny Huang return 1; 244794e27ecSJohnny Huang else 245794e27ecSJohnny Huang return 0; 246794e27ecSJohnny Huang } 247794e27ecSJohnny Huang 248794e27ecSJohnny Huang static int get_rid_num(u32 *rid) 249794e27ecSJohnny Huang { 250794e27ecSJohnny Huang int i; 251794e27ecSJohnny Huang int fz = 0; 252794e27ecSJohnny Huang int rid_num = 0; 253794e27ecSJohnny Huang int ret = 0; 254794e27ecSJohnny Huang 255794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 256794e27ecSJohnny Huang if (get_dw_bit(rid, i) == 0) { 257794e27ecSJohnny Huang if (!fz) 258794e27ecSJohnny Huang fz = 1; 259794e27ecSJohnny Huang 260794e27ecSJohnny Huang } else { 261794e27ecSJohnny Huang rid_num++; 262794e27ecSJohnny Huang if (fz) 263794e27ecSJohnny Huang ret = OTP_FAILURE; 264794e27ecSJohnny Huang } 265794e27ecSJohnny Huang } 266794e27ecSJohnny Huang if (ret) 267794e27ecSJohnny Huang return ret; 268794e27ecSJohnny Huang 269794e27ecSJohnny Huang return rid_num; 270794e27ecSJohnny Huang } 271794e27ecSJohnny Huang 272a219f6deSJohnny Huang static u32 chip_version(void) 2739a4fe690SJohnny Huang { 274e417205bSJohnny Huang u32 revid0, revid1; 2759a4fe690SJohnny Huang 276e417205bSJohnny Huang revid0 = readl(ASPEED_REVISION_ID0); 277e417205bSJohnny Huang revid1 = readl(ASPEED_REVISION_ID1); 2789a4fe690SJohnny Huang 279e417205bSJohnny Huang if (revid0 == ID0_AST2600A0 && revid1 == ID1_AST2600A0) { 280badd21c2SJohnny Huang /* AST2600-A0 */ 281e417205bSJohnny Huang return OTP_A0; 282e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A1 && revid1 == ID1_AST2600A1) { 283badd21c2SJohnny Huang /* AST2600-A1 */ 284e417205bSJohnny Huang return OTP_A1; 285e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A2 && revid1 == ID1_AST2600A2) { 286badd21c2SJohnny Huang /* AST2600-A2 */ 287e417205bSJohnny Huang return OTP_A2; 288e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A3 && revid1 == ID1_AST2600A3) { 28964b66712SJohnny Huang /* AST2600-A3 */ 290e417205bSJohnny Huang return OTP_A3; 291e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A1 && revid1 == ID1_AST2620A1) { 292e417205bSJohnny Huang /* AST2620-A1 */ 293e417205bSJohnny Huang return OTP_A1; 294e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A2 && revid1 == ID1_AST2620A2) { 295e417205bSJohnny Huang /* AST2620-A2 */ 296e417205bSJohnny Huang return OTP_A2; 297e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A3 && revid1 == ID1_AST2620A3) { 29864b66712SJohnny Huang /* AST2620-A3 */ 299e417205bSJohnny Huang return OTP_A3; 300e417205bSJohnny Huang } else if (revid0 == ID0_AST2605A2 && revid1 == ID1_AST2605A2) { 301e417205bSJohnny Huang /* AST2605-A2 */ 302e417205bSJohnny Huang return OTP_A2; 303e417205bSJohnny Huang } else if (revid0 == ID0_AST2605A3 && revid1 == ID1_AST2605A3) { 304e417205bSJohnny Huang /* AST2605-A3 */ 305e417205bSJohnny Huang return OTP_A3; 306e417205bSJohnny Huang } else if (revid0 == ID0_AST2625A3 && revid1 == ID1_AST2625A3) { 307e417205bSJohnny Huang /* AST2605-A3 */ 308e417205bSJohnny Huang return OTP_A3; 3090dae9d52SJohnny Huang } 310f347c284SJohnny Huang return OTP_FAILURE; 3119a4fe690SJohnny Huang } 3129a4fe690SJohnny Huang 3132031a123SJohnny Huang static int wait_complete(void) 3143d3688adSJohnny Huang { 3152031a123SJohnny Huang u32 val; 3162031a123SJohnny Huang int ret; 3173d3688adSJohnny Huang 3182031a123SJohnny Huang udelay(1); 3192031a123SJohnny Huang ret = readl_poll_timeout(OTP_STATUS, val, (val & 0x6) == 0x6, 100000); 3202031a123SJohnny Huang if (ret) 3212031a123SJohnny Huang printf("%s: timeout, SEC14 = 0x%x\n", __func__, val); 3222031a123SJohnny Huang 3232031a123SJohnny Huang return ret; 3243d3688adSJohnny Huang } 3253d3688adSJohnny Huang 326a219f6deSJohnny Huang static void otp_write(u32 otp_addr, u32 data) 327dacbba92SJohnny Huang { 328dacbba92SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 329dacbba92SJohnny Huang writel(data, OTP_COMPARE_1); //write data 330dacbba92SJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 331dacbba92SJohnny Huang wait_complete(); 332dacbba92SJohnny Huang } 333dacbba92SJohnny Huang 334dacbba92SJohnny Huang static void otp_soak(int soak) 335dacbba92SJohnny Huang { 336e417205bSJohnny Huang if (info_cb.version == OTP_A2 || info_cb.version == OTP_A3) { 337dacbba92SJohnny Huang switch (soak) { 338dacbba92SJohnny Huang case 0: //default 339377f8cd7SJohnny Huang otp_write(0x3000, 0x0); // Write MRA 340377f8cd7SJohnny Huang otp_write(0x5000, 0x0); // Write MRB 341dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 342dacbba92SJohnny Huang break; 343dacbba92SJohnny Huang case 1: //normal program 344377f8cd7SJohnny Huang otp_write(0x3000, 0x1320); // Write MRA 345377f8cd7SJohnny Huang otp_write(0x5000, 0x1008); // Write MRB 346377f8cd7SJohnny Huang otp_write(0x1000, 0x0024); // Write MR 347feea3fdfSJohnny Huang writel(0x04191388, OTP_TIMING); // 200us 348dacbba92SJohnny Huang break; 349dacbba92SJohnny Huang case 2: //soak program 350377f8cd7SJohnny Huang otp_write(0x3000, 0x1320); // Write MRA 351377f8cd7SJohnny Huang otp_write(0x5000, 0x0007); // Write MRB 352377f8cd7SJohnny Huang otp_write(0x1000, 0x0100); // Write MR 353feea3fdfSJohnny Huang writel(0x04193a98, OTP_TIMING); // 600us 354dacbba92SJohnny Huang break; 355dacbba92SJohnny Huang } 356dacbba92SJohnny Huang } else { 357dacbba92SJohnny Huang switch (soak) { 358dacbba92SJohnny Huang case 0: //default 359dacbba92SJohnny Huang otp_write(0x3000, 0x0); // Write MRA 360dacbba92SJohnny Huang otp_write(0x5000, 0x0); // Write MRB 361dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 362dacbba92SJohnny Huang break; 363dacbba92SJohnny Huang case 1: //normal program 364dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 365dacbba92SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 366dacbba92SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 367feea3fdfSJohnny Huang writel(0x04190760, OTP_TIMING); // 75us 368dacbba92SJohnny Huang break; 369dacbba92SJohnny Huang case 2: //soak program 370dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 371dacbba92SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 372dacbba92SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 373feea3fdfSJohnny Huang writel(0x041930d4, OTP_TIMING); // 500us 374dacbba92SJohnny Huang break; 375dacbba92SJohnny Huang } 376dacbba92SJohnny Huang } 377dacbba92SJohnny Huang 378dacbba92SJohnny Huang wait_complete(); 379dacbba92SJohnny Huang } 380dacbba92SJohnny Huang 381a219f6deSJohnny Huang static void otp_read_data(u32 offset, u32 *data) 38269d5fd8fSJohnny Huang { 3833d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 3843d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 3853d3688adSJohnny Huang wait_complete(); 3863d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 3873d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 38869d5fd8fSJohnny Huang } 38969d5fd8fSJohnny Huang 390f347c284SJohnny Huang static void otp_read_conf(u32 offset, u32 *data) 39169d5fd8fSJohnny Huang { 39269d5fd8fSJohnny Huang int config_offset; 39369d5fd8fSJohnny Huang 39469d5fd8fSJohnny Huang config_offset = 0x800; 39569d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 39669d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 39769d5fd8fSJohnny Huang 3983d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 3993d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4003d3688adSJohnny Huang wait_complete(); 4013d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 40269d5fd8fSJohnny Huang } 40369d5fd8fSJohnny Huang 404a219f6deSJohnny Huang static int otp_compare(u32 otp_addr, u32 addr) 40569d5fd8fSJohnny Huang { 406a219f6deSJohnny Huang u32 ret; 407a219f6deSJohnny Huang u32 *buf; 40869d5fd8fSJohnny Huang 40969d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 41069d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 41169d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 41269d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 41369d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 4143d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 4153d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 4163d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 4173d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 4183d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 4193d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 4203d3688adSJohnny Huang wait_complete(); 4213d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 42269d5fd8fSJohnny Huang if (ret & 0x1) 423f347c284SJohnny Huang return OTP_SUCCESS; 42469d5fd8fSJohnny Huang else 425f347c284SJohnny Huang return OTP_FAILURE; 42669d5fd8fSJohnny Huang } 42769d5fd8fSJohnny Huang 428a219f6deSJohnny Huang static int verify_bit(u32 otp_addr, int bit_offset, int value) 42969d5fd8fSJohnny Huang { 430a219f6deSJohnny Huang u32 ret[2]; 43169d5fd8fSJohnny Huang 43230a8c590SJohnny Huang if (otp_addr % 2 == 0) 4333d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 43430a8c590SJohnny Huang else 4353d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 43630a8c590SJohnny Huang 4373d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4383d3688adSJohnny Huang wait_complete(); 4393d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4403d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 44183655e91SJohnny Huang 44230a8c590SJohnny Huang if (otp_addr % 2 == 0) { 44330a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 444f347c284SJohnny Huang return OTP_SUCCESS; 44569d5fd8fSJohnny Huang else 446f347c284SJohnny Huang return OTP_FAILURE; 44730a8c590SJohnny Huang } else { 44830a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 449f347c284SJohnny Huang return OTP_SUCCESS; 45030a8c590SJohnny Huang else 451f347c284SJohnny Huang return OTP_FAILURE; 45230a8c590SJohnny Huang } 45369d5fd8fSJohnny Huang } 45469d5fd8fSJohnny Huang 455a219f6deSJohnny Huang static u32 verify_dw(u32 otp_addr, u32 *value, u32 *ignore, u32 *compare, int size) 4564c1c9b35SJohnny Huang { 457a219f6deSJohnny Huang u32 ret[2]; 4584c1c9b35SJohnny Huang 4594c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4604c1c9b35SJohnny Huang 4614c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4623d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 4634c1c9b35SJohnny Huang else 4643d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 4653d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4663d3688adSJohnny Huang wait_complete(); 4673d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4683d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 4694c1c9b35SJohnny Huang if (size == 1) { 4704c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4714c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 472696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) { 4734c1c9b35SJohnny Huang compare[0] = 0; 474f347c284SJohnny Huang return OTP_SUCCESS; 475a219f6deSJohnny Huang } 4764c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 477f347c284SJohnny Huang return OTP_FAILURE; 4784c1c9b35SJohnny Huang 4794c1c9b35SJohnny Huang } else { 4804c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 481696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) { 4824c1c9b35SJohnny Huang compare[0] = ~0; 483f347c284SJohnny Huang return OTP_SUCCESS; 484a219f6deSJohnny Huang } 485d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 486f347c284SJohnny Huang return OTP_FAILURE; 4874c1c9b35SJohnny Huang } 4884c1c9b35SJohnny Huang } else if (size == 2) { 4894c1c9b35SJohnny Huang // otp_addr should be even 490696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) { 4914c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4924c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4934c1c9b35SJohnny Huang compare[0] = 0; 4944c1c9b35SJohnny Huang compare[1] = ~0; 495f347c284SJohnny Huang return OTP_SUCCESS; 496a219f6deSJohnny Huang } 4974c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4984c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4994c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 5004c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 501f347c284SJohnny Huang return OTP_FAILURE; 5024c1c9b35SJohnny Huang } else { 503f347c284SJohnny Huang return OTP_FAILURE; 5044c1c9b35SJohnny Huang } 5054c1c9b35SJohnny Huang } 5064c1c9b35SJohnny Huang 5072031a123SJohnny Huang static int otp_prog(u32 otp_addr, u32 prog_bit) 50883655e91SJohnny Huang { 50990965bb3SJohnny Huang otp_write(0x0, prog_bit); 51083655e91SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 51183655e91SJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 51283655e91SJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 5132031a123SJohnny Huang 5142031a123SJohnny Huang return wait_complete(); 51583655e91SJohnny Huang } 51683655e91SJohnny Huang 5172031a123SJohnny Huang static int _otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset) 51883655e91SJohnny Huang { 51983655e91SJohnny Huang int prog_bit; 52083655e91SJohnny Huang 52183655e91SJohnny Huang if (prog_address % 2 == 0) { 52283655e91SJohnny Huang if (value) 52383655e91SJohnny Huang prog_bit = ~(0x1 << bit_offset); 52483655e91SJohnny Huang else 5252031a123SJohnny Huang return 0; 52683655e91SJohnny Huang } else { 527e417205bSJohnny Huang if (info_cb.version != OTP_A3) 52883655e91SJohnny Huang prog_address |= 1 << 15; 52983655e91SJohnny Huang if (!value) 53083655e91SJohnny Huang prog_bit = 0x1 << bit_offset; 53183655e91SJohnny Huang else 5322031a123SJohnny Huang return 0; 53383655e91SJohnny Huang } 5342031a123SJohnny Huang return otp_prog(prog_address, prog_bit); 53583655e91SJohnny Huang } 53683655e91SJohnny Huang 537f347c284SJohnny Huang static int otp_prog_dc_b(u32 value, u32 prog_address, u32 bit_offset) 53883655e91SJohnny Huang { 53983655e91SJohnny Huang int pass; 54083655e91SJohnny Huang int i; 5412031a123SJohnny Huang int ret; 54283655e91SJohnny Huang 54383655e91SJohnny Huang otp_soak(1); 5442031a123SJohnny Huang ret = _otp_prog_bit(value, prog_address, bit_offset); 5452031a123SJohnny Huang if (ret) 5462031a123SJohnny Huang return OTP_FAILURE; 54783655e91SJohnny Huang pass = 0; 54883655e91SJohnny Huang 54983655e91SJohnny Huang for (i = 0; i < RETRY; i++) { 55083655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 55183655e91SJohnny Huang otp_soak(2); 5522031a123SJohnny Huang ret = _otp_prog_bit(value, prog_address, bit_offset); 5532031a123SJohnny Huang if (ret) 5542031a123SJohnny Huang return OTP_FAILURE; 55583655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 55683655e91SJohnny Huang otp_soak(1); 55783655e91SJohnny Huang } else { 55883655e91SJohnny Huang pass = 1; 55983655e91SJohnny Huang break; 56083655e91SJohnny Huang } 56183655e91SJohnny Huang } else { 56283655e91SJohnny Huang pass = 1; 56383655e91SJohnny Huang break; 56483655e91SJohnny Huang } 56583655e91SJohnny Huang } 566794e27ecSJohnny Huang if (pass) 567794e27ecSJohnny Huang return OTP_SUCCESS; 56883655e91SJohnny Huang 569794e27ecSJohnny Huang return OTP_FAILURE; 57083655e91SJohnny Huang } 57183655e91SJohnny Huang 5722031a123SJohnny Huang static int otp_prog_dw(u32 value, u32 ignore, u32 prog_address) 573d90825e2SJohnny Huang { 574d90825e2SJohnny Huang int j, bit_value, prog_bit; 5752031a123SJohnny Huang int ret; 576d90825e2SJohnny Huang 577d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 578696656c6SJohnny Huang if ((ignore >> j) & 0x1) 579d90825e2SJohnny Huang continue; 580d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 581d90825e2SJohnny Huang if (prog_address % 2 == 0) { 582d90825e2SJohnny Huang if (bit_value) 583d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 584d90825e2SJohnny Huang else 585d90825e2SJohnny Huang continue; 586d90825e2SJohnny Huang } else { 587e417205bSJohnny Huang if (info_cb.version != OTP_A3) 588d90825e2SJohnny Huang prog_address |= 1 << 15; 589d90825e2SJohnny Huang if (bit_value) 590d90825e2SJohnny Huang continue; 591d90825e2SJohnny Huang else 592d90825e2SJohnny Huang prog_bit = 0x1 << j; 593d90825e2SJohnny Huang } 5942031a123SJohnny Huang ret = otp_prog(prog_address, prog_bit); 5952031a123SJohnny Huang if (ret) 5962031a123SJohnny Huang return ret; 597d90825e2SJohnny Huang } 5982031a123SJohnny Huang return 0; 599d90825e2SJohnny Huang } 600d90825e2SJohnny Huang 601a219f6deSJohnny Huang static int otp_prog_verify_2dw(u32 *data, u32 *buf, u32 *ignore_mask, u32 prog_address) 60254552c69SJohnny Huang { 60354552c69SJohnny Huang int pass; 60454552c69SJohnny Huang int i; 605a219f6deSJohnny Huang u32 data0_masked; 606a219f6deSJohnny Huang u32 data1_masked; 607a219f6deSJohnny Huang u32 buf0_masked; 608a219f6deSJohnny Huang u32 buf1_masked; 609a219f6deSJohnny Huang u32 compare[2]; 6102031a123SJohnny Huang int ret; 61154552c69SJohnny Huang 61254552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 61354552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 61454552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 61554552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 616a219f6deSJohnny Huang if (data0_masked == buf0_masked && data1_masked == buf1_masked) 617f347c284SJohnny Huang return OTP_SUCCESS; 61854552c69SJohnny Huang 619b64ca396SJohnny Huang for (i = 0; i < 32; i++) { 620b64ca396SJohnny Huang if (((data0_masked >> i) & 0x1) == 1 && ((buf0_masked >> i) & 0x1) == 0) 621b64ca396SJohnny Huang return OTP_FAILURE; 622b64ca396SJohnny Huang if (((data1_masked >> i) & 0x1) == 0 && ((buf1_masked >> i) & 0x1) == 1) 623b64ca396SJohnny Huang return OTP_FAILURE; 624b64ca396SJohnny Huang } 625b64ca396SJohnny Huang 62654552c69SJohnny Huang otp_soak(1); 6272031a123SJohnny Huang if (data0_masked != buf0_masked) { 6282031a123SJohnny Huang ret = otp_prog_dw(buf[0], ignore_mask[0], prog_address); 6292031a123SJohnny Huang if (ret) 6302031a123SJohnny Huang return OTP_FAILURE; 6312031a123SJohnny Huang } 6322031a123SJohnny Huang 6332031a123SJohnny Huang if (data1_masked != buf1_masked) { 6342031a123SJohnny Huang ret = otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 6352031a123SJohnny Huang if (ret) 6362031a123SJohnny Huang return OTP_FAILURE; 6372031a123SJohnny Huang } 63854552c69SJohnny Huang 63954552c69SJohnny Huang pass = 0; 64054552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 64154552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 64254552c69SJohnny Huang otp_soak(2); 6432031a123SJohnny Huang if (compare[0] != 0) { 6442031a123SJohnny Huang ret = otp_prog_dw(compare[0], ignore_mask[0], prog_address); 6452031a123SJohnny Huang if (ret) 6462031a123SJohnny Huang return OTP_FAILURE; 6472031a123SJohnny Huang } 6482031a123SJohnny Huang if (compare[1] != ~0) { 6492031a123SJohnny Huang ret = otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1); 6502031a123SJohnny Huang if (ret) 6512031a123SJohnny Huang return OTP_FAILURE; 6522031a123SJohnny Huang } 65354552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 65454552c69SJohnny Huang otp_soak(1); 65554552c69SJohnny Huang } else { 65654552c69SJohnny Huang pass = 1; 65754552c69SJohnny Huang break; 65854552c69SJohnny Huang } 65954552c69SJohnny Huang } else { 66054552c69SJohnny Huang pass = 1; 66154552c69SJohnny Huang break; 66254552c69SJohnny Huang } 66354552c69SJohnny Huang } 66454552c69SJohnny Huang 66554552c69SJohnny Huang if (!pass) { 66654552c69SJohnny Huang otp_soak(0); 66754552c69SJohnny Huang return OTP_FAILURE; 66854552c69SJohnny Huang } 66954552c69SJohnny Huang return OTP_SUCCESS; 67054552c69SJohnny Huang } 67154552c69SJohnny Huang 672541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 67376d13988SJohnny Huang { 674a219f6deSJohnny Huang u32 OTPSTRAP_RAW[2]; 6755010032bSJohnny Huang int strap_end; 67676d13988SJohnny Huang int i, j; 67776d13988SJohnny Huang 678e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 67976d13988SJohnny Huang for (j = 0; j < 64; j++) { 68076d13988SJohnny Huang otpstrap[j].value = 0; 68176d13988SJohnny Huang otpstrap[j].remain_times = 7; 68276d13988SJohnny Huang otpstrap[j].writeable_option = -1; 68376d13988SJohnny Huang otpstrap[j].protected = 0; 68476d13988SJohnny Huang } 6855010032bSJohnny Huang strap_end = 30; 6865010032bSJohnny Huang } else { 6875010032bSJohnny Huang for (j = 0; j < 64; j++) { 6885010032bSJohnny Huang otpstrap[j].value = 0; 6895010032bSJohnny Huang otpstrap[j].remain_times = 6; 6905010032bSJohnny Huang otpstrap[j].writeable_option = -1; 6915010032bSJohnny Huang otpstrap[j].protected = 0; 6925010032bSJohnny Huang } 6935010032bSJohnny Huang strap_end = 28; 6945010032bSJohnny Huang } 69576d13988SJohnny Huang 696dacbba92SJohnny Huang otp_soak(0); 6975010032bSJohnny Huang for (i = 16; i < strap_end; i += 2) { 69876d13988SJohnny Huang int option = (i - 16) / 2; 699a219f6deSJohnny Huang 700f347c284SJohnny Huang otp_read_conf(i, &OTPSTRAP_RAW[0]); 701f347c284SJohnny Huang otp_read_conf(i + 1, &OTPSTRAP_RAW[1]); 70276d13988SJohnny Huang for (j = 0; j < 32; j++) { 70376d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 704a219f6deSJohnny Huang 705a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 70676d13988SJohnny Huang otpstrap[j].writeable_option = option; 70776d13988SJohnny Huang if (bit_value == 1) 70876d13988SJohnny Huang otpstrap[j].remain_times--; 70976d13988SJohnny Huang otpstrap[j].value ^= bit_value; 71076d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 71176d13988SJohnny Huang } 71276d13988SJohnny Huang for (j = 32; j < 64; j++) { 71376d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 714a219f6deSJohnny Huang 715a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 71676d13988SJohnny Huang otpstrap[j].writeable_option = option; 71776d13988SJohnny Huang if (bit_value == 1) 71876d13988SJohnny Huang otpstrap[j].remain_times--; 71976d13988SJohnny Huang otpstrap[j].value ^= bit_value; 72076d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 72176d13988SJohnny Huang } 72276d13988SJohnny Huang } 7235010032bSJohnny Huang 724f347c284SJohnny Huang otp_read_conf(30, &OTPSTRAP_RAW[0]); 725f347c284SJohnny Huang otp_read_conf(31, &OTPSTRAP_RAW[1]); 72676d13988SJohnny Huang for (j = 0; j < 32; j++) { 72776d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 72876d13988SJohnny Huang otpstrap[j].protected = 1; 72976d13988SJohnny Huang } 73076d13988SJohnny Huang for (j = 32; j < 64; j++) { 73176d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 73276d13988SJohnny Huang otpstrap[j].protected = 1; 73376d13988SJohnny Huang } 73476d13988SJohnny Huang } 73576d13988SJohnny Huang 7367e523e3bSJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit) 737f347c284SJohnny Huang { 738f347c284SJohnny Huang int prog_flag = 0; 739f347c284SJohnny Huang 740f347c284SJohnny Huang // ignore this bit 741f347c284SJohnny Huang if (ibit == 1) 742f347c284SJohnny Huang return OTP_SUCCESS; 743b489486eSJohnny Huang printf("OTPSTRAP[0x%X]:\n", offset); 744f347c284SJohnny Huang 745f347c284SJohnny Huang if (bit == otpstrap->value) { 7467e523e3bSJohnny Huang if (!pbit) { 747f347c284SJohnny Huang printf(" The value is same as before, skip it.\n"); 748f347c284SJohnny Huang return OTP_PROG_SKIP; 749f347c284SJohnny Huang } 750f347c284SJohnny Huang printf(" The value is same as before.\n"); 751f347c284SJohnny Huang } else { 752f347c284SJohnny Huang prog_flag = 1; 753f347c284SJohnny Huang } 754f347c284SJohnny Huang if (otpstrap->protected == 1 && prog_flag) { 755f347c284SJohnny Huang printf(" This bit is protected and is not writable\n"); 756f347c284SJohnny Huang return OTP_FAILURE; 757f347c284SJohnny Huang } 758f347c284SJohnny Huang if (otpstrap->remain_times == 0 && prog_flag) { 759b489486eSJohnny Huang printf(" This bit has no remaining chance to write.\n"); 760f347c284SJohnny Huang return OTP_FAILURE; 761f347c284SJohnny Huang } 762f347c284SJohnny Huang if (pbit == 1) 763f347c284SJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 764f347c284SJohnny Huang if (prog_flag) 765b489486eSJohnny Huang printf(" Write 1 to OTPSTRAP[0x%X] OPTION[0x%X], that value becomes from 0x%X to 0x%X.\n", offset, otpstrap->writeable_option + 1, otpstrap->value, otpstrap->value ^ 1); 766f347c284SJohnny Huang 767f347c284SJohnny Huang return OTP_SUCCESS; 768f347c284SJohnny Huang } 769f347c284SJohnny Huang 770f347c284SJohnny Huang static int otp_prog_strap_b(int bit_offset, int value) 771f347c284SJohnny Huang { 772f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 773f347c284SJohnny Huang u32 prog_address; 774f347c284SJohnny Huang int offset; 775f347c284SJohnny Huang int ret; 776f347c284SJohnny Huang 777f347c284SJohnny Huang otp_strap_status(otpstrap); 778f347c284SJohnny Huang 7797e523e3bSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0); 780f347c284SJohnny Huang 781f347c284SJohnny Huang if (ret != OTP_SUCCESS) 782f347c284SJohnny Huang return ret; 783f347c284SJohnny Huang 784f347c284SJohnny Huang prog_address = 0x800; 785f347c284SJohnny Huang if (bit_offset < 32) { 786f347c284SJohnny Huang offset = bit_offset; 787f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200; 788f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2; 789f347c284SJohnny Huang 790f347c284SJohnny Huang } else { 791f347c284SJohnny Huang offset = (bit_offset - 32); 792f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200; 793f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2; 794f347c284SJohnny Huang } 795f347c284SJohnny Huang 796f347c284SJohnny Huang return otp_prog_dc_b(1, prog_address, offset); 797f347c284SJohnny Huang } 798f347c284SJohnny Huang 799f347c284SJohnny Huang static int otp_print_conf(u32 offset, int dw_count) 800f347c284SJohnny Huang { 801f347c284SJohnny Huang int i; 802f347c284SJohnny Huang u32 ret[1]; 803f347c284SJohnny Huang 804f347c284SJohnny Huang if (offset + dw_count > 32) 805f347c284SJohnny Huang return OTP_USAGE; 806f347c284SJohnny Huang otp_soak(0); 807f347c284SJohnny Huang for (i = offset; i < offset + dw_count; i++) { 808f347c284SJohnny Huang otp_read_conf(i, ret); 809b489486eSJohnny Huang printf("OTPCFG0x%X: 0x%08X\n", i, ret[0]); 810f347c284SJohnny Huang } 811f347c284SJohnny Huang printf("\n"); 812f347c284SJohnny Huang return OTP_SUCCESS; 813f347c284SJohnny Huang } 814f347c284SJohnny Huang 815f347c284SJohnny Huang static int otp_print_data(u32 offset, int dw_count) 816f347c284SJohnny Huang { 817f347c284SJohnny Huang int i; 818f347c284SJohnny Huang u32 ret[2]; 819f347c284SJohnny Huang 820f347c284SJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 821f347c284SJohnny Huang return OTP_USAGE; 822f347c284SJohnny Huang otp_soak(0); 823f347c284SJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 824f347c284SJohnny Huang otp_read_data(i, ret); 825f347c284SJohnny Huang if (i % 4 == 0) 826f347c284SJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 827f347c284SJohnny Huang else 828f347c284SJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 829f347c284SJohnny Huang } 830f347c284SJohnny Huang printf("\n"); 831f347c284SJohnny Huang return OTP_SUCCESS; 832f347c284SJohnny Huang } 833f347c284SJohnny Huang 834f347c284SJohnny Huang static int otp_print_strap(int start, int count) 835f347c284SJohnny Huang { 836f347c284SJohnny Huang int i, j; 837f347c284SJohnny Huang int remains; 838f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 839f347c284SJohnny Huang 840f347c284SJohnny Huang if (start < 0 || start > 64) 841f347c284SJohnny Huang return OTP_USAGE; 842f347c284SJohnny Huang 843f347c284SJohnny Huang if ((start + count) < 0 || (start + count) > 64) 844f347c284SJohnny Huang return OTP_USAGE; 845f347c284SJohnny Huang 846f347c284SJohnny Huang otp_strap_status(otpstrap); 847f347c284SJohnny Huang 8487e523e3bSJohnny Huang if (info_cb.version == OTP_A0) 849f347c284SJohnny Huang remains = 7; 8507e523e3bSJohnny Huang else 851f347c284SJohnny Huang remains = 6; 8527e523e3bSJohnny Huang printf("BIT(hex) Value Option Status\n"); 853f347c284SJohnny Huang printf("______________________________________________________________________________\n"); 854f347c284SJohnny Huang 855f347c284SJohnny Huang for (i = start; i < start + count; i++) { 856f347c284SJohnny Huang printf("0x%-8X", i); 857f347c284SJohnny Huang printf("%-7d", otpstrap[i].value); 858f347c284SJohnny Huang for (j = 0; j < remains; j++) 859f347c284SJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 860f347c284SJohnny Huang printf(" "); 861f347c284SJohnny Huang if (otpstrap[i].protected == 1) { 862f347c284SJohnny Huang printf("protected and not writable"); 863f347c284SJohnny Huang } else { 864f347c284SJohnny Huang printf("not protected "); 865f347c284SJohnny Huang if (otpstrap[i].remain_times == 0) 866f347c284SJohnny Huang printf("and no remaining times to write."); 867f347c284SJohnny Huang else 868f347c284SJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 869f347c284SJohnny Huang } 870f347c284SJohnny Huang printf("\n"); 871f347c284SJohnny Huang } 872f347c284SJohnny Huang 873f347c284SJohnny Huang return OTP_SUCCESS; 874f347c284SJohnny Huang } 875f347c284SJohnny Huang 876794e27ecSJohnny Huang static void otp_print_revid(u32 *rid) 877794e27ecSJohnny Huang { 878794e27ecSJohnny Huang int bit_offset; 879794e27ecSJohnny Huang int i, j; 880794e27ecSJohnny Huang 881794e27ecSJohnny Huang printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); 882794e27ecSJohnny Huang printf("___________________________________________________\n"); 883794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 884794e27ecSJohnny Huang if (i < 32) { 885794e27ecSJohnny Huang j = 0; 886794e27ecSJohnny Huang bit_offset = i; 887794e27ecSJohnny Huang } else { 888794e27ecSJohnny Huang j = 1; 889794e27ecSJohnny Huang bit_offset = i - 32; 890794e27ecSJohnny Huang } 891794e27ecSJohnny Huang if (i % 16 == 0) 892794e27ecSJohnny Huang printf("%2x | ", i); 893794e27ecSJohnny Huang printf("%d ", (rid[j] >> bit_offset) & 0x1); 894794e27ecSJohnny Huang if ((i + 1) % 16 == 0) 895794e27ecSJohnny Huang printf("\n"); 896794e27ecSJohnny Huang } 897794e27ecSJohnny Huang } 898794e27ecSJohnny Huang 899b25f02d2SJohnny Huang static int otp_print_scu_image(struct otp_image_layout *image_layout) 900b25f02d2SJohnny Huang { 901b25f02d2SJohnny Huang const struct scu_info *scu_info = info_cb.scu_info; 902b25f02d2SJohnny Huang u32 *OTPSCU = (u32 *)image_layout->scu_pro; 903b25f02d2SJohnny Huang u32 *OTPSCU_IGNORE = (u32 *)image_layout->scu_pro_ignore; 904b25f02d2SJohnny Huang int i; 905b25f02d2SJohnny Huang u32 scu_offset; 906b25f02d2SJohnny Huang u32 dw_offset; 907b25f02d2SJohnny Huang u32 bit_offset; 908b25f02d2SJohnny Huang u32 mask; 909b25f02d2SJohnny Huang u32 otp_value; 910b25f02d2SJohnny Huang u32 otp_ignore; 911b25f02d2SJohnny Huang 912b25f02d2SJohnny Huang printf("SCU BIT reg_protect Description\n"); 913b25f02d2SJohnny Huang printf("____________________________________________________________________\n"); 914b25f02d2SJohnny Huang for (i = 0; i < info_cb.scu_info_len; i++) { 915b25f02d2SJohnny Huang mask = BIT(scu_info[i].length) - 1; 916b25f02d2SJohnny Huang 917b25f02d2SJohnny Huang if (scu_info[i].bit_offset > 31) { 918b25f02d2SJohnny Huang scu_offset = 0x510; 919b25f02d2SJohnny Huang dw_offset = 1; 920b25f02d2SJohnny Huang bit_offset = scu_info[i].bit_offset - 32; 921b25f02d2SJohnny Huang } else { 922b25f02d2SJohnny Huang scu_offset = 0x500; 923b25f02d2SJohnny Huang dw_offset = 0; 924b25f02d2SJohnny Huang bit_offset = scu_info[i].bit_offset; 925b25f02d2SJohnny Huang } 926b25f02d2SJohnny Huang 927b25f02d2SJohnny Huang otp_value = (OTPSCU[dw_offset] >> bit_offset) & mask; 928b25f02d2SJohnny Huang otp_ignore = (OTPSCU_IGNORE[dw_offset] >> bit_offset) & mask; 929b25f02d2SJohnny Huang 930b25f02d2SJohnny Huang if (otp_ignore == mask) 931b25f02d2SJohnny Huang continue; 932b25f02d2SJohnny Huang else if (otp_ignore != 0) 933b25f02d2SJohnny Huang return OTP_FAILURE; 934b25f02d2SJohnny Huang 935b25f02d2SJohnny Huang if (otp_value != 0 && otp_value != mask) 936b25f02d2SJohnny Huang return OTP_FAILURE; 937b25f02d2SJohnny Huang 938b25f02d2SJohnny Huang printf("0x%-6X", scu_offset); 939b25f02d2SJohnny Huang if (scu_info[i].length == 1) 940b25f02d2SJohnny Huang printf("0x%-11X", bit_offset); 941b25f02d2SJohnny Huang else 9422131c250SJohnny Huang printf("0x%-2X:0x%-6x", bit_offset, bit_offset + scu_info[i].length - 1); 943b25f02d2SJohnny Huang printf("0x%-14X", otp_value); 944b25f02d2SJohnny Huang printf("%s\n", scu_info[i].information); 945b25f02d2SJohnny Huang } 946b25f02d2SJohnny Huang return OTP_SUCCESS; 947b25f02d2SJohnny Huang } 948b25f02d2SJohnny Huang 9490dc9a440SJohnny Huang static void otp_print_scu_info(void) 9500dc9a440SJohnny Huang { 9510dc9a440SJohnny Huang const struct scu_info *scu_info = info_cb.scu_info; 9520dc9a440SJohnny Huang u32 OTPCFG[2]; 9530dc9a440SJohnny Huang u32 scu_offset; 9540dc9a440SJohnny Huang u32 bit_offset; 9550dc9a440SJohnny Huang u32 reg_p; 9560dc9a440SJohnny Huang u32 length; 9570dc9a440SJohnny Huang int i, j; 9580dc9a440SJohnny Huang 9590dc9a440SJohnny Huang otp_soak(0); 9600dc9a440SJohnny Huang otp_read_conf(28, &OTPCFG[0]); 9610dc9a440SJohnny Huang otp_read_conf(29, &OTPCFG[1]); 9620dc9a440SJohnny Huang printf("SCU BIT reg_protect Description\n"); 9630dc9a440SJohnny Huang printf("____________________________________________________________________\n"); 9640dc9a440SJohnny Huang for (i = 0; i < info_cb.scu_info_len; i++) { 9650dc9a440SJohnny Huang length = scu_info[i].length; 9660dc9a440SJohnny Huang for (j = 0; j < length; j++) { 9670dc9a440SJohnny Huang if (scu_info[i].bit_offset + j < 32) { 9680dc9a440SJohnny Huang scu_offset = 0x500; 9690dc9a440SJohnny Huang bit_offset = scu_info[i].bit_offset + j; 9700dc9a440SJohnny Huang reg_p = (OTPCFG[0] >> bit_offset) & 0x1; 9710dc9a440SJohnny Huang } else { 9720dc9a440SJohnny Huang scu_offset = 0x510; 9730dc9a440SJohnny Huang bit_offset = scu_info[i].bit_offset + j - 32; 9740dc9a440SJohnny Huang reg_p = (OTPCFG[1] >> bit_offset) & 0x1; 9750dc9a440SJohnny Huang } 9760dc9a440SJohnny Huang printf("0x%-6X", scu_offset); 9770dc9a440SJohnny Huang printf("0x%-4X", bit_offset); 9780dc9a440SJohnny Huang printf("0x%-13X", reg_p); 9790dc9a440SJohnny Huang if (length == 1) { 9800dc9a440SJohnny Huang printf(" %s\n", scu_info[i].information); 9810dc9a440SJohnny Huang continue; 9820dc9a440SJohnny Huang } 9830dc9a440SJohnny Huang 9840dc9a440SJohnny Huang if (j == 0) 9850dc9a440SJohnny Huang printf("/%s\n", scu_info[i].information); 9860dc9a440SJohnny Huang else if (j == length - 1) 9870dc9a440SJohnny Huang printf("\\ \"\n"); 9880dc9a440SJohnny Huang else 9890dc9a440SJohnny Huang printf("| \"\n"); 9900dc9a440SJohnny Huang } 9910dc9a440SJohnny Huang } 9920dc9a440SJohnny Huang } 9930dc9a440SJohnny Huang 994696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout) 99569d5fd8fSJohnny Huang { 99679e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 997a219f6deSJohnny Huang u32 *OTPCFG = (u32 *)image_layout->conf; 998a219f6deSJohnny Huang u32 *OTPCFG_IGNORE = (u32 *)image_layout->conf_ignore; 999a219f6deSJohnny Huang u32 mask; 1000a219f6deSJohnny Huang u32 dw_offset; 1001a219f6deSJohnny Huang u32 bit_offset; 1002a219f6deSJohnny Huang u32 otp_value; 1003a219f6deSJohnny Huang u32 otp_ignore; 1004b458cd62SJohnny Huang int fail = 0; 10057adec5f6SJohnny Huang int mask_err; 1006794e27ecSJohnny Huang int rid_num = 0; 100773f11549SJohnny Huang char valid_bit[20]; 1008794e27ecSJohnny Huang int fz; 100966f2f8e5SJohnny Huang int i; 101073f11549SJohnny Huang int j; 101166f2f8e5SJohnny Huang 1012737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 101366f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 10143cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 10157adec5f6SJohnny Huang mask_err = 0; 10163cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 10173cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 10183cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 1019b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 1020696656c6SJohnny Huang otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask; 1021b458cd62SJohnny Huang 10227adec5f6SJohnny Huang if (conf_info[i].value == OTP_REG_VALID_BIT) { 10237adec5f6SJohnny Huang if (((otp_value + otp_ignore) & mask) != mask) { 1024b458cd62SJohnny Huang fail = 1; 10257adec5f6SJohnny Huang mask_err = 1; 10267adec5f6SJohnny Huang } 10277adec5f6SJohnny Huang } else { 10287adec5f6SJohnny Huang if (otp_ignore == mask) { 10297adec5f6SJohnny Huang continue; 10307adec5f6SJohnny Huang } else if (otp_ignore != 0) { 10317adec5f6SJohnny Huang fail = 1; 10327adec5f6SJohnny Huang mask_err = 1; 10337adec5f6SJohnny Huang } 10347adec5f6SJohnny Huang } 1035b458cd62SJohnny Huang 1036a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 10373cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 10383cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 10393cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 1040b458cd62SJohnny Huang continue; 1041b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 1042b458cd62SJohnny Huang 10433cb28812SJohnny Huang if (conf_info[i].length == 1) { 10443cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 104566f2f8e5SJohnny Huang } else { 1046b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10473cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 10483cb28812SJohnny Huang conf_info[i].bit_offset); 104966f2f8e5SJohnny Huang } 1050b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1051b458cd62SJohnny Huang 10527adec5f6SJohnny Huang if (mask_err) { 10537adec5f6SJohnny Huang printf("Ignore, mask error\n"); 1054a219f6deSJohnny Huang continue; 1055a219f6deSJohnny Huang } 10563cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1057b458cd62SJohnny Huang printf("Reserved\n"); 10583cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10593cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1060b458cd62SJohnny Huang printf("\n"); 10613cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1062b458cd62SJohnny Huang if (otp_value != 0) { 106373f11549SJohnny Huang for (j = 0; j < 7; j++) { 1064e2b82258SJohnny Huang if (otp_value & (1 << j)) 106573f11549SJohnny Huang valid_bit[j * 2] = '1'; 1066a219f6deSJohnny Huang else 106773f11549SJohnny Huang valid_bit[j * 2] = '0'; 106873f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 106973f11549SJohnny Huang } 107073f11549SJohnny Huang valid_bit[15] = 0; 107173f11549SJohnny Huang } else { 107273f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1073b458cd62SJohnny Huang } 10743cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1075b458cd62SJohnny Huang printf("\n"); 1076b458cd62SJohnny Huang } else { 10773cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1078b458cd62SJohnny Huang } 1079b458cd62SJohnny Huang } 1080b458cd62SJohnny Huang 1081794e27ecSJohnny Huang if (OTPCFG[0xa] != 0 || OTPCFG[0xb] != 0) { 1082794e27ecSJohnny Huang if (OTPCFG_IGNORE[0xa] != 0 && OTPCFG_IGNORE[0xb] != 0) { 1083794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 1084794e27ecSJohnny Huang fail = 1; 1085794e27ecSJohnny Huang } else { 1086794e27ecSJohnny Huang fz = 0; 1087794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 1088794e27ecSJohnny Huang if (get_dw_bit(&OTPCFG[0xa], i) == 0) { 1089794e27ecSJohnny Huang if (!fz) 1090794e27ecSJohnny Huang fz = 1; 1091794e27ecSJohnny Huang } else { 1092794e27ecSJohnny Huang rid_num++; 1093794e27ecSJohnny Huang if (fz) { 1094794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 1095794e27ecSJohnny Huang fail = 1; 1096794e27ecSJohnny Huang break; 1097794e27ecSJohnny Huang } 1098794e27ecSJohnny Huang } 1099794e27ecSJohnny Huang } 1100794e27ecSJohnny Huang } 1101794e27ecSJohnny Huang if (fail) 1102794e27ecSJohnny Huang printf("OTP revision ID\n"); 1103794e27ecSJohnny Huang else 1104794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 1105794e27ecSJohnny Huang otp_print_revid(&OTPCFG[0xa]); 1106794e27ecSJohnny Huang } 1107794e27ecSJohnny Huang 1108b458cd62SJohnny Huang if (fail) 1109b458cd62SJohnny Huang return OTP_FAILURE; 1110b458cd62SJohnny Huang 111166f2f8e5SJohnny Huang return OTP_SUCCESS; 111266f2f8e5SJohnny Huang } 111366f2f8e5SJohnny Huang 11142d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 111566f2f8e5SJohnny Huang { 111679e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 1117a219f6deSJohnny Huang u32 OTPCFG[16]; 1118a219f6deSJohnny Huang u32 mask; 1119a219f6deSJohnny Huang u32 dw_offset; 1120a219f6deSJohnny Huang u32 bit_offset; 1121a219f6deSJohnny Huang u32 otp_value; 112273f11549SJohnny Huang char valid_bit[20]; 112366f2f8e5SJohnny Huang int i; 112473f11549SJohnny Huang int j; 112566f2f8e5SJohnny Huang 1126dacbba92SJohnny Huang otp_soak(0); 1127bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 1128f347c284SJohnny Huang otp_read_conf(i, &OTPCFG[i]); 112966f2f8e5SJohnny Huang 1130b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 1131b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 11323cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 11333cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 11342d4b0742SJohnny Huang continue; 11353cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 11363cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 11373cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 1138b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 1139b458cd62SJohnny Huang 1140a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 11413cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 11423cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 11433cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 1144b458cd62SJohnny Huang continue; 1145b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 1146b458cd62SJohnny Huang 11473cb28812SJohnny Huang if (conf_info[i].length == 1) { 11483cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 1149b458cd62SJohnny Huang } else { 1150b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 11513cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 11523cb28812SJohnny Huang conf_info[i].bit_offset); 1153b458cd62SJohnny Huang } 1154b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1155b458cd62SJohnny Huang 11563cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1157b458cd62SJohnny Huang printf("Reserved\n"); 11583cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 11593cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1160b458cd62SJohnny Huang printf("\n"); 11613cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1162b458cd62SJohnny Huang if (otp_value != 0) { 116373f11549SJohnny Huang for (j = 0; j < 7; j++) { 1164030cb4a7SJohnny Huang if (otp_value & (1 << j)) 116573f11549SJohnny Huang valid_bit[j * 2] = '1'; 1166a219f6deSJohnny Huang else 116773f11549SJohnny Huang valid_bit[j * 2] = '0'; 116873f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 116973f11549SJohnny Huang } 117073f11549SJohnny Huang valid_bit[15] = 0; 117173f11549SJohnny Huang } else { 117273f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1173b458cd62SJohnny Huang } 11743cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1175b458cd62SJohnny Huang printf("\n"); 1176b458cd62SJohnny Huang } else { 11773cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1178b458cd62SJohnny Huang } 1179b458cd62SJohnny Huang } 1180b458cd62SJohnny Huang return OTP_SUCCESS; 118166f2f8e5SJohnny Huang } 118266f2f8e5SJohnny Huang 11835010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout) 118476d13988SJohnny Huang { 118579e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1186a219f6deSJohnny Huang u32 *OTPSTRAP; 1187a219f6deSJohnny Huang u32 *OTPSTRAP_PRO; 1188a219f6deSJohnny Huang u32 *OTPSTRAP_IGNORE; 118976d13988SJohnny Huang int i; 1190a8bd6d8cSJohnny Huang int fail = 0; 1191a219f6deSJohnny Huang u32 bit_offset; 1192a219f6deSJohnny Huang u32 dw_offset; 1193a219f6deSJohnny Huang u32 mask; 1194a219f6deSJohnny Huang u32 otp_value; 1195a219f6deSJohnny Huang u32 otp_protect; 1196a219f6deSJohnny Huang u32 otp_ignore; 119776d13988SJohnny Huang 1198a219f6deSJohnny Huang OTPSTRAP = (u32 *)image_layout->strap; 1199a219f6deSJohnny Huang OTPSTRAP_PRO = (u32 *)image_layout->strap_pro; 1200a219f6deSJohnny Huang OTPSTRAP_IGNORE = (u32 *)image_layout->strap_ignore; 12017e523e3bSJohnny Huang 1202a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1203de6b0cc4SJohnny Huang printf("__________________________________________________________________________________________\n"); 1204b458cd62SJohnny Huang 12053cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 12067adec5f6SJohnny Huang fail = 0; 1207696656c6SJohnny Huang if (strap_info[i].bit_offset > 31) { 1208a8bd6d8cSJohnny Huang dw_offset = 1; 12093cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1210a8bd6d8cSJohnny Huang } else { 1211a8bd6d8cSJohnny Huang dw_offset = 0; 12123cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1213a8bd6d8cSJohnny Huang } 121476d13988SJohnny Huang 12153cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1216a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1217a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1218696656c6SJohnny Huang otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask; 1219a8bd6d8cSJohnny Huang 1220a219f6deSJohnny Huang if (otp_ignore == mask) 1221a8bd6d8cSJohnny Huang continue; 1222a219f6deSJohnny Huang else if (otp_ignore != 0) 1223a8bd6d8cSJohnny Huang fail = 1; 1224a8bd6d8cSJohnny Huang 1225a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 12263cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1227a8bd6d8cSJohnny Huang continue; 1228a8bd6d8cSJohnny Huang 12293cb28812SJohnny Huang if (strap_info[i].length == 1) { 12303cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1231a8bd6d8cSJohnny Huang } else { 1232b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 12333cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 12343cb28812SJohnny Huang strap_info[i].bit_offset); 1235a8bd6d8cSJohnny Huang } 1236a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1237a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1238a8bd6d8cSJohnny Huang 1239a8bd6d8cSJohnny Huang if (fail) { 1240696656c6SJohnny Huang printf("Ignore mask error\n"); 1241a8bd6d8cSJohnny Huang } else { 12423cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 12433cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1244a8bd6d8cSJohnny Huang else 1245a8bd6d8cSJohnny Huang printf("Reserved\n"); 1246a8bd6d8cSJohnny Huang } 1247a8bd6d8cSJohnny Huang } 1248a8bd6d8cSJohnny Huang 1249a8bd6d8cSJohnny Huang if (fail) 125076d13988SJohnny Huang return OTP_FAILURE; 125176d13988SJohnny Huang 125276d13988SJohnny Huang return OTP_SUCCESS; 125376d13988SJohnny Huang } 125476d13988SJohnny Huang 1255b458cd62SJohnny Huang static int otp_print_strap_info(int view) 125676d13988SJohnny Huang { 125779e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 125876d13988SJohnny Huang struct otpstrap_status strap_status[64]; 125907baa4e8SJohnny Huang int i, j; 1260b458cd62SJohnny Huang int fail = 0; 1261a219f6deSJohnny Huang u32 bit_offset; 1262a219f6deSJohnny Huang u32 length; 1263a219f6deSJohnny Huang u32 otp_value; 1264a219f6deSJohnny Huang u32 otp_protect; 126576d13988SJohnny Huang 1266541eb887SJohnny Huang otp_strap_status(strap_status); 126776d13988SJohnny Huang 1268b458cd62SJohnny Huang if (view) { 126907baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 127007baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1271b458cd62SJohnny Huang } else { 1272b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1273b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 127476d13988SJohnny Huang } 12753cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1276b458cd62SJohnny Huang otp_value = 0; 12773cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 12783cb28812SJohnny Huang length = strap_info[i].length; 1279b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1280c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1281c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1282b458cd62SJohnny Huang } 1283a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 12843cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1285b458cd62SJohnny Huang continue; 1286b458cd62SJohnny Huang if (view) { 1287b458cd62SJohnny Huang for (j = 0; j < length; j++) { 12883cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1289b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 129007baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1291e1a7245eSJohnny Huang printf("0x%-7X", strap_status[bit_offset + j].protected); 12923cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1293b458cd62SJohnny Huang printf(" Reserved\n"); 1294b458cd62SJohnny Huang continue; 1295b458cd62SJohnny Huang } 1296b458cd62SJohnny Huang if (length == 1) { 12973cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1298b458cd62SJohnny Huang continue; 129976d13988SJohnny Huang } 130076d13988SJohnny Huang 1301b458cd62SJohnny Huang if (j == 0) 13023cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1303b458cd62SJohnny Huang else if (j == length - 1) 1304b458cd62SJohnny Huang printf("\\ \"\n"); 1305b458cd62SJohnny Huang else 1306b458cd62SJohnny Huang printf("| \"\n"); 130776d13988SJohnny Huang } 1308b458cd62SJohnny Huang } else { 1309c947ef08SJohnny Huang if (length == 1) { 13103cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1311b458cd62SJohnny Huang } else { 1312b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1313b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1314b458cd62SJohnny Huang } 1315b458cd62SJohnny Huang 1316b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1317b458cd62SJohnny Huang 13183cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 13193cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1320b458cd62SJohnny Huang else 1321b458cd62SJohnny Huang printf("Reserved\n"); 1322b458cd62SJohnny Huang } 1323b458cd62SJohnny Huang } 1324b458cd62SJohnny Huang 1325b458cd62SJohnny Huang if (fail) 1326b458cd62SJohnny Huang return OTP_FAILURE; 1327b458cd62SJohnny Huang 1328b458cd62SJohnny Huang return OTP_SUCCESS; 1329b458cd62SJohnny Huang } 1330b458cd62SJohnny Huang 133188bd7d58SJohnny Huang static void _otp_print_key(u32 *data) 133269d5fd8fSJohnny Huang { 133388bd7d58SJohnny Huang int i, j; 133469d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 13359a4fe690SJohnny Huang struct otpkey_type key_info; 133688bd7d58SJohnny Huang const struct otpkey_type *key_info_array = info_cb.key_info; 133788bd7d58SJohnny Huang int len = 0; 1338a219f6deSJohnny Huang u8 *byte_buf; 133988bd7d58SJohnny Huang int empty; 134054552c69SJohnny Huang 134188bd7d58SJohnny Huang byte_buf = (u8 *)data; 13429d998018SJohnny Huang 134388bd7d58SJohnny Huang empty = 1; 13449d998018SJohnny Huang for (i = 0; i < 16; i++) { 134588bd7d58SJohnny Huang if (i % 2) { 134688bd7d58SJohnny Huang if (data[i] != 0xffffffff) 134788bd7d58SJohnny Huang empty = 0; 134888bd7d58SJohnny Huang } else { 134988bd7d58SJohnny Huang if (data[i] != 0) 13509d998018SJohnny Huang empty = 0; 13519d998018SJohnny Huang } 135288bd7d58SJohnny Huang } 135388bd7d58SJohnny Huang if (empty) { 135488bd7d58SJohnny Huang printf("OTP data header is empty\n"); 135588bd7d58SJohnny Huang return; 135688bd7d58SJohnny Huang } 13579d998018SJohnny Huang 135888bd7d58SJohnny Huang for (i = 0; i < 16; i++) { 135988bd7d58SJohnny Huang key_id = data[i] & 0x7; 136088bd7d58SJohnny Huang key_offset = data[i] & 0x1ff8; 136188bd7d58SJohnny Huang last = (data[i] >> 13) & 1; 136288bd7d58SJohnny Huang key_type = (data[i] >> 14) & 0xf; 136388bd7d58SJohnny Huang key_length = (data[i] >> 18) & 0x3; 136488bd7d58SJohnny Huang exp_length = (data[i] >> 20) & 0xfff; 13659a4fe690SJohnny Huang 136688bd7d58SJohnny Huang key_info.value = -1; 13679a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 13689a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 13699a4fe690SJohnny Huang key_info = key_info_array[j]; 13709a4fe690SJohnny Huang break; 13719a4fe690SJohnny Huang } 13729a4fe690SJohnny Huang } 137388bd7d58SJohnny Huang if (key_info.value == -1) 137488bd7d58SJohnny Huang break; 13759a4fe690SJohnny Huang 13767f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 137769d5fd8fSJohnny Huang printf("Key Type: "); 13789a4fe690SJohnny Huang printf("%s\n", key_info.information); 13799a4fe690SJohnny Huang 13809a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 138169d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 138269d5fd8fSJohnny Huang switch (key_length) { 138369d5fd8fSJohnny Huang case 0: 138469d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 138569d5fd8fSJohnny Huang break; 138669d5fd8fSJohnny Huang case 1: 138769d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 138869d5fd8fSJohnny Huang break; 138969d5fd8fSJohnny Huang case 2: 139069d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 139169d5fd8fSJohnny Huang break; 139269d5fd8fSJohnny Huang case 3: 139369d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 139469d5fd8fSJohnny Huang break; 139569d5fd8fSJohnny Huang } 1396181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV || 1397181f72d8SJohnny Huang key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 139869d5fd8fSJohnny Huang printf("RSA SHA Type: "); 139969d5fd8fSJohnny Huang switch (key_length) { 140069d5fd8fSJohnny Huang case 0: 140169d5fd8fSJohnny Huang printf("RSA1024\n"); 140269d5fd8fSJohnny Huang len = 0x100; 140369d5fd8fSJohnny Huang break; 140469d5fd8fSJohnny Huang case 1: 140569d5fd8fSJohnny Huang printf("RSA2048\n"); 140669d5fd8fSJohnny Huang len = 0x200; 140769d5fd8fSJohnny Huang break; 140869d5fd8fSJohnny Huang case 2: 140969d5fd8fSJohnny Huang printf("RSA3072\n"); 141069d5fd8fSJohnny Huang len = 0x300; 141169d5fd8fSJohnny Huang break; 141269d5fd8fSJohnny Huang case 3: 141369d5fd8fSJohnny Huang printf("RSA4096\n"); 141469d5fd8fSJohnny Huang len = 0x400; 141569d5fd8fSJohnny Huang break; 141669d5fd8fSJohnny Huang } 141769d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 141869d5fd8fSJohnny Huang } 14199a4fe690SJohnny Huang if (key_info.need_id) 142069d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 142169d5fd8fSJohnny Huang printf("Key Value:\n"); 14229a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 142369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 14249a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 14259a4fe690SJohnny Huang printf("AES Key:\n"); 14269a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 1427e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 14289a4fe690SJohnny Huang printf("AES IV:\n"); 14299a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 14309a4fe690SJohnny Huang } 14319a4fe690SJohnny Huang 14329a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 1433e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 143469d5fd8fSJohnny Huang printf("AES Key:\n"); 143569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 143669d5fd8fSJohnny Huang printf("AES IV:\n"); 143769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 14385fdde29fSJohnny Huang } else { 14399a4fe690SJohnny Huang printf("AES Key 1:\n"); 14409a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 14419a4fe690SJohnny Huang printf("AES Key 2:\n"); 14429a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 14439a4fe690SJohnny Huang } 1444181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV) { 144569d5fd8fSJohnny Huang printf("RSA mod:\n"); 144669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 144769d5fd8fSJohnny Huang printf("RSA exp:\n"); 144869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 1449181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 1450181f72d8SJohnny Huang printf("RSA mod:\n"); 1451181f72d8SJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 1452181f72d8SJohnny Huang printf("RSA exp:\n"); 1453a219f6deSJohnny Huang buf_print((u8 *)"\x01\x00\x01", 3); 145469d5fd8fSJohnny Huang } 145569d5fd8fSJohnny Huang if (last) 145669d5fd8fSJohnny Huang break; 145769d5fd8fSJohnny Huang } 145888bd7d58SJohnny Huang } 145988bd7d58SJohnny Huang 146088bd7d58SJohnny Huang static int otp_print_data_image(struct otp_image_layout *image_layout) 146188bd7d58SJohnny Huang { 146288bd7d58SJohnny Huang u32 *buf; 146388bd7d58SJohnny Huang 146488bd7d58SJohnny Huang buf = (u32 *)image_layout->data; 146588bd7d58SJohnny Huang _otp_print_key(buf); 146688bd7d58SJohnny Huang 1467f347c284SJohnny Huang return OTP_SUCCESS; 1468f347c284SJohnny Huang } 1469f347c284SJohnny Huang 147088bd7d58SJohnny Huang static void otp_print_key_info(void) 147188bd7d58SJohnny Huang { 147288bd7d58SJohnny Huang u32 data[2048]; 147388bd7d58SJohnny Huang int i; 147488bd7d58SJohnny Huang 147588bd7d58SJohnny Huang for (i = 0; i < 2048 ; i += 2) 147688bd7d58SJohnny Huang otp_read_data(i, &data[i]); 147788bd7d58SJohnny Huang 147888bd7d58SJohnny Huang _otp_print_key(data); 147988bd7d58SJohnny Huang } 148088bd7d58SJohnny Huang 1481b64ca396SJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout, u32 *data) 1482f347c284SJohnny Huang { 1483f347c284SJohnny Huang int i; 1484f347c284SJohnny Huang int ret; 1485f347c284SJohnny Huang u32 *buf; 1486f347c284SJohnny Huang u32 *buf_ignore; 1487f347c284SJohnny Huang 1488f347c284SJohnny Huang buf = (u32 *)image_layout->data; 1489f347c284SJohnny Huang buf_ignore = (u32 *)image_layout->data_ignore; 1490f347c284SJohnny Huang printf("Start Programing...\n"); 1491f347c284SJohnny Huang 1492f347c284SJohnny Huang // programing ecc region first 1493f347c284SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1494f347c284SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 1495f347c284SJohnny Huang if (ret != OTP_SUCCESS) { 1496f347c284SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1497f347c284SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 1498f347c284SJohnny Huang return ret; 1499f347c284SJohnny Huang } 1500f347c284SJohnny Huang } 1501f347c284SJohnny Huang 1502f347c284SJohnny Huang for (i = 0; i < 1792; i += 2) { 1503f347c284SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 1504f347c284SJohnny Huang if (ret != OTP_SUCCESS) { 1505f347c284SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1506f347c284SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 1507f347c284SJohnny Huang return ret; 1508f347c284SJohnny Huang } 1509f347c284SJohnny Huang } 1510f347c284SJohnny Huang otp_soak(0); 1511f347c284SJohnny Huang return OTP_SUCCESS; 1512f347c284SJohnny Huang } 1513f347c284SJohnny Huang 1514b64ca396SJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout, struct otpstrap_status *otpstrap) 1515f347c284SJohnny Huang { 1516f347c284SJohnny Huang u32 *strap; 1517f347c284SJohnny Huang u32 *strap_ignore; 1518f347c284SJohnny Huang u32 *strap_pro; 1519f347c284SJohnny Huang u32 prog_address; 1520f347c284SJohnny Huang int i; 15217e523e3bSJohnny Huang int bit, pbit, ibit, offset; 1522f347c284SJohnny Huang int fail = 0; 1523f347c284SJohnny Huang int ret; 1524f347c284SJohnny Huang int prog_flag = 0; 1525f347c284SJohnny Huang 1526f347c284SJohnny Huang strap = (u32 *)image_layout->strap; 1527f347c284SJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1528f347c284SJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1529f347c284SJohnny Huang 1530f347c284SJohnny Huang for (i = 0; i < 64; i++) { 1531f347c284SJohnny Huang prog_address = 0x800; 1532f347c284SJohnny Huang if (i < 32) { 1533f347c284SJohnny Huang offset = i; 1534f347c284SJohnny Huang bit = (strap[0] >> offset) & 0x1; 1535f347c284SJohnny Huang ibit = (strap_ignore[0] >> offset) & 0x1; 1536f347c284SJohnny Huang pbit = (strap_pro[0] >> offset) & 0x1; 1537f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 1538f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 1539f347c284SJohnny Huang 1540f347c284SJohnny Huang } else { 1541f347c284SJohnny Huang offset = (i - 32); 1542f347c284SJohnny Huang bit = (strap[1] >> offset) & 0x1; 1543f347c284SJohnny Huang ibit = (strap_ignore[1] >> offset) & 0x1; 1544f347c284SJohnny Huang pbit = (strap_pro[1] >> offset) & 0x1; 1545f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 1546f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 1547f347c284SJohnny Huang } 1548f347c284SJohnny Huang 1549f347c284SJohnny Huang if (ibit == 1) 1550f347c284SJohnny Huang continue; 1551f347c284SJohnny Huang if (bit == otpstrap[i].value) 1552f347c284SJohnny Huang prog_flag = 0; 1553f347c284SJohnny Huang else 1554f347c284SJohnny Huang prog_flag = 1; 1555f347c284SJohnny Huang 1556f347c284SJohnny Huang if (otpstrap[i].protected == 1 && prog_flag) { 1557f347c284SJohnny Huang fail = 1; 1558f347c284SJohnny Huang continue; 1559f347c284SJohnny Huang } 1560f347c284SJohnny Huang if (otpstrap[i].remain_times == 0 && prog_flag) { 1561f347c284SJohnny Huang fail = 1; 1562f347c284SJohnny Huang continue; 1563f347c284SJohnny Huang } 1564f347c284SJohnny Huang 1565f347c284SJohnny Huang if (prog_flag) { 1566f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, offset); 1567f347c284SJohnny Huang if (ret) 1568f347c284SJohnny Huang return OTP_FAILURE; 1569f347c284SJohnny Huang } 1570f347c284SJohnny Huang 1571f347c284SJohnny Huang if (pbit != 0) { 1572f347c284SJohnny Huang prog_address = 0x800; 1573f347c284SJohnny Huang if (i < 32) 1574f347c284SJohnny Huang prog_address |= 0x60c; 1575f347c284SJohnny Huang else 1576f347c284SJohnny Huang prog_address |= 0x60e; 1577f347c284SJohnny Huang 1578f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, offset); 1579f347c284SJohnny Huang if (ret) 1580f347c284SJohnny Huang return OTP_FAILURE; 1581f347c284SJohnny Huang } 1582f347c284SJohnny Huang } 1583f347c284SJohnny Huang otp_soak(0); 1584f347c284SJohnny Huang if (fail == 1) 1585f347c284SJohnny Huang return OTP_FAILURE; 1586f347c284SJohnny Huang return OTP_SUCCESS; 158769d5fd8fSJohnny Huang } 158869d5fd8fSJohnny Huang 1589b64ca396SJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout, u32 *otp_conf) 159069d5fd8fSJohnny Huang { 1591a6d0d645SJohnny Huang int i, k; 1592d90825e2SJohnny Huang int pass = 0; 1593a219f6deSJohnny Huang u32 prog_address; 1594a219f6deSJohnny Huang u32 compare[2]; 1595a219f6deSJohnny Huang u32 *conf = (u32 *)image_layout->conf; 1596a219f6deSJohnny Huang u32 *conf_ignore = (u32 *)image_layout->conf_ignore; 1597a219f6deSJohnny Huang u32 data_masked; 1598a219f6deSJohnny Huang u32 buf_masked; 15992031a123SJohnny Huang int ret; 160069d5fd8fSJohnny Huang 1601a6d0d645SJohnny Huang printf("Start Programing...\n"); 1602d90825e2SJohnny Huang otp_soak(0); 1603bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 1604b64ca396SJohnny Huang data_masked = otp_conf[i] & ~conf_ignore[i]; 16055010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1606a6d0d645SJohnny Huang prog_address = 0x800; 1607a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1608a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1609bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1610bb34a7bfSJohnny Huang pass = 1; 1611a6d0d645SJohnny Huang continue; 1612bb34a7bfSJohnny Huang } 1613de6fbf1cSJohnny Huang 1614de6fbf1cSJohnny Huang otp_soak(1); 16152031a123SJohnny Huang ret = otp_prog_dw(conf[i], conf_ignore[i], prog_address); 16162031a123SJohnny Huang if (ret) 16172031a123SJohnny Huang return OTP_FAILURE; 1618a6d0d645SJohnny Huang 161969d5fd8fSJohnny Huang pass = 0; 162069d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 16215010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1622de6fbf1cSJohnny Huang otp_soak(2); 16232031a123SJohnny Huang ret = otp_prog_dw(compare[0], conf_ignore[i], prog_address); 16242031a123SJohnny Huang if (ret) 16252031a123SJohnny Huang return OTP_FAILURE; 16265010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1627de6fbf1cSJohnny Huang otp_soak(1); 1628de6fbf1cSJohnny Huang } else { 1629de6fbf1cSJohnny Huang pass = 1; 1630de6fbf1cSJohnny Huang break; 1631de6fbf1cSJohnny Huang } 1632a6d0d645SJohnny Huang } else { 163369d5fd8fSJohnny Huang pass = 1; 163469d5fd8fSJohnny Huang break; 163569d5fd8fSJohnny Huang } 163669d5fd8fSJohnny Huang } 1637bb34a7bfSJohnny Huang if (pass == 0) { 1638b64ca396SJohnny Huang printf("address: %08x, otp_conf: %08x, input_conf: %08x, mask: %08x\n", 1639b64ca396SJohnny Huang i, otp_conf[i], conf[i], conf_ignore[i]); 1640bb34a7bfSJohnny Huang break; 1641bb34a7bfSJohnny Huang } 1642a6d0d645SJohnny Huang } 1643a6d0d645SJohnny Huang 1644de6fbf1cSJohnny Huang otp_soak(0); 164569d5fd8fSJohnny Huang if (!pass) 16462a856b9aSJohnny Huang return OTP_FAILURE; 1647a6d0d645SJohnny Huang 16482a856b9aSJohnny Huang return OTP_SUCCESS; 164969d5fd8fSJohnny Huang } 165069d5fd8fSJohnny Huang 1651b25f02d2SJohnny Huang static int otp_prog_scu_protect(struct otp_image_layout *image_layout, u32 *scu_pro) 1652b25f02d2SJohnny Huang { 1653b25f02d2SJohnny Huang int i, k; 1654b25f02d2SJohnny Huang int pass = 0; 1655b25f02d2SJohnny Huang u32 prog_address; 1656b25f02d2SJohnny Huang u32 compare[2]; 1657b25f02d2SJohnny Huang u32 *OTPSCU = (u32 *)image_layout->scu_pro; 1658b25f02d2SJohnny Huang u32 *OTPSCU_IGNORE = (u32 *)image_layout->scu_pro_ignore; 1659b25f02d2SJohnny Huang u32 data_masked; 1660b25f02d2SJohnny Huang u32 buf_masked; 16612031a123SJohnny Huang int ret; 1662b25f02d2SJohnny Huang 1663b25f02d2SJohnny Huang printf("Start Programing...\n"); 1664b25f02d2SJohnny Huang otp_soak(0); 1665b25f02d2SJohnny Huang for (i = 0; i < 2; i++) { 1666b25f02d2SJohnny Huang data_masked = scu_pro[i] & ~OTPSCU_IGNORE[i]; 1667b25f02d2SJohnny Huang buf_masked = OTPSCU[i] & ~OTPSCU_IGNORE[i]; 1668b25f02d2SJohnny Huang prog_address = 0xe08 + i * 2; 1669b25f02d2SJohnny Huang if (data_masked == buf_masked) { 1670b25f02d2SJohnny Huang pass = 1; 1671b25f02d2SJohnny Huang continue; 1672b25f02d2SJohnny Huang } 1673b25f02d2SJohnny Huang 1674b25f02d2SJohnny Huang otp_soak(1); 16752031a123SJohnny Huang ret = otp_prog_dw(OTPSCU[i], OTPSCU_IGNORE[i], prog_address); 16762031a123SJohnny Huang if (ret) 16772031a123SJohnny Huang return OTP_FAILURE; 1678b25f02d2SJohnny Huang pass = 0; 1679b25f02d2SJohnny Huang for (k = 0; k < RETRY; k++) { 1680b25f02d2SJohnny Huang if (verify_dw(prog_address, &OTPSCU[i], &OTPSCU_IGNORE[i], compare, 1) != 0) { 1681b25f02d2SJohnny Huang otp_soak(2); 16822031a123SJohnny Huang ret = otp_prog_dw(compare[0], OTPSCU_IGNORE[i], prog_address); 16832031a123SJohnny Huang if (ret) 16842031a123SJohnny Huang return OTP_FAILURE; 1685b25f02d2SJohnny Huang if (verify_dw(prog_address, &OTPSCU[i], &OTPSCU_IGNORE[i], compare, 1) != 0) { 1686b25f02d2SJohnny Huang otp_soak(1); 1687b25f02d2SJohnny Huang } else { 1688b25f02d2SJohnny Huang pass = 1; 1689b25f02d2SJohnny Huang break; 1690b25f02d2SJohnny Huang } 1691b25f02d2SJohnny Huang } else { 1692b25f02d2SJohnny Huang pass = 1; 1693b25f02d2SJohnny Huang break; 1694b25f02d2SJohnny Huang } 1695b25f02d2SJohnny Huang } 1696b25f02d2SJohnny Huang if (pass == 0) { 1697b489486eSJohnny Huang printf("OTPCFG0x%x: 0x%08x, input: 0x%08x, mask: 0x%08x\n", 1698b25f02d2SJohnny Huang i + 28, scu_pro[i], OTPSCU[i], OTPSCU_IGNORE[i]); 1699b25f02d2SJohnny Huang break; 1700b25f02d2SJohnny Huang } 1701b25f02d2SJohnny Huang } 1702b25f02d2SJohnny Huang 1703b25f02d2SJohnny Huang otp_soak(0); 1704b25f02d2SJohnny Huang if (!pass) 1705b25f02d2SJohnny Huang return OTP_FAILURE; 1706b25f02d2SJohnny Huang 1707b25f02d2SJohnny Huang return OTP_SUCCESS; 1708b25f02d2SJohnny Huang } 1709b25f02d2SJohnny Huang 1710b64ca396SJohnny Huang static int otp_check_data_image(struct otp_image_layout *image_layout, u32 *data) 1711b64ca396SJohnny Huang { 1712b64ca396SJohnny Huang int data_dw; 1713b64ca396SJohnny Huang u32 data_masked; 1714b64ca396SJohnny Huang u32 buf_masked; 1715b64ca396SJohnny Huang u32 *buf = (u32 *)image_layout->data; 1716b64ca396SJohnny Huang u32 *buf_ignore = (u32 *)image_layout->data_ignore; 1717b64ca396SJohnny Huang int i; 1718b64ca396SJohnny Huang 1719b64ca396SJohnny Huang data_dw = image_layout->data_length / 4; 1720b64ca396SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1721b64ca396SJohnny Huang for (i = 0; i < data_dw - 2; i++) { 1722b64ca396SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1723b64ca396SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 1724b64ca396SJohnny Huang if (data_masked == buf_masked) 1725b64ca396SJohnny Huang continue; 1726b64ca396SJohnny Huang if (i % 2 == 0) { 1727b64ca396SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1728b64ca396SJohnny Huang continue; 1729b64ca396SJohnny Huang } else { 1730b64ca396SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1731b489486eSJohnny Huang printf("OTP_ADDR[0x%x] = 0x%x\n", i, data[i]); 1732b489486eSJohnny Huang printf("Input [0x%x] = 0x%x\n", i, buf[i]); 1733b489486eSJohnny Huang printf("Mask [0x%x] = 0x%x\n", i, ~buf_ignore[i]); 1734b64ca396SJohnny Huang return OTP_FAILURE; 1735b64ca396SJohnny Huang } 1736b64ca396SJohnny Huang } else { 1737b64ca396SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1738b64ca396SJohnny Huang continue; 1739b64ca396SJohnny Huang } else { 1740b64ca396SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1741b489486eSJohnny Huang printf("OTP_ADDR[0x%x] = 0x%x\n", i, data[i]); 1742b489486eSJohnny Huang printf("Input [0x%x] = 0x%x\n", i, buf[i]); 1743b489486eSJohnny Huang printf("Mask [0x%x] = 0x%x\n", i, ~buf_ignore[i]); 1744b64ca396SJohnny Huang return OTP_FAILURE; 1745b64ca396SJohnny Huang } 1746b64ca396SJohnny Huang } 1747b64ca396SJohnny Huang } 1748b64ca396SJohnny Huang return OTP_SUCCESS; 1749b64ca396SJohnny Huang } 1750b64ca396SJohnny Huang 1751b64ca396SJohnny Huang static int otp_check_strap_image(struct otp_image_layout *image_layout, struct otpstrap_status *otpstrap) 1752b64ca396SJohnny Huang { 1753b64ca396SJohnny Huang int i; 1754b64ca396SJohnny Huang u32 *strap; 1755b64ca396SJohnny Huang u32 *strap_ignore; 1756b64ca396SJohnny Huang u32 *strap_pro; 1757b64ca396SJohnny Huang int bit, pbit, ibit; 1758b64ca396SJohnny Huang int fail = 0; 1759b64ca396SJohnny Huang int ret; 1760b64ca396SJohnny Huang 1761b64ca396SJohnny Huang strap = (u32 *)image_layout->strap; 1762b64ca396SJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1763b64ca396SJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1764b64ca396SJohnny Huang 1765b64ca396SJohnny Huang for (i = 0; i < 64; i++) { 1766b64ca396SJohnny Huang if (i < 32) { 1767b64ca396SJohnny Huang bit = (strap[0] >> i) & 0x1; 1768b64ca396SJohnny Huang ibit = (strap_ignore[0] >> i) & 0x1; 1769b64ca396SJohnny Huang pbit = (strap_pro[0] >> i) & 0x1; 1770b64ca396SJohnny Huang } else { 1771b64ca396SJohnny Huang bit = (strap[1] >> (i - 32)) & 0x1; 1772b64ca396SJohnny Huang ibit = (strap_ignore[1] >> (i - 32)) & 0x1; 1773b64ca396SJohnny Huang pbit = (strap_pro[1] >> (i - 32)) & 0x1; 1774b64ca396SJohnny Huang } 1775b64ca396SJohnny Huang 1776b64ca396SJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit); 1777b64ca396SJohnny Huang 1778b64ca396SJohnny Huang if (ret == OTP_FAILURE) 1779b64ca396SJohnny Huang fail = 1; 1780b64ca396SJohnny Huang } 1781b64ca396SJohnny Huang if (fail == 1) { 1782b64ca396SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1783b64ca396SJohnny Huang return OTP_FAILURE; 1784b64ca396SJohnny Huang } 1785b64ca396SJohnny Huang return OTP_SUCCESS; 1786b64ca396SJohnny Huang } 1787b64ca396SJohnny Huang 1788b64ca396SJohnny Huang static int otp_check_conf_image(struct otp_image_layout *image_layout, u32 *otp_conf) 1789b64ca396SJohnny Huang { 1790b64ca396SJohnny Huang u32 *conf = (u32 *)image_layout->conf; 1791b64ca396SJohnny Huang u32 *conf_ignore = (u32 *)image_layout->conf_ignore; 1792b64ca396SJohnny Huang u32 data_masked; 1793b64ca396SJohnny Huang u32 buf_masked; 1794b64ca396SJohnny Huang int i; 1795b64ca396SJohnny Huang 1796b64ca396SJohnny Huang for (i = 0; i < 16; i++) { 1797b64ca396SJohnny Huang data_masked = otp_conf[i] & ~conf_ignore[i]; 1798b64ca396SJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1799b64ca396SJohnny Huang if (data_masked == buf_masked) 1800b64ca396SJohnny Huang continue; 1801b64ca396SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1802b64ca396SJohnny Huang continue; 1803b64ca396SJohnny Huang } else { 1804b64ca396SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1805b64ca396SJohnny Huang printf("OTPCFG[%X] = %x\n", i, otp_conf[i]); 1806b64ca396SJohnny Huang printf("Input [%X] = %x\n", i, conf[i]); 1807b64ca396SJohnny Huang printf("Mask [%X] = %x\n", i, ~conf_ignore[i]); 1808b64ca396SJohnny Huang return OTP_FAILURE; 1809b64ca396SJohnny Huang } 1810b64ca396SJohnny Huang } 1811b64ca396SJohnny Huang return OTP_SUCCESS; 1812b64ca396SJohnny Huang } 1813b64ca396SJohnny Huang 1814b25f02d2SJohnny Huang static int otp_check_scu_image(struct otp_image_layout *image_layout, u32 *scu_pro) 1815b25f02d2SJohnny Huang { 1816b25f02d2SJohnny Huang u32 *OTPSCU = (u32 *)image_layout->scu_pro; 1817b25f02d2SJohnny Huang u32 *OTPSCU_IGNORE = (u32 *)image_layout->scu_pro_ignore; 1818b25f02d2SJohnny Huang u32 data_masked; 1819b25f02d2SJohnny Huang u32 buf_masked; 1820b25f02d2SJohnny Huang int i; 1821b25f02d2SJohnny Huang 1822b25f02d2SJohnny Huang for (i = 0; i < 2; i++) { 1823b25f02d2SJohnny Huang data_masked = scu_pro[i] & ~OTPSCU_IGNORE[i]; 1824b25f02d2SJohnny Huang buf_masked = OTPSCU[i] & ~OTPSCU_IGNORE[i]; 1825b25f02d2SJohnny Huang if (data_masked == buf_masked) 1826b25f02d2SJohnny Huang continue; 1827b25f02d2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1828b25f02d2SJohnny Huang continue; 1829b25f02d2SJohnny Huang } else { 1830b25f02d2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1831b489486eSJohnny Huang printf("OTPCFG[0x%X] = 0x%X\n", 28 + i, scu_pro[i]); 1832b489486eSJohnny Huang printf("Input [0x%X] = 0x%X\n", 28 + i, OTPSCU[i]); 1833b489486eSJohnny Huang printf("Mask [0x%X] = 0x%X\n", 28 + i, ~OTPSCU_IGNORE[i]); 1834b25f02d2SJohnny Huang return OTP_FAILURE; 1835b25f02d2SJohnny Huang } 1836b25f02d2SJohnny Huang } 1837b25f02d2SJohnny Huang return OTP_SUCCESS; 1838b25f02d2SJohnny Huang } 1839b25f02d2SJohnny Huang 1840f347c284SJohnny Huang static int otp_verify_image(u8 *src_buf, u32 length, u8 *digest_buf) 1841696656c6SJohnny Huang { 1842*a3dcef30SJohnny Huang sha512_context ctx; 1843696656c6SJohnny Huang u8 digest_ret[CHECKSUM_LEN]; 1844696656c6SJohnny Huang 1845*a3dcef30SJohnny Huang sha384_starts(&ctx); 1846*a3dcef30SJohnny Huang sha384_update(&ctx, src_buf, length); 1847*a3dcef30SJohnny Huang sha384_finish(&ctx, digest_ret); 1848696656c6SJohnny Huang 1849696656c6SJohnny Huang if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN)) 1850f347c284SJohnny Huang return OTP_SUCCESS; 1851f347c284SJohnny Huang return OTP_FAILURE; 1852696656c6SJohnny Huang } 1853696656c6SJohnny Huang 1854f347c284SJohnny Huang static int otp_prog_image(int addr, int nconfirm) 185569d5fd8fSJohnny Huang { 185669d5fd8fSJohnny Huang int ret; 185761a6cda7SJohnny Huang int image_soc_ver = 0; 1858696656c6SJohnny Huang struct otp_header *otp_header; 1859696656c6SJohnny Huang struct otp_image_layout image_layout; 1860696656c6SJohnny Huang int image_size; 1861a219f6deSJohnny Huang u8 *buf; 1862a219f6deSJohnny Huang u8 *checksum; 1863b64ca396SJohnny Huang int i; 1864b64ca396SJohnny Huang u32 data[2048]; 1865b64ca396SJohnny Huang u32 conf[16]; 1866b25f02d2SJohnny Huang u32 scu_pro[2]; 1867b64ca396SJohnny Huang struct otpstrap_status otpstrap[64]; 186869d5fd8fSJohnny Huang 1869696656c6SJohnny Huang otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK); 1870696656c6SJohnny Huang if (!otp_header) { 1871030cb4a7SJohnny Huang printf("Failed to map physical memory\n"); 18722a856b9aSJohnny Huang return OTP_FAILURE; 187369d5fd8fSJohnny Huang } 1874d90825e2SJohnny Huang 1875696656c6SJohnny Huang image_size = OTP_IMAGE_SIZE(otp_header->image_info); 1876696656c6SJohnny Huang unmap_physmem(otp_header, MAP_WRBACK); 1877696656c6SJohnny Huang 1878696656c6SJohnny Huang buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK); 1879696656c6SJohnny Huang 1880696656c6SJohnny Huang if (!buf) { 1881030cb4a7SJohnny Huang printf("Failed to map physical memory\n"); 1882696656c6SJohnny Huang return OTP_FAILURE; 1883696656c6SJohnny Huang } 1884696656c6SJohnny Huang otp_header = (struct otp_header *)buf; 1885696656c6SJohnny Huang checksum = buf + otp_header->checksum_offset; 1886696656c6SJohnny Huang 1887696656c6SJohnny Huang if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) { 1888030cb4a7SJohnny Huang printf("Image is invalid\n"); 1889696656c6SJohnny Huang return OTP_FAILURE; 1890696656c6SJohnny Huang } 1891696656c6SJohnny Huang 18925010032bSJohnny Huang image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2); 18935010032bSJohnny Huang image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info); 18945010032bSJohnny Huang image_layout.data_ignore = image_layout.data + image_layout.data_length; 18955010032bSJohnny Huang 18965010032bSJohnny Huang image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2); 1897696656c6SJohnny Huang image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 18985010032bSJohnny Huang image_layout.conf_ignore = image_layout.conf + image_layout.conf_length; 1899696656c6SJohnny Huang 1900696656c6SJohnny Huang image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 19015010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3); 19025010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + image_layout.strap_length; 19035010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length; 19047e523e3bSJohnny Huang 1905b25f02d2SJohnny Huang image_layout.scu_pro = buf + OTP_REGION_OFFSET(otp_header->scu_protect_info); 1906b25f02d2SJohnny Huang image_layout.scu_pro_length = (int)(OTP_REGION_SIZE(otp_header->scu_protect_info) / 2); 1907b25f02d2SJohnny Huang image_layout.scu_pro_ignore = image_layout.scu_pro + image_layout.scu_pro_length; 1908b25f02d2SJohnny Huang 19097e523e3bSJohnny Huang if (otp_header->soc_ver == SOC_AST2600A0) { 19107e523e3bSJohnny Huang image_soc_ver = OTP_A0; 191161a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A1) { 191261a6cda7SJohnny Huang image_soc_ver = OTP_A1; 191361a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A2) { 191461a6cda7SJohnny Huang image_soc_ver = OTP_A2; 191561a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A3) { 191661a6cda7SJohnny Huang image_soc_ver = OTP_A3; 1917696656c6SJohnny Huang } else { 1918030cb4a7SJohnny Huang printf("Image SOC Version is not supported\n"); 1919696656c6SJohnny Huang return OTP_FAILURE; 1920696656c6SJohnny Huang } 1921696656c6SJohnny Huang 192261a6cda7SJohnny Huang if (image_soc_ver != info_cb.version) { 19235e096f11SJohnny Huang printf("Image SOC version is not match to HW SOC version\n"); 19249a4fe690SJohnny Huang return OTP_FAILURE; 19259a4fe690SJohnny Huang } 19269a4fe690SJohnny Huang 19275e096f11SJohnny Huang if (OTPTOOL_VERSION_MAJOR(otp_header->otptool_ver) != OTPTOOL_COMPT_VERSION) { 1928*a3dcef30SJohnny Huang printf("OTP image is not generated by otptool v2.x.x\n"); 192961a6cda7SJohnny Huang return OTP_FAILURE; 193061a6cda7SJohnny Huang } 193161a6cda7SJohnny Huang 1932f347c284SJohnny Huang if (otp_verify_image(buf, image_size, checksum)) { 1933030cb4a7SJohnny Huang printf("checksum is invalid\n"); 1934696656c6SJohnny Huang return OTP_FAILURE; 1935d90825e2SJohnny Huang } 19367332532cSJohnny Huang 1937030cb4a7SJohnny Huang if (info_cb.pro_sts.mem_lock) { 1938030cb4a7SJohnny Huang printf("OTP memory is locked\n"); 1939030cb4a7SJohnny Huang return OTP_FAILURE; 1940030cb4a7SJohnny Huang } 1941b64ca396SJohnny Huang ret = 0; 1942030cb4a7SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 1943030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_data) { 1944030cb4a7SJohnny Huang printf("OTP data region is protected\n"); 1945030cb4a7SJohnny Huang ret = -1; 1946030cb4a7SJohnny Huang } 1947030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_sec) { 1948030cb4a7SJohnny Huang printf("OTP secure region is protected\n"); 1949030cb4a7SJohnny Huang ret = -1; 1950030cb4a7SJohnny Huang } 1951b64ca396SJohnny Huang printf("Read OTP Data Region:\n"); 1952b64ca396SJohnny Huang for (i = 0; i < 2048 ; i += 2) 1953b64ca396SJohnny Huang otp_read_data(i, &data[i]); 1954b64ca396SJohnny Huang 1955b64ca396SJohnny Huang printf("Check writable...\n"); 1956b64ca396SJohnny Huang if (otp_check_data_image(&image_layout, data) == OTP_FAILURE) 1957b64ca396SJohnny Huang ret = -1; 1958030cb4a7SJohnny Huang } 1959030cb4a7SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 1960030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_conf) { 1961030cb4a7SJohnny Huang printf("OTP config region is protected\n"); 1962030cb4a7SJohnny Huang ret = -1; 1963030cb4a7SJohnny Huang } 1964b64ca396SJohnny Huang printf("Read OTP Config Region:\n"); 1965b64ca396SJohnny Huang for (i = 0; i < 16 ; i++) 1966b64ca396SJohnny Huang otp_read_conf(i, &conf[i]); 1967b64ca396SJohnny Huang 1968b64ca396SJohnny Huang printf("Check writable...\n"); 1969b64ca396SJohnny Huang if (otp_check_conf_image(&image_layout, conf) == OTP_FAILURE) 1970b64ca396SJohnny Huang ret = -1; 1971030cb4a7SJohnny Huang } 1972030cb4a7SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 1973030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_strap) { 1974030cb4a7SJohnny Huang printf("OTP strap region is protected\n"); 1975030cb4a7SJohnny Huang ret = -1; 1976030cb4a7SJohnny Huang } 1977b64ca396SJohnny Huang printf("Read OTP Strap Region:\n"); 1978b64ca396SJohnny Huang otp_strap_status(otpstrap); 1979b64ca396SJohnny Huang 1980b64ca396SJohnny Huang printf("Check writable...\n"); 1981b64ca396SJohnny Huang if (otp_check_strap_image(&image_layout, otpstrap) == OTP_FAILURE) 1982b64ca396SJohnny Huang ret = -1; 1983030cb4a7SJohnny Huang } 1984b25f02d2SJohnny Huang if (otp_header->image_info & OTP_INC_SCU_PRO) { 1985b25f02d2SJohnny Huang if (info_cb.pro_sts.pro_strap) { 1986b25f02d2SJohnny Huang printf("OTP strap region is protected\n"); 1987b25f02d2SJohnny Huang ret = -1; 1988b25f02d2SJohnny Huang } 1989b25f02d2SJohnny Huang printf("Read SCU Protect Region:\n"); 1990b25f02d2SJohnny Huang otp_read_conf(28, &scu_pro[0]); 1991b25f02d2SJohnny Huang otp_read_conf(29, &scu_pro[1]); 1992b25f02d2SJohnny Huang 1993b25f02d2SJohnny Huang printf("Check writable...\n"); 1994b25f02d2SJohnny Huang if (otp_check_scu_image(&image_layout, scu_pro) == OTP_FAILURE) 1995b25f02d2SJohnny Huang ret = -1; 1996b25f02d2SJohnny Huang } 1997030cb4a7SJohnny Huang if (ret == -1) 1998030cb4a7SJohnny Huang return OTP_FAILURE; 1999b64ca396SJohnny Huang 200069d5fd8fSJohnny Huang if (!nconfirm) { 2001696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 20027f795e57SJohnny Huang printf("\nOTP data region :\n"); 2003f347c284SJohnny Huang if (otp_print_data_image(&image_layout) < 0) { 200469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 20052a856b9aSJohnny Huang return OTP_FAILURE; 200669d5fd8fSJohnny Huang } 200769d5fd8fSJohnny Huang } 2008696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 20097332532cSJohnny Huang printf("\nOTP configuration region :\n"); 2010696656c6SJohnny Huang if (otp_print_conf_image(&image_layout) < 0) { 20117332532cSJohnny Huang printf("OTP config error, please check.\n"); 20127332532cSJohnny Huang return OTP_FAILURE; 20137332532cSJohnny Huang } 20147332532cSJohnny Huang } 20157adec5f6SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 20167adec5f6SJohnny Huang printf("\nOTP strap region :\n"); 20177adec5f6SJohnny Huang if (otp_print_strap_image(&image_layout) < 0) { 20187adec5f6SJohnny Huang printf("OTP strap error, please check.\n"); 20197adec5f6SJohnny Huang return OTP_FAILURE; 20207adec5f6SJohnny Huang } 20217adec5f6SJohnny Huang } 2022b25f02d2SJohnny Huang if (otp_header->image_info & OTP_INC_SCU_PRO) { 2023b25f02d2SJohnny Huang printf("\nOTP scu protect region :\n"); 2024b25f02d2SJohnny Huang if (otp_print_scu_image(&image_layout) < 0) { 2025b25f02d2SJohnny Huang printf("OTP scu protect error, please check.\n"); 2026b25f02d2SJohnny Huang return OTP_FAILURE; 2027b25f02d2SJohnny Huang } 2028b25f02d2SJohnny Huang } 20297332532cSJohnny Huang 203069d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 203169d5fd8fSJohnny Huang if (!confirm_yesno()) { 203269d5fd8fSJohnny Huang printf(" Aborting\n"); 20332a856b9aSJohnny Huang return OTP_FAILURE; 203469d5fd8fSJohnny Huang } 203569d5fd8fSJohnny Huang } 20367332532cSJohnny Huang 20375010032bSJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 20385010032bSJohnny Huang printf("programing data region ...\n"); 2039b64ca396SJohnny Huang ret = otp_prog_data(&image_layout, data); 20405010032bSJohnny Huang if (ret != 0) { 20415010032bSJohnny Huang printf("Error\n"); 20425010032bSJohnny Huang return ret; 20435010032bSJohnny Huang } 2044a219f6deSJohnny Huang printf("Done\n"); 20455010032bSJohnny Huang } 20465010032bSJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 20475010032bSJohnny Huang printf("programing strap region ...\n"); 2048b64ca396SJohnny Huang ret = otp_prog_strap(&image_layout, otpstrap); 20495010032bSJohnny Huang if (ret != 0) { 20505010032bSJohnny Huang printf("Error\n"); 20515010032bSJohnny Huang return ret; 20525010032bSJohnny Huang } 2053a219f6deSJohnny Huang printf("Done\n"); 20545010032bSJohnny Huang } 2055b25f02d2SJohnny Huang if (otp_header->image_info & OTP_INC_SCU_PRO) { 2056b25f02d2SJohnny Huang printf("programing scu protect region ...\n"); 2057b25f02d2SJohnny Huang ret = otp_prog_scu_protect(&image_layout, scu_pro); 2058b25f02d2SJohnny Huang if (ret != 0) { 2059b25f02d2SJohnny Huang printf("Error\n"); 2060b25f02d2SJohnny Huang return ret; 2061b25f02d2SJohnny Huang } 2062b25f02d2SJohnny Huang printf("Done\n"); 2063b25f02d2SJohnny Huang } 20645010032bSJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 20655010032bSJohnny Huang printf("programing configuration region ...\n"); 2066b64ca396SJohnny Huang ret = otp_prog_conf(&image_layout, conf); 20675010032bSJohnny Huang if (ret != 0) { 20685010032bSJohnny Huang printf("Error\n"); 20695010032bSJohnny Huang return ret; 20705010032bSJohnny Huang } 20715010032bSJohnny Huang printf("Done\n"); 20725010032bSJohnny Huang } 2073cd1610b4SJohnny Huang 20747332532cSJohnny Huang return OTP_SUCCESS; 20752a856b9aSJohnny Huang } 20762a856b9aSJohnny Huang 2077f347c284SJohnny Huang static int otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 2078cd1610b4SJohnny Huang { 2079a219f6deSJohnny Huang u32 read[2]; 2080a219f6deSJohnny Huang u32 prog_address = 0; 208166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 2082cd1610b4SJohnny Huang int otp_bit; 208383655e91SJohnny Huang int ret = 0; 2084cd1610b4SJohnny Huang 2085dacbba92SJohnny Huang otp_soak(0); 2086cd1610b4SJohnny Huang switch (mode) { 2087a6d0d645SJohnny Huang case OTP_REGION_CONF: 2088f347c284SJohnny Huang otp_read_conf(otp_dw_offset, read); 2089cd1610b4SJohnny Huang prog_address = 0x800; 2090cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 2091cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 2092a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2093cd1610b4SJohnny Huang if (otp_bit == value) { 2094b489486eSJohnny Huang printf("OTPCFG0x%X[0x%X] = %d\n", otp_dw_offset, bit_offset, value); 2095cd1610b4SJohnny Huang printf("No need to program\n"); 20962a856b9aSJohnny Huang return OTP_SUCCESS; 2097cd1610b4SJohnny Huang } 2098cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2099b489486eSJohnny Huang printf("OTPCFG0x%X[0x%X] = 1\n", otp_dw_offset, bit_offset); 21000dc9a440SJohnny Huang printf("OTP is programmed, which can't be clean\n"); 21012a856b9aSJohnny Huang return OTP_FAILURE; 2102cd1610b4SJohnny Huang } 2103b489486eSJohnny Huang printf("Program OTPCFG0x%X[0x%X] to 1\n", otp_dw_offset, bit_offset); 2104cd1610b4SJohnny Huang break; 2105a6d0d645SJohnny Huang case OTP_REGION_DATA: 2106cd1610b4SJohnny Huang prog_address = otp_dw_offset; 2107cd1610b4SJohnny Huang 2108cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 2109a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 2110a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2111643b9cfdSJohnny Huang 2112643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 2113b489486eSJohnny Huang printf("OTPDATA0x%X[0x%X] = 1\n", otp_dw_offset, bit_offset); 2114b64ca396SJohnny Huang printf("OTP is programmed, which can't be cleared\n"); 2115643b9cfdSJohnny Huang return OTP_FAILURE; 2116643b9cfdSJohnny Huang } 2117cd1610b4SJohnny Huang } else { 2118a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 2119a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 2120643b9cfdSJohnny Huang 2121643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 2122b489486eSJohnny Huang printf("OTPDATA0x%X[0x%X] = 1\n", otp_dw_offset, bit_offset); 2123b64ca396SJohnny Huang printf("OTP is programmed, which can't be written\n"); 2124643b9cfdSJohnny Huang return OTP_FAILURE; 2125643b9cfdSJohnny Huang } 2126cd1610b4SJohnny Huang } 2127cd1610b4SJohnny Huang if (otp_bit == value) { 2128b489486eSJohnny Huang printf("OTPDATA0x%X[0x%X] = %d\n", otp_dw_offset, bit_offset, value); 2129cd1610b4SJohnny Huang printf("No need to program\n"); 21302a856b9aSJohnny Huang return OTP_SUCCESS; 2131cd1610b4SJohnny Huang } 2132643b9cfdSJohnny Huang 2133b489486eSJohnny Huang printf("Program OTPDATA0x%X[0x%X] to 1\n", otp_dw_offset, bit_offset); 2134cd1610b4SJohnny Huang break; 2135a6d0d645SJohnny Huang case OTP_REGION_STRAP: 21368848d5dcSJohnny Huang otp_strap_status(otpstrap); 21378848d5dcSJohnny Huang otp_print_strap(bit_offset, 1); 21387e523e3bSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0); 21398848d5dcSJohnny Huang if (ret == OTP_FAILURE) 21408848d5dcSJohnny Huang return OTP_FAILURE; 21418848d5dcSJohnny Huang else if (ret == OTP_PROG_SKIP) 21428848d5dcSJohnny Huang return OTP_SUCCESS; 2143a6af4a17SJohnny Huang 2144cd1610b4SJohnny Huang break; 2145cd1610b4SJohnny Huang } 2146cd1610b4SJohnny Huang 2147cd1610b4SJohnny Huang if (!nconfirm) { 2148cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2149cd1610b4SJohnny Huang if (!confirm_yesno()) { 2150cd1610b4SJohnny Huang printf(" Aborting\n"); 21512a856b9aSJohnny Huang return OTP_FAILURE; 2152cd1610b4SJohnny Huang } 2153cd1610b4SJohnny Huang } 2154cd1610b4SJohnny Huang 2155cd1610b4SJohnny Huang switch (mode) { 2156a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2157f347c284SJohnny Huang ret = otp_prog_strap_b(bit_offset, value); 215883655e91SJohnny Huang break; 2159a6d0d645SJohnny Huang case OTP_REGION_CONF: 2160a6d0d645SJohnny Huang case OTP_REGION_DATA: 2161f347c284SJohnny Huang ret = otp_prog_dc_b(value, prog_address, bit_offset); 2162de6fbf1cSJohnny Huang break; 2163de6fbf1cSJohnny Huang } 2164de6fbf1cSJohnny Huang otp_soak(0); 216583655e91SJohnny Huang if (ret) { 21660dc9a440SJohnny Huang printf("OTP cannot be programmed\n"); 2167794e27ecSJohnny Huang printf("FAILURE\n"); 2168794e27ecSJohnny Huang return OTP_FAILURE; 2169794e27ecSJohnny Huang } 2170794e27ecSJohnny Huang 21719009c25dSJohnny Huang printf("SUCCESS\n"); 21722a856b9aSJohnny Huang return OTP_SUCCESS; 2173a219f6deSJohnny Huang } 2174a219f6deSJohnny Huang 2175794e27ecSJohnny Huang static int otp_update_rid(u32 update_num, int force) 2176794e27ecSJohnny Huang { 2177794e27ecSJohnny Huang u32 otp_rid[2]; 2178a8789b47SJohnny Huang u32 sw_rid[2]; 2179794e27ecSJohnny Huang int rid_num = 0; 2180a8789b47SJohnny Huang int sw_rid_num = 0; 2181794e27ecSJohnny Huang int bit_offset; 2182794e27ecSJohnny Huang int dw_offset; 2183794e27ecSJohnny Huang int i; 2184794e27ecSJohnny Huang int ret; 2185794e27ecSJohnny Huang 2186f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 2187f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 2188794e27ecSJohnny Huang 2189a8789b47SJohnny Huang sw_rid[0] = readl(SW_REV_ID0); 2190a8789b47SJohnny Huang sw_rid[1] = readl(SW_REV_ID1); 2191a8789b47SJohnny Huang 2192794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 2193a8789b47SJohnny Huang sw_rid_num = get_rid_num(sw_rid); 2194a8789b47SJohnny Huang 2195a8789b47SJohnny Huang if (sw_rid_num < 0) { 2196a8789b47SJohnny Huang printf("SW revision id is invalid, please check.\n"); 2197a8789b47SJohnny Huang return OTP_FAILURE; 2198a8789b47SJohnny Huang } 2199a8789b47SJohnny Huang 2200a8789b47SJohnny Huang if (update_num > sw_rid_num) { 2201a8789b47SJohnny Huang printf("current SW revision ID: 0x%x\n", sw_rid_num); 2202a8789b47SJohnny Huang printf("update number could not bigger than current SW revision id\n"); 2203a8789b47SJohnny Huang return OTP_FAILURE; 2204a8789b47SJohnny Huang } 2205794e27ecSJohnny Huang 2206794e27ecSJohnny Huang if (rid_num < 0) { 2207b64ca396SJohnny Huang printf("Current OTP revision ID cannot handle by this command,\n" 2208b64ca396SJohnny Huang "please use 'otp pb' command to update it manually\n"); 2209794e27ecSJohnny Huang otp_print_revid(otp_rid); 22109009c25dSJohnny Huang return OTP_FAILURE; 22119009c25dSJohnny Huang } 2212cd1610b4SJohnny Huang 2213794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 2214794e27ecSJohnny Huang otp_print_revid(otp_rid); 2215794e27ecSJohnny Huang printf("input update number: 0x%x\n", update_num); 2216794e27ecSJohnny Huang 2217a8789b47SJohnny Huang if (rid_num > update_num) { 2218a8789b47SJohnny Huang printf("OTP rev_id is bigger than 0x%X\n", update_num); 2219a8789b47SJohnny Huang printf("Skip\n"); 2220a8789b47SJohnny Huang return OTP_FAILURE; 2221a8789b47SJohnny Huang } else if (rid_num == update_num) { 2222a8789b47SJohnny Huang printf("OTP rev_id is same as input\n"); 2223794e27ecSJohnny Huang printf("Skip\n"); 2224794e27ecSJohnny Huang return OTP_FAILURE; 2225794e27ecSJohnny Huang } 2226794e27ecSJohnny Huang 2227794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 2228794e27ecSJohnny Huang if (i < 32) { 2229794e27ecSJohnny Huang dw_offset = 0xa; 2230794e27ecSJohnny Huang bit_offset = i; 2231794e27ecSJohnny Huang } else { 2232794e27ecSJohnny Huang dw_offset = 0xb; 2233794e27ecSJohnny Huang bit_offset = i - 32; 2234794e27ecSJohnny Huang } 2235b489486eSJohnny Huang printf("OTPCFG0x%X[0x%X]", dw_offset, bit_offset); 2236794e27ecSJohnny Huang if (i + 1 != update_num) 2237794e27ecSJohnny Huang printf(", "); 2238794e27ecSJohnny Huang } 2239794e27ecSJohnny Huang 2240794e27ecSJohnny Huang printf(" will be programmed\n"); 2241794e27ecSJohnny Huang if (force == 0) { 2242794e27ecSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2243794e27ecSJohnny Huang if (!confirm_yesno()) { 2244794e27ecSJohnny Huang printf(" Aborting\n"); 2245794e27ecSJohnny Huang return OTP_FAILURE; 2246794e27ecSJohnny Huang } 2247794e27ecSJohnny Huang } 2248794e27ecSJohnny Huang 2249794e27ecSJohnny Huang ret = 0; 2250794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 2251794e27ecSJohnny Huang if (i < 32) { 2252794e27ecSJohnny Huang dw_offset = 0xa04; 2253794e27ecSJohnny Huang bit_offset = i; 2254794e27ecSJohnny Huang } else { 2255794e27ecSJohnny Huang dw_offset = 0xa06; 2256794e27ecSJohnny Huang bit_offset = i - 32; 2257794e27ecSJohnny Huang } 2258f347c284SJohnny Huang if (otp_prog_dc_b(1, dw_offset, bit_offset)) { 2259b489486eSJohnny Huang printf("OTPCFG0x%X[0x%X] programming failed\n", dw_offset, bit_offset); 2260794e27ecSJohnny Huang ret = OTP_FAILURE; 2261794e27ecSJohnny Huang break; 2262794e27ecSJohnny Huang } 2263794e27ecSJohnny Huang } 2264061d3279SJohnny Huang otp_soak(0); 2265f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 2266f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 2267794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 2268794e27ecSJohnny Huang if (rid_num >= 0) 2269794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 2270794e27ecSJohnny Huang else 2271794e27ecSJohnny Huang printf("OTP revision ID\n"); 2272794e27ecSJohnny Huang otp_print_revid(otp_rid); 2273794e27ecSJohnny Huang if (!ret) 2274794e27ecSJohnny Huang printf("SUCCESS\n"); 2275794e27ecSJohnny Huang else 2276794e27ecSJohnny Huang printf("FAILED\n"); 2277794e27ecSJohnny Huang return ret; 2278794e27ecSJohnny Huang } 2279794e27ecSJohnny Huang 2280883625c5SJohnny Huang static int otp_retire_key(u32 retire_id, int force) 2281883625c5SJohnny Huang { 2282883625c5SJohnny Huang u32 otpcfg4; 2283883625c5SJohnny Huang u32 krb; 2284883625c5SJohnny Huang u32 krb_b; 2285883625c5SJohnny Huang u32 krb_or; 2286883625c5SJohnny Huang u32 current_id; 2287883625c5SJohnny Huang 2288883625c5SJohnny Huang otp_read_conf(4, &otpcfg4); 2289883625c5SJohnny Huang current_id = readl(SEC_KEY_NUM) & 7; 2290883625c5SJohnny Huang krb = otpcfg4 & 0xff; 2291883625c5SJohnny Huang krb_b = (otpcfg4 >> 16) & 0xff; 2292883625c5SJohnny Huang krb_or = krb | krb_b; 2293883625c5SJohnny Huang 2294883625c5SJohnny Huang printf("current Key ID: 0x%x\n", current_id); 2295883625c5SJohnny Huang printf("input retire ID: 0x%x\n", retire_id); 2296883625c5SJohnny Huang printf("OTPCFG0x4 = 0x%X\n", otpcfg4); 2297883625c5SJohnny Huang 2298883625c5SJohnny Huang if (info_cb.pro_sts.pro_key_ret) { 2299883625c5SJohnny Huang printf("OTPCFG4 is protected\n"); 2300883625c5SJohnny Huang return OTP_FAILURE; 2301883625c5SJohnny Huang } 2302883625c5SJohnny Huang 2303883625c5SJohnny Huang if (retire_id >= current_id) { 2304883625c5SJohnny Huang printf("Retire key id is equal or bigger than current boot key\n"); 2305883625c5SJohnny Huang return OTP_FAILURE; 2306883625c5SJohnny Huang } 2307883625c5SJohnny Huang 2308883625c5SJohnny Huang if (krb_or & (1 << retire_id)) { 2309883625c5SJohnny Huang printf("Key 0x%X already retired\n", retire_id); 2310883625c5SJohnny Huang return OTP_SUCCESS; 2311883625c5SJohnny Huang } 2312883625c5SJohnny Huang 2313883625c5SJohnny Huang printf("OTPCFG0x4[0x%X] will be programmed\n", retire_id); 2314883625c5SJohnny Huang if (force == 0) { 2315883625c5SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2316883625c5SJohnny Huang if (!confirm_yesno()) { 2317883625c5SJohnny Huang printf(" Aborting\n"); 2318883625c5SJohnny Huang return OTP_FAILURE; 2319883625c5SJohnny Huang } 2320883625c5SJohnny Huang } 2321883625c5SJohnny Huang 2322883625c5SJohnny Huang if (otp_prog_dc_b(1, 0x808, retire_id) == OTP_FAILURE) { 2323883625c5SJohnny Huang printf("OTPCFG0x4[0x%X] programming failed\n", retire_id); 2324883625c5SJohnny Huang printf("try to program backup OTPCFG0x4[0x%X]\n", retire_id + 16); 2325883625c5SJohnny Huang if (otp_prog_dc_b(1, 0x808, retire_id + 16) == OTP_FAILURE) 2326883625c5SJohnny Huang printf("OTPCFG0x4[0x%X] programming failed", retire_id + 16); 2327883625c5SJohnny Huang } 2328883625c5SJohnny Huang 2329883625c5SJohnny Huang otp_soak(0); 2330883625c5SJohnny Huang otp_read_conf(4, &otpcfg4); 2331883625c5SJohnny Huang krb = otpcfg4 & 0xff; 2332883625c5SJohnny Huang krb_b = (otpcfg4 >> 16) & 0xff; 2333883625c5SJohnny Huang krb_or = krb | krb_b; 2334883625c5SJohnny Huang if (krb_or & (1 << retire_id)) { 2335883625c5SJohnny Huang printf("SUCCESS\n"); 2336883625c5SJohnny Huang return OTP_SUCCESS; 2337883625c5SJohnny Huang } 2338883625c5SJohnny Huang printf("FAILED\n"); 2339883625c5SJohnny Huang return OTP_FAILURE; 2340883625c5SJohnny Huang } 2341883625c5SJohnny Huang 23422a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 234369d5fd8fSJohnny Huang { 2344a219f6deSJohnny Huang u32 offset, count; 23452a856b9aSJohnny Huang int ret; 234669d5fd8fSJohnny Huang 23472a856b9aSJohnny Huang if (argc == 4) { 23482a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 23492a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 23502a856b9aSJohnny Huang } else if (argc == 3) { 23512a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 23522a856b9aSJohnny Huang count = 1; 23532a856b9aSJohnny Huang } else { 235469d5fd8fSJohnny Huang return CMD_RET_USAGE; 235569d5fd8fSJohnny Huang } 235669d5fd8fSJohnny Huang 2357030cb4a7SJohnny Huang if (!strcmp(argv[1], "conf")) 2358f347c284SJohnny Huang ret = otp_print_conf(offset, count); 2359030cb4a7SJohnny Huang else if (!strcmp(argv[1], "data")) 23602a856b9aSJohnny Huang ret = otp_print_data(offset, count); 2361030cb4a7SJohnny Huang else if (!strcmp(argv[1], "strap")) 23622a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 2363030cb4a7SJohnny Huang else 23642a856b9aSJohnny Huang return CMD_RET_USAGE; 236569d5fd8fSJohnny Huang 23662a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 23672a856b9aSJohnny Huang return CMD_RET_SUCCESS; 23682a856b9aSJohnny Huang return CMD_RET_USAGE; 23692a856b9aSJohnny Huang } 23702a856b9aSJohnny Huang 23712a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 23722a856b9aSJohnny Huang { 23732a856b9aSJohnny Huang phys_addr_t addr; 23742a856b9aSJohnny Huang int ret; 23752a856b9aSJohnny Huang 2376de6b0cc4SJohnny Huang if (argc == 3) { 2377ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 23782a856b9aSJohnny Huang return CMD_RET_USAGE; 23792a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 2380f347c284SJohnny Huang ret = otp_prog_image(addr, 1); 2381de6b0cc4SJohnny Huang } else if (argc == 2) { 23822a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 2383f347c284SJohnny Huang ret = otp_prog_image(addr, 0); 23842a856b9aSJohnny Huang } else { 23852a856b9aSJohnny Huang return CMD_RET_USAGE; 23862a856b9aSJohnny Huang } 23872a856b9aSJohnny Huang 23882a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 23892a856b9aSJohnny Huang return CMD_RET_SUCCESS; 23902a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 23912a856b9aSJohnny Huang return CMD_RET_FAILURE; 23922a856b9aSJohnny Huang else 23932a856b9aSJohnny Huang return CMD_RET_USAGE; 23942a856b9aSJohnny Huang } 23952a856b9aSJohnny Huang 23962a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 23972a856b9aSJohnny Huang { 23982a856b9aSJohnny Huang int mode = 0; 23992a856b9aSJohnny Huang int nconfirm = 0; 24002a856b9aSJohnny Huang int otp_addr = 0; 24012a856b9aSJohnny Huang int bit_offset; 24022a856b9aSJohnny Huang int value; 24032a856b9aSJohnny Huang int ret; 2404030cb4a7SJohnny Huang u32 otp_strap_pro; 24052a856b9aSJohnny Huang 24062a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 24072a856b9aSJohnny Huang return CMD_RET_USAGE; 24082a856b9aSJohnny Huang 24092a856b9aSJohnny Huang /* Drop the pb cmd */ 24102a856b9aSJohnny Huang argc--; 24112a856b9aSJohnny Huang argv++; 24122a856b9aSJohnny Huang 24132a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2414a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 24152a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2416a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 24172a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2418a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2419cd1610b4SJohnny Huang else 24202a856b9aSJohnny Huang return CMD_RET_USAGE; 24212a856b9aSJohnny Huang 24222a856b9aSJohnny Huang /* Drop the region cmd */ 24232a856b9aSJohnny Huang argc--; 24242a856b9aSJohnny Huang argv++; 24252a856b9aSJohnny Huang 2426ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2427cd1610b4SJohnny Huang nconfirm = 1; 24282a856b9aSJohnny Huang /* Drop the force option */ 24292a856b9aSJohnny Huang argc--; 24302a856b9aSJohnny Huang argv++; 24312a856b9aSJohnny Huang } 2432cd1610b4SJohnny Huang 2433a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 24342a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 24352a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 24360808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 24372a856b9aSJohnny Huang return CMD_RET_USAGE; 2438cd1610b4SJohnny Huang } else { 24392a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 24402a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 24412a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 24420808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 24432a856b9aSJohnny Huang return CMD_RET_USAGE; 24440808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 244578855207SJohnny Huang if (otp_addr >= 0x800) 24460808cc55SJohnny Huang return CMD_RET_USAGE; 24470808cc55SJohnny Huang } else { 244878855207SJohnny Huang if (otp_addr >= 0x20) 24490808cc55SJohnny Huang return CMD_RET_USAGE; 24500808cc55SJohnny Huang } 2451cd1610b4SJohnny Huang } 2452cd1610b4SJohnny Huang if (value != 0 && value != 1) 24532a856b9aSJohnny Huang return CMD_RET_USAGE; 2454cd1610b4SJohnny Huang 2455030cb4a7SJohnny Huang ret = 0; 2456030cb4a7SJohnny Huang if (info_cb.pro_sts.mem_lock) { 2457030cb4a7SJohnny Huang printf("OTP memory is locked\n"); 2458030cb4a7SJohnny Huang return CMD_RET_FAILURE; 2459030cb4a7SJohnny Huang } 2460030cb4a7SJohnny Huang if (mode == OTP_REGION_DATA) { 2461030cb4a7SJohnny Huang if (info_cb.pro_sts.sec_size == 0) { 2462030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_data) { 2463030cb4a7SJohnny Huang printf("OTP data region is protected\n"); 2464030cb4a7SJohnny Huang ret = -1; 2465030cb4a7SJohnny Huang } 2466030cb4a7SJohnny Huang } else if (otp_addr < info_cb.pro_sts.sec_size && otp_addr >= 16) { 2467030cb4a7SJohnny Huang printf("OTP secure region is not readable, skip it to prevent unpredictable result\n"); 2468030cb4a7SJohnny Huang ret = -1; 2469030cb4a7SJohnny Huang } else if (otp_addr < info_cb.pro_sts.sec_size) { 2470030cb4a7SJohnny Huang // header region(0x0~0x40) is still readable even secure region is set. 2471030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_sec) { 2472030cb4a7SJohnny Huang printf("OTP secure region is protected\n"); 2473030cb4a7SJohnny Huang ret = -1; 2474030cb4a7SJohnny Huang } 2475030cb4a7SJohnny Huang } else if (info_cb.pro_sts.pro_data) { 2476030cb4a7SJohnny Huang printf("OTP data region is protected\n"); 2477030cb4a7SJohnny Huang ret = -1; 2478030cb4a7SJohnny Huang } 2479030cb4a7SJohnny Huang } else if (mode == OTP_REGION_CONF) { 2480030cb4a7SJohnny Huang if (otp_addr != 4 && otp_addr != 10 && otp_addr != 11 && otp_addr < 16) { 2481030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_conf) { 2482030cb4a7SJohnny Huang printf("OTP config region is protected\n"); 2483030cb4a7SJohnny Huang ret = -1; 2484030cb4a7SJohnny Huang } 2485030cb4a7SJohnny Huang } else if (otp_addr == 10 || otp_addr == 11) { 2486030cb4a7SJohnny Huang u32 otp_rid[2]; 2487030cb4a7SJohnny Huang u32 sw_rid[2]; 2488030cb4a7SJohnny Huang u64 *otp_rid64 = (u64 *)otp_rid; 2489030cb4a7SJohnny Huang u64 *sw_rid64 = (u64 *)sw_rid; 2490030cb4a7SJohnny Huang 2491030cb4a7SJohnny Huang otp_read_conf(10, &otp_rid[0]); 2492030cb4a7SJohnny Huang otp_read_conf(11, &otp_rid[1]); 2493030cb4a7SJohnny Huang sw_rid[0] = readl(SW_REV_ID0); 2494030cb4a7SJohnny Huang sw_rid[1] = readl(SW_REV_ID1); 2495030cb4a7SJohnny Huang 2496030cb4a7SJohnny Huang if (otp_addr == 10) 2497030cb4a7SJohnny Huang otp_rid[0] |= 1 << bit_offset; 2498030cb4a7SJohnny Huang else 2499030cb4a7SJohnny Huang otp_rid[1] |= 1 << bit_offset; 2500030cb4a7SJohnny Huang 2501030cb4a7SJohnny Huang if (*otp_rid64 > *sw_rid64) { 2502030cb4a7SJohnny Huang printf("update number could not bigger than current SW revision id\n"); 2503030cb4a7SJohnny Huang ret = -1; 2504030cb4a7SJohnny Huang } 2505030cb4a7SJohnny Huang } else if (otp_addr == 4) { 2506030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_key_ret) { 2507030cb4a7SJohnny Huang printf("OTPCFG4 is protected\n"); 2508030cb4a7SJohnny Huang ret = -1; 2509030cb4a7SJohnny Huang } else { 2510030cb4a7SJohnny Huang if ((bit_offset >= 0 && bit_offset <= 7) || 2511030cb4a7SJohnny Huang (bit_offset >= 16 && bit_offset <= 23)) { 2512030cb4a7SJohnny Huang u32 key_num; 2513030cb4a7SJohnny Huang u32 retire; 2514030cb4a7SJohnny Huang 2515030cb4a7SJohnny Huang key_num = readl(SEC_KEY_NUM) & 3; 2516030cb4a7SJohnny Huang if (bit_offset >= 16) 2517030cb4a7SJohnny Huang retire = bit_offset - 16; 2518030cb4a7SJohnny Huang else 2519030cb4a7SJohnny Huang retire = bit_offset; 2520030cb4a7SJohnny Huang if (retire >= key_num) { 2521030cb4a7SJohnny Huang printf("Retire key id is equal or bigger than current boot key\n"); 2522030cb4a7SJohnny Huang ret = -1; 2523030cb4a7SJohnny Huang } 2524030cb4a7SJohnny Huang } 2525030cb4a7SJohnny Huang } 2526030cb4a7SJohnny Huang } else if (otp_addr >= 16 && otp_addr <= 31) { 2527030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_strap) { 2528030cb4a7SJohnny Huang printf("OTP strap region is protected\n"); 2529030cb4a7SJohnny Huang ret = -1; 2530030cb4a7SJohnny Huang } else if ((otp_addr < 30 && info_cb.version == OTP_A0) || 2531030cb4a7SJohnny Huang (otp_addr < 28 && info_cb.version != OTP_A0)) { 2532030cb4a7SJohnny Huang if (otp_addr % 2 == 0) 2533030cb4a7SJohnny Huang otp_read_conf(30, &otp_strap_pro); 2534030cb4a7SJohnny Huang else 2535030cb4a7SJohnny Huang otp_read_conf(31, &otp_strap_pro); 2536030cb4a7SJohnny Huang if (otp_strap_pro >> bit_offset & 0x1) { 2537b489486eSJohnny Huang printf("OTPCFG0x%X[0x%X] is protected\n", otp_addr, bit_offset); 2538030cb4a7SJohnny Huang ret = -1; 2539030cb4a7SJohnny Huang } 2540030cb4a7SJohnny Huang } 2541030cb4a7SJohnny Huang } 2542030cb4a7SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 2543030cb4a7SJohnny Huang // per bit protection will check in otp_strap_bit_confirm 2544030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_strap) { 2545030cb4a7SJohnny Huang printf("OTP strap region is protected\n"); 2546030cb4a7SJohnny Huang ret = -1; 2547030cb4a7SJohnny Huang } 2548030cb4a7SJohnny Huang } 2549030cb4a7SJohnny Huang 2550030cb4a7SJohnny Huang if (ret == -1) 2551030cb4a7SJohnny Huang return CMD_RET_FAILURE; 2552030cb4a7SJohnny Huang 2553f347c284SJohnny Huang ret = otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 25542a856b9aSJohnny Huang 25552a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 25562a856b9aSJohnny Huang return CMD_RET_SUCCESS; 25572a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 25582a856b9aSJohnny Huang return CMD_RET_FAILURE; 25592a856b9aSJohnny Huang else 25602a856b9aSJohnny Huang return CMD_RET_USAGE; 25612a856b9aSJohnny Huang } 25622a856b9aSJohnny Huang 25632a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 25642a856b9aSJohnny Huang { 25652a856b9aSJohnny Huang phys_addr_t addr; 25662a856b9aSJohnny Huang int otp_addr = 0; 2567b8590031SJohnny Huang int ret; 25682a856b9aSJohnny Huang 25692a856b9aSJohnny Huang if (argc != 3) 25702a856b9aSJohnny Huang return CMD_RET_USAGE; 25712a856b9aSJohnny Huang 25722a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 25732a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 2574b8590031SJohnny Huang ret = otp_compare(otp_addr, addr); 2575b8590031SJohnny Huang if (ret == 0) { 257669d5fd8fSJohnny Huang printf("Compare pass\n"); 25772a856b9aSJohnny Huang return CMD_RET_SUCCESS; 2578a219f6deSJohnny Huang } 257969d5fd8fSJohnny Huang printf("Compare fail\n"); 25802a856b9aSJohnny Huang return CMD_RET_FAILURE; 258169d5fd8fSJohnny Huang } 258269d5fd8fSJohnny Huang 258366f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 258466f2f8e5SJohnny Huang { 2585a8bd6d8cSJohnny Huang int view = 0; 25862d4b0742SJohnny Huang int input; 2587a8bd6d8cSJohnny Huang 2588a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 258966f2f8e5SJohnny Huang return CMD_RET_USAGE; 259066f2f8e5SJohnny Huang 25912d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 25922d4b0742SJohnny Huang if (argc == 3) { 25932d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 25942d4b0742SJohnny Huang otp_print_conf_info(input); 25952d4b0742SJohnny Huang } else { 25962d4b0742SJohnny Huang otp_print_conf_info(-1); 25972d4b0742SJohnny Huang } 25982d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 25992d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2600a8bd6d8cSJohnny Huang view = 1; 2601a8bd6d8cSJohnny Huang /* Drop the view option */ 2602a8bd6d8cSJohnny Huang argc--; 2603a8bd6d8cSJohnny Huang argv++; 2604a8bd6d8cSJohnny Huang } 2605b458cd62SJohnny Huang otp_print_strap_info(view); 26060dc9a440SJohnny Huang } else if (!strcmp(argv[1], "scu")) { 26070dc9a440SJohnny Huang otp_print_scu_info(); 260888bd7d58SJohnny Huang } else if (!strcmp(argv[1], "key")) { 260988bd7d58SJohnny Huang otp_print_key_info(); 261066f2f8e5SJohnny Huang } else { 261166f2f8e5SJohnny Huang return CMD_RET_USAGE; 261266f2f8e5SJohnny Huang } 26132d4b0742SJohnny Huang 261466f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 261566f2f8e5SJohnny Huang } 261666f2f8e5SJohnny Huang 26170dc9a440SJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2618737ed20bSJohnny Huang { 26190dc9a440SJohnny Huang u32 input; 26200dc9a440SJohnny Huang u32 bit_offset; 2621e14b073cSJohnny Huang u32 prog_address; 2622030cb4a7SJohnny Huang char force; 262383655e91SJohnny Huang int ret; 2624a219f6deSJohnny Huang 2625737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2626737ed20bSJohnny Huang return CMD_RET_USAGE; 2627737ed20bSJohnny Huang 2628e14b073cSJohnny Huang if (!strcmp(argv[1], "o")) { 2629737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2630030cb4a7SJohnny Huang force = 1; 2631737ed20bSJohnny Huang } else { 2632737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2633030cb4a7SJohnny Huang force = 0; 2634737ed20bSJohnny Huang } 2635737ed20bSJohnny Huang 2636737ed20bSJohnny Huang if (input < 32) { 2637737ed20bSJohnny Huang bit_offset = input; 26380dc9a440SJohnny Huang prog_address = 0xe0c; 2639737ed20bSJohnny Huang } else if (input < 64) { 2640737ed20bSJohnny Huang bit_offset = input - 32; 26410dc9a440SJohnny Huang prog_address = 0xe0e; 2642737ed20bSJohnny Huang } else { 2643737ed20bSJohnny Huang return CMD_RET_USAGE; 2644737ed20bSJohnny Huang } 2645737ed20bSJohnny Huang 2646030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_strap) { 2647030cb4a7SJohnny Huang printf("OTP strap region is protected\n"); 2648030cb4a7SJohnny Huang return CMD_RET_FAILURE; 2649030cb4a7SJohnny Huang } 2650030cb4a7SJohnny Huang 2651030cb4a7SJohnny Huang if (!force) { 2652b489486eSJohnny Huang printf("OTPSTRAP[0x%X] will be protected\n", input); 2653030cb4a7SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2654030cb4a7SJohnny Huang if (!confirm_yesno()) { 2655030cb4a7SJohnny Huang printf(" Aborting\n"); 2656030cb4a7SJohnny Huang return CMD_RET_FAILURE; 2657030cb4a7SJohnny Huang } 2658030cb4a7SJohnny Huang } 2659030cb4a7SJohnny Huang 2660e14b073cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2661b489486eSJohnny Huang printf("OTPSTRAP[0x%X] already protected\n", input); 2662e14b073cSJohnny Huang return CMD_RET_SUCCESS; 2663e14b073cSJohnny Huang } 2664de6fbf1cSJohnny Huang 2665f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, bit_offset); 2666de6fbf1cSJohnny Huang otp_soak(0); 266783655e91SJohnny Huang 266883655e91SJohnny Huang if (ret) { 2669b489486eSJohnny Huang printf("Protect OTPSTRAP[0x%X] fail\n", input); 2670737ed20bSJohnny Huang return CMD_RET_FAILURE; 2671737ed20bSJohnny Huang } 26729a4fe690SJohnny Huang 2673b489486eSJohnny Huang printf("OTPSTRAP[0x%X] is protected\n", input); 2674794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2675794e27ecSJohnny Huang } 2676794e27ecSJohnny Huang 26770dc9a440SJohnny Huang static int do_otp_scuprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2678e14b073cSJohnny Huang { 26790dc9a440SJohnny Huang u32 scu_offset; 26800dc9a440SJohnny Huang u32 bit_offset; 26810dc9a440SJohnny Huang u32 conf_offset; 26820dc9a440SJohnny Huang u32 prog_address; 26830dc9a440SJohnny Huang char force; 26840dc9a440SJohnny Huang int ret; 26850dc9a440SJohnny Huang 26860dc9a440SJohnny Huang if (argc != 4 && argc != 3) 26870dc9a440SJohnny Huang return CMD_RET_USAGE; 26880dc9a440SJohnny Huang 26890dc9a440SJohnny Huang if (!strcmp(argv[1], "o")) { 26900dc9a440SJohnny Huang scu_offset = simple_strtoul(argv[2], NULL, 16); 26910dc9a440SJohnny Huang bit_offset = simple_strtoul(argv[3], NULL, 16); 26920dc9a440SJohnny Huang force = 1; 26930dc9a440SJohnny Huang } else { 26940dc9a440SJohnny Huang scu_offset = simple_strtoul(argv[1], NULL, 16); 26950dc9a440SJohnny Huang bit_offset = simple_strtoul(argv[2], NULL, 16); 26960dc9a440SJohnny Huang force = 0; 26970dc9a440SJohnny Huang } 26980dc9a440SJohnny Huang if (scu_offset == 0x500) { 26990dc9a440SJohnny Huang prog_address = 0xe08; 27000dc9a440SJohnny Huang conf_offset = 28; 27010dc9a440SJohnny Huang } else if (scu_offset == 0x510) { 27020dc9a440SJohnny Huang prog_address = 0xe0a; 27030dc9a440SJohnny Huang conf_offset = 29; 27040dc9a440SJohnny Huang } else { 27050dc9a440SJohnny Huang return CMD_RET_USAGE; 27060dc9a440SJohnny Huang } 27070dc9a440SJohnny Huang if (bit_offset < 0 || bit_offset > 31) 27080dc9a440SJohnny Huang return CMD_RET_USAGE; 2709030cb4a7SJohnny Huang if (info_cb.pro_sts.pro_strap) { 2710030cb4a7SJohnny Huang printf("OTP strap region is protected\n"); 2711030cb4a7SJohnny Huang return CMD_RET_FAILURE; 2712030cb4a7SJohnny Huang } 27130dc9a440SJohnny Huang if (!force) { 2714b489486eSJohnny Huang printf("OTPCONF0x%X[0x%X] will be programmed\n", conf_offset, bit_offset); 2715b489486eSJohnny Huang printf("SCU0x%X[0x%X] will be protected\n", scu_offset, bit_offset); 27160dc9a440SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 27170dc9a440SJohnny Huang if (!confirm_yesno()) { 27180dc9a440SJohnny Huang printf(" Aborting\n"); 27190dc9a440SJohnny Huang return CMD_RET_FAILURE; 27200dc9a440SJohnny Huang } 2721e14b073cSJohnny Huang } 2722e14b073cSJohnny Huang 27230dc9a440SJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2724b489486eSJohnny Huang printf("OTPCONF0x%X[0x%X] already programmed\n", conf_offset, bit_offset); 27250dc9a440SJohnny Huang return CMD_RET_SUCCESS; 27260dc9a440SJohnny Huang } 27270dc9a440SJohnny Huang 27280dc9a440SJohnny Huang ret = otp_prog_dc_b(1, prog_address, bit_offset); 27290dc9a440SJohnny Huang otp_soak(0); 27300dc9a440SJohnny Huang 27310dc9a440SJohnny Huang if (ret) { 2732b489486eSJohnny Huang printf("Program OTPCONF0x%X[0x%X] fail\n", conf_offset, bit_offset); 27330dc9a440SJohnny Huang return CMD_RET_FAILURE; 27340dc9a440SJohnny Huang } 27350dc9a440SJohnny Huang 2736b489486eSJohnny Huang printf("OTPCONF0x%X[0x%X] programmed success\n", conf_offset, bit_offset); 27370dc9a440SJohnny Huang return CMD_RET_SUCCESS; 2738e14b073cSJohnny Huang } 2739e14b073cSJohnny Huang 2740f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2741f67375f7SJohnny Huang { 2742e417205bSJohnny Huang printf("SOC OTP version: %s\n", info_cb.ver_name); 2743f67375f7SJohnny Huang printf("OTP tool version: %s\n", OTP_VER); 2744f67375f7SJohnny Huang printf("OTP info version: %s\n", OTP_INFO_VER); 2745f67375f7SJohnny Huang 2746f67375f7SJohnny Huang return CMD_RET_SUCCESS; 2747f67375f7SJohnny Huang } 2748f67375f7SJohnny Huang 2749794e27ecSJohnny Huang static int do_otpupdate(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2750794e27ecSJohnny Huang { 2751794e27ecSJohnny Huang u32 update_num; 2752794e27ecSJohnny Huang int force = 0; 2753794e27ecSJohnny Huang int ret; 2754794e27ecSJohnny Huang 2755794e27ecSJohnny Huang if (argc == 3) { 2756794e27ecSJohnny Huang if (strcmp(argv[1], "o")) 2757794e27ecSJohnny Huang return CMD_RET_USAGE; 2758794e27ecSJohnny Huang force = 1; 2759794e27ecSJohnny Huang update_num = simple_strtoul(argv[2], NULL, 16); 2760794e27ecSJohnny Huang } else if (argc == 2) { 2761794e27ecSJohnny Huang update_num = simple_strtoul(argv[1], NULL, 16); 2762794e27ecSJohnny Huang } else { 2763794e27ecSJohnny Huang return CMD_RET_USAGE; 2764794e27ecSJohnny Huang } 2765794e27ecSJohnny Huang 2766794e27ecSJohnny Huang if (update_num > 64) 2767794e27ecSJohnny Huang return CMD_RET_USAGE; 2768794e27ecSJohnny Huang ret = otp_update_rid(update_num, force); 2769b8590031SJohnny Huang 2770794e27ecSJohnny Huang if (ret) 2771794e27ecSJohnny Huang return CMD_RET_FAILURE; 2772794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2773794e27ecSJohnny Huang } 2774794e27ecSJohnny Huang 2775794e27ecSJohnny Huang static int do_otprid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2776794e27ecSJohnny Huang { 2777794e27ecSJohnny Huang u32 otp_rid[2]; 2778a8789b47SJohnny Huang u32 sw_rid[2]; 2779794e27ecSJohnny Huang int rid_num = 0; 2780a8789b47SJohnny Huang int sw_rid_num = 0; 2781794e27ecSJohnny Huang int ret; 2782794e27ecSJohnny Huang 2783794e27ecSJohnny Huang if (argc != 1) 2784794e27ecSJohnny Huang return CMD_RET_USAGE; 2785794e27ecSJohnny Huang 2786f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 2787f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 2788794e27ecSJohnny Huang 2789a8789b47SJohnny Huang sw_rid[0] = readl(SW_REV_ID0); 2790a8789b47SJohnny Huang sw_rid[1] = readl(SW_REV_ID1); 2791794e27ecSJohnny Huang 2792a8789b47SJohnny Huang rid_num = get_rid_num(otp_rid); 2793a8789b47SJohnny Huang sw_rid_num = get_rid_num(sw_rid); 2794a8789b47SJohnny Huang 2795030cb4a7SJohnny Huang if (sw_rid_num < 0) { 2796030cb4a7SJohnny Huang printf("SW revision id is invalid, please check.\n"); 2797030cb4a7SJohnny Huang printf("SEC68:0x%x\n", sw_rid[0]); 2798030cb4a7SJohnny Huang printf("SEC6C:0x%x\n", sw_rid[1]); 2799030cb4a7SJohnny Huang } else { 2800a8789b47SJohnny Huang printf("current SW revision ID: 0x%x\n", sw_rid_num); 2801030cb4a7SJohnny Huang } 2802794e27ecSJohnny Huang if (rid_num >= 0) { 2803794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 2804794e27ecSJohnny Huang ret = CMD_RET_SUCCESS; 2805794e27ecSJohnny Huang } else { 2806b64ca396SJohnny Huang printf("Current OTP revision ID cannot handle by 'otp update',\n" 2807b64ca396SJohnny Huang "please use 'otp pb' command to update it manually\n" 2808794e27ecSJohnny Huang "current OTP revision ID\n"); 2809794e27ecSJohnny Huang ret = CMD_RET_FAILURE; 2810794e27ecSJohnny Huang } 2811794e27ecSJohnny Huang otp_print_revid(otp_rid); 2812794e27ecSJohnny Huang 2813794e27ecSJohnny Huang return ret; 2814794e27ecSJohnny Huang } 2815794e27ecSJohnny Huang 2816883625c5SJohnny Huang static int do_otpretire(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2817883625c5SJohnny Huang { 2818883625c5SJohnny Huang u32 retire_id; 2819883625c5SJohnny Huang int force = 0; 2820883625c5SJohnny Huang int ret; 2821883625c5SJohnny Huang 2822883625c5SJohnny Huang if (argc == 3) { 2823883625c5SJohnny Huang if (strcmp(argv[1], "o")) 2824883625c5SJohnny Huang return CMD_RET_USAGE; 2825883625c5SJohnny Huang force = 1; 2826883625c5SJohnny Huang retire_id = simple_strtoul(argv[2], NULL, 16); 2827883625c5SJohnny Huang } else if (argc == 2) { 2828883625c5SJohnny Huang retire_id = simple_strtoul(argv[1], NULL, 16); 2829883625c5SJohnny Huang } else { 2830883625c5SJohnny Huang return CMD_RET_USAGE; 2831883625c5SJohnny Huang } 2832883625c5SJohnny Huang 2833883625c5SJohnny Huang if (retire_id > 7) 2834883625c5SJohnny Huang return CMD_RET_USAGE; 2835883625c5SJohnny Huang ret = otp_retire_key(retire_id, force); 2836883625c5SJohnny Huang 2837883625c5SJohnny Huang if (ret) 2838883625c5SJohnny Huang return CMD_RET_FAILURE; 2839883625c5SJohnny Huang return CMD_RET_SUCCESS; 2840883625c5SJohnny Huang } 2841883625c5SJohnny Huang 28422a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 2843f67375f7SJohnny Huang U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""), 28442a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2845a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 2846de6b0cc4SJohnny Huang U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""), 28472a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2848737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 28490dc9a440SJohnny Huang U_BOOT_CMD_MKENT(scuprotect, 4, 0, do_otp_scuprotect, "", ""), 28502a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 2851794e27ecSJohnny Huang U_BOOT_CMD_MKENT(update, 3, 0, do_otpupdate, "", ""), 2852794e27ecSJohnny Huang U_BOOT_CMD_MKENT(rid, 1, 0, do_otprid, "", ""), 2853883625c5SJohnny Huang U_BOOT_CMD_MKENT(retire, 3, 0, do_otpretire, "", ""), 28542a856b9aSJohnny Huang }; 28552a856b9aSJohnny Huang 28562a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 28572a856b9aSJohnny Huang { 2858030cb4a7SJohnny Huang struct otp_pro_sts *pro_sts; 28592a856b9aSJohnny Huang cmd_tbl_t *cp; 2860a219f6deSJohnny Huang u32 ver; 2861e14b073cSJohnny Huang int ret; 2862030cb4a7SJohnny Huang u32 otp_conf0; 28632a856b9aSJohnny Huang 28642a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 28652a856b9aSJohnny Huang 2866737ed20bSJohnny Huang /* Drop the otp command */ 28672a856b9aSJohnny Huang argc--; 28682a856b9aSJohnny Huang argv++; 28692a856b9aSJohnny Huang 2870a219f6deSJohnny Huang if (!cp || argc > cp->maxargs) 28712a856b9aSJohnny Huang return CMD_RET_USAGE; 28722a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 28732a856b9aSJohnny Huang return CMD_RET_SUCCESS; 28742a856b9aSJohnny Huang 28750dae9d52SJohnny Huang ver = chip_version(); 28760dae9d52SJohnny Huang switch (ver) { 2877e417205bSJohnny Huang case OTP_A0: 2878e417205bSJohnny Huang info_cb.version = OTP_A0; 28799a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 28809a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 28819a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 28829a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 28839a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 28849a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 2885e417205bSJohnny Huang sprintf(info_cb.ver_name, "A0"); 28860dae9d52SJohnny Huang break; 2887e417205bSJohnny Huang case OTP_A1: 2888e417205bSJohnny Huang info_cb.version = OTP_A1; 28893cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 28903cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 28913cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 28923cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 28939a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 28949a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 28950dc9a440SJohnny Huang info_cb.scu_info = a1_scu_info; 28960dc9a440SJohnny Huang info_cb.scu_info_len = ARRAY_SIZE(a1_scu_info); 2897e417205bSJohnny Huang sprintf(info_cb.ver_name, "A1"); 28980dae9d52SJohnny Huang break; 2899e417205bSJohnny Huang case OTP_A2: 2900e417205bSJohnny Huang info_cb.version = OTP_A2; 29015fdde29fSJohnny Huang info_cb.conf_info = a2_conf_info; 29025fdde29fSJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info); 2903fed30023SJohnny Huang info_cb.strap_info = a1_strap_info; 2904fed30023SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 29055fdde29fSJohnny Huang info_cb.key_info = a2_key_type; 29065fdde29fSJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a2_key_type); 29070dc9a440SJohnny Huang info_cb.scu_info = a1_scu_info; 29080dc9a440SJohnny Huang info_cb.scu_info_len = ARRAY_SIZE(a1_scu_info); 2909e417205bSJohnny Huang sprintf(info_cb.ver_name, "A2"); 29100dae9d52SJohnny Huang break; 2911e417205bSJohnny Huang case OTP_A3: 2912e417205bSJohnny Huang info_cb.version = OTP_A3; 2913b63af886SJohnny Huang info_cb.conf_info = a3_conf_info; 2914b63af886SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a3_conf_info); 2915fed30023SJohnny Huang info_cb.strap_info = a1_strap_info; 2916fed30023SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 2917181f72d8SJohnny Huang info_cb.key_info = a3_key_type; 2918181f72d8SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a3_key_type); 29190dc9a440SJohnny Huang info_cb.scu_info = a1_scu_info; 29200dc9a440SJohnny Huang info_cb.scu_info_len = ARRAY_SIZE(a1_scu_info); 2921e417205bSJohnny Huang sprintf(info_cb.ver_name, "A3"); 292264b66712SJohnny Huang break; 29230dae9d52SJohnny Huang default: 2924f1be5099SJohnny Huang printf("SOC is not supported\n"); 29250dae9d52SJohnny Huang return CMD_RET_FAILURE; 29269a4fe690SJohnny Huang } 29279a4fe690SJohnny Huang 2928030cb4a7SJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2929030cb4a7SJohnny Huang otp_read_conf(0, &otp_conf0); 2930030cb4a7SJohnny Huang pro_sts = &info_cb.pro_sts; 2931030cb4a7SJohnny Huang 2932030cb4a7SJohnny Huang pro_sts->mem_lock = (otp_conf0 >> 31) & 0x1; 2933030cb4a7SJohnny Huang pro_sts->pro_key_ret = (otp_conf0 >> 29) & 0x1; 2934030cb4a7SJohnny Huang pro_sts->pro_strap = (otp_conf0 >> 25) & 0x1; 2935030cb4a7SJohnny Huang pro_sts->pro_conf = (otp_conf0 >> 24) & 0x1; 2936030cb4a7SJohnny Huang pro_sts->pro_data = (otp_conf0 >> 23) & 0x1; 2937030cb4a7SJohnny Huang pro_sts->pro_sec = (otp_conf0 >> 22) & 0x1; 2938030cb4a7SJohnny Huang pro_sts->sec_size = ((otp_conf0 >> 16) & 0x3f) << 5; 2939030cb4a7SJohnny Huang 2940e14b073cSJohnny Huang ret = cp->cmd(cmdtp, flag, argc, argv); 2941b8590031SJohnny Huang writel(1, OTP_PROTECT_KEY); //protect otp controller 2942e14b073cSJohnny Huang 2943e14b073cSJohnny Huang return ret; 294469d5fd8fSJohnny Huang } 294569d5fd8fSJohnny Huang 2946a219f6deSJohnny Huang U_BOOT_CMD(otp, 7, 0, do_ast_otp, 294769d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 2948f67375f7SJohnny Huang "version\n" 2949f67375f7SJohnny Huang "otp read conf|data <otp_dw_offset> <dw_count>\n" 29502a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 29512d4b0742SJohnny Huang "otp info strap [v]\n" 29522d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 29530dc9a440SJohnny Huang "otp info scu\n" 295488bd7d58SJohnny Huang "otp info key\n" 2955de6b0cc4SJohnny Huang "otp prog [o] <addr>\n" 2956ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2957ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2958ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 29590dc9a440SJohnny Huang "otp scuprotect [o] <scu_offset> <bit_offset>\n" 2960794e27ecSJohnny Huang "otp update [o] <revision_id>\n" 2961794e27ecSJohnny Huang "otp rid\n" 2962883625c5SJohnny Huang "otp retire [o] <key_id>\n" 296369d5fd8fSJohnny Huang ); 2964