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> 18696656c6SJohnny Huang #include <u-boot/sha256.h> 190cee9a95SJohnny Huang #include "otp_info.h" 2069d5fd8fSJohnny Huang 2169d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2269d5fd8fSJohnny Huang 23f347c284SJohnny Huang #define OTP_VER "1.1.0" 24f67375f7SJohnny Huang 2569d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 26dacbba92SJohnny Huang #define RETRY 20 277332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 287332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 297332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3069d5fd8fSJohnny Huang 312a856b9aSJohnny Huang #define OTP_USAGE -1 322a856b9aSJohnny Huang #define OTP_FAILURE -2 332a856b9aSJohnny Huang #define OTP_SUCCESS 0 342a856b9aSJohnny Huang 35a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 36a6af4a17SJohnny Huang 37181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PUB 1 38181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PRIV 2 39181f72d8SJohnny Huang #define OTP_KEY_TYPE_AES 3 40181f72d8SJohnny Huang #define OTP_KEY_TYPE_VAULT 4 41181f72d8SJohnny Huang #define OTP_KEY_TYPE_HMAC 5 429a4fe690SJohnny Huang 434c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 444c1c9b35SJohnny Huang #define PBWIDTH 60 454c1c9b35SJohnny Huang 463d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 473d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 483d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 493d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 503d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 513d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 523d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 533d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 543d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 553d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 56a8789b47SJohnny Huang #define SW_REV_ID0 OTP_BASE + 0x68 57a8789b47SJohnny Huang #define SW_REV_ID1 OTP_BASE + 0x6c 583d3688adSJohnny Huang 59696656c6SJohnny Huang #define OTP_MAGIC "SOCOTP" 60696656c6SJohnny Huang #define CHECKSUM_LEN 32 61a219f6deSJohnny Huang #define OTP_INC_DATA BIT(31) 62a219f6deSJohnny Huang #define OTP_INC_CONFIG BIT(30) 63a219f6deSJohnny Huang #define OTP_INC_STRAP BIT(29) 64a219f6deSJohnny Huang #define OTP_ECC_EN BIT(28) 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)) 10361a6cda7SJohnny Huang 104696656c6SJohnny Huang struct otp_header { 105696656c6SJohnny Huang u8 otp_magic[8]; 10661a6cda7SJohnny Huang u32 soc_ver; 10761a6cda7SJohnny Huang u32 otptool_ver; 108696656c6SJohnny Huang u32 image_info; 109696656c6SJohnny Huang u32 data_info; 110696656c6SJohnny Huang u32 config_info; 111696656c6SJohnny Huang u32 strap_info; 112*7e523e3bSJohnny Huang u32 scu_protect_info; 113696656c6SJohnny Huang u32 checksum_offset; 114a219f6deSJohnny Huang } __packed; 115696656c6SJohnny Huang 11666f2f8e5SJohnny Huang struct otpstrap_status { 11769d5fd8fSJohnny Huang int value; 11869d5fd8fSJohnny Huang int option_array[7]; 11969d5fd8fSJohnny Huang int remain_times; 12069d5fd8fSJohnny Huang int writeable_option; 12169d5fd8fSJohnny Huang int protected; 12269d5fd8fSJohnny Huang }; 12369d5fd8fSJohnny Huang 1249a4fe690SJohnny Huang struct otpkey_type { 1259a4fe690SJohnny Huang int value; 1269a4fe690SJohnny Huang int key_type; 1279a4fe690SJohnny Huang int need_id; 1289a4fe690SJohnny Huang char information[110]; 1299a4fe690SJohnny Huang }; 1309a4fe690SJohnny Huang 1319a4fe690SJohnny Huang struct otp_info_cb { 1329a4fe690SJohnny Huang int version; 133e417205bSJohnny Huang char ver_name[3]; 13479e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1359a4fe690SJohnny Huang int strap_info_len; 13679e42a59SJoel Stanley const struct otpconf_info *conf_info; 1379a4fe690SJohnny Huang int conf_info_len; 13879e42a59SJoel Stanley const struct otpkey_type *key_info; 1399a4fe690SJohnny Huang int key_info_len; 1409a4fe690SJohnny Huang }; 1419a4fe690SJohnny Huang 142696656c6SJohnny Huang struct otp_image_layout { 1435010032bSJohnny Huang int data_length; 1445010032bSJohnny Huang int conf_length; 1455010032bSJohnny Huang int strap_length; 146a219f6deSJohnny Huang u8 *data; 147a219f6deSJohnny Huang u8 *data_ignore; 148a219f6deSJohnny Huang u8 *conf; 149a219f6deSJohnny Huang u8 *conf_ignore; 150a219f6deSJohnny Huang u8 *strap; 151a219f6deSJohnny Huang u8 *strap_pro; 152a219f6deSJohnny Huang u8 *strap_ignore; 153696656c6SJohnny Huang }; 154696656c6SJohnny Huang 1559a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1569a4fe690SJohnny Huang 15779e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 1589a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 1599a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1609a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 161181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 162181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as SOC public key"}, 163181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 164181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as SOC private key"}, 165181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1669a4fe690SJohnny Huang }; 1679a4fe690SJohnny Huang 16879e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 1699a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1709a4fe690SJohnny 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"}, 171181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 172181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 173181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1749a4fe690SJohnny Huang }; 1759a4fe690SJohnny Huang 1765fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = { 1775fdde29fSJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1785fdde29fSJohnny 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"}, 179181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 180181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 181181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 182181f72d8SJohnny Huang }; 183181f72d8SJohnny Huang 184181f72d8SJohnny Huang static const struct otpkey_type a3_key_type[] = { 185181f72d8SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 186181f72d8SJohnny 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"}, 187181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 188181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2(big endian)"}, 189181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 190181f72d8SJohnny Huang {11, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key(big endian)"}, 191181f72d8SJohnny Huang {12, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 192181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key(big endian)"}, 1935fdde29fSJohnny Huang }; 1945fdde29fSJohnny Huang 195f347c284SJohnny Huang static void buf_print(u8 *buf, int len) 196f347c284SJohnny Huang { 197f347c284SJohnny Huang int i; 198f347c284SJohnny Huang 199f347c284SJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 200f347c284SJohnny Huang for (i = 0; i < len; i++) { 201f347c284SJohnny Huang if (i % 16 == 0) 202f347c284SJohnny Huang printf("%04X: ", i); 203f347c284SJohnny Huang printf("%02X ", buf[i]); 204f347c284SJohnny Huang if ((i + 1) % 16 == 0) 205f347c284SJohnny Huang printf("\n"); 206f347c284SJohnny Huang } 207f347c284SJohnny Huang } 208f347c284SJohnny Huang 209794e27ecSJohnny Huang static int get_dw_bit(u32 *rid, int offset) 210794e27ecSJohnny Huang { 211794e27ecSJohnny Huang int bit_offset; 212794e27ecSJohnny Huang int i; 213794e27ecSJohnny Huang 214794e27ecSJohnny Huang if (offset < 32) { 215794e27ecSJohnny Huang i = 0; 216794e27ecSJohnny Huang bit_offset = offset; 217794e27ecSJohnny Huang } else { 218794e27ecSJohnny Huang i = 1; 219794e27ecSJohnny Huang bit_offset = offset - 32; 220794e27ecSJohnny Huang } 221794e27ecSJohnny Huang if ((rid[i] >> bit_offset) & 0x1) 222794e27ecSJohnny Huang return 1; 223794e27ecSJohnny Huang else 224794e27ecSJohnny Huang return 0; 225794e27ecSJohnny Huang } 226794e27ecSJohnny Huang 227794e27ecSJohnny Huang static int get_rid_num(u32 *rid) 228794e27ecSJohnny Huang { 229794e27ecSJohnny Huang int i; 230794e27ecSJohnny Huang int fz = 0; 231794e27ecSJohnny Huang int rid_num = 0; 232794e27ecSJohnny Huang int ret = 0; 233794e27ecSJohnny Huang 234794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 235794e27ecSJohnny Huang if (get_dw_bit(rid, i) == 0) { 236794e27ecSJohnny Huang if (!fz) 237794e27ecSJohnny Huang fz = 1; 238794e27ecSJohnny Huang 239794e27ecSJohnny Huang } else { 240794e27ecSJohnny Huang rid_num++; 241794e27ecSJohnny Huang if (fz) 242794e27ecSJohnny Huang ret = OTP_FAILURE; 243794e27ecSJohnny Huang } 244794e27ecSJohnny Huang } 245794e27ecSJohnny Huang if (ret) 246794e27ecSJohnny Huang return ret; 247794e27ecSJohnny Huang 248794e27ecSJohnny Huang return rid_num; 249794e27ecSJohnny Huang } 250794e27ecSJohnny Huang 251a219f6deSJohnny Huang static u32 chip_version(void) 2529a4fe690SJohnny Huang { 253e417205bSJohnny Huang u32 revid0, revid1; 2549a4fe690SJohnny Huang 255e417205bSJohnny Huang revid0 = readl(ASPEED_REVISION_ID0); 256e417205bSJohnny Huang revid1 = readl(ASPEED_REVISION_ID1); 2579a4fe690SJohnny Huang 258e417205bSJohnny Huang if (revid0 == ID0_AST2600A0 && revid1 == ID1_AST2600A0) { 259badd21c2SJohnny Huang /* AST2600-A0 */ 260e417205bSJohnny Huang return OTP_A0; 261e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A1 && revid1 == ID1_AST2600A1) { 262badd21c2SJohnny Huang /* AST2600-A1 */ 263e417205bSJohnny Huang return OTP_A1; 264e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A2 && revid1 == ID1_AST2600A2) { 265badd21c2SJohnny Huang /* AST2600-A2 */ 266e417205bSJohnny Huang return OTP_A2; 267e417205bSJohnny Huang } else if (revid0 == ID0_AST2600A3 && revid1 == ID1_AST2600A3) { 26864b66712SJohnny Huang /* AST2600-A3 */ 269e417205bSJohnny Huang return OTP_A3; 270e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A1 && revid1 == ID1_AST2620A1) { 271e417205bSJohnny Huang /* AST2620-A1 */ 272e417205bSJohnny Huang return OTP_A1; 273e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A2 && revid1 == ID1_AST2620A2) { 274e417205bSJohnny Huang /* AST2620-A2 */ 275e417205bSJohnny Huang return OTP_A2; 276e417205bSJohnny Huang } else if (revid0 == ID0_AST2620A3 && revid1 == ID1_AST2620A3) { 27764b66712SJohnny Huang /* AST2620-A3 */ 278e417205bSJohnny Huang return OTP_A3; 279e417205bSJohnny Huang } else if (revid0 == ID0_AST2605A2 && revid1 == ID1_AST2605A2) { 280e417205bSJohnny Huang /* AST2605-A2 */ 281e417205bSJohnny Huang return OTP_A2; 282e417205bSJohnny Huang } else if (revid0 == ID0_AST2605A3 && revid1 == ID1_AST2605A3) { 283e417205bSJohnny Huang /* AST2605-A3 */ 284e417205bSJohnny Huang return OTP_A3; 285e417205bSJohnny Huang } else if (revid0 == ID0_AST2625A3 && revid1 == ID1_AST2625A3) { 286e417205bSJohnny Huang /* AST2605-A3 */ 287e417205bSJohnny Huang return OTP_A3; 2880dae9d52SJohnny Huang } 289f347c284SJohnny Huang return OTP_FAILURE; 2909a4fe690SJohnny Huang } 2919a4fe690SJohnny Huang 2923d3688adSJohnny Huang static void wait_complete(void) 2933d3688adSJohnny Huang { 2943d3688adSJohnny Huang int reg; 2953d3688adSJohnny Huang 2963d3688adSJohnny Huang do { 2973d3688adSJohnny Huang reg = readl(OTP_STATUS); 2983d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 2993d3688adSJohnny Huang } 3003d3688adSJohnny Huang 301a219f6deSJohnny Huang static void otp_write(u32 otp_addr, u32 data) 302dacbba92SJohnny Huang { 303dacbba92SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 304dacbba92SJohnny Huang writel(data, OTP_COMPARE_1); //write data 305dacbba92SJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 306dacbba92SJohnny Huang wait_complete(); 307dacbba92SJohnny Huang } 308dacbba92SJohnny Huang 309dacbba92SJohnny Huang static void otp_soak(int soak) 310dacbba92SJohnny Huang { 311e417205bSJohnny Huang if (info_cb.version == OTP_A2 || info_cb.version == OTP_A3) { 312dacbba92SJohnny Huang switch (soak) { 313dacbba92SJohnny Huang case 0: //default 314377f8cd7SJohnny Huang otp_write(0x3000, 0x0); // Write MRA 315377f8cd7SJohnny Huang otp_write(0x5000, 0x0); // Write MRB 316dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 317dacbba92SJohnny Huang break; 318dacbba92SJohnny Huang case 1: //normal program 319377f8cd7SJohnny Huang otp_write(0x3000, 0x1320); // Write MRA 320377f8cd7SJohnny Huang otp_write(0x5000, 0x1008); // Write MRB 321377f8cd7SJohnny Huang otp_write(0x1000, 0x0024); // Write MR 322feea3fdfSJohnny Huang writel(0x04191388, OTP_TIMING); // 200us 323dacbba92SJohnny Huang break; 324dacbba92SJohnny Huang case 2: //soak program 325377f8cd7SJohnny Huang otp_write(0x3000, 0x1320); // Write MRA 326377f8cd7SJohnny Huang otp_write(0x5000, 0x0007); // Write MRB 327377f8cd7SJohnny Huang otp_write(0x1000, 0x0100); // Write MR 328feea3fdfSJohnny Huang writel(0x04193a98, OTP_TIMING); // 600us 329dacbba92SJohnny Huang break; 330dacbba92SJohnny Huang } 331dacbba92SJohnny Huang } else { 332dacbba92SJohnny Huang switch (soak) { 333dacbba92SJohnny Huang case 0: //default 334dacbba92SJohnny Huang otp_write(0x3000, 0x0); // Write MRA 335dacbba92SJohnny Huang otp_write(0x5000, 0x0); // Write MRB 336dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 337dacbba92SJohnny Huang break; 338dacbba92SJohnny Huang case 1: //normal program 339dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 340dacbba92SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 341dacbba92SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 342feea3fdfSJohnny Huang writel(0x04190760, OTP_TIMING); // 75us 343dacbba92SJohnny Huang break; 344dacbba92SJohnny Huang case 2: //soak program 345dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 346dacbba92SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 347dacbba92SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 348feea3fdfSJohnny Huang writel(0x041930d4, OTP_TIMING); // 500us 349dacbba92SJohnny Huang break; 350dacbba92SJohnny Huang } 351dacbba92SJohnny Huang } 352dacbba92SJohnny Huang 353dacbba92SJohnny Huang wait_complete(); 354dacbba92SJohnny Huang } 355dacbba92SJohnny Huang 356a219f6deSJohnny Huang static void otp_read_data(u32 offset, u32 *data) 35769d5fd8fSJohnny Huang { 3583d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 3593d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 3603d3688adSJohnny Huang wait_complete(); 3613d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 3623d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 36369d5fd8fSJohnny Huang } 36469d5fd8fSJohnny Huang 365f347c284SJohnny Huang static void otp_read_conf(u32 offset, u32 *data) 36669d5fd8fSJohnny Huang { 36769d5fd8fSJohnny Huang int config_offset; 36869d5fd8fSJohnny Huang 36969d5fd8fSJohnny Huang config_offset = 0x800; 37069d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 37169d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 37269d5fd8fSJohnny Huang 3733d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 3743d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 3753d3688adSJohnny Huang wait_complete(); 3763d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 37769d5fd8fSJohnny Huang } 37869d5fd8fSJohnny Huang 379a219f6deSJohnny Huang static int otp_compare(u32 otp_addr, u32 addr) 38069d5fd8fSJohnny Huang { 381a219f6deSJohnny Huang u32 ret; 382a219f6deSJohnny Huang u32 *buf; 38369d5fd8fSJohnny Huang 38469d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 38569d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 38669d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 38769d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 38869d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 3893d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 3903d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 3913d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 3923d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 3933d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 3943d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 3953d3688adSJohnny Huang wait_complete(); 3963d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 39769d5fd8fSJohnny Huang if (ret & 0x1) 398f347c284SJohnny Huang return OTP_SUCCESS; 39969d5fd8fSJohnny Huang else 400f347c284SJohnny Huang return OTP_FAILURE; 40169d5fd8fSJohnny Huang } 40269d5fd8fSJohnny Huang 403a219f6deSJohnny Huang static int verify_bit(u32 otp_addr, int bit_offset, int value) 40469d5fd8fSJohnny Huang { 405a219f6deSJohnny Huang u32 ret[2]; 40669d5fd8fSJohnny Huang 40730a8c590SJohnny Huang if (otp_addr % 2 == 0) 4083d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 40930a8c590SJohnny Huang else 4103d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 41130a8c590SJohnny Huang 4123d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4133d3688adSJohnny Huang wait_complete(); 4143d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4153d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 41683655e91SJohnny Huang 41730a8c590SJohnny Huang if (otp_addr % 2 == 0) { 41830a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 419f347c284SJohnny Huang return OTP_SUCCESS; 42069d5fd8fSJohnny Huang else 421f347c284SJohnny Huang return OTP_FAILURE; 42230a8c590SJohnny Huang } else { 42330a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 424f347c284SJohnny Huang return OTP_SUCCESS; 42530a8c590SJohnny Huang else 426f347c284SJohnny Huang return OTP_FAILURE; 42730a8c590SJohnny Huang } 42869d5fd8fSJohnny Huang } 42969d5fd8fSJohnny Huang 430a219f6deSJohnny Huang static u32 verify_dw(u32 otp_addr, u32 *value, u32 *ignore, u32 *compare, int size) 4314c1c9b35SJohnny Huang { 432a219f6deSJohnny Huang u32 ret[2]; 4334c1c9b35SJohnny Huang 4344c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4354c1c9b35SJohnny Huang 4364c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4373d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 4384c1c9b35SJohnny Huang else 4393d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 4403d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4413d3688adSJohnny Huang wait_complete(); 4423d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4433d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 4444c1c9b35SJohnny Huang if (size == 1) { 4454c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4464c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 447696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) { 4484c1c9b35SJohnny Huang compare[0] = 0; 449f347c284SJohnny Huang return OTP_SUCCESS; 450a219f6deSJohnny Huang } 4514c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 452f347c284SJohnny Huang return OTP_FAILURE; 4534c1c9b35SJohnny Huang 4544c1c9b35SJohnny Huang } else { 4554c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 456696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) { 4574c1c9b35SJohnny Huang compare[0] = ~0; 458f347c284SJohnny Huang return OTP_SUCCESS; 459a219f6deSJohnny Huang } 460d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 461f347c284SJohnny Huang return OTP_FAILURE; 4624c1c9b35SJohnny Huang } 4634c1c9b35SJohnny Huang } else if (size == 2) { 4644c1c9b35SJohnny Huang // otp_addr should be even 465696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) { 4664c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4674c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4684c1c9b35SJohnny Huang compare[0] = 0; 4694c1c9b35SJohnny Huang compare[1] = ~0; 470f347c284SJohnny Huang return OTP_SUCCESS; 471a219f6deSJohnny Huang } 4724c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4734c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4744c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4754c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 476f347c284SJohnny Huang return OTP_FAILURE; 4774c1c9b35SJohnny Huang } else { 478f347c284SJohnny Huang return OTP_FAILURE; 4794c1c9b35SJohnny Huang } 4804c1c9b35SJohnny Huang } 4814c1c9b35SJohnny Huang 482a219f6deSJohnny Huang static void otp_prog(u32 otp_addr, u32 prog_bit) 48383655e91SJohnny Huang { 48490965bb3SJohnny Huang otp_write(0x0, prog_bit); 48583655e91SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 48683655e91SJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 48783655e91SJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 48883655e91SJohnny Huang wait_complete(); 48983655e91SJohnny Huang } 49083655e91SJohnny Huang 491a219f6deSJohnny Huang static void _otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset) 49283655e91SJohnny Huang { 49383655e91SJohnny Huang int prog_bit; 49483655e91SJohnny Huang 49583655e91SJohnny Huang if (prog_address % 2 == 0) { 49683655e91SJohnny Huang if (value) 49783655e91SJohnny Huang prog_bit = ~(0x1 << bit_offset); 49883655e91SJohnny Huang else 49983655e91SJohnny Huang return; 50083655e91SJohnny Huang } else { 501e417205bSJohnny Huang if (info_cb.version != OTP_A3) 50283655e91SJohnny Huang prog_address |= 1 << 15; 50383655e91SJohnny Huang if (!value) 50483655e91SJohnny Huang prog_bit = 0x1 << bit_offset; 50583655e91SJohnny Huang else 50683655e91SJohnny Huang return; 50783655e91SJohnny Huang } 50883655e91SJohnny Huang otp_prog(prog_address, prog_bit); 50983655e91SJohnny Huang } 51083655e91SJohnny Huang 511f347c284SJohnny Huang static int otp_prog_dc_b(u32 value, u32 prog_address, u32 bit_offset) 51283655e91SJohnny Huang { 51383655e91SJohnny Huang int pass; 51483655e91SJohnny Huang int i; 51583655e91SJohnny Huang 51683655e91SJohnny Huang otp_soak(1); 51783655e91SJohnny Huang _otp_prog_bit(value, prog_address, bit_offset); 51883655e91SJohnny Huang pass = 0; 51983655e91SJohnny Huang 52083655e91SJohnny Huang for (i = 0; i < RETRY; i++) { 52183655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 52283655e91SJohnny Huang otp_soak(2); 52383655e91SJohnny Huang _otp_prog_bit(value, prog_address, bit_offset); 52483655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 52583655e91SJohnny Huang otp_soak(1); 52683655e91SJohnny Huang } else { 52783655e91SJohnny Huang pass = 1; 52883655e91SJohnny Huang break; 52983655e91SJohnny Huang } 53083655e91SJohnny Huang } else { 53183655e91SJohnny Huang pass = 1; 53283655e91SJohnny Huang break; 53383655e91SJohnny Huang } 53483655e91SJohnny Huang } 535794e27ecSJohnny Huang if (pass) 536794e27ecSJohnny Huang return OTP_SUCCESS; 53783655e91SJohnny Huang 538794e27ecSJohnny Huang return OTP_FAILURE; 53983655e91SJohnny Huang } 54083655e91SJohnny Huang 541a219f6deSJohnny Huang static void otp_prog_dw(u32 value, u32 ignore, u32 prog_address) 542d90825e2SJohnny Huang { 543d90825e2SJohnny Huang int j, bit_value, prog_bit; 544d90825e2SJohnny Huang 545d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 546696656c6SJohnny Huang if ((ignore >> j) & 0x1) 547d90825e2SJohnny Huang continue; 548d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 549d90825e2SJohnny Huang if (prog_address % 2 == 0) { 550d90825e2SJohnny Huang if (bit_value) 551d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 552d90825e2SJohnny Huang else 553d90825e2SJohnny Huang continue; 554d90825e2SJohnny Huang } else { 555e417205bSJohnny Huang if (info_cb.version != OTP_A3) 556d90825e2SJohnny Huang prog_address |= 1 << 15; 557d90825e2SJohnny Huang if (bit_value) 558d90825e2SJohnny Huang continue; 559d90825e2SJohnny Huang else 560d90825e2SJohnny Huang prog_bit = 0x1 << j; 561d90825e2SJohnny Huang } 562d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 563d90825e2SJohnny Huang } 564d90825e2SJohnny Huang } 565d90825e2SJohnny Huang 566a219f6deSJohnny Huang static int otp_prog_verify_2dw(u32 *data, u32 *buf, u32 *ignore_mask, u32 prog_address) 56754552c69SJohnny Huang { 56854552c69SJohnny Huang int pass; 56954552c69SJohnny Huang int i; 570a219f6deSJohnny Huang u32 data0_masked; 571a219f6deSJohnny Huang u32 data1_masked; 572a219f6deSJohnny Huang u32 buf0_masked; 573a219f6deSJohnny Huang u32 buf1_masked; 574a219f6deSJohnny Huang u32 compare[2]; 57554552c69SJohnny Huang 57654552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 57754552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 57854552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 57954552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 580a219f6deSJohnny Huang if (data0_masked == buf0_masked && data1_masked == buf1_masked) 581f347c284SJohnny Huang return OTP_SUCCESS; 58254552c69SJohnny Huang 58354552c69SJohnny Huang otp_soak(1); 58454552c69SJohnny Huang if (data0_masked != buf0_masked) 58554552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 58654552c69SJohnny Huang if (data1_masked != buf1_masked) 58754552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 58854552c69SJohnny Huang 58954552c69SJohnny Huang pass = 0; 59054552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 59154552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 59254552c69SJohnny Huang otp_soak(2); 593a219f6deSJohnny Huang if (compare[0] != 0) 59454552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 595a219f6deSJohnny Huang if (compare[1] != ~0) 5965537bc72SJohnny Huang otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1); 59754552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 59854552c69SJohnny Huang otp_soak(1); 59954552c69SJohnny Huang } else { 60054552c69SJohnny Huang pass = 1; 60154552c69SJohnny Huang break; 60254552c69SJohnny Huang } 60354552c69SJohnny Huang } else { 60454552c69SJohnny Huang pass = 1; 60554552c69SJohnny Huang break; 60654552c69SJohnny Huang } 60754552c69SJohnny Huang } 60854552c69SJohnny Huang 60954552c69SJohnny Huang if (!pass) { 61054552c69SJohnny Huang otp_soak(0); 61154552c69SJohnny Huang return OTP_FAILURE; 61254552c69SJohnny Huang } 61354552c69SJohnny Huang return OTP_SUCCESS; 61454552c69SJohnny Huang } 61554552c69SJohnny Huang 616541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 61776d13988SJohnny Huang { 618a219f6deSJohnny Huang u32 OTPSTRAP_RAW[2]; 6195010032bSJohnny Huang int strap_end; 62076d13988SJohnny Huang int i, j; 62176d13988SJohnny Huang 622e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 62376d13988SJohnny Huang for (j = 0; j < 64; j++) { 62476d13988SJohnny Huang otpstrap[j].value = 0; 62576d13988SJohnny Huang otpstrap[j].remain_times = 7; 62676d13988SJohnny Huang otpstrap[j].writeable_option = -1; 62776d13988SJohnny Huang otpstrap[j].protected = 0; 62876d13988SJohnny Huang } 6295010032bSJohnny Huang strap_end = 30; 6305010032bSJohnny Huang } else { 6315010032bSJohnny Huang for (j = 0; j < 64; j++) { 6325010032bSJohnny Huang otpstrap[j].value = 0; 6335010032bSJohnny Huang otpstrap[j].remain_times = 6; 6345010032bSJohnny Huang otpstrap[j].writeable_option = -1; 6355010032bSJohnny Huang otpstrap[j].protected = 0; 6365010032bSJohnny Huang } 6375010032bSJohnny Huang strap_end = 28; 6385010032bSJohnny Huang } 63976d13988SJohnny Huang 640dacbba92SJohnny Huang otp_soak(0); 6415010032bSJohnny Huang for (i = 16; i < strap_end; i += 2) { 64276d13988SJohnny Huang int option = (i - 16) / 2; 643a219f6deSJohnny Huang 644f347c284SJohnny Huang otp_read_conf(i, &OTPSTRAP_RAW[0]); 645f347c284SJohnny Huang otp_read_conf(i + 1, &OTPSTRAP_RAW[1]); 64676d13988SJohnny Huang for (j = 0; j < 32; j++) { 64776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 648a219f6deSJohnny Huang 649a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 65076d13988SJohnny Huang otpstrap[j].writeable_option = option; 65176d13988SJohnny Huang if (bit_value == 1) 65276d13988SJohnny Huang otpstrap[j].remain_times--; 65376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 65476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 65576d13988SJohnny Huang } 65676d13988SJohnny Huang for (j = 32; j < 64; j++) { 65776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 658a219f6deSJohnny Huang 659a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 66076d13988SJohnny Huang otpstrap[j].writeable_option = option; 66176d13988SJohnny Huang if (bit_value == 1) 66276d13988SJohnny Huang otpstrap[j].remain_times--; 66376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 66476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 66576d13988SJohnny Huang } 66676d13988SJohnny Huang } 6675010032bSJohnny Huang 668f347c284SJohnny Huang otp_read_conf(30, &OTPSTRAP_RAW[0]); 669f347c284SJohnny Huang otp_read_conf(31, &OTPSTRAP_RAW[1]); 67076d13988SJohnny Huang for (j = 0; j < 32; j++) { 67176d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 67276d13988SJohnny Huang otpstrap[j].protected = 1; 67376d13988SJohnny Huang } 67476d13988SJohnny Huang for (j = 32; j < 64; j++) { 67576d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 67676d13988SJohnny Huang otpstrap[j].protected = 1; 67776d13988SJohnny Huang } 67876d13988SJohnny Huang } 67976d13988SJohnny Huang 680*7e523e3bSJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit) 681f347c284SJohnny Huang { 682f347c284SJohnny Huang int prog_flag = 0; 683f347c284SJohnny Huang 684f347c284SJohnny Huang // ignore this bit 685f347c284SJohnny Huang if (ibit == 1) 686f347c284SJohnny Huang return OTP_SUCCESS; 687f347c284SJohnny Huang printf("OTPSTRAP[%X]:\n", offset); 688f347c284SJohnny Huang 689f347c284SJohnny Huang if (bit == otpstrap->value) { 690*7e523e3bSJohnny Huang if (!pbit) { 691f347c284SJohnny Huang printf(" The value is same as before, skip it.\n"); 692f347c284SJohnny Huang return OTP_PROG_SKIP; 693f347c284SJohnny Huang } 694f347c284SJohnny Huang printf(" The value is same as before.\n"); 695f347c284SJohnny Huang } else { 696f347c284SJohnny Huang prog_flag = 1; 697f347c284SJohnny Huang } 698f347c284SJohnny Huang if (otpstrap->protected == 1 && prog_flag) { 699f347c284SJohnny Huang printf(" This bit is protected and is not writable\n"); 700f347c284SJohnny Huang return OTP_FAILURE; 701f347c284SJohnny Huang } 702f347c284SJohnny Huang if (otpstrap->remain_times == 0 && prog_flag) { 703f347c284SJohnny Huang printf(" This bit is no remaining times to write.\n"); 704f347c284SJohnny Huang return OTP_FAILURE; 705f347c284SJohnny Huang } 706f347c284SJohnny Huang if (pbit == 1) 707f347c284SJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 708f347c284SJohnny Huang if (prog_flag) 709f347c284SJohnny Huang printf(" Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", offset, otpstrap->writeable_option + 1, otpstrap->value, otpstrap->value ^ 1); 710f347c284SJohnny Huang 711f347c284SJohnny Huang return OTP_SUCCESS; 712f347c284SJohnny Huang } 713f347c284SJohnny Huang 714f347c284SJohnny Huang static int otp_prog_strap_b(int bit_offset, int value) 715f347c284SJohnny Huang { 716f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 717f347c284SJohnny Huang u32 prog_address; 718f347c284SJohnny Huang int offset; 719f347c284SJohnny Huang int ret; 720f347c284SJohnny Huang 721f347c284SJohnny Huang otp_strap_status(otpstrap); 722f347c284SJohnny Huang 723*7e523e3bSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0); 724f347c284SJohnny Huang 725f347c284SJohnny Huang if (ret != OTP_SUCCESS) 726f347c284SJohnny Huang return ret; 727f347c284SJohnny Huang 728f347c284SJohnny Huang prog_address = 0x800; 729f347c284SJohnny Huang if (bit_offset < 32) { 730f347c284SJohnny Huang offset = bit_offset; 731f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200; 732f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2; 733f347c284SJohnny Huang 734f347c284SJohnny Huang } else { 735f347c284SJohnny Huang offset = (bit_offset - 32); 736f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200; 737f347c284SJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2; 738f347c284SJohnny Huang } 739f347c284SJohnny Huang 740f347c284SJohnny Huang return otp_prog_dc_b(1, prog_address, offset); 741f347c284SJohnny Huang } 742f347c284SJohnny Huang 743f347c284SJohnny Huang static int otp_print_conf(u32 offset, int dw_count) 744f347c284SJohnny Huang { 745f347c284SJohnny Huang int i; 746f347c284SJohnny Huang u32 ret[1]; 747f347c284SJohnny Huang 748f347c284SJohnny Huang if (offset + dw_count > 32) 749f347c284SJohnny Huang return OTP_USAGE; 750f347c284SJohnny Huang otp_soak(0); 751f347c284SJohnny Huang for (i = offset; i < offset + dw_count; i++) { 752f347c284SJohnny Huang otp_read_conf(i, ret); 753f347c284SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 754f347c284SJohnny Huang } 755f347c284SJohnny Huang printf("\n"); 756f347c284SJohnny Huang return OTP_SUCCESS; 757f347c284SJohnny Huang } 758f347c284SJohnny Huang 759f347c284SJohnny Huang static int otp_print_data(u32 offset, int dw_count) 760f347c284SJohnny Huang { 761f347c284SJohnny Huang int i; 762f347c284SJohnny Huang u32 ret[2]; 763f347c284SJohnny Huang 764f347c284SJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 765f347c284SJohnny Huang return OTP_USAGE; 766f347c284SJohnny Huang otp_soak(0); 767f347c284SJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 768f347c284SJohnny Huang otp_read_data(i, ret); 769f347c284SJohnny Huang if (i % 4 == 0) 770f347c284SJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 771f347c284SJohnny Huang else 772f347c284SJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 773f347c284SJohnny Huang } 774f347c284SJohnny Huang printf("\n"); 775f347c284SJohnny Huang return OTP_SUCCESS; 776f347c284SJohnny Huang } 777f347c284SJohnny Huang 778f347c284SJohnny Huang static int otp_print_strap(int start, int count) 779f347c284SJohnny Huang { 780f347c284SJohnny Huang int i, j; 781f347c284SJohnny Huang int remains; 782f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 783f347c284SJohnny Huang 784f347c284SJohnny Huang if (start < 0 || start > 64) 785f347c284SJohnny Huang return OTP_USAGE; 786f347c284SJohnny Huang 787f347c284SJohnny Huang if ((start + count) < 0 || (start + count) > 64) 788f347c284SJohnny Huang return OTP_USAGE; 789f347c284SJohnny Huang 790f347c284SJohnny Huang otp_strap_status(otpstrap); 791f347c284SJohnny Huang 792*7e523e3bSJohnny Huang if (info_cb.version == OTP_A0) 793f347c284SJohnny Huang remains = 7; 794*7e523e3bSJohnny Huang else 795f347c284SJohnny Huang remains = 6; 796*7e523e3bSJohnny Huang printf("BIT(hex) Value Option Status\n"); 797f347c284SJohnny Huang printf("______________________________________________________________________________\n"); 798f347c284SJohnny Huang 799f347c284SJohnny Huang for (i = start; i < start + count; i++) { 800f347c284SJohnny Huang printf("0x%-8X", i); 801f347c284SJohnny Huang printf("%-7d", otpstrap[i].value); 802f347c284SJohnny Huang for (j = 0; j < remains; j++) 803f347c284SJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 804f347c284SJohnny Huang printf(" "); 805f347c284SJohnny Huang if (otpstrap[i].protected == 1) { 806f347c284SJohnny Huang printf("protected and not writable"); 807f347c284SJohnny Huang } else { 808f347c284SJohnny Huang printf("not protected "); 809f347c284SJohnny Huang if (otpstrap[i].remain_times == 0) 810f347c284SJohnny Huang printf("and no remaining times to write."); 811f347c284SJohnny Huang else 812f347c284SJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 813f347c284SJohnny Huang } 814f347c284SJohnny Huang printf("\n"); 815f347c284SJohnny Huang } 816f347c284SJohnny Huang 817f347c284SJohnny Huang return OTP_SUCCESS; 818f347c284SJohnny Huang } 819f347c284SJohnny Huang 820794e27ecSJohnny Huang static void otp_print_revid(u32 *rid) 821794e27ecSJohnny Huang { 822794e27ecSJohnny Huang int bit_offset; 823794e27ecSJohnny Huang int i, j; 824794e27ecSJohnny Huang 825794e27ecSJohnny Huang printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); 826794e27ecSJohnny Huang printf("___________________________________________________\n"); 827794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 828794e27ecSJohnny Huang if (i < 32) { 829794e27ecSJohnny Huang j = 0; 830794e27ecSJohnny Huang bit_offset = i; 831794e27ecSJohnny Huang } else { 832794e27ecSJohnny Huang j = 1; 833794e27ecSJohnny Huang bit_offset = i - 32; 834794e27ecSJohnny Huang } 835794e27ecSJohnny Huang if (i % 16 == 0) 836794e27ecSJohnny Huang printf("%2x | ", i); 837794e27ecSJohnny Huang printf("%d ", (rid[j] >> bit_offset) & 0x1); 838794e27ecSJohnny Huang if ((i + 1) % 16 == 0) 839794e27ecSJohnny Huang printf("\n"); 840794e27ecSJohnny Huang } 841794e27ecSJohnny Huang } 842794e27ecSJohnny Huang 843696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout) 84469d5fd8fSJohnny Huang { 84579e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 846a219f6deSJohnny Huang u32 *OTPCFG = (u32 *)image_layout->conf; 847a219f6deSJohnny Huang u32 *OTPCFG_IGNORE = (u32 *)image_layout->conf_ignore; 848a219f6deSJohnny Huang u32 mask; 849a219f6deSJohnny Huang u32 dw_offset; 850a219f6deSJohnny Huang u32 bit_offset; 851a219f6deSJohnny Huang u32 otp_value; 852a219f6deSJohnny Huang u32 otp_ignore; 853b458cd62SJohnny Huang int fail = 0; 8547adec5f6SJohnny Huang int mask_err; 855794e27ecSJohnny Huang int rid_num = 0; 85673f11549SJohnny Huang char valid_bit[20]; 857794e27ecSJohnny Huang int fz; 85866f2f8e5SJohnny Huang int i; 85973f11549SJohnny Huang int j; 86066f2f8e5SJohnny Huang 861737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 86266f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 8633cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8647adec5f6SJohnny Huang mask_err = 0; 8653cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8663cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8673cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 868b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 869696656c6SJohnny Huang otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask; 870b458cd62SJohnny Huang 8717adec5f6SJohnny Huang if (conf_info[i].value == OTP_REG_VALID_BIT) { 8727adec5f6SJohnny Huang if (((otp_value + otp_ignore) & mask) != mask) { 873b458cd62SJohnny Huang fail = 1; 8747adec5f6SJohnny Huang mask_err = 1; 8757adec5f6SJohnny Huang } 8767adec5f6SJohnny Huang } else { 8777adec5f6SJohnny Huang if (otp_ignore == mask) { 8787adec5f6SJohnny Huang continue; 8797adec5f6SJohnny Huang } else if (otp_ignore != 0) { 8807adec5f6SJohnny Huang fail = 1; 8817adec5f6SJohnny Huang mask_err = 1; 8827adec5f6SJohnny Huang } 8837adec5f6SJohnny Huang } 884b458cd62SJohnny Huang 885a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 8863cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 8873cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 8883cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 889b458cd62SJohnny Huang continue; 890b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 891b458cd62SJohnny Huang 8923cb28812SJohnny Huang if (conf_info[i].length == 1) { 8933cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 89466f2f8e5SJohnny Huang } else { 895b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 8963cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 8973cb28812SJohnny Huang conf_info[i].bit_offset); 89866f2f8e5SJohnny Huang } 899b458cd62SJohnny Huang printf("0x%-10x", otp_value); 900b458cd62SJohnny Huang 9017adec5f6SJohnny Huang if (mask_err) { 9027adec5f6SJohnny Huang printf("Ignore, mask error\n"); 903a219f6deSJohnny Huang continue; 904a219f6deSJohnny Huang } 9053cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 906b458cd62SJohnny Huang printf("Reserved\n"); 9073cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 9083cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 909b458cd62SJohnny Huang printf("\n"); 9103cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 911b458cd62SJohnny Huang if (otp_value != 0) { 91273f11549SJohnny Huang for (j = 0; j < 7; j++) { 913a219f6deSJohnny Huang if (otp_value == (1 << j)) 91473f11549SJohnny Huang valid_bit[j * 2] = '1'; 915a219f6deSJohnny Huang else 91673f11549SJohnny Huang valid_bit[j * 2] = '0'; 91773f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 91873f11549SJohnny Huang } 91973f11549SJohnny Huang valid_bit[15] = 0; 92073f11549SJohnny Huang } else { 92173f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 922b458cd62SJohnny Huang } 9233cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 924b458cd62SJohnny Huang printf("\n"); 925b458cd62SJohnny Huang } else { 9263cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 927b458cd62SJohnny Huang } 928b458cd62SJohnny Huang } 929b458cd62SJohnny Huang 930794e27ecSJohnny Huang if (OTPCFG[0xa] != 0 || OTPCFG[0xb] != 0) { 931794e27ecSJohnny Huang if (OTPCFG_IGNORE[0xa] != 0 && OTPCFG_IGNORE[0xb] != 0) { 932794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 933794e27ecSJohnny Huang fail = 1; 934794e27ecSJohnny Huang } else { 935794e27ecSJohnny Huang fz = 0; 936794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 937794e27ecSJohnny Huang if (get_dw_bit(&OTPCFG[0xa], i) == 0) { 938794e27ecSJohnny Huang if (!fz) 939794e27ecSJohnny Huang fz = 1; 940794e27ecSJohnny Huang } else { 941794e27ecSJohnny Huang rid_num++; 942794e27ecSJohnny Huang if (fz) { 943794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 944794e27ecSJohnny Huang fail = 1; 945794e27ecSJohnny Huang break; 946794e27ecSJohnny Huang } 947794e27ecSJohnny Huang } 948794e27ecSJohnny Huang } 949794e27ecSJohnny Huang } 950794e27ecSJohnny Huang if (fail) 951794e27ecSJohnny Huang printf("OTP revision ID\n"); 952794e27ecSJohnny Huang else 953794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 954794e27ecSJohnny Huang otp_print_revid(&OTPCFG[0xa]); 955794e27ecSJohnny Huang } 956794e27ecSJohnny Huang 957b458cd62SJohnny Huang if (fail) 958b458cd62SJohnny Huang return OTP_FAILURE; 959b458cd62SJohnny Huang 96066f2f8e5SJohnny Huang return OTP_SUCCESS; 96166f2f8e5SJohnny Huang } 96266f2f8e5SJohnny Huang 9632d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 96466f2f8e5SJohnny Huang { 96579e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 966a219f6deSJohnny Huang u32 OTPCFG[16]; 967a219f6deSJohnny Huang u32 mask; 968a219f6deSJohnny Huang u32 dw_offset; 969a219f6deSJohnny Huang u32 bit_offset; 970a219f6deSJohnny Huang u32 otp_value; 97173f11549SJohnny Huang char valid_bit[20]; 97266f2f8e5SJohnny Huang int i; 97373f11549SJohnny Huang int j; 97466f2f8e5SJohnny Huang 975dacbba92SJohnny Huang otp_soak(0); 976bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 977f347c284SJohnny Huang otp_read_conf(i, &OTPCFG[i]); 97866f2f8e5SJohnny Huang 979b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 980b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 9813cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 9823cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 9832d4b0742SJohnny Huang continue; 9843cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 9853cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 9863cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 987b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 988b458cd62SJohnny Huang 989a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 9903cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 9913cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 9923cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 993b458cd62SJohnny Huang continue; 994b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 995b458cd62SJohnny Huang 9963cb28812SJohnny Huang if (conf_info[i].length == 1) { 9973cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 998b458cd62SJohnny Huang } else { 999b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10003cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 10013cb28812SJohnny Huang conf_info[i].bit_offset); 1002b458cd62SJohnny Huang } 1003b458cd62SJohnny Huang printf("0x%-10x", otp_value); 1004b458cd62SJohnny Huang 10053cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 1006b458cd62SJohnny Huang printf("Reserved\n"); 10073cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 10083cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 1009b458cd62SJohnny Huang printf("\n"); 10103cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 1011b458cd62SJohnny Huang if (otp_value != 0) { 101273f11549SJohnny Huang for (j = 0; j < 7; j++) { 1013a219f6deSJohnny Huang if (otp_value == (1 << j)) 101473f11549SJohnny Huang valid_bit[j * 2] = '1'; 1015a219f6deSJohnny Huang else 101673f11549SJohnny Huang valid_bit[j * 2] = '0'; 101773f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 101873f11549SJohnny Huang } 101973f11549SJohnny Huang valid_bit[15] = 0; 102073f11549SJohnny Huang } else { 102173f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 1022b458cd62SJohnny Huang } 10233cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 1024b458cd62SJohnny Huang printf("\n"); 1025b458cd62SJohnny Huang } else { 10263cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 1027b458cd62SJohnny Huang } 1028b458cd62SJohnny Huang } 1029b458cd62SJohnny Huang return OTP_SUCCESS; 103066f2f8e5SJohnny Huang } 103166f2f8e5SJohnny Huang 10325010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout) 103376d13988SJohnny Huang { 103479e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 1035a219f6deSJohnny Huang u32 *OTPSTRAP; 1036a219f6deSJohnny Huang u32 *OTPSTRAP_PRO; 1037a219f6deSJohnny Huang u32 *OTPSTRAP_IGNORE; 103876d13988SJohnny Huang int i; 1039a8bd6d8cSJohnny Huang int fail = 0; 1040a219f6deSJohnny Huang u32 bit_offset; 1041a219f6deSJohnny Huang u32 dw_offset; 1042a219f6deSJohnny Huang u32 mask; 1043a219f6deSJohnny Huang u32 otp_value; 1044a219f6deSJohnny Huang u32 otp_protect; 1045a219f6deSJohnny Huang u32 otp_ignore; 104676d13988SJohnny Huang 1047a219f6deSJohnny Huang OTPSTRAP = (u32 *)image_layout->strap; 1048a219f6deSJohnny Huang OTPSTRAP_PRO = (u32 *)image_layout->strap_pro; 1049a219f6deSJohnny Huang OTPSTRAP_IGNORE = (u32 *)image_layout->strap_ignore; 1050*7e523e3bSJohnny Huang 1051a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1052de6b0cc4SJohnny Huang printf("__________________________________________________________________________________________\n"); 1053b458cd62SJohnny Huang 10543cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 10557adec5f6SJohnny Huang fail = 0; 1056696656c6SJohnny Huang if (strap_info[i].bit_offset > 31) { 1057a8bd6d8cSJohnny Huang dw_offset = 1; 10583cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 1059a8bd6d8cSJohnny Huang } else { 1060a8bd6d8cSJohnny Huang dw_offset = 0; 10613cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 1062a8bd6d8cSJohnny Huang } 106376d13988SJohnny Huang 10643cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 1065a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1066a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1067696656c6SJohnny Huang otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask; 1068a8bd6d8cSJohnny Huang 1069a219f6deSJohnny Huang if (otp_ignore == mask) 1070a8bd6d8cSJohnny Huang continue; 1071a219f6deSJohnny Huang else if (otp_ignore != 0) 1072a8bd6d8cSJohnny Huang fail = 1; 1073a8bd6d8cSJohnny Huang 1074a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 10753cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1076a8bd6d8cSJohnny Huang continue; 1077a8bd6d8cSJohnny Huang 10783cb28812SJohnny Huang if (strap_info[i].length == 1) { 10793cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1080a8bd6d8cSJohnny Huang } else { 1081b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 10823cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 10833cb28812SJohnny Huang strap_info[i].bit_offset); 1084a8bd6d8cSJohnny Huang } 1085a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1086a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1087a8bd6d8cSJohnny Huang 1088a8bd6d8cSJohnny Huang if (fail) { 1089696656c6SJohnny Huang printf("Ignore mask error\n"); 1090a8bd6d8cSJohnny Huang } else { 10913cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10923cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1093a8bd6d8cSJohnny Huang else 1094a8bd6d8cSJohnny Huang printf("Reserved\n"); 1095a8bd6d8cSJohnny Huang } 1096a8bd6d8cSJohnny Huang } 1097a8bd6d8cSJohnny Huang 1098a8bd6d8cSJohnny Huang if (fail) 109976d13988SJohnny Huang return OTP_FAILURE; 110076d13988SJohnny Huang 110176d13988SJohnny Huang return OTP_SUCCESS; 110276d13988SJohnny Huang } 110376d13988SJohnny Huang 1104b458cd62SJohnny Huang static int otp_print_strap_info(int view) 110576d13988SJohnny Huang { 110679e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 110776d13988SJohnny Huang struct otpstrap_status strap_status[64]; 110807baa4e8SJohnny Huang int i, j; 1109b458cd62SJohnny Huang int fail = 0; 1110a219f6deSJohnny Huang u32 bit_offset; 1111a219f6deSJohnny Huang u32 length; 1112a219f6deSJohnny Huang u32 otp_value; 1113a219f6deSJohnny Huang u32 otp_protect; 111476d13988SJohnny Huang 1115541eb887SJohnny Huang otp_strap_status(strap_status); 111676d13988SJohnny Huang 1117b458cd62SJohnny Huang if (view) { 111807baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 111907baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1120b458cd62SJohnny Huang } else { 1121b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1122b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 112376d13988SJohnny Huang } 11243cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1125b458cd62SJohnny Huang otp_value = 0; 11263cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 11273cb28812SJohnny Huang length = strap_info[i].length; 1128b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1129c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1130c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1131b458cd62SJohnny Huang } 1132a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 11333cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1134b458cd62SJohnny Huang continue; 1135b458cd62SJohnny Huang if (view) { 1136b458cd62SJohnny Huang for (j = 0; j < length; j++) { 11373cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1138b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 113907baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 1140e1a7245eSJohnny Huang printf("0x%-7X", strap_status[bit_offset + j].protected); 11413cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1142b458cd62SJohnny Huang printf(" Reserved\n"); 1143b458cd62SJohnny Huang continue; 1144b458cd62SJohnny Huang } 1145b458cd62SJohnny Huang if (length == 1) { 11463cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1147b458cd62SJohnny Huang continue; 114876d13988SJohnny Huang } 114976d13988SJohnny Huang 1150b458cd62SJohnny Huang if (j == 0) 11513cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1152b458cd62SJohnny Huang else if (j == length - 1) 1153b458cd62SJohnny Huang printf("\\ \"\n"); 1154b458cd62SJohnny Huang else 1155b458cd62SJohnny Huang printf("| \"\n"); 115676d13988SJohnny Huang } 1157b458cd62SJohnny Huang } else { 1158c947ef08SJohnny Huang if (length == 1) { 11593cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1160b458cd62SJohnny Huang } else { 1161b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1162b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1163b458cd62SJohnny Huang } 1164b458cd62SJohnny Huang 1165b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1166b458cd62SJohnny Huang 11673cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 11683cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1169b458cd62SJohnny Huang else 1170b458cd62SJohnny Huang printf("Reserved\n"); 1171b458cd62SJohnny Huang } 1172b458cd62SJohnny Huang } 1173b458cd62SJohnny Huang 1174b458cd62SJohnny Huang if (fail) 1175b458cd62SJohnny Huang return OTP_FAILURE; 1176b458cd62SJohnny Huang 1177b458cd62SJohnny Huang return OTP_SUCCESS; 1178b458cd62SJohnny Huang } 1179b458cd62SJohnny Huang 1180f347c284SJohnny Huang static int otp_print_data_image(struct otp_image_layout *image_layout) 118169d5fd8fSJohnny Huang { 118269d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 118379e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 11849a4fe690SJohnny Huang struct otpkey_type key_info; 1185a219f6deSJohnny Huang u32 *buf; 1186a219f6deSJohnny Huang u8 *byte_buf; 11879d998018SJohnny Huang char empty = 1; 118869d5fd8fSJohnny Huang int i = 0, len = 0; 11899a4fe690SJohnny Huang int j; 119054552c69SJohnny Huang 1191696656c6SJohnny Huang byte_buf = image_layout->data; 1192a219f6deSJohnny Huang buf = (u32 *)byte_buf; 11939d998018SJohnny Huang 11949d998018SJohnny Huang for (i = 0; i < 16; i++) { 1195a219f6deSJohnny Huang if (buf[i] != 0) 11969d998018SJohnny Huang empty = 0; 11979d998018SJohnny Huang } 11989d998018SJohnny Huang if (empty) 1199f347c284SJohnny Huang return OTP_SUCCESS; 12009d998018SJohnny Huang 12019d998018SJohnny Huang i = 0; 120269d5fd8fSJohnny Huang while (1) { 120369d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 120469d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 120569d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 120669d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 120769d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 120869d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 12099a4fe690SJohnny Huang 12109a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 12119a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 12129a4fe690SJohnny Huang key_info = key_info_array[j]; 12139a4fe690SJohnny Huang break; 12149a4fe690SJohnny Huang } 12159a4fe690SJohnny Huang } 12169a4fe690SJohnny Huang 12177f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 121869d5fd8fSJohnny Huang printf("Key Type: "); 12199a4fe690SJohnny Huang printf("%s\n", key_info.information); 12209a4fe690SJohnny Huang 12219a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 122269d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 122369d5fd8fSJohnny Huang switch (key_length) { 122469d5fd8fSJohnny Huang case 0: 122569d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 122669d5fd8fSJohnny Huang break; 122769d5fd8fSJohnny Huang case 1: 122869d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 122969d5fd8fSJohnny Huang break; 123069d5fd8fSJohnny Huang case 2: 123169d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 123269d5fd8fSJohnny Huang break; 123369d5fd8fSJohnny Huang case 3: 123469d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 123569d5fd8fSJohnny Huang break; 123669d5fd8fSJohnny Huang } 1237181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV || 1238181f72d8SJohnny Huang key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 123969d5fd8fSJohnny Huang printf("RSA SHA Type: "); 124069d5fd8fSJohnny Huang switch (key_length) { 124169d5fd8fSJohnny Huang case 0: 124269d5fd8fSJohnny Huang printf("RSA1024\n"); 124369d5fd8fSJohnny Huang len = 0x100; 124469d5fd8fSJohnny Huang break; 124569d5fd8fSJohnny Huang case 1: 124669d5fd8fSJohnny Huang printf("RSA2048\n"); 124769d5fd8fSJohnny Huang len = 0x200; 124869d5fd8fSJohnny Huang break; 124969d5fd8fSJohnny Huang case 2: 125069d5fd8fSJohnny Huang printf("RSA3072\n"); 125169d5fd8fSJohnny Huang len = 0x300; 125269d5fd8fSJohnny Huang break; 125369d5fd8fSJohnny Huang case 3: 125469d5fd8fSJohnny Huang printf("RSA4096\n"); 125569d5fd8fSJohnny Huang len = 0x400; 125669d5fd8fSJohnny Huang break; 125769d5fd8fSJohnny Huang } 125869d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 125969d5fd8fSJohnny Huang } 12609a4fe690SJohnny Huang if (key_info.need_id) 126169d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 126269d5fd8fSJohnny Huang printf("Key Value:\n"); 12639a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 126469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 12659a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 12669a4fe690SJohnny Huang printf("AES Key:\n"); 12679a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 1268e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 12699a4fe690SJohnny Huang printf("AES IV:\n"); 12709a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12719a4fe690SJohnny Huang } 12729a4fe690SJohnny Huang 12739a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 1274e417205bSJohnny Huang if (info_cb.version == OTP_A0) { 127569d5fd8fSJohnny Huang printf("AES Key:\n"); 127669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 127769d5fd8fSJohnny Huang printf("AES IV:\n"); 127869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 12795fdde29fSJohnny Huang } else { 12809a4fe690SJohnny Huang printf("AES Key 1:\n"); 12819a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 12829a4fe690SJohnny Huang printf("AES Key 2:\n"); 12839a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 12849a4fe690SJohnny Huang } 1285181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV) { 128669d5fd8fSJohnny Huang printf("RSA mod:\n"); 128769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 128869d5fd8fSJohnny Huang printf("RSA exp:\n"); 128969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 1290181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 1291181f72d8SJohnny Huang printf("RSA mod:\n"); 1292181f72d8SJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 1293181f72d8SJohnny Huang printf("RSA exp:\n"); 1294a219f6deSJohnny Huang buf_print((u8 *)"\x01\x00\x01", 3); 129569d5fd8fSJohnny Huang } 129669d5fd8fSJohnny Huang if (last) 129769d5fd8fSJohnny Huang break; 129869d5fd8fSJohnny Huang i++; 129969d5fd8fSJohnny Huang } 1300f347c284SJohnny Huang return OTP_SUCCESS; 1301f347c284SJohnny Huang } 1302f347c284SJohnny Huang 1303f347c284SJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout) 1304f347c284SJohnny Huang { 1305f347c284SJohnny Huang int i; 1306f347c284SJohnny Huang u32 *strap; 1307f347c284SJohnny Huang u32 *strap_ignore; 1308f347c284SJohnny Huang u32 *strap_pro; 1309*7e523e3bSJohnny Huang int bit, pbit, ibit; 1310f347c284SJohnny Huang int fail = 0; 1311f347c284SJohnny Huang int ret; 1312f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 1313f347c284SJohnny Huang 1314f347c284SJohnny Huang strap = (u32 *)image_layout->strap; 1315f347c284SJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1316f347c284SJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1317f347c284SJohnny Huang 1318f347c284SJohnny Huang otp_strap_status(otpstrap); 1319f347c284SJohnny Huang for (i = 0; i < 64; i++) { 1320f347c284SJohnny Huang if (i < 32) { 1321f347c284SJohnny Huang bit = (strap[0] >> i) & 0x1; 1322f347c284SJohnny Huang ibit = (strap_ignore[0] >> i) & 0x1; 1323f347c284SJohnny Huang pbit = (strap_pro[0] >> i) & 0x1; 1324f347c284SJohnny Huang } else { 1325f347c284SJohnny Huang bit = (strap[1] >> (i - 32)) & 0x1; 1326f347c284SJohnny Huang ibit = (strap_ignore[1] >> (i - 32)) & 0x1; 1327f347c284SJohnny Huang pbit = (strap_pro[1] >> (i - 32)) & 0x1; 1328f347c284SJohnny Huang } 1329f347c284SJohnny Huang 1330*7e523e3bSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit); 1331f347c284SJohnny Huang 1332f347c284SJohnny Huang if (ret == OTP_FAILURE) 1333f347c284SJohnny Huang fail = 1; 1334f347c284SJohnny Huang } 1335f347c284SJohnny Huang if (fail == 1) 1336f347c284SJohnny Huang return OTP_FAILURE; 1337f347c284SJohnny Huang else 1338f347c284SJohnny Huang return OTP_SUCCESS; 1339f347c284SJohnny Huang } 1340f347c284SJohnny Huang 1341f347c284SJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout) 1342f347c284SJohnny Huang { 1343f347c284SJohnny Huang int i; 1344f347c284SJohnny Huang int ret; 1345f347c284SJohnny Huang int data_dw; 1346f347c284SJohnny Huang u32 data[2048]; 1347f347c284SJohnny Huang u32 *buf; 1348f347c284SJohnny Huang u32 *buf_ignore; 1349f347c284SJohnny Huang u32 data_masked; 1350f347c284SJohnny Huang u32 buf_masked; 1351f347c284SJohnny Huang 1352f347c284SJohnny Huang buf = (u32 *)image_layout->data; 1353f347c284SJohnny Huang buf_ignore = (u32 *)image_layout->data_ignore; 1354f347c284SJohnny Huang 1355f347c284SJohnny Huang data_dw = image_layout->data_length / 4; 1356f347c284SJohnny Huang 1357f347c284SJohnny Huang printf("Read OTP Data:\n"); 1358f347c284SJohnny Huang 1359f347c284SJohnny Huang for (i = 0; i < data_dw - 2 ; i += 2) 1360f347c284SJohnny Huang otp_read_data(i, &data[i]); 1361f347c284SJohnny Huang 1362f347c284SJohnny Huang printf("Check writable...\n"); 1363f347c284SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 1364f347c284SJohnny Huang for (i = 0; i < data_dw - 2; i++) { 1365f347c284SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1366f347c284SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 1367f347c284SJohnny Huang if (data_masked == buf_masked) 1368f347c284SJohnny Huang continue; 1369f347c284SJohnny Huang if (i % 2 == 0) { 1370f347c284SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1371f347c284SJohnny Huang continue; 1372f347c284SJohnny Huang } else { 1373f347c284SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1374f347c284SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1375f347c284SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1376f347c284SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 1377f347c284SJohnny Huang return OTP_FAILURE; 1378f347c284SJohnny Huang } 1379f347c284SJohnny Huang } else { 1380f347c284SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1381f347c284SJohnny Huang continue; 1382f347c284SJohnny Huang } else { 1383f347c284SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1384f347c284SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1385f347c284SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1386f347c284SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 1387f347c284SJohnny Huang return OTP_FAILURE; 1388f347c284SJohnny Huang } 1389f347c284SJohnny Huang } 1390f347c284SJohnny Huang } 1391f347c284SJohnny Huang 1392f347c284SJohnny Huang printf("Start Programing...\n"); 1393f347c284SJohnny Huang 1394f347c284SJohnny Huang // programing ecc region first 1395f347c284SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1396f347c284SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 1397f347c284SJohnny Huang if (ret != OTP_SUCCESS) { 1398f347c284SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1399f347c284SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 1400f347c284SJohnny Huang return ret; 1401f347c284SJohnny Huang } 1402f347c284SJohnny Huang } 1403f347c284SJohnny Huang 1404f347c284SJohnny Huang for (i = 0; i < 1792; i += 2) { 1405f347c284SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 1406f347c284SJohnny Huang if (ret != OTP_SUCCESS) { 1407f347c284SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1408f347c284SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 1409f347c284SJohnny Huang return ret; 1410f347c284SJohnny Huang } 1411f347c284SJohnny Huang } 1412f347c284SJohnny Huang otp_soak(0); 1413f347c284SJohnny Huang return OTP_SUCCESS; 1414f347c284SJohnny Huang } 1415f347c284SJohnny Huang 1416f347c284SJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout) 1417f347c284SJohnny Huang { 1418f347c284SJohnny Huang u32 *strap; 1419f347c284SJohnny Huang u32 *strap_ignore; 1420f347c284SJohnny Huang u32 *strap_pro; 1421f347c284SJohnny Huang u32 prog_address; 1422f347c284SJohnny Huang int i; 1423*7e523e3bSJohnny Huang int bit, pbit, ibit, offset; 1424f347c284SJohnny Huang int fail = 0; 1425f347c284SJohnny Huang int ret; 1426f347c284SJohnny Huang int prog_flag = 0; 1427f347c284SJohnny Huang struct otpstrap_status otpstrap[64]; 1428f347c284SJohnny Huang 1429f347c284SJohnny Huang strap = (u32 *)image_layout->strap; 1430f347c284SJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1431f347c284SJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1432f347c284SJohnny Huang 1433f347c284SJohnny Huang printf("Read OTP Strap Region:\n"); 1434f347c284SJohnny Huang otp_strap_status(otpstrap); 1435f347c284SJohnny Huang 1436f347c284SJohnny Huang printf("Check writable...\n"); 1437f347c284SJohnny Huang if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) { 1438f347c284SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1439f347c284SJohnny Huang return OTP_FAILURE; 1440f347c284SJohnny Huang } 1441f347c284SJohnny Huang 1442f347c284SJohnny Huang for (i = 0; i < 64; i++) { 1443f347c284SJohnny Huang prog_address = 0x800; 1444f347c284SJohnny Huang if (i < 32) { 1445f347c284SJohnny Huang offset = i; 1446f347c284SJohnny Huang bit = (strap[0] >> offset) & 0x1; 1447f347c284SJohnny Huang ibit = (strap_ignore[0] >> offset) & 0x1; 1448f347c284SJohnny Huang pbit = (strap_pro[0] >> offset) & 0x1; 1449f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 1450f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 1451f347c284SJohnny Huang 1452f347c284SJohnny Huang } else { 1453f347c284SJohnny Huang offset = (i - 32); 1454f347c284SJohnny Huang bit = (strap[1] >> offset) & 0x1; 1455f347c284SJohnny Huang ibit = (strap_ignore[1] >> offset) & 0x1; 1456f347c284SJohnny Huang pbit = (strap_pro[1] >> offset) & 0x1; 1457f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 1458f347c284SJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 1459f347c284SJohnny Huang } 1460f347c284SJohnny Huang 1461f347c284SJohnny Huang if (ibit == 1) 1462f347c284SJohnny Huang continue; 1463f347c284SJohnny Huang if (bit == otpstrap[i].value) 1464f347c284SJohnny Huang prog_flag = 0; 1465f347c284SJohnny Huang else 1466f347c284SJohnny Huang prog_flag = 1; 1467f347c284SJohnny Huang 1468f347c284SJohnny Huang if (otpstrap[i].protected == 1 && prog_flag) { 1469f347c284SJohnny Huang fail = 1; 1470f347c284SJohnny Huang continue; 1471f347c284SJohnny Huang } 1472f347c284SJohnny Huang if (otpstrap[i].remain_times == 0 && prog_flag) { 1473f347c284SJohnny Huang fail = 1; 1474f347c284SJohnny Huang continue; 1475f347c284SJohnny Huang } 1476f347c284SJohnny Huang 1477f347c284SJohnny Huang if (prog_flag) { 1478f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, offset); 1479f347c284SJohnny Huang if (ret) 1480f347c284SJohnny Huang return OTP_FAILURE; 1481f347c284SJohnny Huang } 1482f347c284SJohnny Huang 1483f347c284SJohnny Huang if (pbit != 0) { 1484f347c284SJohnny Huang prog_address = 0x800; 1485f347c284SJohnny Huang if (i < 32) 1486f347c284SJohnny Huang prog_address |= 0x60c; 1487f347c284SJohnny Huang else 1488f347c284SJohnny Huang prog_address |= 0x60e; 1489f347c284SJohnny Huang 1490f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, offset); 1491f347c284SJohnny Huang if (ret) 1492f347c284SJohnny Huang return OTP_FAILURE; 1493f347c284SJohnny Huang } 1494f347c284SJohnny Huang } 1495f347c284SJohnny Huang otp_soak(0); 1496f347c284SJohnny Huang if (fail == 1) 1497f347c284SJohnny Huang return OTP_FAILURE; 1498f347c284SJohnny Huang return OTP_SUCCESS; 149969d5fd8fSJohnny Huang } 150069d5fd8fSJohnny Huang 15015010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout) 150269d5fd8fSJohnny Huang { 1503a6d0d645SJohnny Huang int i, k; 1504d90825e2SJohnny Huang int pass = 0; 1505a219f6deSJohnny Huang u32 prog_address; 1506a219f6deSJohnny Huang u32 data[16]; 1507a219f6deSJohnny Huang u32 compare[2]; 1508a219f6deSJohnny Huang u32 *conf = (u32 *)image_layout->conf; 1509a219f6deSJohnny Huang u32 *conf_ignore = (u32 *)image_layout->conf_ignore; 1510a219f6deSJohnny Huang u32 data_masked; 1511a219f6deSJohnny Huang u32 buf_masked; 151269d5fd8fSJohnny Huang 1513a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1514a6d0d645SJohnny Huang 1515bb34a7bfSJohnny Huang for (i = 0; i < 16 ; i++) { 151669d5fd8fSJohnny Huang prog_address = 0x800; 1517a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1518a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1519a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1520a6d0d645SJohnny Huang } 1521a6d0d645SJohnny Huang 1522a6d0d645SJohnny Huang printf("Check writable...\n"); 1523bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 15245010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 15255010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1526d90825e2SJohnny Huang if (data_masked == buf_masked) 152769d5fd8fSJohnny Huang continue; 1528d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1529a6d0d645SJohnny Huang continue; 1530a6d0d645SJohnny Huang } else { 1531a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1532a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 15335010032bSJohnny Huang printf("Input [%X] = %x\n", i, conf[i]); 15345010032bSJohnny Huang printf("Mask [%X] = %x\n", i, ~conf_ignore[i]); 15352a856b9aSJohnny Huang return OTP_FAILURE; 1536a6d0d645SJohnny Huang } 1537a6d0d645SJohnny Huang } 1538a6d0d645SJohnny Huang 1539a6d0d645SJohnny Huang printf("Start Programing...\n"); 1540d90825e2SJohnny Huang otp_soak(0); 1541bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 15425010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 15435010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1544a6d0d645SJohnny Huang prog_address = 0x800; 1545a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1546a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1547bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1548bb34a7bfSJohnny Huang pass = 1; 1549a6d0d645SJohnny Huang continue; 1550bb34a7bfSJohnny Huang } 1551de6fbf1cSJohnny Huang 1552de6fbf1cSJohnny Huang otp_soak(1); 15535010032bSJohnny Huang otp_prog_dw(conf[i], conf_ignore[i], prog_address); 1554a6d0d645SJohnny Huang 155569d5fd8fSJohnny Huang pass = 0; 155669d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 15575010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1558de6fbf1cSJohnny Huang otp_soak(2); 1559feea3fdfSJohnny Huang otp_prog_dw(compare[0], conf_ignore[i], prog_address); 15605010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1561de6fbf1cSJohnny Huang otp_soak(1); 1562de6fbf1cSJohnny Huang } else { 1563de6fbf1cSJohnny Huang pass = 1; 1564de6fbf1cSJohnny Huang break; 1565de6fbf1cSJohnny Huang } 1566a6d0d645SJohnny Huang } else { 156769d5fd8fSJohnny Huang pass = 1; 156869d5fd8fSJohnny Huang break; 156969d5fd8fSJohnny Huang } 157069d5fd8fSJohnny Huang } 1571bb34a7bfSJohnny Huang if (pass == 0) { 1572bb34a7bfSJohnny Huang printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n", 15735010032bSJohnny Huang i, data[i], conf[i], conf_ignore[i]); 1574bb34a7bfSJohnny Huang break; 1575bb34a7bfSJohnny Huang } 1576a6d0d645SJohnny Huang } 1577a6d0d645SJohnny Huang 1578de6fbf1cSJohnny Huang otp_soak(0); 157969d5fd8fSJohnny Huang if (!pass) 15802a856b9aSJohnny Huang return OTP_FAILURE; 1581a6d0d645SJohnny Huang 15822a856b9aSJohnny Huang return OTP_SUCCESS; 158369d5fd8fSJohnny Huang } 158469d5fd8fSJohnny Huang 1585f347c284SJohnny Huang static int otp_verify_image(u8 *src_buf, u32 length, u8 *digest_buf) 1586696656c6SJohnny Huang { 1587696656c6SJohnny Huang sha256_context ctx; 1588696656c6SJohnny Huang u8 digest_ret[CHECKSUM_LEN]; 1589696656c6SJohnny Huang 1590696656c6SJohnny Huang sha256_starts(&ctx); 1591696656c6SJohnny Huang sha256_update(&ctx, src_buf, length); 1592696656c6SJohnny Huang sha256_finish(&ctx, digest_ret); 1593696656c6SJohnny Huang 1594696656c6SJohnny Huang if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN)) 1595f347c284SJohnny Huang return OTP_SUCCESS; 1596f347c284SJohnny Huang return OTP_FAILURE; 1597696656c6SJohnny Huang } 1598696656c6SJohnny Huang 1599f347c284SJohnny Huang static int otp_prog_image(int addr, int nconfirm) 160069d5fd8fSJohnny Huang { 160169d5fd8fSJohnny Huang int ret; 160261a6cda7SJohnny Huang int image_soc_ver = 0; 1603696656c6SJohnny Huang struct otp_header *otp_header; 1604696656c6SJohnny Huang struct otp_image_layout image_layout; 1605696656c6SJohnny Huang int image_size; 1606a219f6deSJohnny Huang u8 *buf; 1607a219f6deSJohnny Huang u8 *checksum; 160869d5fd8fSJohnny Huang 1609696656c6SJohnny Huang otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK); 1610696656c6SJohnny Huang if (!otp_header) { 161169d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16122a856b9aSJohnny Huang return OTP_FAILURE; 161369d5fd8fSJohnny Huang } 1614d90825e2SJohnny Huang 1615696656c6SJohnny Huang image_size = OTP_IMAGE_SIZE(otp_header->image_info); 1616696656c6SJohnny Huang unmap_physmem(otp_header, MAP_WRBACK); 1617696656c6SJohnny Huang 1618696656c6SJohnny Huang buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK); 1619696656c6SJohnny Huang 1620696656c6SJohnny Huang if (!buf) { 1621696656c6SJohnny Huang puts("Failed to map physical memory\n"); 1622696656c6SJohnny Huang return OTP_FAILURE; 1623696656c6SJohnny Huang } 1624696656c6SJohnny Huang otp_header = (struct otp_header *)buf; 1625696656c6SJohnny Huang checksum = buf + otp_header->checksum_offset; 1626696656c6SJohnny Huang 1627696656c6SJohnny Huang if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) { 1628696656c6SJohnny Huang puts("Image is invalid\n"); 1629696656c6SJohnny Huang return OTP_FAILURE; 1630696656c6SJohnny Huang } 1631696656c6SJohnny Huang 16325010032bSJohnny Huang image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2); 16335010032bSJohnny Huang image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info); 16345010032bSJohnny Huang image_layout.data_ignore = image_layout.data + image_layout.data_length; 16355010032bSJohnny Huang 16365010032bSJohnny Huang image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2); 1637696656c6SJohnny Huang image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 16385010032bSJohnny Huang image_layout.conf_ignore = image_layout.conf + image_layout.conf_length; 1639696656c6SJohnny Huang 1640696656c6SJohnny Huang image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 16415010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3); 16425010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + image_layout.strap_length; 16435010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length; 1644*7e523e3bSJohnny Huang 1645*7e523e3bSJohnny Huang if (otp_header->soc_ver == SOC_AST2600A0) { 1646*7e523e3bSJohnny Huang image_soc_ver = OTP_A0; 164761a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A1) { 164861a6cda7SJohnny Huang image_soc_ver = OTP_A1; 164961a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A2) { 165061a6cda7SJohnny Huang image_soc_ver = OTP_A2; 165161a6cda7SJohnny Huang } else if (otp_header->soc_ver == SOC_AST2600A3) { 165261a6cda7SJohnny Huang image_soc_ver = OTP_A3; 1653696656c6SJohnny Huang } else { 165461a6cda7SJohnny Huang puts("Image SOC Version is not supported\n"); 1655696656c6SJohnny Huang return OTP_FAILURE; 1656696656c6SJohnny Huang } 1657696656c6SJohnny Huang 165861a6cda7SJohnny Huang if (image_soc_ver != info_cb.version) { 16599a4fe690SJohnny Huang puts("Version is not match\n"); 16609a4fe690SJohnny Huang return OTP_FAILURE; 16619a4fe690SJohnny Huang } 16629a4fe690SJohnny Huang 166361a6cda7SJohnny Huang if (otp_header->otptool_ver != OTPTOOL_VERSION(1, 0, 0)) { 166461a6cda7SJohnny Huang puts("OTP image is not generated by otptool v1.0.0\n"); 166561a6cda7SJohnny Huang return OTP_FAILURE; 166661a6cda7SJohnny Huang } 166761a6cda7SJohnny Huang 1668f347c284SJohnny Huang if (otp_verify_image(buf, image_size, checksum)) { 1669696656c6SJohnny Huang puts("checksum is invalid\n"); 1670696656c6SJohnny Huang return OTP_FAILURE; 1671d90825e2SJohnny Huang } 16727332532cSJohnny Huang 167369d5fd8fSJohnny Huang if (!nconfirm) { 1674696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 16757f795e57SJohnny Huang printf("\nOTP data region :\n"); 1676f347c284SJohnny Huang if (otp_print_data_image(&image_layout) < 0) { 167769d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16782a856b9aSJohnny Huang return OTP_FAILURE; 167969d5fd8fSJohnny Huang } 168069d5fd8fSJohnny Huang } 1681696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 16827332532cSJohnny Huang printf("\nOTP configuration region :\n"); 1683696656c6SJohnny Huang if (otp_print_conf_image(&image_layout) < 0) { 16847332532cSJohnny Huang printf("OTP config error, please check.\n"); 16857332532cSJohnny Huang return OTP_FAILURE; 16867332532cSJohnny Huang } 16877332532cSJohnny Huang } 16887adec5f6SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 16897adec5f6SJohnny Huang printf("\nOTP strap region :\n"); 16907adec5f6SJohnny Huang if (otp_print_strap_image(&image_layout) < 0) { 16917adec5f6SJohnny Huang printf("OTP strap error, please check.\n"); 16927adec5f6SJohnny Huang return OTP_FAILURE; 16937adec5f6SJohnny Huang } 16947adec5f6SJohnny Huang } 16957332532cSJohnny Huang 169669d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 169769d5fd8fSJohnny Huang if (!confirm_yesno()) { 169869d5fd8fSJohnny Huang printf(" Aborting\n"); 16992a856b9aSJohnny Huang return OTP_FAILURE; 170069d5fd8fSJohnny Huang } 170169d5fd8fSJohnny Huang } 17027332532cSJohnny Huang 17035010032bSJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 17045010032bSJohnny Huang printf("programing data region ...\n"); 17055010032bSJohnny Huang ret = otp_prog_data(&image_layout); 17065010032bSJohnny Huang if (ret != 0) { 17075010032bSJohnny Huang printf("Error\n"); 17085010032bSJohnny Huang return ret; 17095010032bSJohnny Huang } 1710a219f6deSJohnny Huang printf("Done\n"); 17115010032bSJohnny Huang } 17125010032bSJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 17135010032bSJohnny Huang printf("programing strap region ...\n"); 17145010032bSJohnny Huang ret = otp_prog_strap(&image_layout); 17155010032bSJohnny Huang if (ret != 0) { 17165010032bSJohnny Huang printf("Error\n"); 17175010032bSJohnny Huang return ret; 17185010032bSJohnny Huang } 1719a219f6deSJohnny Huang printf("Done\n"); 17205010032bSJohnny Huang } 17215010032bSJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 17225010032bSJohnny Huang printf("programing configuration region ...\n"); 17235010032bSJohnny Huang ret = otp_prog_conf(&image_layout); 17245010032bSJohnny Huang if (ret != 0) { 17255010032bSJohnny Huang printf("Error\n"); 17265010032bSJohnny Huang return ret; 17275010032bSJohnny Huang } 17285010032bSJohnny Huang printf("Done\n"); 17295010032bSJohnny Huang } 1730cd1610b4SJohnny Huang 17317332532cSJohnny Huang return OTP_SUCCESS; 17322a856b9aSJohnny Huang } 17332a856b9aSJohnny Huang 1734f347c284SJohnny Huang static int otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1735cd1610b4SJohnny Huang { 1736a219f6deSJohnny Huang u32 read[2]; 1737a219f6deSJohnny Huang u32 prog_address = 0; 173866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1739cd1610b4SJohnny Huang int otp_bit; 174083655e91SJohnny Huang int ret = 0; 1741cd1610b4SJohnny Huang 1742dacbba92SJohnny Huang otp_soak(0); 1743cd1610b4SJohnny Huang switch (mode) { 1744a6d0d645SJohnny Huang case OTP_REGION_CONF: 1745f347c284SJohnny Huang otp_read_conf(otp_dw_offset, read); 1746cd1610b4SJohnny Huang prog_address = 0x800; 1747cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1748cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1749a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1750cd1610b4SJohnny Huang if (otp_bit == value) { 1751a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1752cd1610b4SJohnny Huang printf("No need to program\n"); 17532a856b9aSJohnny Huang return OTP_SUCCESS; 1754cd1610b4SJohnny Huang } 1755cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1756a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1757cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17582a856b9aSJohnny Huang return OTP_FAILURE; 1759cd1610b4SJohnny Huang } 1760a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1761cd1610b4SJohnny Huang break; 1762a6d0d645SJohnny Huang case OTP_REGION_DATA: 1763cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1764cd1610b4SJohnny Huang 1765cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1766a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1767a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1768643b9cfdSJohnny Huang 1769643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1770643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1771643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1772643b9cfdSJohnny Huang return OTP_FAILURE; 1773643b9cfdSJohnny Huang } 1774cd1610b4SJohnny Huang } else { 1775a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1776a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1777643b9cfdSJohnny Huang 1778643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1779643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1780643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1781643b9cfdSJohnny Huang return OTP_FAILURE; 1782643b9cfdSJohnny Huang } 1783cd1610b4SJohnny Huang } 1784cd1610b4SJohnny Huang if (otp_bit == value) { 1785a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1786cd1610b4SJohnny Huang printf("No need to program\n"); 17872a856b9aSJohnny Huang return OTP_SUCCESS; 1788cd1610b4SJohnny Huang } 1789643b9cfdSJohnny Huang 1790a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1791cd1610b4SJohnny Huang break; 1792a6d0d645SJohnny Huang case OTP_REGION_STRAP: 17938848d5dcSJohnny Huang otp_strap_status(otpstrap); 17948848d5dcSJohnny Huang otp_print_strap(bit_offset, 1); 1795*7e523e3bSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0); 17968848d5dcSJohnny Huang if (ret == OTP_FAILURE) 17978848d5dcSJohnny Huang return OTP_FAILURE; 17988848d5dcSJohnny Huang else if (ret == OTP_PROG_SKIP) 17998848d5dcSJohnny Huang return OTP_SUCCESS; 1800a6af4a17SJohnny Huang 1801cd1610b4SJohnny Huang break; 1802cd1610b4SJohnny Huang } 1803cd1610b4SJohnny Huang 1804cd1610b4SJohnny Huang if (!nconfirm) { 1805cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1806cd1610b4SJohnny Huang if (!confirm_yesno()) { 1807cd1610b4SJohnny Huang printf(" Aborting\n"); 18082a856b9aSJohnny Huang return OTP_FAILURE; 1809cd1610b4SJohnny Huang } 1810cd1610b4SJohnny Huang } 1811cd1610b4SJohnny Huang 1812cd1610b4SJohnny Huang switch (mode) { 1813a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1814f347c284SJohnny Huang ret = otp_prog_strap_b(bit_offset, value); 181583655e91SJohnny Huang break; 1816a6d0d645SJohnny Huang case OTP_REGION_CONF: 1817a6d0d645SJohnny Huang case OTP_REGION_DATA: 1818f347c284SJohnny Huang ret = otp_prog_dc_b(value, prog_address, bit_offset); 1819de6fbf1cSJohnny Huang break; 1820de6fbf1cSJohnny Huang } 1821de6fbf1cSJohnny Huang otp_soak(0); 182283655e91SJohnny Huang if (ret) { 1823794e27ecSJohnny Huang printf("OTP cannot be programed\n"); 1824794e27ecSJohnny Huang printf("FAILURE\n"); 1825794e27ecSJohnny Huang return OTP_FAILURE; 1826794e27ecSJohnny Huang } 1827794e27ecSJohnny Huang 18289009c25dSJohnny Huang printf("SUCCESS\n"); 18292a856b9aSJohnny Huang return OTP_SUCCESS; 1830a219f6deSJohnny Huang } 1831a219f6deSJohnny Huang 1832794e27ecSJohnny Huang static int otp_update_rid(u32 update_num, int force) 1833794e27ecSJohnny Huang { 1834794e27ecSJohnny Huang u32 otp_rid[2]; 1835a8789b47SJohnny Huang u32 sw_rid[2]; 1836794e27ecSJohnny Huang int rid_num = 0; 1837a8789b47SJohnny Huang int sw_rid_num = 0; 1838794e27ecSJohnny Huang int bit_offset; 1839794e27ecSJohnny Huang int dw_offset; 1840794e27ecSJohnny Huang int i; 1841794e27ecSJohnny Huang int ret; 1842794e27ecSJohnny Huang 1843f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 1844f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 1845794e27ecSJohnny Huang 1846a8789b47SJohnny Huang sw_rid[0] = readl(SW_REV_ID0); 1847a8789b47SJohnny Huang sw_rid[1] = readl(SW_REV_ID1); 1848a8789b47SJohnny Huang 1849794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 1850a8789b47SJohnny Huang sw_rid_num = get_rid_num(sw_rid); 1851a8789b47SJohnny Huang 1852a8789b47SJohnny Huang if (sw_rid_num < 0) { 1853a8789b47SJohnny Huang printf("SW revision id is invalid, please check.\n"); 1854a8789b47SJohnny Huang return OTP_FAILURE; 1855a8789b47SJohnny Huang } 1856a8789b47SJohnny Huang 1857a8789b47SJohnny Huang if (update_num > sw_rid_num) { 1858a8789b47SJohnny Huang printf("current SW revision ID: 0x%x\n", sw_rid_num); 1859a8789b47SJohnny Huang printf("update number could not bigger than current SW revision id\n"); 1860a8789b47SJohnny Huang return OTP_FAILURE; 1861a8789b47SJohnny Huang } 1862794e27ecSJohnny Huang 1863794e27ecSJohnny Huang if (rid_num < 0) { 1864794e27ecSJohnny Huang printf("Currennt OTP revision ID cannot handle by this command,\n" 1865794e27ecSJohnny Huang "plase use 'otp pb' command to update it manually\n"); 1866794e27ecSJohnny Huang otp_print_revid(otp_rid); 18679009c25dSJohnny Huang return OTP_FAILURE; 18689009c25dSJohnny Huang } 1869cd1610b4SJohnny Huang 1870794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 1871794e27ecSJohnny Huang otp_print_revid(otp_rid); 1872794e27ecSJohnny Huang printf("input update number: 0x%x\n", update_num); 1873794e27ecSJohnny Huang 1874a8789b47SJohnny Huang if (rid_num > update_num) { 1875a8789b47SJohnny Huang printf("OTP rev_id is bigger than 0x%X\n", update_num); 1876a8789b47SJohnny Huang printf("Skip\n"); 1877a8789b47SJohnny Huang return OTP_FAILURE; 1878a8789b47SJohnny Huang } else if (rid_num == update_num) { 1879a8789b47SJohnny Huang printf("OTP rev_id is same as input\n"); 1880794e27ecSJohnny Huang printf("Skip\n"); 1881794e27ecSJohnny Huang return OTP_FAILURE; 1882794e27ecSJohnny Huang } 1883794e27ecSJohnny Huang 1884794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 1885794e27ecSJohnny Huang if (i < 32) { 1886794e27ecSJohnny Huang dw_offset = 0xa; 1887794e27ecSJohnny Huang bit_offset = i; 1888794e27ecSJohnny Huang } else { 1889794e27ecSJohnny Huang dw_offset = 0xb; 1890794e27ecSJohnny Huang bit_offset = i - 32; 1891794e27ecSJohnny Huang } 1892794e27ecSJohnny Huang printf("OTPCFG%X[%d]", dw_offset, bit_offset); 1893794e27ecSJohnny Huang if (i + 1 != update_num) 1894794e27ecSJohnny Huang printf(", "); 1895794e27ecSJohnny Huang } 1896794e27ecSJohnny Huang 1897794e27ecSJohnny Huang printf(" will be programmed\n"); 1898794e27ecSJohnny Huang if (force == 0) { 1899794e27ecSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1900794e27ecSJohnny Huang if (!confirm_yesno()) { 1901794e27ecSJohnny Huang printf(" Aborting\n"); 1902794e27ecSJohnny Huang return OTP_FAILURE; 1903794e27ecSJohnny Huang } 1904794e27ecSJohnny Huang } 1905794e27ecSJohnny Huang 1906794e27ecSJohnny Huang ret = 0; 1907794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 1908794e27ecSJohnny Huang if (i < 32) { 1909794e27ecSJohnny Huang dw_offset = 0xa04; 1910794e27ecSJohnny Huang bit_offset = i; 1911794e27ecSJohnny Huang } else { 1912794e27ecSJohnny Huang dw_offset = 0xa06; 1913794e27ecSJohnny Huang bit_offset = i - 32; 1914794e27ecSJohnny Huang } 1915f347c284SJohnny Huang if (otp_prog_dc_b(1, dw_offset, bit_offset)) { 1916794e27ecSJohnny Huang printf("OTPCFG%X[%d] programming failed\n", dw_offset, bit_offset); 1917794e27ecSJohnny Huang ret = OTP_FAILURE; 1918794e27ecSJohnny Huang break; 1919794e27ecSJohnny Huang } 1920794e27ecSJohnny Huang } 1921794e27ecSJohnny Huang 1922f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 1923f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 1924794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 1925794e27ecSJohnny Huang if (rid_num >= 0) 1926794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 1927794e27ecSJohnny Huang else 1928794e27ecSJohnny Huang printf("OTP revision ID\n"); 1929794e27ecSJohnny Huang otp_print_revid(otp_rid); 1930794e27ecSJohnny Huang if (!ret) 1931794e27ecSJohnny Huang printf("SUCCESS\n"); 1932794e27ecSJohnny Huang else 1933794e27ecSJohnny Huang printf("FAILED\n"); 1934794e27ecSJohnny Huang return ret; 1935794e27ecSJohnny Huang } 1936794e27ecSJohnny Huang 19372a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 193869d5fd8fSJohnny Huang { 1939a219f6deSJohnny Huang u32 offset, count; 19402a856b9aSJohnny Huang int ret; 194169d5fd8fSJohnny Huang 19422a856b9aSJohnny Huang if (argc == 4) { 19432a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19442a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19452a856b9aSJohnny Huang } else if (argc == 3) { 19462a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19472a856b9aSJohnny Huang count = 1; 19482a856b9aSJohnny Huang } else { 194969d5fd8fSJohnny Huang return CMD_RET_USAGE; 195069d5fd8fSJohnny Huang } 195169d5fd8fSJohnny Huang 19522a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19533d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 1954f347c284SJohnny Huang ret = otp_print_conf(offset, count); 19552a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19563d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19572a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19582a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19593d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19602a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19612a856b9aSJohnny Huang } else { 19622a856b9aSJohnny Huang return CMD_RET_USAGE; 196369d5fd8fSJohnny Huang } 196469d5fd8fSJohnny Huang 19652a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19662a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19672a856b9aSJohnny Huang return CMD_RET_USAGE; 19682a856b9aSJohnny Huang } 19692a856b9aSJohnny Huang 19702a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19712a856b9aSJohnny Huang { 19722a856b9aSJohnny Huang phys_addr_t addr; 19732a856b9aSJohnny Huang int ret; 19742a856b9aSJohnny Huang 1975de6b0cc4SJohnny Huang if (argc == 3) { 1976ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19772a856b9aSJohnny Huang return CMD_RET_USAGE; 19782a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19793d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 1980f347c284SJohnny Huang ret = otp_prog_image(addr, 1); 1981de6b0cc4SJohnny Huang } else if (argc == 2) { 19822a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19833d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 1984f347c284SJohnny Huang ret = otp_prog_image(addr, 0); 19852a856b9aSJohnny Huang } else { 19862a856b9aSJohnny Huang return CMD_RET_USAGE; 19872a856b9aSJohnny Huang } 19882a856b9aSJohnny Huang 19892a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19902a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19912a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19922a856b9aSJohnny Huang return CMD_RET_FAILURE; 19932a856b9aSJohnny Huang else 19942a856b9aSJohnny Huang return CMD_RET_USAGE; 19952a856b9aSJohnny Huang } 19962a856b9aSJohnny Huang 19972a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19982a856b9aSJohnny Huang { 19992a856b9aSJohnny Huang int mode = 0; 20002a856b9aSJohnny Huang int nconfirm = 0; 20012a856b9aSJohnny Huang int otp_addr = 0; 20022a856b9aSJohnny Huang int bit_offset; 20032a856b9aSJohnny Huang int value; 20042a856b9aSJohnny Huang int ret; 20052a856b9aSJohnny Huang 20062a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 20072a856b9aSJohnny Huang return CMD_RET_USAGE; 20082a856b9aSJohnny Huang 20092a856b9aSJohnny Huang /* Drop the pb cmd */ 20102a856b9aSJohnny Huang argc--; 20112a856b9aSJohnny Huang argv++; 20122a856b9aSJohnny Huang 20132a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2014a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 20152a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2016a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 20172a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2018a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2019cd1610b4SJohnny Huang else 20202a856b9aSJohnny Huang return CMD_RET_USAGE; 20212a856b9aSJohnny Huang 20222a856b9aSJohnny Huang /* Drop the region cmd */ 20232a856b9aSJohnny Huang argc--; 20242a856b9aSJohnny Huang argv++; 20252a856b9aSJohnny Huang 2026ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2027cd1610b4SJohnny Huang nconfirm = 1; 20282a856b9aSJohnny Huang /* Drop the force option */ 20292a856b9aSJohnny Huang argc--; 20302a856b9aSJohnny Huang argv++; 20312a856b9aSJohnny Huang } 2032cd1610b4SJohnny Huang 2033a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20342a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20352a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20360808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20372a856b9aSJohnny Huang return CMD_RET_USAGE; 2038cd1610b4SJohnny Huang } else { 20392a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20402a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20412a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20420808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20432a856b9aSJohnny Huang return CMD_RET_USAGE; 20440808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 204578855207SJohnny Huang if (otp_addr >= 0x800) 20460808cc55SJohnny Huang return CMD_RET_USAGE; 20470808cc55SJohnny Huang } else { 204878855207SJohnny Huang if (otp_addr >= 0x20) 20490808cc55SJohnny Huang return CMD_RET_USAGE; 20500808cc55SJohnny Huang } 2051cd1610b4SJohnny Huang } 2052cd1610b4SJohnny Huang if (value != 0 && value != 1) 20532a856b9aSJohnny Huang return CMD_RET_USAGE; 2054cd1610b4SJohnny Huang 20553d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2056f347c284SJohnny Huang ret = otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20572a856b9aSJohnny Huang 20582a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20592a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20602a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20612a856b9aSJohnny Huang return CMD_RET_FAILURE; 20622a856b9aSJohnny Huang else 20632a856b9aSJohnny Huang return CMD_RET_USAGE; 20642a856b9aSJohnny Huang } 20652a856b9aSJohnny Huang 20662a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20672a856b9aSJohnny Huang { 20682a856b9aSJohnny Huang phys_addr_t addr; 20692a856b9aSJohnny Huang int otp_addr = 0; 20702a856b9aSJohnny Huang 20712a856b9aSJohnny Huang if (argc != 3) 20722a856b9aSJohnny Huang return CMD_RET_USAGE; 20732a856b9aSJohnny Huang 20743d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20752a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20762a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20772a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 207869d5fd8fSJohnny Huang printf("Compare pass\n"); 20792a856b9aSJohnny Huang return CMD_RET_SUCCESS; 2080a219f6deSJohnny Huang } 208169d5fd8fSJohnny Huang printf("Compare fail\n"); 20822a856b9aSJohnny Huang return CMD_RET_FAILURE; 208369d5fd8fSJohnny Huang } 208469d5fd8fSJohnny Huang 208566f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 208666f2f8e5SJohnny Huang { 2087a8bd6d8cSJohnny Huang int view = 0; 20882d4b0742SJohnny Huang int input; 2089a8bd6d8cSJohnny Huang 2090a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 209166f2f8e5SJohnny Huang return CMD_RET_USAGE; 209266f2f8e5SJohnny Huang 20932d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 20943d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20952d4b0742SJohnny Huang if (argc == 3) { 20962d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 20972d4b0742SJohnny Huang otp_print_conf_info(input); 20982d4b0742SJohnny Huang } else { 20992d4b0742SJohnny Huang otp_print_conf_info(-1); 21002d4b0742SJohnny Huang } 21012d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 21022d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2103a8bd6d8cSJohnny Huang view = 1; 2104a8bd6d8cSJohnny Huang /* Drop the view option */ 2105a8bd6d8cSJohnny Huang argc--; 2106a8bd6d8cSJohnny Huang argv++; 2107a8bd6d8cSJohnny Huang } 21083d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2109b458cd62SJohnny Huang otp_print_strap_info(view); 211066f2f8e5SJohnny Huang } else { 211166f2f8e5SJohnny Huang return CMD_RET_USAGE; 211266f2f8e5SJohnny Huang } 21132d4b0742SJohnny Huang 211466f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 211566f2f8e5SJohnny Huang } 211666f2f8e5SJohnny Huang 2117e14b073cSJohnny Huang static int _do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[], int preg) 2118737ed20bSJohnny Huang { 2119737ed20bSJohnny Huang int input; 2120737ed20bSJohnny Huang int bit_offset; 2121e14b073cSJohnny Huang u32 prog_address; 212283655e91SJohnny Huang int ret; 2123e14b073cSJohnny Huang char info[10]; 2124e14b073cSJohnny Huang 2125e14b073cSJohnny Huang if (preg) { 2126e14b073cSJohnny Huang sprintf(info, "register "); 2127e14b073cSJohnny Huang prog_address = 0xe08; 2128e14b073cSJohnny Huang } else { 2129e14b073cSJohnny Huang info[0] = 0; 2130e14b073cSJohnny Huang prog_address = 0xe0c; 2131e14b073cSJohnny Huang } 2132a219f6deSJohnny Huang 2133737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2134737ed20bSJohnny Huang return CMD_RET_USAGE; 2135737ed20bSJohnny Huang 2136e14b073cSJohnny Huang if (!strcmp(argv[1], "o")) { 2137737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2138737ed20bSJohnny Huang } else { 2139737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2140e14b073cSJohnny Huang printf("OTPSTRAP[%d] %swill be protected\n", input, info); 2141737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2142737ed20bSJohnny Huang if (!confirm_yesno()) { 2143737ed20bSJohnny Huang printf(" Aborting\n"); 2144737ed20bSJohnny Huang return CMD_RET_FAILURE; 2145737ed20bSJohnny Huang } 2146737ed20bSJohnny Huang } 2147737ed20bSJohnny Huang 2148737ed20bSJohnny Huang if (input < 32) { 2149737ed20bSJohnny Huang bit_offset = input; 2150737ed20bSJohnny Huang } else if (input < 64) { 2151737ed20bSJohnny Huang bit_offset = input - 32; 2152e14b073cSJohnny Huang prog_address += 2; 2153737ed20bSJohnny Huang } else { 2154737ed20bSJohnny Huang return CMD_RET_USAGE; 2155737ed20bSJohnny Huang } 2156737ed20bSJohnny Huang 2157e14b073cSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2158e14b073cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2159e14b073cSJohnny Huang printf("OTPSTRAP[%d] %salready protected\n", input, info); 2160e14b073cSJohnny Huang return CMD_RET_SUCCESS; 2161e14b073cSJohnny Huang } 2162de6fbf1cSJohnny Huang 2163f347c284SJohnny Huang ret = otp_prog_dc_b(1, prog_address, bit_offset); 2164de6fbf1cSJohnny Huang otp_soak(0); 216583655e91SJohnny Huang 216683655e91SJohnny Huang if (ret) { 2167e14b073cSJohnny Huang printf("Protect OTPSTRAP[%d] %sfail\n", input, info); 2168737ed20bSJohnny Huang return CMD_RET_FAILURE; 2169737ed20bSJohnny Huang } 21709a4fe690SJohnny Huang 2171794e27ecSJohnny Huang printf("OTPSTRAP[%d] %sis protected\n", input, info); 2172794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2173794e27ecSJohnny Huang } 2174794e27ecSJohnny Huang 2175e14b073cSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2176e14b073cSJohnny Huang { 2177e14b073cSJohnny Huang return _do_otpprotect(cmdtp, flag, argc, argv, 0); 2178e14b073cSJohnny Huang } 2179e14b073cSJohnny Huang 2180e14b073cSJohnny Huang static int do_otprprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2181e14b073cSJohnny Huang { 2182e14b073cSJohnny Huang return _do_otpprotect(cmdtp, flag, argc, argv, 1); 2183e14b073cSJohnny Huang } 2184e14b073cSJohnny Huang 2185f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2186f67375f7SJohnny Huang { 2187e417205bSJohnny Huang printf("SOC OTP version: %s\n", info_cb.ver_name); 2188f67375f7SJohnny Huang printf("OTP tool version: %s\n", OTP_VER); 2189f67375f7SJohnny Huang printf("OTP info version: %s\n", OTP_INFO_VER); 2190f67375f7SJohnny Huang 2191f67375f7SJohnny Huang return CMD_RET_SUCCESS; 2192f67375f7SJohnny Huang } 2193f67375f7SJohnny Huang 2194794e27ecSJohnny Huang static int do_otpupdate(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2195794e27ecSJohnny Huang { 2196794e27ecSJohnny Huang u32 update_num; 2197794e27ecSJohnny Huang int force = 0; 2198794e27ecSJohnny Huang int ret; 2199794e27ecSJohnny Huang 2200794e27ecSJohnny Huang if (argc == 3) { 2201794e27ecSJohnny Huang if (strcmp(argv[1], "o")) 2202794e27ecSJohnny Huang return CMD_RET_USAGE; 2203794e27ecSJohnny Huang force = 1; 2204794e27ecSJohnny Huang update_num = simple_strtoul(argv[2], NULL, 16); 2205794e27ecSJohnny Huang } else if (argc == 2) { 2206794e27ecSJohnny Huang update_num = simple_strtoul(argv[1], NULL, 16); 2207794e27ecSJohnny Huang } else { 2208794e27ecSJohnny Huang return CMD_RET_USAGE; 2209794e27ecSJohnny Huang } 2210794e27ecSJohnny Huang 2211794e27ecSJohnny Huang if (update_num > 64) 2212794e27ecSJohnny Huang return CMD_RET_USAGE; 2213794e27ecSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2214794e27ecSJohnny Huang ret = otp_update_rid(update_num, force); 2215794e27ecSJohnny Huang if (ret) 2216794e27ecSJohnny Huang return CMD_RET_FAILURE; 2217794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2218794e27ecSJohnny Huang } 2219794e27ecSJohnny Huang 2220794e27ecSJohnny Huang static int do_otprid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2221794e27ecSJohnny Huang { 2222794e27ecSJohnny Huang u32 otp_rid[2]; 2223a8789b47SJohnny Huang u32 sw_rid[2]; 2224794e27ecSJohnny Huang int rid_num = 0; 2225a8789b47SJohnny Huang int sw_rid_num = 0; 2226794e27ecSJohnny Huang int ret; 2227794e27ecSJohnny Huang 2228794e27ecSJohnny Huang if (argc != 1) 2229794e27ecSJohnny Huang return CMD_RET_USAGE; 2230794e27ecSJohnny Huang 2231794e27ecSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2232f347c284SJohnny Huang otp_read_conf(10, &otp_rid[0]); 2233f347c284SJohnny Huang otp_read_conf(11, &otp_rid[1]); 2234794e27ecSJohnny Huang 2235a8789b47SJohnny Huang sw_rid[0] = readl(SW_REV_ID0); 2236a8789b47SJohnny Huang sw_rid[1] = readl(SW_REV_ID1); 2237794e27ecSJohnny Huang 2238a8789b47SJohnny Huang rid_num = get_rid_num(otp_rid); 2239a8789b47SJohnny Huang sw_rid_num = get_rid_num(sw_rid); 2240a8789b47SJohnny Huang 2241a8789b47SJohnny Huang printf("current SW revision ID: 0x%x\n", sw_rid_num); 2242794e27ecSJohnny Huang if (rid_num >= 0) { 2243794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 2244794e27ecSJohnny Huang ret = CMD_RET_SUCCESS; 2245794e27ecSJohnny Huang } else { 2246794e27ecSJohnny Huang printf("Currennt OTP revision ID cannot handle by 'otp update',\n" 2247794e27ecSJohnny Huang "plase use 'otp pb' command to update it manually\n" 2248794e27ecSJohnny Huang "current OTP revision ID\n"); 2249794e27ecSJohnny Huang ret = CMD_RET_FAILURE; 2250794e27ecSJohnny Huang } 2251794e27ecSJohnny Huang otp_print_revid(otp_rid); 2252794e27ecSJohnny Huang 2253794e27ecSJohnny Huang return ret; 2254794e27ecSJohnny Huang } 2255794e27ecSJohnny Huang 22562a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 2257f67375f7SJohnny Huang U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""), 22582a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2259a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 2260de6b0cc4SJohnny Huang U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""), 22612a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2262737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 2263e14b073cSJohnny Huang U_BOOT_CMD_MKENT(rprotect, 3, 0, do_otprprotect, "", ""), 22642a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 2265794e27ecSJohnny Huang U_BOOT_CMD_MKENT(update, 3, 0, do_otpupdate, "", ""), 2266794e27ecSJohnny Huang U_BOOT_CMD_MKENT(rid, 1, 0, do_otprid, "", ""), 22672a856b9aSJohnny Huang }; 22682a856b9aSJohnny Huang 22692a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 22702a856b9aSJohnny Huang { 22712a856b9aSJohnny Huang cmd_tbl_t *cp; 2272a219f6deSJohnny Huang u32 ver; 2273e14b073cSJohnny Huang int ret; 22742a856b9aSJohnny Huang 22752a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 22762a856b9aSJohnny Huang 2277737ed20bSJohnny Huang /* Drop the otp command */ 22782a856b9aSJohnny Huang argc--; 22792a856b9aSJohnny Huang argv++; 22802a856b9aSJohnny Huang 2281a219f6deSJohnny Huang if (!cp || argc > cp->maxargs) 22822a856b9aSJohnny Huang return CMD_RET_USAGE; 22832a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 22842a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22852a856b9aSJohnny Huang 22860dae9d52SJohnny Huang ver = chip_version(); 22870dae9d52SJohnny Huang switch (ver) { 2288e417205bSJohnny Huang case OTP_A0: 2289e417205bSJohnny Huang info_cb.version = OTP_A0; 22909a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 22919a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 22929a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 22939a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 22949a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 22959a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 2296e417205bSJohnny Huang sprintf(info_cb.ver_name, "A0"); 22970dae9d52SJohnny Huang break; 2298e417205bSJohnny Huang case OTP_A1: 2299e417205bSJohnny Huang info_cb.version = OTP_A1; 23003cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 23013cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 23023cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 23033cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 23049a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 23059a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 2306e417205bSJohnny Huang sprintf(info_cb.ver_name, "A1"); 23070dae9d52SJohnny Huang break; 2308e417205bSJohnny Huang case OTP_A2: 2309e417205bSJohnny Huang info_cb.version = OTP_A2; 23105fdde29fSJohnny Huang info_cb.conf_info = a2_conf_info; 23115fdde29fSJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info); 2312fed30023SJohnny Huang info_cb.strap_info = a1_strap_info; 2313fed30023SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 23145fdde29fSJohnny Huang info_cb.key_info = a2_key_type; 23155fdde29fSJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a2_key_type); 2316e417205bSJohnny Huang sprintf(info_cb.ver_name, "A2"); 23170dae9d52SJohnny Huang break; 2318e417205bSJohnny Huang case OTP_A3: 2319e417205bSJohnny Huang info_cb.version = OTP_A3; 2320b63af886SJohnny Huang info_cb.conf_info = a3_conf_info; 2321b63af886SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a3_conf_info); 2322fed30023SJohnny Huang info_cb.strap_info = a1_strap_info; 2323fed30023SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 2324181f72d8SJohnny Huang info_cb.key_info = a3_key_type; 2325181f72d8SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a3_key_type); 2326e417205bSJohnny Huang sprintf(info_cb.ver_name, "A3"); 232764b66712SJohnny Huang break; 23280dae9d52SJohnny Huang default: 2329f1be5099SJohnny Huang printf("SOC is not supported\n"); 23300dae9d52SJohnny Huang return CMD_RET_FAILURE; 23319a4fe690SJohnny Huang } 23329a4fe690SJohnny Huang 2333e14b073cSJohnny Huang ret = cp->cmd(cmdtp, flag, argc, argv); 2334e14b073cSJohnny Huang writel(1, OTP_PROTECT_KEY); //password 2335e14b073cSJohnny Huang 2336e14b073cSJohnny Huang return ret; 233769d5fd8fSJohnny Huang } 233869d5fd8fSJohnny Huang 2339a219f6deSJohnny Huang U_BOOT_CMD(otp, 7, 0, do_ast_otp, 234069d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 2341f67375f7SJohnny Huang "version\n" 2342f67375f7SJohnny Huang "otp read conf|data <otp_dw_offset> <dw_count>\n" 23432a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 23442d4b0742SJohnny Huang "otp info strap [v]\n" 23452d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2346de6b0cc4SJohnny Huang "otp prog [o] <addr>\n" 2347ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2348ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2349ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 2350e14b073cSJohnny Huang "otp rprotect [o] <bit_offset>\n" 2351794e27ecSJohnny Huang "otp update [o] <revision_id>\n" 2352794e27ecSJohnny Huang "otp rid\n" 235369d5fd8fSJohnny Huang ); 2354