1a219f6deSJohnny Huang // SPDX-License-Identifier: GPL-2.0+ 269d5fd8fSJohnny Huang /* 3a219f6deSJohnny Huang * Copyright 2021 Aspeed Technology Inc. 469d5fd8fSJohnny Huang */ 54c1c9b35SJohnny Huang #include <stdlib.h> 669d5fd8fSJohnny Huang #include <common.h> 769d5fd8fSJohnny Huang #include <console.h> 869d5fd8fSJohnny Huang #include <bootretry.h> 969d5fd8fSJohnny Huang #include <cli.h> 1069d5fd8fSJohnny Huang #include <command.h> 1169d5fd8fSJohnny Huang #include <console.h> 124c1c9b35SJohnny Huang #include <malloc.h> 1369d5fd8fSJohnny Huang #include <inttypes.h> 1469d5fd8fSJohnny Huang #include <mapmem.h> 1569d5fd8fSJohnny Huang #include <asm/io.h> 1669d5fd8fSJohnny Huang #include <linux/compiler.h> 17696656c6SJohnny Huang #include <u-boot/sha256.h> 180cee9a95SJohnny Huang #include "otp_info.h" 1969d5fd8fSJohnny Huang 2069d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2169d5fd8fSJohnny Huang 2264b66712SJohnny Huang #define OTP_VER "1.0.3" 23f67375f7SJohnny Huang 2469d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 25dacbba92SJohnny Huang #define RETRY 20 267332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 277332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 287332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 2969d5fd8fSJohnny Huang 302a856b9aSJohnny Huang #define OTP_USAGE -1 312a856b9aSJohnny Huang #define OTP_FAILURE -2 322a856b9aSJohnny Huang #define OTP_SUCCESS 0 332a856b9aSJohnny Huang 34a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 35a6af4a17SJohnny Huang 36181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PUB 1 37181f72d8SJohnny Huang #define OTP_KEY_TYPE_RSA_PRIV 2 38181f72d8SJohnny Huang #define OTP_KEY_TYPE_AES 3 39181f72d8SJohnny Huang #define OTP_KEY_TYPE_VAULT 4 40181f72d8SJohnny Huang #define OTP_KEY_TYPE_HMAC 5 419a4fe690SJohnny Huang 424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 434c1c9b35SJohnny Huang #define PBWIDTH 60 444c1c9b35SJohnny Huang 453d3688adSJohnny Huang #define OTP_BASE 0x1e6f2000 463d3688adSJohnny Huang #define OTP_PROTECT_KEY OTP_BASE 473d3688adSJohnny Huang #define OTP_COMMAND OTP_BASE + 0x4 483d3688adSJohnny Huang #define OTP_TIMING OTP_BASE + 0x8 493d3688adSJohnny Huang #define OTP_ADDR OTP_BASE + 0x10 503d3688adSJohnny Huang #define OTP_STATUS OTP_BASE + 0x14 513d3688adSJohnny Huang #define OTP_COMPARE_1 OTP_BASE + 0x20 523d3688adSJohnny Huang #define OTP_COMPARE_2 OTP_BASE + 0x24 533d3688adSJohnny Huang #define OTP_COMPARE_3 OTP_BASE + 0x28 543d3688adSJohnny Huang #define OTP_COMPARE_4 OTP_BASE + 0x2c 553d3688adSJohnny Huang 56696656c6SJohnny Huang #define OTP_MAGIC "SOCOTP" 57696656c6SJohnny Huang #define CHECKSUM_LEN 32 58a219f6deSJohnny Huang #define OTP_INC_DATA BIT(31) 59a219f6deSJohnny Huang #define OTP_INC_CONFIG BIT(30) 60a219f6deSJohnny Huang #define OTP_INC_STRAP BIT(29) 61a219f6deSJohnny Huang #define OTP_ECC_EN BIT(28) 62696656c6SJohnny Huang #define OTP_REGION_SIZE(info) ((info >> 16) & 0xffff) 63696656c6SJohnny Huang #define OTP_REGION_OFFSET(info) (info & 0xffff) 64696656c6SJohnny Huang #define OTP_IMAGE_SIZE(info) (info & 0xffff) 65696656c6SJohnny Huang 66696656c6SJohnny Huang #define OTP_AST2600A0 0 67696656c6SJohnny Huang #define OTP_AST2600A1 1 680dae9d52SJohnny Huang #define OTP_AST2600A2 2 6964b66712SJohnny Huang #define OTP_AST2600A3 3 70696656c6SJohnny Huang 71696656c6SJohnny Huang struct otp_header { 72696656c6SJohnny Huang u8 otp_magic[8]; 73696656c6SJohnny Huang u8 otp_version[8]; 74696656c6SJohnny Huang u32 image_info; 75696656c6SJohnny Huang u32 data_info; 76696656c6SJohnny Huang u32 config_info; 77696656c6SJohnny Huang u32 strap_info; 78696656c6SJohnny Huang u32 checksum_offset; 79a219f6deSJohnny Huang } __packed; 80696656c6SJohnny Huang 8166f2f8e5SJohnny Huang struct otpstrap_status { 8269d5fd8fSJohnny Huang int value; 8369d5fd8fSJohnny Huang int option_array[7]; 8469d5fd8fSJohnny Huang int remain_times; 8569d5fd8fSJohnny Huang int writeable_option; 865010032bSJohnny Huang int reg_protected; 8769d5fd8fSJohnny Huang int protected; 8869d5fd8fSJohnny Huang }; 8969d5fd8fSJohnny Huang 9066f2f8e5SJohnny Huang struct otpconf_parse { 9166f2f8e5SJohnny Huang int dw_offset; 9266f2f8e5SJohnny Huang int bit; 9366f2f8e5SJohnny Huang int length; 9466f2f8e5SJohnny Huang int value; 95696656c6SJohnny Huang int ignore; 9666f2f8e5SJohnny Huang char status[80]; 9766f2f8e5SJohnny Huang }; 9866f2f8e5SJohnny Huang 999a4fe690SJohnny Huang struct otpkey_type { 1009a4fe690SJohnny Huang int value; 1019a4fe690SJohnny Huang int key_type; 1029a4fe690SJohnny Huang int need_id; 1039a4fe690SJohnny Huang char information[110]; 1049a4fe690SJohnny Huang }; 1059a4fe690SJohnny Huang 1069a4fe690SJohnny Huang struct otp_info_cb { 1079a4fe690SJohnny Huang int version; 10879e42a59SJoel Stanley const struct otpstrap_info *strap_info; 1099a4fe690SJohnny Huang int strap_info_len; 11079e42a59SJoel Stanley const struct otpconf_info *conf_info; 1119a4fe690SJohnny Huang int conf_info_len; 11279e42a59SJoel Stanley const struct otpkey_type *key_info; 1139a4fe690SJohnny Huang int key_info_len; 1145010032bSJohnny Huang 1159a4fe690SJohnny Huang }; 1169a4fe690SJohnny Huang 117696656c6SJohnny Huang struct otp_image_layout { 1185010032bSJohnny Huang int data_length; 1195010032bSJohnny Huang int conf_length; 1205010032bSJohnny Huang int strap_length; 121a219f6deSJohnny Huang u8 *data; 122a219f6deSJohnny Huang u8 *data_ignore; 123a219f6deSJohnny Huang u8 *conf; 124a219f6deSJohnny Huang u8 *conf_ignore; 125a219f6deSJohnny Huang u8 *strap; 126a219f6deSJohnny Huang u8 *strap_reg_pro; 127a219f6deSJohnny Huang u8 *strap_pro; 128a219f6deSJohnny Huang u8 *strap_ignore; 129696656c6SJohnny Huang }; 130696656c6SJohnny Huang 1319a4fe690SJohnny Huang static struct otp_info_cb info_cb; 1329a4fe690SJohnny Huang 13379e42a59SJoel Stanley static const struct otpkey_type a0_key_type[] = { 1349a4fe690SJohnny Huang {0, OTP_KEY_TYPE_AES, 0, "AES-256 as OEM platform key for image encryption/decryption"}, 1359a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1369a4fe690SJohnny Huang {4, OTP_KEY_TYPE_HMAC, 1, "HMAC as encrypted OEM HMAC keys in Mode 1"}, 137181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 138181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as SOC public key"}, 139181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 140181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as SOC private key"}, 141181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1429a4fe690SJohnny Huang }; 1439a4fe690SJohnny Huang 14479e42a59SJoel Stanley static const struct otpkey_type a1_key_type[] = { 1459a4fe690SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1469a4fe690SJohnny 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"}, 147181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 148181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 149181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 1509a4fe690SJohnny Huang }; 1519a4fe690SJohnny Huang 1525fdde29fSJohnny Huang static const struct otpkey_type a2_key_type[] = { 1535fdde29fSJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 1545fdde29fSJohnny 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"}, 155181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 156181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 157181f72d8SJohnny Huang {14, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 158181f72d8SJohnny Huang }; 159181f72d8SJohnny Huang 160181f72d8SJohnny Huang static const struct otpkey_type a3_key_type[] = { 161181f72d8SJohnny Huang {1, OTP_KEY_TYPE_VAULT, 0, "AES-256 as secret vault key"}, 162181f72d8SJohnny 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"}, 163181f72d8SJohnny Huang {8, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2"}, 164181f72d8SJohnny Huang {9, OTP_KEY_TYPE_RSA_PUB, 1, "RSA-public as OEM DSS public keys in Mode 2(big endian)"}, 165181f72d8SJohnny Huang {10, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key"}, 166181f72d8SJohnny Huang {11, OTP_KEY_TYPE_RSA_PUB, 0, "RSA-public as AES key decryption key(big endian)"}, 167181f72d8SJohnny Huang {12, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key"}, 168181f72d8SJohnny Huang {13, OTP_KEY_TYPE_RSA_PRIV, 0, "RSA-private as AES key decryption key(big endian)"}, 1695fdde29fSJohnny Huang }; 1705fdde29fSJohnny Huang 171*794e27ecSJohnny Huang static int get_dw_bit(u32 *rid, int offset) 172*794e27ecSJohnny Huang { 173*794e27ecSJohnny Huang int bit_offset; 174*794e27ecSJohnny Huang int i; 175*794e27ecSJohnny Huang 176*794e27ecSJohnny Huang if (offset < 32) { 177*794e27ecSJohnny Huang i = 0; 178*794e27ecSJohnny Huang bit_offset = offset; 179*794e27ecSJohnny Huang } else { 180*794e27ecSJohnny Huang i = 1; 181*794e27ecSJohnny Huang bit_offset = offset - 32; 182*794e27ecSJohnny Huang } 183*794e27ecSJohnny Huang if ((rid[i] >> bit_offset) & 0x1) 184*794e27ecSJohnny Huang return 1; 185*794e27ecSJohnny Huang else 186*794e27ecSJohnny Huang return 0; 187*794e27ecSJohnny Huang } 188*794e27ecSJohnny Huang 189*794e27ecSJohnny Huang static int get_rid_num(u32 *rid) 190*794e27ecSJohnny Huang { 191*794e27ecSJohnny Huang int i; 192*794e27ecSJohnny Huang int fz = 0; 193*794e27ecSJohnny Huang int rid_num = 0; 194*794e27ecSJohnny Huang int ret = 0; 195*794e27ecSJohnny Huang 196*794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 197*794e27ecSJohnny Huang if (get_dw_bit(rid, i) == 0) { 198*794e27ecSJohnny Huang if (!fz) 199*794e27ecSJohnny Huang fz = 1; 200*794e27ecSJohnny Huang 201*794e27ecSJohnny Huang } else { 202*794e27ecSJohnny Huang rid_num++; 203*794e27ecSJohnny Huang if (fz) 204*794e27ecSJohnny Huang ret = OTP_FAILURE; 205*794e27ecSJohnny Huang } 206*794e27ecSJohnny Huang } 207*794e27ecSJohnny Huang if (ret) 208*794e27ecSJohnny Huang return ret; 209*794e27ecSJohnny Huang 210*794e27ecSJohnny Huang return rid_num; 211*794e27ecSJohnny Huang } 212*794e27ecSJohnny Huang 213*794e27ecSJohnny Huang static void buf_print(u8 *buf, int len) 214*794e27ecSJohnny Huang { 215*794e27ecSJohnny Huang int i; 216*794e27ecSJohnny Huang 217*794e27ecSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 218*794e27ecSJohnny Huang for (i = 0; i < len; i++) { 219*794e27ecSJohnny Huang if (i % 16 == 0) 220*794e27ecSJohnny Huang printf("%04X: ", i); 221*794e27ecSJohnny Huang printf("%02X ", buf[i]); 222*794e27ecSJohnny Huang if ((i + 1) % 16 == 0) 223*794e27ecSJohnny Huang printf("\n"); 224*794e27ecSJohnny Huang } 225*794e27ecSJohnny Huang } 226*794e27ecSJohnny Huang 227a219f6deSJohnny Huang static u32 chip_version(void) 2289a4fe690SJohnny Huang { 229badd21c2SJohnny Huang u64 rev_id; 2309a4fe690SJohnny Huang 231badd21c2SJohnny Huang rev_id = readl(ASPEED_REVISION_ID0); 232badd21c2SJohnny Huang rev_id = ((u64)readl(ASPEED_REVISION_ID1) << 32) | rev_id; 2339a4fe690SJohnny Huang 234badd21c2SJohnny Huang if (rev_id == 0x0500030305000303) { 235badd21c2SJohnny Huang /* AST2600-A0 */ 2360dae9d52SJohnny Huang return OTP_AST2600A0; 237badd21c2SJohnny Huang } else if (rev_id == 0x0501030305010303) { 238badd21c2SJohnny Huang /* AST2600-A1 */ 2390dae9d52SJohnny Huang return OTP_AST2600A1; 240badd21c2SJohnny Huang } else if (rev_id == 0x0501020305010203) { 241badd21c2SJohnny Huang /* AST2620-A1 */ 242badd21c2SJohnny Huang return OTP_AST2600A1; 243badd21c2SJohnny Huang } else if (rev_id == 0x0502030305010303) { 244badd21c2SJohnny Huang /* AST2600-A2 */ 2450dae9d52SJohnny Huang return OTP_AST2600A2; 246badd21c2SJohnny Huang } else if (rev_id == 0x0502020305010203) { 247badd21c2SJohnny Huang /* AST2620-A2 */ 248badd21c2SJohnny Huang return OTP_AST2600A2; 249badd21c2SJohnny Huang } else if (rev_id == 0x0502010305010103) { 250badd21c2SJohnny Huang /* AST2605-A2 */ 2510dae9d52SJohnny Huang return OTP_AST2600A2; 25264b66712SJohnny Huang } else if (rev_id == 0x0503030305030303) { 25364b66712SJohnny Huang /* AST2600-A3 */ 25464b66712SJohnny Huang return OTP_AST2600A3; 25564b66712SJohnny Huang } else if (rev_id == 0x0503020305030203) { 25664b66712SJohnny Huang /* AST2620-A3 */ 25764b66712SJohnny Huang return OTP_AST2600A3; 2580dae9d52SJohnny Huang } 2590dae9d52SJohnny Huang 2605fdde29fSJohnny Huang return -1; 2619a4fe690SJohnny Huang } 2629a4fe690SJohnny Huang 2633d3688adSJohnny Huang static void wait_complete(void) 2643d3688adSJohnny Huang { 2653d3688adSJohnny Huang int reg; 2663d3688adSJohnny Huang 2673d3688adSJohnny Huang do { 2683d3688adSJohnny Huang reg = readl(OTP_STATUS); 2693d3688adSJohnny Huang } while ((reg & 0x6) != 0x6); 2703d3688adSJohnny Huang } 2713d3688adSJohnny Huang 272a219f6deSJohnny Huang static void otp_write(u32 otp_addr, u32 data) 273dacbba92SJohnny Huang { 274dacbba92SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 275dacbba92SJohnny Huang writel(data, OTP_COMPARE_1); //write data 276dacbba92SJohnny Huang writel(0x23b1e362, OTP_COMMAND); //write command 277dacbba92SJohnny Huang wait_complete(); 278dacbba92SJohnny Huang } 279dacbba92SJohnny Huang 280dacbba92SJohnny Huang static void otp_soak(int soak) 281dacbba92SJohnny Huang { 28264b66712SJohnny Huang if (info_cb.version == OTP_AST2600A2 || info_cb.version == OTP_AST2600A3) { 283dacbba92SJohnny Huang switch (soak) { 284dacbba92SJohnny Huang case 0: //default 285dacbba92SJohnny Huang otp_write(0x3000, 0x0210); // Write MRA 286dacbba92SJohnny Huang otp_write(0x5000, 0x2000); // Write MRB 287dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 288dacbba92SJohnny Huang break; 289dacbba92SJohnny Huang case 1: //normal program 290dacbba92SJohnny Huang otp_write(0x3000, 0x1200); // Write MRA 291feea3fdfSJohnny Huang otp_write(0x5000, 0x107F); // Write MRB 292dacbba92SJohnny Huang otp_write(0x1000, 0x1024); // Write MR 293feea3fdfSJohnny Huang writel(0x04191388, OTP_TIMING); // 200us 294dacbba92SJohnny Huang break; 295dacbba92SJohnny Huang case 2: //soak program 296dacbba92SJohnny Huang otp_write(0x3000, 0x1220); // Write MRA 297feea3fdfSJohnny Huang otp_write(0x5000, 0x2074); // Write MRB 298dacbba92SJohnny Huang otp_write(0x1000, 0x08a4); // Write MR 299feea3fdfSJohnny Huang writel(0x04193a98, OTP_TIMING); // 600us 300dacbba92SJohnny Huang break; 301dacbba92SJohnny Huang } 302dacbba92SJohnny Huang } else { 303dacbba92SJohnny Huang switch (soak) { 304dacbba92SJohnny Huang case 0: //default 305dacbba92SJohnny Huang otp_write(0x3000, 0x0); // Write MRA 306dacbba92SJohnny Huang otp_write(0x5000, 0x0); // Write MRB 307dacbba92SJohnny Huang otp_write(0x1000, 0x0); // Write MR 308dacbba92SJohnny Huang break; 309dacbba92SJohnny Huang case 1: //normal program 310dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 311dacbba92SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 312dacbba92SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 313feea3fdfSJohnny Huang writel(0x04190760, OTP_TIMING); // 75us 314dacbba92SJohnny Huang break; 315dacbba92SJohnny Huang case 2: //soak program 316dacbba92SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 317dacbba92SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 318dacbba92SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 319feea3fdfSJohnny Huang writel(0x041930d4, OTP_TIMING); // 500us 320dacbba92SJohnny Huang break; 321dacbba92SJohnny Huang } 322dacbba92SJohnny Huang } 323dacbba92SJohnny Huang 324dacbba92SJohnny Huang wait_complete(); 325dacbba92SJohnny Huang } 326dacbba92SJohnny Huang 327a219f6deSJohnny Huang static void otp_read_data(u32 offset, u32 *data) 32869d5fd8fSJohnny Huang { 3293d3688adSJohnny Huang writel(offset, OTP_ADDR); //Read address 3303d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 3313d3688adSJohnny Huang wait_complete(); 3323d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 3333d3688adSJohnny Huang data[1] = readl(OTP_COMPARE_2); 33469d5fd8fSJohnny Huang } 33569d5fd8fSJohnny Huang 336a219f6deSJohnny Huang static void otp_read_config(u32 offset, u32 *data) 33769d5fd8fSJohnny Huang { 33869d5fd8fSJohnny Huang int config_offset; 33969d5fd8fSJohnny Huang 34069d5fd8fSJohnny Huang config_offset = 0x800; 34169d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 34269d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 34369d5fd8fSJohnny Huang 3443d3688adSJohnny Huang writel(config_offset, OTP_ADDR); //Read address 3453d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 3463d3688adSJohnny Huang wait_complete(); 3473d3688adSJohnny Huang data[0] = readl(OTP_COMPARE_1); 34869d5fd8fSJohnny Huang } 34969d5fd8fSJohnny Huang 350a219f6deSJohnny Huang static int otp_print_config(u32 offset, int dw_count) 35169d5fd8fSJohnny Huang { 35269d5fd8fSJohnny Huang int i; 353a219f6deSJohnny Huang u32 ret[1]; 35469d5fd8fSJohnny Huang 35569d5fd8fSJohnny Huang if (offset + dw_count > 32) 3562a856b9aSJohnny Huang return OTP_USAGE; 357dacbba92SJohnny Huang otp_soak(0); 35869d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i++) { 35969d5fd8fSJohnny Huang otp_read_config(i, ret); 360a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 36169d5fd8fSJohnny Huang } 36269d5fd8fSJohnny Huang printf("\n"); 3632a856b9aSJohnny Huang return OTP_SUCCESS; 36469d5fd8fSJohnny Huang } 36569d5fd8fSJohnny Huang 366a219f6deSJohnny Huang static int otp_print_data(u32 offset, int dw_count) 36769d5fd8fSJohnny Huang { 36869d5fd8fSJohnny Huang int i; 369a219f6deSJohnny Huang u32 ret[2]; 37069d5fd8fSJohnny Huang 37169d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 3722a856b9aSJohnny Huang return OTP_USAGE; 373dacbba92SJohnny Huang otp_soak(0); 37469d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 37569d5fd8fSJohnny Huang otp_read_data(i, ret); 37669d5fd8fSJohnny Huang if (i % 4 == 0) 37769d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 37869d5fd8fSJohnny Huang else 37969d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 38069d5fd8fSJohnny Huang } 38169d5fd8fSJohnny Huang printf("\n"); 3822a856b9aSJohnny Huang return OTP_SUCCESS; 38369d5fd8fSJohnny Huang } 38469d5fd8fSJohnny Huang 385a219f6deSJohnny Huang static int otp_compare(u32 otp_addr, u32 addr) 38669d5fd8fSJohnny Huang { 387a219f6deSJohnny Huang u32 ret; 388a219f6deSJohnny Huang u32 *buf; 38969d5fd8fSJohnny Huang 39069d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 39169d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 39269d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 39369d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 39469d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 3953d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Compare address 3963d3688adSJohnny Huang writel(buf[0], OTP_COMPARE_1); //Compare data 1 3973d3688adSJohnny Huang writel(buf[1], OTP_COMPARE_2); //Compare data 2 3983d3688adSJohnny Huang writel(buf[2], OTP_COMPARE_3); //Compare data 3 3993d3688adSJohnny Huang writel(buf[3], OTP_COMPARE_4); //Compare data 4 4003d3688adSJohnny Huang writel(0x23b1e363, OTP_COMMAND); //Compare command 4013d3688adSJohnny Huang wait_complete(); 4023d3688adSJohnny Huang ret = readl(OTP_STATUS); //Compare command 40369d5fd8fSJohnny Huang if (ret & 0x1) 40469d5fd8fSJohnny Huang return 0; 40569d5fd8fSJohnny Huang else 40669d5fd8fSJohnny Huang return -1; 40769d5fd8fSJohnny Huang } 40869d5fd8fSJohnny Huang 409a219f6deSJohnny Huang static int verify_bit(u32 otp_addr, int bit_offset, int value) 41069d5fd8fSJohnny Huang { 411a219f6deSJohnny Huang u32 ret[2]; 41269d5fd8fSJohnny Huang 41330a8c590SJohnny Huang if (otp_addr % 2 == 0) 4143d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 41530a8c590SJohnny Huang else 4163d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 41730a8c590SJohnny Huang 4183d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4193d3688adSJohnny Huang wait_complete(); 4203d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4213d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 42283655e91SJohnny Huang 42330a8c590SJohnny Huang if (otp_addr % 2 == 0) { 42430a8c590SJohnny Huang if (((ret[0] >> bit_offset) & 1) == value) 42569d5fd8fSJohnny Huang return 0; 42669d5fd8fSJohnny Huang else 42769d5fd8fSJohnny Huang return -1; 42830a8c590SJohnny Huang } else { 42930a8c590SJohnny Huang if (((ret[1] >> bit_offset) & 1) == value) 43030a8c590SJohnny Huang return 0; 43130a8c590SJohnny Huang else 43230a8c590SJohnny Huang return -1; 43330a8c590SJohnny Huang } 43469d5fd8fSJohnny Huang } 43569d5fd8fSJohnny Huang 436a219f6deSJohnny Huang static u32 verify_dw(u32 otp_addr, u32 *value, u32 *ignore, u32 *compare, int size) 4374c1c9b35SJohnny Huang { 438a219f6deSJohnny Huang u32 ret[2]; 4394c1c9b35SJohnny Huang 4404c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4414c1c9b35SJohnny Huang 4424c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4433d3688adSJohnny Huang writel(otp_addr, OTP_ADDR); //Read address 4444c1c9b35SJohnny Huang else 4453d3688adSJohnny Huang writel(otp_addr - 1, OTP_ADDR); //Read address 4463d3688adSJohnny Huang writel(0x23b1e361, OTP_COMMAND); //trigger read 4473d3688adSJohnny Huang wait_complete(); 4483d3688adSJohnny Huang ret[0] = readl(OTP_COMPARE_1); 4493d3688adSJohnny Huang ret[1] = readl(OTP_COMPARE_2); 4504c1c9b35SJohnny Huang if (size == 1) { 4514c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4524c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 453696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0])) { 4544c1c9b35SJohnny Huang compare[0] = 0; 4554c1c9b35SJohnny Huang return 0; 456a219f6deSJohnny Huang } 4574c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4584c1c9b35SJohnny Huang return -1; 4594c1c9b35SJohnny Huang 4604c1c9b35SJohnny Huang } else { 4614c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 462696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[1] & ~ignore[0])) { 4634c1c9b35SJohnny Huang compare[0] = ~0; 4644c1c9b35SJohnny Huang return 0; 465a219f6deSJohnny Huang } 466d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 4674c1c9b35SJohnny Huang return -1; 4684c1c9b35SJohnny Huang } 4694c1c9b35SJohnny Huang } else if (size == 2) { 4704c1c9b35SJohnny Huang // otp_addr should be even 471696656c6SJohnny Huang if ((value[0] & ~ignore[0]) == (ret[0] & ~ignore[0]) && (value[1] & ~ignore[1]) == (ret[1] & ~ignore[1])) { 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] = 0; 4754c1c9b35SJohnny Huang compare[1] = ~0; 4764c1c9b35SJohnny Huang return 0; 477a219f6deSJohnny Huang } 4784c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4794c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4804c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4814c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 4824c1c9b35SJohnny Huang return -1; 4834c1c9b35SJohnny Huang } else { 4844c1c9b35SJohnny Huang return -1; 4854c1c9b35SJohnny Huang } 4864c1c9b35SJohnny Huang } 4874c1c9b35SJohnny Huang 488a219f6deSJohnny Huang static void otp_prog(u32 otp_addr, u32 prog_bit) 48983655e91SJohnny Huang { 49090965bb3SJohnny Huang otp_write(0x0, prog_bit); 49183655e91SJohnny Huang writel(otp_addr, OTP_ADDR); //write address 49283655e91SJohnny Huang writel(prog_bit, OTP_COMPARE_1); //write data 49383655e91SJohnny Huang writel(0x23b1e364, OTP_COMMAND); //write command 49483655e91SJohnny Huang wait_complete(); 49583655e91SJohnny Huang } 49683655e91SJohnny Huang 497a219f6deSJohnny Huang static void _otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset) 49883655e91SJohnny Huang { 49983655e91SJohnny Huang int prog_bit; 50083655e91SJohnny Huang 50183655e91SJohnny Huang if (prog_address % 2 == 0) { 50283655e91SJohnny Huang if (value) 50383655e91SJohnny Huang prog_bit = ~(0x1 << bit_offset); 50483655e91SJohnny Huang else 50583655e91SJohnny Huang return; 50683655e91SJohnny Huang } else { 50764b66712SJohnny Huang if (info_cb.version != OTP_AST2600A3) 50883655e91SJohnny Huang prog_address |= 1 << 15; 50983655e91SJohnny Huang if (!value) 51083655e91SJohnny Huang prog_bit = 0x1 << bit_offset; 51183655e91SJohnny Huang else 51283655e91SJohnny Huang return; 51383655e91SJohnny Huang } 51483655e91SJohnny Huang otp_prog(prog_address, prog_bit); 51583655e91SJohnny Huang } 51683655e91SJohnny Huang 517a219f6deSJohnny Huang static int otp_prog_bit(u32 value, u32 prog_address, u32 bit_offset) 51883655e91SJohnny Huang { 51983655e91SJohnny Huang int pass; 52083655e91SJohnny Huang int i; 52183655e91SJohnny Huang 52283655e91SJohnny Huang otp_soak(1); 52383655e91SJohnny Huang _otp_prog_bit(value, prog_address, bit_offset); 52483655e91SJohnny Huang pass = 0; 52583655e91SJohnny Huang 52683655e91SJohnny Huang for (i = 0; i < RETRY; i++) { 52783655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 52883655e91SJohnny Huang otp_soak(2); 52983655e91SJohnny Huang _otp_prog_bit(value, prog_address, bit_offset); 53083655e91SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 53183655e91SJohnny Huang otp_soak(1); 53283655e91SJohnny Huang } else { 53383655e91SJohnny Huang pass = 1; 53483655e91SJohnny Huang break; 53583655e91SJohnny Huang } 53683655e91SJohnny Huang } else { 53783655e91SJohnny Huang pass = 1; 53883655e91SJohnny Huang break; 53983655e91SJohnny Huang } 54083655e91SJohnny Huang } 541*794e27ecSJohnny Huang if (pass) 542*794e27ecSJohnny Huang return OTP_SUCCESS; 54383655e91SJohnny Huang 544*794e27ecSJohnny Huang return OTP_FAILURE; 54583655e91SJohnny Huang } 54683655e91SJohnny Huang 547a219f6deSJohnny Huang static void otp_prog_dw(u32 value, u32 ignore, u32 prog_address) 548d90825e2SJohnny Huang { 549d90825e2SJohnny Huang int j, bit_value, prog_bit; 550d90825e2SJohnny Huang 551d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 552696656c6SJohnny Huang if ((ignore >> j) & 0x1) 553d90825e2SJohnny Huang continue; 554d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 555d90825e2SJohnny Huang if (prog_address % 2 == 0) { 556d90825e2SJohnny Huang if (bit_value) 557d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 558d90825e2SJohnny Huang else 559d90825e2SJohnny Huang continue; 560d90825e2SJohnny Huang } else { 56164b66712SJohnny Huang if (info_cb.version != OTP_AST2600A3) 562d90825e2SJohnny Huang prog_address |= 1 << 15; 563d90825e2SJohnny Huang if (bit_value) 564d90825e2SJohnny Huang continue; 565d90825e2SJohnny Huang else 566d90825e2SJohnny Huang prog_bit = 0x1 << j; 567d90825e2SJohnny Huang } 568d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 569d90825e2SJohnny Huang } 570d90825e2SJohnny Huang } 571d90825e2SJohnny Huang 572a219f6deSJohnny Huang static int otp_prog_verify_2dw(u32 *data, u32 *buf, u32 *ignore_mask, u32 prog_address) 57354552c69SJohnny Huang { 57454552c69SJohnny Huang int pass; 57554552c69SJohnny Huang int i; 576a219f6deSJohnny Huang u32 data0_masked; 577a219f6deSJohnny Huang u32 data1_masked; 578a219f6deSJohnny Huang u32 buf0_masked; 579a219f6deSJohnny Huang u32 buf1_masked; 580a219f6deSJohnny Huang u32 compare[2]; 58154552c69SJohnny Huang 58254552c69SJohnny Huang data0_masked = data[0] & ~ignore_mask[0]; 58354552c69SJohnny Huang buf0_masked = buf[0] & ~ignore_mask[0]; 58454552c69SJohnny Huang data1_masked = data[1] & ~ignore_mask[1]; 58554552c69SJohnny Huang buf1_masked = buf[1] & ~ignore_mask[1]; 586a219f6deSJohnny Huang if (data0_masked == buf0_masked && data1_masked == buf1_masked) 58754552c69SJohnny Huang return 0; 58854552c69SJohnny Huang 58954552c69SJohnny Huang otp_soak(1); 59054552c69SJohnny Huang if (data0_masked != buf0_masked) 59154552c69SJohnny Huang otp_prog_dw(buf[0], ignore_mask[0], prog_address); 59254552c69SJohnny Huang if (data1_masked != buf1_masked) 59354552c69SJohnny Huang otp_prog_dw(buf[1], ignore_mask[1], prog_address + 1); 59454552c69SJohnny Huang 59554552c69SJohnny Huang pass = 0; 59654552c69SJohnny Huang for (i = 0; i < RETRY; i++) { 59754552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 59854552c69SJohnny Huang otp_soak(2); 599a219f6deSJohnny Huang if (compare[0] != 0) 60054552c69SJohnny Huang otp_prog_dw(compare[0], ignore_mask[0], prog_address); 601a219f6deSJohnny Huang if (compare[1] != ~0) 6025537bc72SJohnny Huang otp_prog_dw(compare[1], ignore_mask[1], prog_address + 1); 60354552c69SJohnny Huang if (verify_dw(prog_address, buf, ignore_mask, compare, 2) != 0) { 60454552c69SJohnny Huang otp_soak(1); 60554552c69SJohnny Huang } else { 60654552c69SJohnny Huang pass = 1; 60754552c69SJohnny Huang break; 60854552c69SJohnny Huang } 60954552c69SJohnny Huang } else { 61054552c69SJohnny Huang pass = 1; 61154552c69SJohnny Huang break; 61254552c69SJohnny Huang } 61354552c69SJohnny Huang } 61454552c69SJohnny Huang 61554552c69SJohnny Huang if (!pass) { 61654552c69SJohnny Huang otp_soak(0); 61754552c69SJohnny Huang return OTP_FAILURE; 61854552c69SJohnny Huang } 61954552c69SJohnny Huang return OTP_SUCCESS; 62054552c69SJohnny Huang } 62154552c69SJohnny Huang 622541eb887SJohnny Huang static void otp_strap_status(struct otpstrap_status *otpstrap) 62376d13988SJohnny Huang { 624a219f6deSJohnny Huang u32 OTPSTRAP_RAW[2]; 6255010032bSJohnny Huang int strap_end; 62676d13988SJohnny Huang int i, j; 62776d13988SJohnny Huang 6285010032bSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 62976d13988SJohnny Huang for (j = 0; j < 64; j++) { 63076d13988SJohnny Huang otpstrap[j].value = 0; 63176d13988SJohnny Huang otpstrap[j].remain_times = 7; 63276d13988SJohnny Huang otpstrap[j].writeable_option = -1; 63376d13988SJohnny Huang otpstrap[j].protected = 0; 63476d13988SJohnny Huang } 6355010032bSJohnny Huang strap_end = 30; 6365010032bSJohnny Huang } else { 6375010032bSJohnny Huang for (j = 0; j < 64; j++) { 6385010032bSJohnny Huang otpstrap[j].value = 0; 6395010032bSJohnny Huang otpstrap[j].remain_times = 6; 6405010032bSJohnny Huang otpstrap[j].writeable_option = -1; 6415010032bSJohnny Huang otpstrap[j].reg_protected = 0; 6425010032bSJohnny Huang otpstrap[j].protected = 0; 6435010032bSJohnny Huang } 6445010032bSJohnny Huang strap_end = 28; 6455010032bSJohnny Huang } 64676d13988SJohnny Huang 647dacbba92SJohnny Huang otp_soak(0); 6485010032bSJohnny Huang for (i = 16; i < strap_end; i += 2) { 64976d13988SJohnny Huang int option = (i - 16) / 2; 650a219f6deSJohnny Huang 65176d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 65276d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 65376d13988SJohnny Huang for (j = 0; j < 32; j++) { 65476d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 655a219f6deSJohnny Huang 656a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 65776d13988SJohnny Huang otpstrap[j].writeable_option = option; 65876d13988SJohnny Huang if (bit_value == 1) 65976d13988SJohnny Huang otpstrap[j].remain_times--; 66076d13988SJohnny Huang otpstrap[j].value ^= bit_value; 66176d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 66276d13988SJohnny Huang } 66376d13988SJohnny Huang for (j = 32; j < 64; j++) { 66476d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 665a219f6deSJohnny Huang 666a219f6deSJohnny Huang if (bit_value == 0 && otpstrap[j].writeable_option == -1) 66776d13988SJohnny Huang otpstrap[j].writeable_option = option; 66876d13988SJohnny Huang if (bit_value == 1) 66976d13988SJohnny Huang otpstrap[j].remain_times--; 67076d13988SJohnny Huang otpstrap[j].value ^= bit_value; 67176d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 67276d13988SJohnny Huang } 67376d13988SJohnny Huang } 6745010032bSJohnny Huang 6755010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 6765010032bSJohnny Huang otp_read_config(28, &OTPSTRAP_RAW[0]); 6775010032bSJohnny Huang otp_read_config(29, &OTPSTRAP_RAW[1]); 6785010032bSJohnny Huang for (j = 0; j < 32; j++) { 6795010032bSJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 6805010032bSJohnny Huang otpstrap[j].reg_protected = 1; 6815010032bSJohnny Huang } 6825010032bSJohnny Huang for (j = 32; j < 64; j++) { 6835010032bSJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 6845010032bSJohnny Huang otpstrap[j].reg_protected = 1; 6855010032bSJohnny Huang } 6865010032bSJohnny Huang } 6875010032bSJohnny Huang 68876d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 68976d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 69076d13988SJohnny Huang for (j = 0; j < 32; j++) { 69176d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 69276d13988SJohnny Huang otpstrap[j].protected = 1; 69376d13988SJohnny Huang } 69476d13988SJohnny Huang for (j = 32; j < 64; j++) { 69576d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 69676d13988SJohnny Huang otpstrap[j].protected = 1; 69776d13988SJohnny Huang } 69876d13988SJohnny Huang } 69976d13988SJohnny Huang 700*794e27ecSJohnny Huang static void otp_print_revid(u32 *rid) 701*794e27ecSJohnny Huang { 702*794e27ecSJohnny Huang int bit_offset; 703*794e27ecSJohnny Huang int i, j; 704*794e27ecSJohnny Huang 705*794e27ecSJohnny Huang printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); 706*794e27ecSJohnny Huang printf("___________________________________________________\n"); 707*794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 708*794e27ecSJohnny Huang if (i < 32) { 709*794e27ecSJohnny Huang j = 0; 710*794e27ecSJohnny Huang bit_offset = i; 711*794e27ecSJohnny Huang } else { 712*794e27ecSJohnny Huang j = 1; 713*794e27ecSJohnny Huang bit_offset = i - 32; 714*794e27ecSJohnny Huang } 715*794e27ecSJohnny Huang if (i % 16 == 0) 716*794e27ecSJohnny Huang printf("%2x | ", i); 717*794e27ecSJohnny Huang printf("%d ", (rid[j] >> bit_offset) & 0x1); 718*794e27ecSJohnny Huang if ((i + 1) % 16 == 0) 719*794e27ecSJohnny Huang printf("\n"); 720*794e27ecSJohnny Huang } 721*794e27ecSJohnny Huang } 722*794e27ecSJohnny Huang 723696656c6SJohnny Huang static int otp_print_conf_image(struct otp_image_layout *image_layout) 72469d5fd8fSJohnny Huang { 72579e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 726a219f6deSJohnny Huang u32 *OTPCFG = (u32 *)image_layout->conf; 727a219f6deSJohnny Huang u32 *OTPCFG_IGNORE = (u32 *)image_layout->conf_ignore; 728a219f6deSJohnny Huang u32 mask; 729a219f6deSJohnny Huang u32 dw_offset; 730a219f6deSJohnny Huang u32 bit_offset; 731a219f6deSJohnny Huang u32 otp_value; 732a219f6deSJohnny Huang u32 otp_ignore; 733b458cd62SJohnny Huang int fail = 0; 734*794e27ecSJohnny Huang int rid_num = 0; 73573f11549SJohnny Huang char valid_bit[20]; 736*794e27ecSJohnny Huang int fz; 73766f2f8e5SJohnny Huang int i; 73873f11549SJohnny Huang int j; 73966f2f8e5SJohnny Huang 740737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 74166f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 7423cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 7433cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 7443cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 7453cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 746b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 747696656c6SJohnny Huang otp_ignore = (OTPCFG_IGNORE[dw_offset] >> bit_offset) & mask; 748b458cd62SJohnny Huang 749a219f6deSJohnny Huang if (otp_ignore == mask) 750b458cd62SJohnny Huang continue; 751a219f6deSJohnny Huang else if (otp_ignore != 0) 752b458cd62SJohnny Huang fail = 1; 753b458cd62SJohnny Huang 754a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 7553cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 7563cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 7573cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 758b458cd62SJohnny Huang continue; 759b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 760b458cd62SJohnny Huang 7613cb28812SJohnny Huang if (conf_info[i].length == 1) { 7623cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 76366f2f8e5SJohnny Huang } else { 764b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 7653cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 7663cb28812SJohnny Huang conf_info[i].bit_offset); 76766f2f8e5SJohnny Huang } 768b458cd62SJohnny Huang printf("0x%-10x", otp_value); 769b458cd62SJohnny Huang 770b458cd62SJohnny Huang if (fail) { 771696656c6SJohnny Huang printf("Ignore mask error\n"); 772a219f6deSJohnny Huang continue; 773a219f6deSJohnny Huang } 7743cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 775b458cd62SJohnny Huang printf("Reserved\n"); 7763cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 7773cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 778b458cd62SJohnny Huang printf("\n"); 7793cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 780b458cd62SJohnny Huang if (otp_value != 0) { 78173f11549SJohnny Huang for (j = 0; j < 7; j++) { 782a219f6deSJohnny Huang if (otp_value == (1 << j)) 78373f11549SJohnny Huang valid_bit[j * 2] = '1'; 784a219f6deSJohnny Huang else 78573f11549SJohnny Huang valid_bit[j * 2] = '0'; 78673f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 78773f11549SJohnny Huang } 78873f11549SJohnny Huang valid_bit[15] = 0; 78973f11549SJohnny Huang } else { 79073f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 791b458cd62SJohnny Huang } 7923cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 793b458cd62SJohnny Huang printf("\n"); 794b458cd62SJohnny Huang } else { 7953cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 796b458cd62SJohnny Huang } 797b458cd62SJohnny Huang } 798b458cd62SJohnny Huang 799*794e27ecSJohnny Huang if (OTPCFG[0xa] != 0 || OTPCFG[0xb] != 0) { 800*794e27ecSJohnny Huang if (OTPCFG_IGNORE[0xa] != 0 && OTPCFG_IGNORE[0xb] != 0) { 801*794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 802*794e27ecSJohnny Huang fail = 1; 803*794e27ecSJohnny Huang } else { 804*794e27ecSJohnny Huang fz = 0; 805*794e27ecSJohnny Huang for (i = 0; i < 64; i++) { 806*794e27ecSJohnny Huang if (get_dw_bit(&OTPCFG[0xa], i) == 0) { 807*794e27ecSJohnny Huang if (!fz) 808*794e27ecSJohnny Huang fz = 1; 809*794e27ecSJohnny Huang } else { 810*794e27ecSJohnny Huang rid_num++; 811*794e27ecSJohnny Huang if (fz) { 812*794e27ecSJohnny Huang printf("OTP revision ID is invalid.\n"); 813*794e27ecSJohnny Huang fail = 1; 814*794e27ecSJohnny Huang break; 815*794e27ecSJohnny Huang } 816*794e27ecSJohnny Huang } 817*794e27ecSJohnny Huang } 818*794e27ecSJohnny Huang } 819*794e27ecSJohnny Huang if (fail) 820*794e27ecSJohnny Huang printf("OTP revision ID\n"); 821*794e27ecSJohnny Huang else 822*794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 823*794e27ecSJohnny Huang otp_print_revid(&OTPCFG[0xa]); 824*794e27ecSJohnny Huang } 825*794e27ecSJohnny Huang 826b458cd62SJohnny Huang if (fail) 827b458cd62SJohnny Huang return OTP_FAILURE; 828b458cd62SJohnny Huang 82966f2f8e5SJohnny Huang return OTP_SUCCESS; 83066f2f8e5SJohnny Huang } 83166f2f8e5SJohnny Huang 8322d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 83366f2f8e5SJohnny Huang { 83479e42a59SJoel Stanley const struct otpconf_info *conf_info = info_cb.conf_info; 835a219f6deSJohnny Huang u32 OTPCFG[16]; 836a219f6deSJohnny Huang u32 mask; 837a219f6deSJohnny Huang u32 dw_offset; 838a219f6deSJohnny Huang u32 bit_offset; 839a219f6deSJohnny Huang u32 otp_value; 84073f11549SJohnny Huang char valid_bit[20]; 84166f2f8e5SJohnny Huang int i; 84273f11549SJohnny Huang int j; 84366f2f8e5SJohnny Huang 844dacbba92SJohnny Huang otp_soak(0); 845bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) 84666f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 84766f2f8e5SJohnny Huang 848b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 849b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 8503cb28812SJohnny Huang for (i = 0; i < info_cb.conf_info_len; i++) { 8513cb28812SJohnny Huang if (input_offset != -1 && input_offset != conf_info[i].dw_offset) 8522d4b0742SJohnny Huang continue; 8533cb28812SJohnny Huang dw_offset = conf_info[i].dw_offset; 8543cb28812SJohnny Huang bit_offset = conf_info[i].bit_offset; 8553cb28812SJohnny Huang mask = BIT(conf_info[i].length) - 1; 856b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 857b458cd62SJohnny Huang 858a219f6deSJohnny Huang if (otp_value != conf_info[i].value && 8593cb28812SJohnny Huang conf_info[i].value != OTP_REG_RESERVED && 8603cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALUE && 8613cb28812SJohnny Huang conf_info[i].value != OTP_REG_VALID_BIT) 862b458cd62SJohnny Huang continue; 863b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 864b458cd62SJohnny Huang 8653cb28812SJohnny Huang if (conf_info[i].length == 1) { 8663cb28812SJohnny Huang printf("0x%-9X", conf_info[i].bit_offset); 867b458cd62SJohnny Huang } else { 868b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 8693cb28812SJohnny Huang conf_info[i].bit_offset + conf_info[i].length - 1, 8703cb28812SJohnny Huang conf_info[i].bit_offset); 871b458cd62SJohnny Huang } 872b458cd62SJohnny Huang printf("0x%-10x", otp_value); 873b458cd62SJohnny Huang 8743cb28812SJohnny Huang if (conf_info[i].value == OTP_REG_RESERVED) { 875b458cd62SJohnny Huang printf("Reserved\n"); 8763cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALUE) { 8773cb28812SJohnny Huang printf(conf_info[i].information, otp_value); 878b458cd62SJohnny Huang printf("\n"); 8793cb28812SJohnny Huang } else if (conf_info[i].value == OTP_REG_VALID_BIT) { 880b458cd62SJohnny Huang if (otp_value != 0) { 88173f11549SJohnny Huang for (j = 0; j < 7; j++) { 882a219f6deSJohnny Huang if (otp_value == (1 << j)) 88373f11549SJohnny Huang valid_bit[j * 2] = '1'; 884a219f6deSJohnny Huang else 88573f11549SJohnny Huang valid_bit[j * 2] = '0'; 88673f11549SJohnny Huang valid_bit[j * 2 + 1] = ' '; 88773f11549SJohnny Huang } 88873f11549SJohnny Huang valid_bit[15] = 0; 88973f11549SJohnny Huang } else { 89073f11549SJohnny Huang strcpy(valid_bit, "0 0 0 0 0 0 0 0\0"); 891b458cd62SJohnny Huang } 8923cb28812SJohnny Huang printf(conf_info[i].information, valid_bit); 893b458cd62SJohnny Huang printf("\n"); 894b458cd62SJohnny Huang } else { 8953cb28812SJohnny Huang printf("%s\n", conf_info[i].information); 896b458cd62SJohnny Huang } 897b458cd62SJohnny Huang } 898b458cd62SJohnny Huang return OTP_SUCCESS; 89966f2f8e5SJohnny Huang } 90066f2f8e5SJohnny Huang 9015010032bSJohnny Huang static int otp_print_strap_image(struct otp_image_layout *image_layout) 90276d13988SJohnny Huang { 90379e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 904a219f6deSJohnny Huang u32 *OTPSTRAP; 905a219f6deSJohnny Huang u32 *OTPSTRAP_REG_PRO; 906a219f6deSJohnny Huang u32 *OTPSTRAP_PRO; 907a219f6deSJohnny Huang u32 *OTPSTRAP_IGNORE; 90876d13988SJohnny Huang int i; 909a8bd6d8cSJohnny Huang int fail = 0; 910a219f6deSJohnny Huang u32 bit_offset; 911a219f6deSJohnny Huang u32 dw_offset; 912a219f6deSJohnny Huang u32 mask; 913a219f6deSJohnny Huang u32 otp_value; 914a219f6deSJohnny Huang u32 otp_reg_protect; 915a219f6deSJohnny Huang u32 otp_protect; 916a219f6deSJohnny Huang u32 otp_ignore; 91776d13988SJohnny Huang 918a219f6deSJohnny Huang OTPSTRAP = (u32 *)image_layout->strap; 919a219f6deSJohnny Huang OTPSTRAP_PRO = (u32 *)image_layout->strap_pro; 920a219f6deSJohnny Huang OTPSTRAP_IGNORE = (u32 *)image_layout->strap_ignore; 9215010032bSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 922696656c6SJohnny Huang OTPSTRAP_REG_PRO = NULL; 923a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 924696656c6SJohnny Huang } else { 925a219f6deSJohnny Huang OTPSTRAP_REG_PRO = (u32 *)image_layout->strap_reg_pro; 926de6b0cc4SJohnny Huang printf("BIT(hex) Value Reg_Protect Protect Description\n"); 927696656c6SJohnny Huang } 928de6b0cc4SJohnny Huang printf("__________________________________________________________________________________________\n"); 929b458cd62SJohnny Huang 9303cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 931696656c6SJohnny Huang if (strap_info[i].bit_offset > 31) { 932a8bd6d8cSJohnny Huang dw_offset = 1; 9333cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset - 32; 934a8bd6d8cSJohnny Huang } else { 935a8bd6d8cSJohnny Huang dw_offset = 0; 9363cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 937a8bd6d8cSJohnny Huang } 93876d13988SJohnny Huang 9393cb28812SJohnny Huang mask = BIT(strap_info[i].length) - 1; 940a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 941a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 942696656c6SJohnny Huang otp_ignore = (OTPSTRAP_IGNORE[dw_offset] >> bit_offset) & mask; 943a8bd6d8cSJohnny Huang 9445010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) 945696656c6SJohnny Huang otp_reg_protect = (OTPSTRAP_REG_PRO[dw_offset] >> bit_offset) & mask; 9465010032bSJohnny Huang else 9475010032bSJohnny Huang otp_reg_protect = 0; 948696656c6SJohnny Huang 949a219f6deSJohnny Huang if (otp_ignore == mask) 950a8bd6d8cSJohnny Huang continue; 951a219f6deSJohnny Huang else if (otp_ignore != 0) 952a8bd6d8cSJohnny Huang fail = 1; 953a8bd6d8cSJohnny Huang 954a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 9553cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 956a8bd6d8cSJohnny Huang continue; 957a8bd6d8cSJohnny Huang 9583cb28812SJohnny Huang if (strap_info[i].length == 1) { 9593cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 960a8bd6d8cSJohnny Huang } else { 961b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 9623cb28812SJohnny Huang strap_info[i].bit_offset + strap_info[i].length - 1, 9633cb28812SJohnny Huang strap_info[i].bit_offset); 964a8bd6d8cSJohnny Huang } 965a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 9665010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) 967696656c6SJohnny Huang printf("0x%-10x", otp_reg_protect); 968a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 969a8bd6d8cSJohnny Huang 970a8bd6d8cSJohnny Huang if (fail) { 971696656c6SJohnny Huang printf("Ignore mask error\n"); 972a8bd6d8cSJohnny Huang } else { 9733cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 9743cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 975a8bd6d8cSJohnny Huang else 976a8bd6d8cSJohnny Huang printf("Reserved\n"); 977a8bd6d8cSJohnny Huang } 978a8bd6d8cSJohnny Huang } 979a8bd6d8cSJohnny Huang 980a8bd6d8cSJohnny Huang if (fail) 98176d13988SJohnny Huang return OTP_FAILURE; 98276d13988SJohnny Huang 98376d13988SJohnny Huang return OTP_SUCCESS; 98476d13988SJohnny Huang } 98576d13988SJohnny Huang 986b458cd62SJohnny Huang static int otp_print_strap_info(int view) 98776d13988SJohnny Huang { 98879e42a59SJoel Stanley const struct otpstrap_info *strap_info = info_cb.strap_info; 98976d13988SJohnny Huang struct otpstrap_status strap_status[64]; 99007baa4e8SJohnny Huang int i, j; 991b458cd62SJohnny Huang int fail = 0; 992a219f6deSJohnny Huang u32 bit_offset; 993a219f6deSJohnny Huang u32 length; 994a219f6deSJohnny Huang u32 otp_value; 995a219f6deSJohnny Huang u32 otp_protect; 99676d13988SJohnny Huang 997541eb887SJohnny Huang otp_strap_status(strap_status); 99876d13988SJohnny Huang 999b458cd62SJohnny Huang if (view) { 100083655e91SJohnny Huang if (info_cb.version == OTP_AST2600A0) 100107baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 100283655e91SJohnny Huang else 100383655e91SJohnny Huang printf("BIT(hex) Value Remains Reg_Protect Protect Description\n"); 100407baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 1005b458cd62SJohnny Huang } else { 1006b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 1007b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 100876d13988SJohnny Huang } 10093cb28812SJohnny Huang for (i = 0; i < info_cb.strap_info_len; i++) { 1010b458cd62SJohnny Huang otp_value = 0; 10113cb28812SJohnny Huang bit_offset = strap_info[i].bit_offset; 10123cb28812SJohnny Huang length = strap_info[i].length; 1013b458cd62SJohnny Huang for (j = 0; j < length; j++) { 1014c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 1015c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 1016b458cd62SJohnny Huang } 1017a219f6deSJohnny Huang if (otp_value != strap_info[i].value && 10183cb28812SJohnny Huang strap_info[i].value != OTP_REG_RESERVED) 1019b458cd62SJohnny Huang continue; 1020b458cd62SJohnny Huang if (view) { 1021b458cd62SJohnny Huang for (j = 0; j < length; j++) { 10223cb28812SJohnny Huang printf("0x%-7X", strap_info[i].bit_offset + j); 1023b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 102407baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 102583655e91SJohnny Huang if (info_cb.version != OTP_AST2600A0) 1026e1a7245eSJohnny Huang printf("0x%-10X", strap_status[bit_offset + j].reg_protected); 1027e1a7245eSJohnny Huang printf("0x%-7X", strap_status[bit_offset + j].protected); 10283cb28812SJohnny Huang if (strap_info[i].value == OTP_REG_RESERVED) { 1029b458cd62SJohnny Huang printf(" Reserved\n"); 1030b458cd62SJohnny Huang continue; 1031b458cd62SJohnny Huang } 1032b458cd62SJohnny Huang if (length == 1) { 10333cb28812SJohnny Huang printf(" %s\n", strap_info[i].information); 1034b458cd62SJohnny Huang continue; 103576d13988SJohnny Huang } 103676d13988SJohnny Huang 1037b458cd62SJohnny Huang if (j == 0) 10383cb28812SJohnny Huang printf("/%s\n", strap_info[i].information); 1039b458cd62SJohnny Huang else if (j == length - 1) 1040b458cd62SJohnny Huang printf("\\ \"\n"); 1041b458cd62SJohnny Huang else 1042b458cd62SJohnny Huang printf("| \"\n"); 104376d13988SJohnny Huang } 1044b458cd62SJohnny Huang } else { 1045c947ef08SJohnny Huang if (length == 1) { 10463cb28812SJohnny Huang printf("0x%-9X", strap_info[i].bit_offset); 1047b458cd62SJohnny Huang } else { 1048b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1049b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1050b458cd62SJohnny Huang } 1051b458cd62SJohnny Huang 1052b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1053b458cd62SJohnny Huang 10543cb28812SJohnny Huang if (strap_info[i].value != OTP_REG_RESERVED) 10553cb28812SJohnny Huang printf("%s\n", strap_info[i].information); 1056b458cd62SJohnny Huang else 1057b458cd62SJohnny Huang printf("Reserved\n"); 1058b458cd62SJohnny Huang } 1059b458cd62SJohnny Huang } 1060b458cd62SJohnny Huang 1061b458cd62SJohnny Huang if (fail) 1062b458cd62SJohnny Huang return OTP_FAILURE; 1063b458cd62SJohnny Huang 1064b458cd62SJohnny Huang return OTP_SUCCESS; 1065b458cd62SJohnny Huang } 1066b458cd62SJohnny Huang 1067696656c6SJohnny Huang static int otp_print_data_info(struct otp_image_layout *image_layout) 106869d5fd8fSJohnny Huang { 106969d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 107079e42a59SJoel Stanley const struct otpkey_type *key_info_array = info_cb.key_info; 10719a4fe690SJohnny Huang struct otpkey_type key_info; 1072a219f6deSJohnny Huang u32 *buf; 1073a219f6deSJohnny Huang u8 *byte_buf; 10749d998018SJohnny Huang char empty = 1; 107569d5fd8fSJohnny Huang int i = 0, len = 0; 10769a4fe690SJohnny Huang int j; 107754552c69SJohnny Huang 1078696656c6SJohnny Huang byte_buf = image_layout->data; 1079a219f6deSJohnny Huang buf = (u32 *)byte_buf; 10809d998018SJohnny Huang 10819d998018SJohnny Huang for (i = 0; i < 16; i++) { 1082a219f6deSJohnny Huang if (buf[i] != 0) 10839d998018SJohnny Huang empty = 0; 10849d998018SJohnny Huang } 10859d998018SJohnny Huang if (empty) 10869d998018SJohnny Huang return 0; 10879d998018SJohnny Huang 10889d998018SJohnny Huang i = 0; 108969d5fd8fSJohnny Huang while (1) { 109069d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 109169d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 109269d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 109369d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 109469d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 109569d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 10969a4fe690SJohnny Huang 10979a4fe690SJohnny Huang for (j = 0; j < info_cb.key_info_len; j++) { 10989a4fe690SJohnny Huang if (key_type == key_info_array[j].value) { 10999a4fe690SJohnny Huang key_info = key_info_array[j]; 11009a4fe690SJohnny Huang break; 11019a4fe690SJohnny Huang } 11029a4fe690SJohnny Huang } 11039a4fe690SJohnny Huang 11047f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 110569d5fd8fSJohnny Huang printf("Key Type: "); 11069a4fe690SJohnny Huang printf("%s\n", key_info.information); 11079a4fe690SJohnny Huang 11089a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 110969d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 111069d5fd8fSJohnny Huang switch (key_length) { 111169d5fd8fSJohnny Huang case 0: 111269d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 111369d5fd8fSJohnny Huang break; 111469d5fd8fSJohnny Huang case 1: 111569d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 111669d5fd8fSJohnny Huang break; 111769d5fd8fSJohnny Huang case 2: 111869d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 111969d5fd8fSJohnny Huang break; 112069d5fd8fSJohnny Huang case 3: 112169d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 112269d5fd8fSJohnny Huang break; 112369d5fd8fSJohnny Huang } 1124181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV || 1125181f72d8SJohnny Huang key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 112669d5fd8fSJohnny Huang printf("RSA SHA Type: "); 112769d5fd8fSJohnny Huang switch (key_length) { 112869d5fd8fSJohnny Huang case 0: 112969d5fd8fSJohnny Huang printf("RSA1024\n"); 113069d5fd8fSJohnny Huang len = 0x100; 113169d5fd8fSJohnny Huang break; 113269d5fd8fSJohnny Huang case 1: 113369d5fd8fSJohnny Huang printf("RSA2048\n"); 113469d5fd8fSJohnny Huang len = 0x200; 113569d5fd8fSJohnny Huang break; 113669d5fd8fSJohnny Huang case 2: 113769d5fd8fSJohnny Huang printf("RSA3072\n"); 113869d5fd8fSJohnny Huang len = 0x300; 113969d5fd8fSJohnny Huang break; 114069d5fd8fSJohnny Huang case 3: 114169d5fd8fSJohnny Huang printf("RSA4096\n"); 114269d5fd8fSJohnny Huang len = 0x400; 114369d5fd8fSJohnny Huang break; 114469d5fd8fSJohnny Huang } 114569d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 114669d5fd8fSJohnny Huang } 11479a4fe690SJohnny Huang if (key_info.need_id) 114869d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 114969d5fd8fSJohnny Huang printf("Key Value:\n"); 11509a4fe690SJohnny Huang if (key_info.key_type == OTP_KEY_TYPE_HMAC) { 115169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 11529a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_AES) { 11539a4fe690SJohnny Huang printf("AES Key:\n"); 11549a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 11555fdde29fSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 11569a4fe690SJohnny Huang printf("AES IV:\n"); 11579a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 11589a4fe690SJohnny Huang } 11599a4fe690SJohnny Huang 11609a4fe690SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_VAULT) { 11615fdde29fSJohnny Huang if (info_cb.version == OTP_AST2600A0) { 116269d5fd8fSJohnny Huang printf("AES Key:\n"); 116369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 116469d5fd8fSJohnny Huang printf("AES IV:\n"); 116569d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 11665fdde29fSJohnny Huang } else { 11679a4fe690SJohnny Huang printf("AES Key 1:\n"); 11689a4fe690SJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 11699a4fe690SJohnny Huang printf("AES Key 2:\n"); 11709a4fe690SJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x20); 11719a4fe690SJohnny Huang } 1172181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PRIV) { 117369d5fd8fSJohnny Huang printf("RSA mod:\n"); 117469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 117569d5fd8fSJohnny Huang printf("RSA exp:\n"); 117669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 1177181f72d8SJohnny Huang } else if (key_info.key_type == OTP_KEY_TYPE_RSA_PUB) { 1178181f72d8SJohnny Huang printf("RSA mod:\n"); 1179181f72d8SJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 1180181f72d8SJohnny Huang printf("RSA exp:\n"); 1181a219f6deSJohnny Huang buf_print((u8 *)"\x01\x00\x01", 3); 118269d5fd8fSJohnny Huang } 118369d5fd8fSJohnny Huang if (last) 118469d5fd8fSJohnny Huang break; 118569d5fd8fSJohnny Huang i++; 118669d5fd8fSJohnny Huang } 118769d5fd8fSJohnny Huang return 0; 118869d5fd8fSJohnny Huang } 118969d5fd8fSJohnny Huang 11905010032bSJohnny Huang static int otp_prog_conf(struct otp_image_layout *image_layout) 119169d5fd8fSJohnny Huang { 1192a6d0d645SJohnny Huang int i, k; 1193d90825e2SJohnny Huang int pass = 0; 1194a219f6deSJohnny Huang u32 prog_address; 1195a219f6deSJohnny Huang u32 data[16]; 1196a219f6deSJohnny Huang u32 compare[2]; 1197a219f6deSJohnny Huang u32 *conf = (u32 *)image_layout->conf; 1198a219f6deSJohnny Huang u32 *conf_ignore = (u32 *)image_layout->conf_ignore; 1199a219f6deSJohnny Huang u32 data_masked; 1200a219f6deSJohnny Huang u32 buf_masked; 120169d5fd8fSJohnny Huang 1202a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1203a6d0d645SJohnny Huang 1204bb34a7bfSJohnny Huang for (i = 0; i < 16 ; i++) { 120569d5fd8fSJohnny Huang prog_address = 0x800; 1206a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1207a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1208a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1209a6d0d645SJohnny Huang } 1210a6d0d645SJohnny Huang 1211a6d0d645SJohnny Huang printf("Check writable...\n"); 1212bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 12135010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 12145010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1215d90825e2SJohnny Huang if (data_masked == buf_masked) 121669d5fd8fSJohnny Huang continue; 1217d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1218a6d0d645SJohnny Huang continue; 1219a6d0d645SJohnny Huang } else { 1220a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1221a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 12225010032bSJohnny Huang printf("Input [%X] = %x\n", i, conf[i]); 12235010032bSJohnny Huang printf("Mask [%X] = %x\n", i, ~conf_ignore[i]); 12242a856b9aSJohnny Huang return OTP_FAILURE; 1225a6d0d645SJohnny Huang } 1226a6d0d645SJohnny Huang } 1227a6d0d645SJohnny Huang 1228a6d0d645SJohnny Huang printf("Start Programing...\n"); 1229d90825e2SJohnny Huang otp_soak(0); 1230bb34a7bfSJohnny Huang for (i = 0; i < 16; i++) { 12315010032bSJohnny Huang data_masked = data[i] & ~conf_ignore[i]; 12325010032bSJohnny Huang buf_masked = conf[i] & ~conf_ignore[i]; 1233a6d0d645SJohnny Huang prog_address = 0x800; 1234a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1235a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1236bb34a7bfSJohnny Huang if (data_masked == buf_masked) { 1237bb34a7bfSJohnny Huang pass = 1; 1238a6d0d645SJohnny Huang continue; 1239bb34a7bfSJohnny Huang } 1240de6fbf1cSJohnny Huang 1241de6fbf1cSJohnny Huang otp_soak(1); 12425010032bSJohnny Huang otp_prog_dw(conf[i], conf_ignore[i], prog_address); 1243a6d0d645SJohnny Huang 124469d5fd8fSJohnny Huang pass = 0; 124569d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 12465010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1247de6fbf1cSJohnny Huang otp_soak(2); 1248feea3fdfSJohnny Huang otp_prog_dw(compare[0], conf_ignore[i], prog_address); 12495010032bSJohnny Huang if (verify_dw(prog_address, &conf[i], &conf_ignore[i], compare, 1) != 0) { 1250de6fbf1cSJohnny Huang otp_soak(1); 1251de6fbf1cSJohnny Huang } else { 1252de6fbf1cSJohnny Huang pass = 1; 1253de6fbf1cSJohnny Huang break; 1254de6fbf1cSJohnny Huang } 1255a6d0d645SJohnny Huang } else { 125669d5fd8fSJohnny Huang pass = 1; 125769d5fd8fSJohnny Huang break; 125869d5fd8fSJohnny Huang } 125969d5fd8fSJohnny Huang } 1260bb34a7bfSJohnny Huang if (pass == 0) { 1261bb34a7bfSJohnny Huang printf("address: %08x, data: %08x, buffer: %08x, mask: %08x\n", 12625010032bSJohnny Huang i, data[i], conf[i], conf_ignore[i]); 1263bb34a7bfSJohnny Huang break; 1264bb34a7bfSJohnny Huang } 1265a6d0d645SJohnny Huang } 1266a6d0d645SJohnny Huang 1267de6fbf1cSJohnny Huang otp_soak(0); 126869d5fd8fSJohnny Huang if (!pass) 12692a856b9aSJohnny Huang return OTP_FAILURE; 1270a6d0d645SJohnny Huang 12712a856b9aSJohnny Huang return OTP_SUCCESS; 127269d5fd8fSJohnny Huang } 127369d5fd8fSJohnny Huang 1274eda10d61SJohnny Huang static int otp_strap_bit_confirm(struct otpstrap_status *otpstrap, int offset, int ibit, int bit, int pbit, int rpbit) 1275eda10d61SJohnny Huang { 12769901d43aSJohnny Huang int prog_flag = 0; 12779901d43aSJohnny Huang 12789901d43aSJohnny Huang // ignore this bit 12799901d43aSJohnny Huang if (ibit == 1) 1280eda10d61SJohnny Huang return OTP_SUCCESS; 1281eda10d61SJohnny Huang printf("OTPSTRAP[%X]:\n", offset); 12829901d43aSJohnny Huang 1283eda10d61SJohnny Huang if (bit == otpstrap->value) { 12849901d43aSJohnny Huang if (!pbit && !rpbit) { 1285eda10d61SJohnny Huang printf(" The value is same as before, skip it.\n"); 1286eda10d61SJohnny Huang return OTP_PROG_SKIP; 1287eda10d61SJohnny Huang } 12889901d43aSJohnny Huang printf(" The value is same as before.\n"); 12899901d43aSJohnny Huang } else { 12909901d43aSJohnny Huang prog_flag = 1; 12919901d43aSJohnny Huang } 12929901d43aSJohnny Huang if (otpstrap->protected == 1 && prog_flag) { 1293eda10d61SJohnny Huang printf(" This bit is protected and is not writable\n"); 1294eda10d61SJohnny Huang return OTP_FAILURE; 1295eda10d61SJohnny Huang } 12969901d43aSJohnny Huang if (otpstrap->remain_times == 0 && prog_flag) { 1297eda10d61SJohnny Huang printf(" This bit is no remaining times to write.\n"); 1298eda10d61SJohnny Huang return OTP_FAILURE; 1299eda10d61SJohnny Huang } 13009901d43aSJohnny Huang if (pbit == 1) 1301eda10d61SJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 13029901d43aSJohnny Huang if (rpbit == 1 && info_cb.version != OTP_AST2600A0) 1303eda10d61SJohnny Huang printf(" The relative register will be protected.\n"); 13049901d43aSJohnny Huang if (prog_flag) 1305eda10d61SJohnny 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); 13069901d43aSJohnny Huang 1307eda10d61SJohnny Huang return OTP_SUCCESS; 1308eda10d61SJohnny Huang } 1309eda10d61SJohnny Huang 13105010032bSJohnny Huang static int otp_strap_image_confirm(struct otp_image_layout *image_layout) 131169d5fd8fSJohnny Huang { 131269d5fd8fSJohnny Huang int i; 1313a219f6deSJohnny Huang u32 *strap; 1314a219f6deSJohnny Huang u32 *strap_ignore; 1315a219f6deSJohnny Huang u32 *strap_reg_protect; 1316a219f6deSJohnny Huang u32 *strap_pro; 1317eda10d61SJohnny Huang int bit, pbit, ibit, rpbit; 131869d5fd8fSJohnny Huang int fail = 0; 1319eda10d61SJohnny Huang int ret; 132066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 132169d5fd8fSJohnny Huang 1322a219f6deSJohnny Huang strap = (u32 *)image_layout->strap; 1323a219f6deSJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1324a219f6deSJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1325a219f6deSJohnny Huang strap_reg_protect = (u32 *)image_layout->strap_reg_pro; 13265010032bSJohnny Huang 1327541eb887SJohnny Huang otp_strap_status(otpstrap); 132869d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 132969d5fd8fSJohnny Huang if (i < 32) { 13305010032bSJohnny Huang bit = (strap[0] >> i) & 0x1; 1331eda10d61SJohnny Huang ibit = (strap_ignore[0] >> i) & 0x1; 13325010032bSJohnny Huang pbit = (strap_pro[0] >> i) & 0x1; 133369d5fd8fSJohnny Huang } else { 13345010032bSJohnny Huang bit = (strap[1] >> (i - 32)) & 0x1; 1335eda10d61SJohnny Huang ibit = (strap_ignore[1] >> (i - 32)) & 0x1; 13365010032bSJohnny Huang pbit = (strap_pro[1] >> (i - 32)) & 0x1; 13375010032bSJohnny Huang } 13385010032bSJohnny Huang 13395010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 1340a219f6deSJohnny Huang if (i < 32) 13415010032bSJohnny Huang rpbit = (strap_reg_protect[0] >> i) & 0x1; 1342a219f6deSJohnny Huang else 13435010032bSJohnny Huang rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1; 13445010032bSJohnny Huang } else { 13455010032bSJohnny Huang rpbit = 0; 134669d5fd8fSJohnny Huang } 1347eda10d61SJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[i], i, ibit, bit, pbit, rpbit); 1348eda10d61SJohnny Huang 1349eda10d61SJohnny Huang if (ret == OTP_FAILURE) 135069d5fd8fSJohnny Huang fail = 1; 135169d5fd8fSJohnny Huang } 135269d5fd8fSJohnny Huang if (fail == 1) 1353a6af4a17SJohnny Huang return OTP_FAILURE; 13549901d43aSJohnny Huang else 1355eda10d61SJohnny Huang return OTP_SUCCESS; 135669d5fd8fSJohnny Huang } 135769d5fd8fSJohnny Huang 13582a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 135969d5fd8fSJohnny Huang { 136069d5fd8fSJohnny Huang int i, j; 1361de6b0cc4SJohnny Huang int remains; 136266f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 136369d5fd8fSJohnny Huang 13642a856b9aSJohnny Huang if (start < 0 || start > 64) 13652a856b9aSJohnny Huang return OTP_USAGE; 13662a856b9aSJohnny Huang 13672a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 13682a856b9aSJohnny Huang return OTP_USAGE; 13692a856b9aSJohnny Huang 1370541eb887SJohnny Huang otp_strap_status(otpstrap); 137169d5fd8fSJohnny Huang 1372de6b0cc4SJohnny Huang if (info_cb.version == OTP_AST2600A0) { 1373de6b0cc4SJohnny Huang remains = 7; 137407baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1375de6b0cc4SJohnny Huang } else { 1376de6b0cc4SJohnny Huang remains = 6; 1377de6b0cc4SJohnny Huang printf("BIT(hex) Value Option Reg_Protect Status\n"); 1378de6b0cc4SJohnny Huang } 1379de6b0cc4SJohnny Huang printf("______________________________________________________________________________\n"); 1380737ed20bSJohnny Huang 1381cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 138207baa4e8SJohnny Huang printf("0x%-8X", i); 1383737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1384de6b0cc4SJohnny Huang for (j = 0; j < remains; j++) 1385737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1386737ed20bSJohnny Huang printf(" "); 1387a219f6deSJohnny Huang if (info_cb.version != OTP_AST2600A0) 1388de6b0cc4SJohnny Huang printf("%d ", otpstrap[i].reg_protected); 138969d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1390737ed20bSJohnny Huang printf("protected and not writable"); 139169d5fd8fSJohnny Huang } else { 1392737ed20bSJohnny Huang printf("not protected "); 1393a219f6deSJohnny Huang if (otpstrap[i].remain_times == 0) 1394737ed20bSJohnny Huang printf("and no remaining times to write."); 1395a219f6deSJohnny Huang else 1396737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 139769d5fd8fSJohnny Huang } 1398737ed20bSJohnny Huang printf("\n"); 139969d5fd8fSJohnny Huang } 14002a856b9aSJohnny Huang 14012a856b9aSJohnny Huang return OTP_SUCCESS; 140269d5fd8fSJohnny Huang } 140369d5fd8fSJohnny Huang 14048848d5dcSJohnny Huang static int otp_prog_strap_bit(int bit_offset, int value) 14058848d5dcSJohnny Huang { 14068848d5dcSJohnny Huang struct otpstrap_status otpstrap[64]; 1407a219f6deSJohnny Huang u32 prog_address; 14088848d5dcSJohnny Huang int offset; 14098848d5dcSJohnny Huang int ret; 14108848d5dcSJohnny Huang 14118848d5dcSJohnny Huang otp_strap_status(otpstrap); 14128848d5dcSJohnny Huang 14138848d5dcSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0); 14148848d5dcSJohnny Huang 1415a219f6deSJohnny Huang if (ret != OTP_SUCCESS) 14168848d5dcSJohnny Huang return ret; 14178848d5dcSJohnny Huang 14188848d5dcSJohnny Huang prog_address = 0x800; 14198848d5dcSJohnny Huang if (bit_offset < 32) { 14208848d5dcSJohnny Huang offset = bit_offset; 14218848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) / 8) * 0x200; 14228848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 16) % 8) * 0x2; 14238848d5dcSJohnny Huang 14248848d5dcSJohnny Huang } else { 14258848d5dcSJohnny Huang offset = (bit_offset - 32); 14268848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) / 8) * 0x200; 14278848d5dcSJohnny Huang prog_address |= ((otpstrap[bit_offset].writeable_option * 2 + 17) % 8) * 0x2; 14288848d5dcSJohnny Huang } 14298848d5dcSJohnny Huang 143083655e91SJohnny Huang return otp_prog_bit(1, prog_address, offset); 14318848d5dcSJohnny Huang } 14328848d5dcSJohnny Huang 14335010032bSJohnny Huang static int otp_prog_strap(struct otp_image_layout *image_layout) 143469d5fd8fSJohnny Huang { 1435a219f6deSJohnny Huang u32 *strap; 1436a219f6deSJohnny Huang u32 *strap_ignore; 1437a219f6deSJohnny Huang u32 *strap_pro; 1438a219f6deSJohnny Huang u32 *strap_reg_protect; 1439a219f6deSJohnny Huang u32 prog_address; 144083655e91SJohnny Huang int i; 1441eda10d61SJohnny Huang int bit, pbit, ibit, offset, rpbit; 144269d5fd8fSJohnny Huang int fail = 0; 144383655e91SJohnny Huang int ret; 14449901d43aSJohnny Huang int prog_flag = 0; 144566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 144669d5fd8fSJohnny Huang 1447a219f6deSJohnny Huang strap = (u32 *)image_layout->strap; 1448a219f6deSJohnny Huang strap_pro = (u32 *)image_layout->strap_pro; 1449a219f6deSJohnny Huang strap_ignore = (u32 *)image_layout->strap_ignore; 1450a219f6deSJohnny Huang strap_reg_protect = (u32 *)image_layout->strap_reg_pro; 14515010032bSJohnny Huang 14527f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 1453541eb887SJohnny Huang otp_strap_status(otpstrap); 145469d5fd8fSJohnny Huang 14557f795e57SJohnny Huang printf("Check writable...\n"); 14565010032bSJohnny Huang if (otp_strap_image_confirm(image_layout) == OTP_FAILURE) { 14577f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 14587f795e57SJohnny Huang return OTP_FAILURE; 14597f795e57SJohnny Huang } 14607e22f42dSJohnny Huang 146169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 146269d5fd8fSJohnny Huang prog_address = 0x800; 146369d5fd8fSJohnny Huang if (i < 32) { 146469d5fd8fSJohnny Huang offset = i; 14655010032bSJohnny Huang bit = (strap[0] >> offset) & 0x1; 1466eda10d61SJohnny Huang ibit = (strap_ignore[0] >> offset) & 0x1; 14675010032bSJohnny Huang pbit = (strap_pro[0] >> offset) & 0x1; 146869d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 146969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 147069d5fd8fSJohnny Huang 147169d5fd8fSJohnny Huang } else { 147269d5fd8fSJohnny Huang offset = (i - 32); 14735010032bSJohnny Huang bit = (strap[1] >> offset) & 0x1; 1474eda10d61SJohnny Huang ibit = (strap_ignore[1] >> offset) & 0x1; 14755010032bSJohnny Huang pbit = (strap_pro[1] >> offset) & 0x1; 147669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 147769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 147869d5fd8fSJohnny Huang } 14795010032bSJohnny Huang if (info_cb.version != OTP_AST2600A0) { 1480a219f6deSJohnny Huang if (i < 32) 14815010032bSJohnny Huang rpbit = (strap_reg_protect[0] >> i) & 0x1; 1482a219f6deSJohnny Huang else 14835010032bSJohnny Huang rpbit = (strap_reg_protect[1] >> (i - 32)) & 0x1; 14845010032bSJohnny Huang } else { 14855010032bSJohnny Huang rpbit = 0; 14865010032bSJohnny Huang } 148769d5fd8fSJohnny Huang 1488a219f6deSJohnny Huang if (ibit == 1) 148969d5fd8fSJohnny Huang continue; 14909901d43aSJohnny Huang if (bit == otpstrap[i].value) 14919901d43aSJohnny Huang prog_flag = 0; 14929901d43aSJohnny Huang else 14939901d43aSJohnny Huang prog_flag = 1; 14949901d43aSJohnny Huang 14959901d43aSJohnny Huang if (otpstrap[i].protected == 1 && prog_flag) { 149669d5fd8fSJohnny Huang fail = 1; 149769d5fd8fSJohnny Huang continue; 149869d5fd8fSJohnny Huang } 14999901d43aSJohnny Huang if (otpstrap[i].remain_times == 0 && prog_flag) { 150069d5fd8fSJohnny Huang fail = 1; 150169d5fd8fSJohnny Huang continue; 150269d5fd8fSJohnny Huang } 15037e22f42dSJohnny Huang 15049901d43aSJohnny Huang if (prog_flag) { 150583655e91SJohnny Huang ret = otp_prog_bit(1, prog_address, offset); 1506*794e27ecSJohnny Huang if (ret) 15072a856b9aSJohnny Huang return OTP_FAILURE; 15089901d43aSJohnny Huang } 150969d5fd8fSJohnny Huang 15105010032bSJohnny Huang if (rpbit == 1 && info_cb.version != OTP_AST2600A0) { 151169d5fd8fSJohnny Huang prog_address = 0x800; 151269d5fd8fSJohnny Huang if (i < 32) 15135010032bSJohnny Huang prog_address |= 0x608; 151469d5fd8fSJohnny Huang else 15155010032bSJohnny Huang prog_address |= 0x60a; 15167e22f42dSJohnny Huang 151783655e91SJohnny Huang ret = otp_prog_bit(1, prog_address, offset); 1518*794e27ecSJohnny Huang if (ret) 15192a856b9aSJohnny Huang return OTP_FAILURE; 15205010032bSJohnny Huang } 15215010032bSJohnny Huang 15225010032bSJohnny Huang if (pbit != 0) { 15235010032bSJohnny Huang prog_address = 0x800; 15245010032bSJohnny Huang if (i < 32) 15255010032bSJohnny Huang prog_address |= 0x60c; 15265010032bSJohnny Huang else 15275010032bSJohnny Huang prog_address |= 0x60e; 15285010032bSJohnny Huang 152983655e91SJohnny Huang ret = otp_prog_bit(1, prog_address, offset); 1530*794e27ecSJohnny Huang if (ret) 15315010032bSJohnny Huang return OTP_FAILURE; 15325010032bSJohnny Huang } 153369d5fd8fSJohnny Huang } 1534de6fbf1cSJohnny Huang otp_soak(0); 153569d5fd8fSJohnny Huang if (fail == 1) 15362a856b9aSJohnny Huang return OTP_FAILURE; 15372a856b9aSJohnny Huang return OTP_SUCCESS; 153869d5fd8fSJohnny Huang } 153969d5fd8fSJohnny Huang 15405010032bSJohnny Huang static int otp_prog_data(struct otp_image_layout *image_layout) 15414c1c9b35SJohnny Huang { 154254552c69SJohnny Huang int i; 154354552c69SJohnny Huang int ret; 15445010032bSJohnny Huang int data_dw; 1545a219f6deSJohnny Huang u32 data[2048]; 1546a219f6deSJohnny Huang u32 *buf; 1547a219f6deSJohnny Huang u32 *buf_ignore; 1548a219f6deSJohnny Huang u32 data_masked; 1549a219f6deSJohnny Huang u32 buf_masked; 15504c1c9b35SJohnny Huang 1551a219f6deSJohnny Huang buf = (u32 *)image_layout->data; 1552a219f6deSJohnny Huang buf_ignore = (u32 *)image_layout->data_ignore; 15535010032bSJohnny Huang 15545010032bSJohnny Huang data_dw = image_layout->data_length / 4; 15555010032bSJohnny Huang 15564c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 15574c1c9b35SJohnny Huang 1558a219f6deSJohnny Huang for (i = 0; i < data_dw - 2 ; i += 2) 1559d90825e2SJohnny Huang otp_read_data(i, &data[i]); 1560d90825e2SJohnny Huang 15614c1c9b35SJohnny Huang printf("Check writable...\n"); 156254552c69SJohnny Huang // ignore last two dw, the last two dw is used for slt otp write check. 15635010032bSJohnny Huang for (i = 0; i < data_dw - 2; i++) { 1564696656c6SJohnny Huang data_masked = data[i] & ~buf_ignore[i]; 1565696656c6SJohnny Huang buf_masked = buf[i] & ~buf_ignore[i]; 156654552c69SJohnny Huang if (data_masked == buf_masked) 15674c1c9b35SJohnny Huang continue; 1568d90825e2SJohnny Huang if (i % 2 == 0) { 156954552c69SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 15704c1c9b35SJohnny Huang continue; 15714c1c9b35SJohnny Huang } else { 15724c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1573d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 15744c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1575696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 15762a856b9aSJohnny Huang return OTP_FAILURE; 157769d5fd8fSJohnny Huang } 1578d90825e2SJohnny Huang } else { 157954552c69SJohnny Huang if ((data_masked & buf_masked) == buf_masked) { 1580d90825e2SJohnny Huang continue; 1581d90825e2SJohnny Huang } else { 1582d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1583d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1584d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1585696656c6SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_ignore[i]); 15862a856b9aSJohnny Huang return OTP_FAILURE; 1587d90825e2SJohnny Huang } 1588d90825e2SJohnny Huang } 1589d90825e2SJohnny Huang } 159069d5fd8fSJohnny Huang 1591d90825e2SJohnny Huang printf("Start Programing...\n"); 1592d90825e2SJohnny Huang 159354552c69SJohnny Huang // programing ecc region first 159454552c69SJohnny Huang for (i = 1792; i < 2046; i += 2) { 1595696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 159654552c69SJohnny Huang if (ret != OTP_SUCCESS) { 159754552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1598696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 159954552c69SJohnny Huang return ret; 1600d90825e2SJohnny Huang } 1601d90825e2SJohnny Huang } 1602d90825e2SJohnny Huang 160354552c69SJohnny Huang for (i = 0; i < 1792; i += 2) { 1604696656c6SJohnny Huang ret = otp_prog_verify_2dw(&data[i], &buf[i], &buf_ignore[i], i); 160554552c69SJohnny Huang if (ret != OTP_SUCCESS) { 160654552c69SJohnny Huang printf("address: %08x, data: %08x %08x, buffer: %08x %08x, mask: %08x %08x\n", 1607696656c6SJohnny Huang i, data[i], data[i + 1], buf[i], buf[i + 1], buf_ignore[i], buf_ignore[i + 1]); 160854552c69SJohnny Huang return ret; 1609d90825e2SJohnny Huang } 1610de6fbf1cSJohnny Huang } 1611de6fbf1cSJohnny Huang otp_soak(0); 16122a856b9aSJohnny Huang return OTP_SUCCESS; 1613d90825e2SJohnny Huang } 1614d90825e2SJohnny Huang 1615a219f6deSJohnny Huang static int otp_image_verify(u8 *src_buf, u32 length, u8 *digest_buf) 1616696656c6SJohnny Huang { 1617696656c6SJohnny Huang sha256_context ctx; 1618696656c6SJohnny Huang u8 digest_ret[CHECKSUM_LEN]; 1619696656c6SJohnny Huang 1620696656c6SJohnny Huang sha256_starts(&ctx); 1621696656c6SJohnny Huang sha256_update(&ctx, src_buf, length); 1622696656c6SJohnny Huang sha256_finish(&ctx, digest_ret); 1623696656c6SJohnny Huang 1624696656c6SJohnny Huang if (!memcmp(digest_buf, digest_ret, CHECKSUM_LEN)) 1625696656c6SJohnny Huang return 0; 1626696656c6SJohnny Huang return -1; 1627696656c6SJohnny Huang } 1628696656c6SJohnny Huang 1629de6b0cc4SJohnny Huang static int do_otp_prog(int addr, int nconfirm) 163069d5fd8fSJohnny Huang { 163169d5fd8fSJohnny Huang int ret; 16329a4fe690SJohnny Huang int image_version = 0; 1633696656c6SJohnny Huang struct otp_header *otp_header; 1634696656c6SJohnny Huang struct otp_image_layout image_layout; 1635696656c6SJohnny Huang int image_size; 1636a219f6deSJohnny Huang u8 *buf; 1637a219f6deSJohnny Huang u8 *checksum; 163869d5fd8fSJohnny Huang 1639696656c6SJohnny Huang otp_header = map_physmem(addr, sizeof(struct otp_header), MAP_WRBACK); 1640696656c6SJohnny Huang if (!otp_header) { 164169d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16422a856b9aSJohnny Huang return OTP_FAILURE; 164369d5fd8fSJohnny Huang } 1644d90825e2SJohnny Huang 1645696656c6SJohnny Huang image_size = OTP_IMAGE_SIZE(otp_header->image_info); 1646696656c6SJohnny Huang unmap_physmem(otp_header, MAP_WRBACK); 1647696656c6SJohnny Huang 1648696656c6SJohnny Huang buf = map_physmem(addr, image_size + CHECKSUM_LEN, MAP_WRBACK); 1649696656c6SJohnny Huang 1650696656c6SJohnny Huang if (!buf) { 1651696656c6SJohnny Huang puts("Failed to map physical memory\n"); 1652696656c6SJohnny Huang return OTP_FAILURE; 1653696656c6SJohnny Huang } 1654696656c6SJohnny Huang otp_header = (struct otp_header *)buf; 1655696656c6SJohnny Huang checksum = buf + otp_header->checksum_offset; 1656696656c6SJohnny Huang 1657696656c6SJohnny Huang if (strcmp(OTP_MAGIC, (char *)otp_header->otp_magic) != 0) { 1658696656c6SJohnny Huang puts("Image is invalid\n"); 1659696656c6SJohnny Huang return OTP_FAILURE; 1660696656c6SJohnny Huang } 1661696656c6SJohnny Huang 16625010032bSJohnny Huang image_layout.data_length = (int)(OTP_REGION_SIZE(otp_header->data_info) / 2); 16635010032bSJohnny Huang image_layout.data = buf + OTP_REGION_OFFSET(otp_header->data_info); 16645010032bSJohnny Huang image_layout.data_ignore = image_layout.data + image_layout.data_length; 16655010032bSJohnny Huang 16665010032bSJohnny Huang image_layout.conf_length = (int)(OTP_REGION_SIZE(otp_header->config_info) / 2); 1667696656c6SJohnny Huang image_layout.conf = buf + OTP_REGION_OFFSET(otp_header->config_info); 16685010032bSJohnny Huang image_layout.conf_ignore = image_layout.conf + image_layout.conf_length; 1669696656c6SJohnny Huang 1670696656c6SJohnny Huang image_layout.strap = buf + OTP_REGION_OFFSET(otp_header->strap_info); 1671696656c6SJohnny Huang 1672696656c6SJohnny Huang if (!strcmp("A0", (char *)otp_header->otp_version)) { 1673696656c6SJohnny Huang image_version = OTP_AST2600A0; 16745010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 3); 16755010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + image_layout.strap_length; 16765010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 2 * image_layout.strap_length; 1677696656c6SJohnny Huang } else if (!strcmp("A1", (char *)otp_header->otp_version)) { 1678696656c6SJohnny Huang image_version = OTP_AST2600A1; 16795010032bSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4); 16805010032bSJohnny Huang image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length; 16815010032bSJohnny Huang image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length; 16825010032bSJohnny Huang image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length; 16835fdde29fSJohnny Huang } else if (!strcmp("A2", (char *)otp_header->otp_version)) { 16845fdde29fSJohnny Huang image_version = OTP_AST2600A2; 16855fdde29fSJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4); 16865fdde29fSJohnny Huang image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length; 16875fdde29fSJohnny Huang image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length; 16885fdde29fSJohnny Huang image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length; 168964b66712SJohnny Huang } else if (!strcmp("A3", (char *)otp_header->otp_version)) { 169064b66712SJohnny Huang image_version = OTP_AST2600A3; 169164b66712SJohnny Huang image_layout.strap_length = (int)(OTP_REGION_SIZE(otp_header->strap_info) / 4); 169264b66712SJohnny Huang image_layout.strap_reg_pro = image_layout.strap + image_layout.strap_length; 169364b66712SJohnny Huang image_layout.strap_pro = image_layout.strap + 2 * image_layout.strap_length; 169464b66712SJohnny Huang image_layout.strap_ignore = image_layout.strap + 3 * image_layout.strap_length; 1695696656c6SJohnny Huang } else { 1696696656c6SJohnny Huang puts("Version is not supported\n"); 1697696656c6SJohnny Huang return OTP_FAILURE; 1698696656c6SJohnny Huang } 1699696656c6SJohnny Huang 17009a4fe690SJohnny Huang if (image_version != info_cb.version) { 17019a4fe690SJohnny Huang puts("Version is not match\n"); 17029a4fe690SJohnny Huang return OTP_FAILURE; 17039a4fe690SJohnny Huang } 17049a4fe690SJohnny Huang 1705696656c6SJohnny Huang if (otp_image_verify(buf, image_size, checksum)) { 1706696656c6SJohnny Huang puts("checksum is invalid\n"); 1707696656c6SJohnny Huang return OTP_FAILURE; 1708d90825e2SJohnny Huang } 17097332532cSJohnny Huang 171069d5fd8fSJohnny Huang if (!nconfirm) { 1711696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 17127f795e57SJohnny Huang printf("\nOTP data region :\n"); 1713696656c6SJohnny Huang if (otp_print_data_info(&image_layout) < 0) { 171469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 17152a856b9aSJohnny Huang return OTP_FAILURE; 171669d5fd8fSJohnny Huang } 171769d5fd8fSJohnny Huang } 1718696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 17197332532cSJohnny Huang printf("\nOTP strap region :\n"); 17205010032bSJohnny Huang if (otp_print_strap_image(&image_layout) < 0) { 17217332532cSJohnny Huang printf("OTP strap error, please check.\n"); 17227332532cSJohnny Huang return OTP_FAILURE; 17237332532cSJohnny Huang } 17247332532cSJohnny Huang } 1725696656c6SJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 17267332532cSJohnny Huang printf("\nOTP configuration region :\n"); 1727696656c6SJohnny Huang if (otp_print_conf_image(&image_layout) < 0) { 17287332532cSJohnny Huang printf("OTP config error, please check.\n"); 17297332532cSJohnny Huang return OTP_FAILURE; 17307332532cSJohnny Huang } 17317332532cSJohnny Huang } 17327332532cSJohnny Huang 173369d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 173469d5fd8fSJohnny Huang if (!confirm_yesno()) { 173569d5fd8fSJohnny Huang printf(" Aborting\n"); 17362a856b9aSJohnny Huang return OTP_FAILURE; 173769d5fd8fSJohnny Huang } 173869d5fd8fSJohnny Huang } 17397332532cSJohnny Huang 17405010032bSJohnny Huang if (otp_header->image_info & OTP_INC_DATA) { 17415010032bSJohnny Huang printf("programing data region ...\n"); 17425010032bSJohnny Huang ret = otp_prog_data(&image_layout); 17435010032bSJohnny Huang if (ret != 0) { 17445010032bSJohnny Huang printf("Error\n"); 17455010032bSJohnny Huang return ret; 17465010032bSJohnny Huang } 1747a219f6deSJohnny Huang printf("Done\n"); 17485010032bSJohnny Huang } 17495010032bSJohnny Huang if (otp_header->image_info & OTP_INC_STRAP) { 17505010032bSJohnny Huang printf("programing strap region ...\n"); 17515010032bSJohnny Huang ret = otp_prog_strap(&image_layout); 17525010032bSJohnny Huang if (ret != 0) { 17535010032bSJohnny Huang printf("Error\n"); 17545010032bSJohnny Huang return ret; 17555010032bSJohnny Huang } 1756a219f6deSJohnny Huang printf("Done\n"); 17575010032bSJohnny Huang } 17585010032bSJohnny Huang if (otp_header->image_info & OTP_INC_CONFIG) { 17595010032bSJohnny Huang printf("programing configuration region ...\n"); 17605010032bSJohnny Huang ret = otp_prog_conf(&image_layout); 17615010032bSJohnny Huang if (ret != 0) { 17625010032bSJohnny Huang printf("Error\n"); 17635010032bSJohnny Huang return ret; 17645010032bSJohnny Huang } 17655010032bSJohnny Huang printf("Done\n"); 17665010032bSJohnny Huang } 1767cd1610b4SJohnny Huang 17687332532cSJohnny Huang return OTP_SUCCESS; 17692a856b9aSJohnny Huang } 17702a856b9aSJohnny Huang 17712a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1772cd1610b4SJohnny Huang { 1773a219f6deSJohnny Huang u32 read[2]; 1774a219f6deSJohnny Huang u32 prog_address = 0; 177566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1776cd1610b4SJohnny Huang int otp_bit; 177783655e91SJohnny Huang int ret = 0; 1778cd1610b4SJohnny Huang 1779dacbba92SJohnny Huang otp_soak(0); 1780cd1610b4SJohnny Huang switch (mode) { 1781a6d0d645SJohnny Huang case OTP_REGION_CONF: 1782a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1783cd1610b4SJohnny Huang prog_address = 0x800; 1784cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1785cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1786a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1787cd1610b4SJohnny Huang if (otp_bit == value) { 1788a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1789cd1610b4SJohnny Huang printf("No need to program\n"); 17902a856b9aSJohnny Huang return OTP_SUCCESS; 1791cd1610b4SJohnny Huang } 1792cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1793a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1794cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17952a856b9aSJohnny Huang return OTP_FAILURE; 1796cd1610b4SJohnny Huang } 1797a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1798cd1610b4SJohnny Huang break; 1799a6d0d645SJohnny Huang case OTP_REGION_DATA: 1800cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1801cd1610b4SJohnny Huang 1802cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1803a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1804a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1805643b9cfdSJohnny Huang 1806643b9cfdSJohnny Huang if (otp_bit == 1 && value == 0) { 1807643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1808643b9cfdSJohnny Huang printf("OTP is programed, which can't be cleaned\n"); 1809643b9cfdSJohnny Huang return OTP_FAILURE; 1810643b9cfdSJohnny Huang } 1811cd1610b4SJohnny Huang } else { 1812a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1813a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1814643b9cfdSJohnny Huang 1815643b9cfdSJohnny Huang if (otp_bit == 0 && value == 1) { 1816643b9cfdSJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1817643b9cfdSJohnny Huang printf("OTP is programed, which can't be writen\n"); 1818643b9cfdSJohnny Huang return OTP_FAILURE; 1819643b9cfdSJohnny Huang } 1820cd1610b4SJohnny Huang } 1821cd1610b4SJohnny Huang if (otp_bit == value) { 1822a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1823cd1610b4SJohnny Huang printf("No need to program\n"); 18242a856b9aSJohnny Huang return OTP_SUCCESS; 1825cd1610b4SJohnny Huang } 1826643b9cfdSJohnny Huang 1827a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1828cd1610b4SJohnny Huang break; 1829a6d0d645SJohnny Huang case OTP_REGION_STRAP: 18308848d5dcSJohnny Huang otp_strap_status(otpstrap); 18318848d5dcSJohnny Huang otp_print_strap(bit_offset, 1); 18328848d5dcSJohnny Huang ret = otp_strap_bit_confirm(&otpstrap[bit_offset], bit_offset, 0, value, 0, 0); 18338848d5dcSJohnny Huang if (ret == OTP_FAILURE) 18348848d5dcSJohnny Huang return OTP_FAILURE; 18358848d5dcSJohnny Huang else if (ret == OTP_PROG_SKIP) 18368848d5dcSJohnny Huang return OTP_SUCCESS; 1837a6af4a17SJohnny Huang 1838cd1610b4SJohnny Huang break; 1839cd1610b4SJohnny Huang } 1840cd1610b4SJohnny Huang 1841cd1610b4SJohnny Huang if (!nconfirm) { 1842cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1843cd1610b4SJohnny Huang if (!confirm_yesno()) { 1844cd1610b4SJohnny Huang printf(" Aborting\n"); 18452a856b9aSJohnny Huang return OTP_FAILURE; 1846cd1610b4SJohnny Huang } 1847cd1610b4SJohnny Huang } 1848cd1610b4SJohnny Huang 1849cd1610b4SJohnny Huang switch (mode) { 1850a6d0d645SJohnny Huang case OTP_REGION_STRAP: 185183655e91SJohnny Huang ret = otp_prog_strap_bit(bit_offset, value); 185283655e91SJohnny Huang break; 1853a6d0d645SJohnny Huang case OTP_REGION_CONF: 1854a6d0d645SJohnny Huang case OTP_REGION_DATA: 185583655e91SJohnny Huang ret = otp_prog_bit(value, prog_address, bit_offset); 1856de6fbf1cSJohnny Huang break; 1857de6fbf1cSJohnny Huang } 1858de6fbf1cSJohnny Huang otp_soak(0); 185983655e91SJohnny Huang if (ret) { 1860*794e27ecSJohnny Huang printf("OTP cannot be programed\n"); 1861*794e27ecSJohnny Huang printf("FAILURE\n"); 1862*794e27ecSJohnny Huang return OTP_FAILURE; 1863*794e27ecSJohnny Huang } 1864*794e27ecSJohnny Huang 18659009c25dSJohnny Huang printf("SUCCESS\n"); 18662a856b9aSJohnny Huang return OTP_SUCCESS; 1867a219f6deSJohnny Huang } 1868a219f6deSJohnny Huang 1869*794e27ecSJohnny Huang static int otp_update_rid(u32 update_num, int force) 1870*794e27ecSJohnny Huang { 1871*794e27ecSJohnny Huang u32 otp_rid[2]; 1872*794e27ecSJohnny Huang int rid_num = 0; 1873*794e27ecSJohnny Huang int bit_offset; 1874*794e27ecSJohnny Huang int dw_offset; 1875*794e27ecSJohnny Huang int i; 1876*794e27ecSJohnny Huang int ret; 1877*794e27ecSJohnny Huang 1878*794e27ecSJohnny Huang otp_read_config(10, &otp_rid[0]); 1879*794e27ecSJohnny Huang otp_read_config(11, &otp_rid[1]); 1880*794e27ecSJohnny Huang 1881*794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 1882*794e27ecSJohnny Huang 1883*794e27ecSJohnny Huang if (rid_num < 0) { 1884*794e27ecSJohnny Huang printf("Currennt OTP revision ID cannot handle by this command,\n" 1885*794e27ecSJohnny Huang "plase use 'otp pb' command to update it manually\n"); 1886*794e27ecSJohnny Huang otp_print_revid(otp_rid); 18879009c25dSJohnny Huang return OTP_FAILURE; 18889009c25dSJohnny Huang } 1889cd1610b4SJohnny Huang 1890*794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 1891*794e27ecSJohnny Huang otp_print_revid(otp_rid); 1892*794e27ecSJohnny Huang printf("input update number: 0x%x\n", update_num); 1893*794e27ecSJohnny Huang 1894*794e27ecSJohnny Huang if (rid_num >= update_num) { 1895*794e27ecSJohnny Huang printf("OTP rev_id is bigger than 0x%x\n", update_num); 1896*794e27ecSJohnny Huang printf("Skip\n"); 1897*794e27ecSJohnny Huang return OTP_FAILURE; 1898*794e27ecSJohnny Huang } 1899*794e27ecSJohnny Huang 1900*794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 1901*794e27ecSJohnny Huang if (i < 32) { 1902*794e27ecSJohnny Huang dw_offset = 0xa; 1903*794e27ecSJohnny Huang bit_offset = i; 1904*794e27ecSJohnny Huang } else { 1905*794e27ecSJohnny Huang dw_offset = 0xb; 1906*794e27ecSJohnny Huang bit_offset = i - 32; 1907*794e27ecSJohnny Huang } 1908*794e27ecSJohnny Huang printf("OTPCFG%X[%d]", dw_offset, bit_offset); 1909*794e27ecSJohnny Huang if (i + 1 != update_num) 1910*794e27ecSJohnny Huang printf(", "); 1911*794e27ecSJohnny Huang } 1912*794e27ecSJohnny Huang 1913*794e27ecSJohnny Huang printf(" will be programmed\n"); 1914*794e27ecSJohnny Huang if (force == 0) { 1915*794e27ecSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1916*794e27ecSJohnny Huang if (!confirm_yesno()) { 1917*794e27ecSJohnny Huang printf(" Aborting\n"); 1918*794e27ecSJohnny Huang return OTP_FAILURE; 1919*794e27ecSJohnny Huang } 1920*794e27ecSJohnny Huang } 1921*794e27ecSJohnny Huang 1922*794e27ecSJohnny Huang ret = 0; 1923*794e27ecSJohnny Huang for (i = rid_num; i < update_num; i++) { 1924*794e27ecSJohnny Huang if (i < 32) { 1925*794e27ecSJohnny Huang dw_offset = 0xa04; 1926*794e27ecSJohnny Huang bit_offset = i; 1927*794e27ecSJohnny Huang } else { 1928*794e27ecSJohnny Huang dw_offset = 0xa06; 1929*794e27ecSJohnny Huang bit_offset = i - 32; 1930*794e27ecSJohnny Huang } 1931*794e27ecSJohnny Huang if (otp_prog_bit(1, dw_offset, bit_offset)) { 1932*794e27ecSJohnny Huang printf("OTPCFG%X[%d] programming failed\n", dw_offset, bit_offset); 1933*794e27ecSJohnny Huang ret = OTP_FAILURE; 1934*794e27ecSJohnny Huang break; 1935*794e27ecSJohnny Huang } 1936*794e27ecSJohnny Huang } 1937*794e27ecSJohnny Huang 1938*794e27ecSJohnny Huang otp_read_config(10, &otp_rid[0]); 1939*794e27ecSJohnny Huang otp_read_config(11, &otp_rid[1]); 1940*794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 1941*794e27ecSJohnny Huang if (rid_num >= 0) 1942*794e27ecSJohnny Huang printf("OTP revision ID: 0x%x\n", rid_num); 1943*794e27ecSJohnny Huang else 1944*794e27ecSJohnny Huang printf("OTP revision ID\n"); 1945*794e27ecSJohnny Huang otp_print_revid(otp_rid); 1946*794e27ecSJohnny Huang if (!ret) 1947*794e27ecSJohnny Huang printf("SUCCESS\n"); 1948*794e27ecSJohnny Huang else 1949*794e27ecSJohnny Huang printf("FAILED\n"); 1950*794e27ecSJohnny Huang return ret; 1951*794e27ecSJohnny Huang } 1952*794e27ecSJohnny Huang 19532a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 195469d5fd8fSJohnny Huang { 1955a219f6deSJohnny Huang u32 offset, count; 19562a856b9aSJohnny Huang int ret; 195769d5fd8fSJohnny Huang 19582a856b9aSJohnny Huang if (argc == 4) { 19592a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19602a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 19612a856b9aSJohnny Huang } else if (argc == 3) { 19622a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 19632a856b9aSJohnny Huang count = 1; 19642a856b9aSJohnny Huang } else { 196569d5fd8fSJohnny Huang return CMD_RET_USAGE; 196669d5fd8fSJohnny Huang } 196769d5fd8fSJohnny Huang 19682a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 19693d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19702a856b9aSJohnny Huang ret = otp_print_config(offset, count); 19712a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 19723d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19732a856b9aSJohnny Huang ret = otp_print_data(offset, count); 19742a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19753d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 19762a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 19772a856b9aSJohnny Huang } else { 19782a856b9aSJohnny Huang return CMD_RET_USAGE; 197969d5fd8fSJohnny Huang } 198069d5fd8fSJohnny Huang 19812a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19822a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19832a856b9aSJohnny Huang return CMD_RET_USAGE; 19842a856b9aSJohnny Huang } 19852a856b9aSJohnny Huang 19862a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19872a856b9aSJohnny Huang { 19882a856b9aSJohnny Huang phys_addr_t addr; 19892a856b9aSJohnny Huang int ret; 19902a856b9aSJohnny Huang 1991de6b0cc4SJohnny Huang if (argc == 3) { 1992ed071a2bSJohnny Huang if (strcmp(argv[1], "o")) 19932a856b9aSJohnny Huang return CMD_RET_USAGE; 19942a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 19953d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 1996de6b0cc4SJohnny Huang ret = do_otp_prog(addr, 1); 1997de6b0cc4SJohnny Huang } else if (argc == 2) { 19982a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19993d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2000de6b0cc4SJohnny Huang ret = do_otp_prog(addr, 0); 20012a856b9aSJohnny Huang } else { 20022a856b9aSJohnny Huang return CMD_RET_USAGE; 20032a856b9aSJohnny Huang } 20042a856b9aSJohnny Huang 20052a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20062a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20072a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20082a856b9aSJohnny Huang return CMD_RET_FAILURE; 20092a856b9aSJohnny Huang else 20102a856b9aSJohnny Huang return CMD_RET_USAGE; 20112a856b9aSJohnny Huang } 20122a856b9aSJohnny Huang 20132a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20142a856b9aSJohnny Huang { 20152a856b9aSJohnny Huang int mode = 0; 20162a856b9aSJohnny Huang int nconfirm = 0; 20172a856b9aSJohnny Huang int otp_addr = 0; 20182a856b9aSJohnny Huang int bit_offset; 20192a856b9aSJohnny Huang int value; 20202a856b9aSJohnny Huang int ret; 20212a856b9aSJohnny Huang 20222a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 20232a856b9aSJohnny Huang return CMD_RET_USAGE; 20242a856b9aSJohnny Huang 20252a856b9aSJohnny Huang /* Drop the pb cmd */ 20262a856b9aSJohnny Huang argc--; 20272a856b9aSJohnny Huang argv++; 20282a856b9aSJohnny Huang 20292a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2030a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 20312a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2032a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 20332a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2034a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2035cd1610b4SJohnny Huang else 20362a856b9aSJohnny Huang return CMD_RET_USAGE; 20372a856b9aSJohnny Huang 20382a856b9aSJohnny Huang /* Drop the region cmd */ 20392a856b9aSJohnny Huang argc--; 20402a856b9aSJohnny Huang argv++; 20412a856b9aSJohnny Huang 2042ed071a2bSJohnny Huang if (!strcmp(argv[0], "o")) { 2043cd1610b4SJohnny Huang nconfirm = 1; 20442a856b9aSJohnny Huang /* Drop the force option */ 20452a856b9aSJohnny Huang argc--; 20462a856b9aSJohnny Huang argv++; 20472a856b9aSJohnny Huang } 2048cd1610b4SJohnny Huang 2049a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 20502a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 20512a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 20520808cc55SJohnny Huang if (bit_offset >= 64 || (value != 0 && value != 1)) 20532a856b9aSJohnny Huang return CMD_RET_USAGE; 2054cd1610b4SJohnny Huang } else { 20552a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 20562a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 20572a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 20580808cc55SJohnny Huang if (bit_offset >= 32 || (value != 0 && value != 1)) 20592a856b9aSJohnny Huang return CMD_RET_USAGE; 20600808cc55SJohnny Huang if (mode == OTP_REGION_DATA) { 206178855207SJohnny Huang if (otp_addr >= 0x800) 20620808cc55SJohnny Huang return CMD_RET_USAGE; 20630808cc55SJohnny Huang } else { 206478855207SJohnny Huang if (otp_addr >= 0x20) 20650808cc55SJohnny Huang return CMD_RET_USAGE; 20660808cc55SJohnny Huang } 2067cd1610b4SJohnny Huang } 2068cd1610b4SJohnny Huang if (value != 0 && value != 1) 20692a856b9aSJohnny Huang return CMD_RET_USAGE; 2070cd1610b4SJohnny Huang 20713d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20722a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 20732a856b9aSJohnny Huang 20742a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 20752a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20762a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 20772a856b9aSJohnny Huang return CMD_RET_FAILURE; 20782a856b9aSJohnny Huang else 20792a856b9aSJohnny Huang return CMD_RET_USAGE; 20802a856b9aSJohnny Huang } 20812a856b9aSJohnny Huang 20822a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20832a856b9aSJohnny Huang { 20842a856b9aSJohnny Huang phys_addr_t addr; 20852a856b9aSJohnny Huang int otp_addr = 0; 20862a856b9aSJohnny Huang 20872a856b9aSJohnny Huang if (argc != 3) 20882a856b9aSJohnny Huang return CMD_RET_USAGE; 20892a856b9aSJohnny Huang 20903d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 20912a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 20922a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 20932a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 209469d5fd8fSJohnny Huang printf("Compare pass\n"); 20952a856b9aSJohnny Huang return CMD_RET_SUCCESS; 2096a219f6deSJohnny Huang } 209769d5fd8fSJohnny Huang printf("Compare fail\n"); 20982a856b9aSJohnny Huang return CMD_RET_FAILURE; 209969d5fd8fSJohnny Huang } 210069d5fd8fSJohnny Huang 210166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 210266f2f8e5SJohnny Huang { 2103a8bd6d8cSJohnny Huang int view = 0; 21042d4b0742SJohnny Huang int input; 2105a8bd6d8cSJohnny Huang 2106a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 210766f2f8e5SJohnny Huang return CMD_RET_USAGE; 210866f2f8e5SJohnny Huang 21092d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 21103d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 21112d4b0742SJohnny Huang if (argc == 3) { 21122d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 21132d4b0742SJohnny Huang otp_print_conf_info(input); 21142d4b0742SJohnny Huang } else { 21152d4b0742SJohnny Huang otp_print_conf_info(-1); 21162d4b0742SJohnny Huang } 21172d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 21182d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 2119a8bd6d8cSJohnny Huang view = 1; 2120a8bd6d8cSJohnny Huang /* Drop the view option */ 2121a8bd6d8cSJohnny Huang argc--; 2122a8bd6d8cSJohnny Huang argv++; 2123a8bd6d8cSJohnny Huang } 21243d3688adSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2125b458cd62SJohnny Huang otp_print_strap_info(view); 212666f2f8e5SJohnny Huang } else { 212766f2f8e5SJohnny Huang return CMD_RET_USAGE; 212866f2f8e5SJohnny Huang } 21292d4b0742SJohnny Huang 213066f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 213166f2f8e5SJohnny Huang } 213266f2f8e5SJohnny Huang 2133e14b073cSJohnny Huang static int _do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[], int preg) 2134737ed20bSJohnny Huang { 2135737ed20bSJohnny Huang int input; 2136737ed20bSJohnny Huang int bit_offset; 2137e14b073cSJohnny Huang u32 prog_address; 213883655e91SJohnny Huang int ret; 2139e14b073cSJohnny Huang char info[10]; 2140e14b073cSJohnny Huang 2141e14b073cSJohnny Huang if (preg) { 2142e14b073cSJohnny Huang sprintf(info, "register "); 2143e14b073cSJohnny Huang prog_address = 0xe08; 2144e14b073cSJohnny Huang } else { 2145e14b073cSJohnny Huang info[0] = 0; 2146e14b073cSJohnny Huang prog_address = 0xe0c; 2147e14b073cSJohnny Huang } 2148a219f6deSJohnny Huang 2149737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2150737ed20bSJohnny Huang return CMD_RET_USAGE; 2151737ed20bSJohnny Huang 2152e14b073cSJohnny Huang if (!strcmp(argv[1], "o")) { 2153737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2154737ed20bSJohnny Huang } else { 2155737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2156e14b073cSJohnny Huang printf("OTPSTRAP[%d] %swill be protected\n", input, info); 2157737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2158737ed20bSJohnny Huang if (!confirm_yesno()) { 2159737ed20bSJohnny Huang printf(" Aborting\n"); 2160737ed20bSJohnny Huang return CMD_RET_FAILURE; 2161737ed20bSJohnny Huang } 2162737ed20bSJohnny Huang } 2163737ed20bSJohnny Huang 2164737ed20bSJohnny Huang if (input < 32) { 2165737ed20bSJohnny Huang bit_offset = input; 2166737ed20bSJohnny Huang } else if (input < 64) { 2167737ed20bSJohnny Huang bit_offset = input - 32; 2168e14b073cSJohnny Huang prog_address += 2; 2169737ed20bSJohnny Huang } else { 2170737ed20bSJohnny Huang return CMD_RET_USAGE; 2171737ed20bSJohnny Huang } 2172737ed20bSJohnny Huang 2173e14b073cSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2174e14b073cSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2175e14b073cSJohnny Huang printf("OTPSTRAP[%d] %salready protected\n", input, info); 2176e14b073cSJohnny Huang return CMD_RET_SUCCESS; 2177e14b073cSJohnny Huang } 2178de6fbf1cSJohnny Huang 217983655e91SJohnny Huang ret = otp_prog_bit(1, prog_address, bit_offset); 2180de6fbf1cSJohnny Huang otp_soak(0); 218183655e91SJohnny Huang 218283655e91SJohnny Huang if (ret) { 2183e14b073cSJohnny Huang printf("Protect OTPSTRAP[%d] %sfail\n", input, info); 2184737ed20bSJohnny Huang return CMD_RET_FAILURE; 2185737ed20bSJohnny Huang } 21869a4fe690SJohnny Huang 2187*794e27ecSJohnny Huang printf("OTPSTRAP[%d] %sis protected\n", input, info); 2188*794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2189*794e27ecSJohnny Huang } 2190*794e27ecSJohnny Huang 2191e14b073cSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2192e14b073cSJohnny Huang { 2193e14b073cSJohnny Huang return _do_otpprotect(cmdtp, flag, argc, argv, 0); 2194e14b073cSJohnny Huang } 2195e14b073cSJohnny Huang 2196e14b073cSJohnny Huang static int do_otprprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2197e14b073cSJohnny Huang { 2198e14b073cSJohnny Huang return _do_otpprotect(cmdtp, flag, argc, argv, 1); 2199e14b073cSJohnny Huang } 2200e14b073cSJohnny Huang 2201f67375f7SJohnny Huang static int do_otpver(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2202f67375f7SJohnny Huang { 2203f67375f7SJohnny Huang printf("OTP tool version: %s\n", OTP_VER); 2204f67375f7SJohnny Huang printf("OTP info version: %s\n", OTP_INFO_VER); 2205f67375f7SJohnny Huang 2206f67375f7SJohnny Huang return CMD_RET_SUCCESS; 2207f67375f7SJohnny Huang } 2208f67375f7SJohnny Huang 2209*794e27ecSJohnny Huang static int do_otpupdate(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2210*794e27ecSJohnny Huang { 2211*794e27ecSJohnny Huang u32 update_num; 2212*794e27ecSJohnny Huang int force = 0; 2213*794e27ecSJohnny Huang int ret; 2214*794e27ecSJohnny Huang 2215*794e27ecSJohnny Huang if (argc == 3) { 2216*794e27ecSJohnny Huang if (strcmp(argv[1], "o")) 2217*794e27ecSJohnny Huang return CMD_RET_USAGE; 2218*794e27ecSJohnny Huang force = 1; 2219*794e27ecSJohnny Huang update_num = simple_strtoul(argv[2], NULL, 16); 2220*794e27ecSJohnny Huang } else if (argc == 2) { 2221*794e27ecSJohnny Huang update_num = simple_strtoul(argv[1], NULL, 16); 2222*794e27ecSJohnny Huang } else { 2223*794e27ecSJohnny Huang return CMD_RET_USAGE; 2224*794e27ecSJohnny Huang } 2225*794e27ecSJohnny Huang 2226*794e27ecSJohnny Huang if (update_num > 64) 2227*794e27ecSJohnny Huang return CMD_RET_USAGE; 2228*794e27ecSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2229*794e27ecSJohnny Huang ret = otp_update_rid(update_num, force); 2230*794e27ecSJohnny Huang if (ret) 2231*794e27ecSJohnny Huang return CMD_RET_FAILURE; 2232*794e27ecSJohnny Huang return CMD_RET_SUCCESS; 2233*794e27ecSJohnny Huang } 2234*794e27ecSJohnny Huang 2235*794e27ecSJohnny Huang static int do_otprid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2236*794e27ecSJohnny Huang { 2237*794e27ecSJohnny Huang u32 otp_rid[2]; 2238*794e27ecSJohnny Huang int rid_num = 0; 2239*794e27ecSJohnny Huang int ret; 2240*794e27ecSJohnny Huang 2241*794e27ecSJohnny Huang if (argc != 1) 2242*794e27ecSJohnny Huang return CMD_RET_USAGE; 2243*794e27ecSJohnny Huang 2244*794e27ecSJohnny Huang writel(OTP_PASSWD, OTP_PROTECT_KEY); //password 2245*794e27ecSJohnny Huang otp_read_config(10, &otp_rid[0]); 2246*794e27ecSJohnny Huang otp_read_config(11, &otp_rid[1]); 2247*794e27ecSJohnny Huang 2248*794e27ecSJohnny Huang rid_num = get_rid_num(otp_rid); 2249*794e27ecSJohnny Huang 2250*794e27ecSJohnny Huang if (rid_num >= 0) { 2251*794e27ecSJohnny Huang printf("current OTP revision ID: 0x%x\n", rid_num); 2252*794e27ecSJohnny Huang ret = CMD_RET_SUCCESS; 2253*794e27ecSJohnny Huang } else { 2254*794e27ecSJohnny Huang printf("Currennt OTP revision ID cannot handle by 'otp update',\n" 2255*794e27ecSJohnny Huang "plase use 'otp pb' command to update it manually\n" 2256*794e27ecSJohnny Huang "current OTP revision ID\n"); 2257*794e27ecSJohnny Huang ret = CMD_RET_FAILURE; 2258*794e27ecSJohnny Huang } 2259*794e27ecSJohnny Huang otp_print_revid(otp_rid); 2260*794e27ecSJohnny Huang 2261*794e27ecSJohnny Huang return ret; 2262*794e27ecSJohnny Huang } 2263*794e27ecSJohnny Huang 22642a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 2265f67375f7SJohnny Huang U_BOOT_CMD_MKENT(version, 1, 0, do_otpver, "", ""), 22662a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2267a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 2268de6b0cc4SJohnny Huang U_BOOT_CMD_MKENT(prog, 3, 0, do_otpprog, "", ""), 22692a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2270737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 2271e14b073cSJohnny Huang U_BOOT_CMD_MKENT(rprotect, 3, 0, do_otprprotect, "", ""), 22722a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 2273*794e27ecSJohnny Huang U_BOOT_CMD_MKENT(update, 3, 0, do_otpupdate, "", ""), 2274*794e27ecSJohnny Huang U_BOOT_CMD_MKENT(rid, 1, 0, do_otprid, "", ""), 22752a856b9aSJohnny Huang }; 22762a856b9aSJohnny Huang 22772a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 22782a856b9aSJohnny Huang { 22792a856b9aSJohnny Huang cmd_tbl_t *cp; 2280a219f6deSJohnny Huang u32 ver; 2281e14b073cSJohnny Huang int ret; 22822a856b9aSJohnny Huang 22832a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 22842a856b9aSJohnny Huang 2285737ed20bSJohnny Huang /* Drop the otp command */ 22862a856b9aSJohnny Huang argc--; 22872a856b9aSJohnny Huang argv++; 22882a856b9aSJohnny Huang 2289a219f6deSJohnny Huang if (!cp || argc > cp->maxargs) 22902a856b9aSJohnny Huang return CMD_RET_USAGE; 22912a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 22922a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22932a856b9aSJohnny Huang 22940dae9d52SJohnny Huang ver = chip_version(); 22950dae9d52SJohnny Huang switch (ver) { 22960dae9d52SJohnny Huang case OTP_AST2600A0: 2297696656c6SJohnny Huang info_cb.version = OTP_AST2600A0; 22989a4fe690SJohnny Huang info_cb.conf_info = a0_conf_info; 22999a4fe690SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a0_conf_info); 23009a4fe690SJohnny Huang info_cb.strap_info = a0_strap_info; 23019a4fe690SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a0_strap_info); 23029a4fe690SJohnny Huang info_cb.key_info = a0_key_type; 23039a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a0_key_type); 23040dae9d52SJohnny Huang break; 23050dae9d52SJohnny Huang case OTP_AST2600A1: 2306696656c6SJohnny Huang info_cb.version = OTP_AST2600A1; 23073cb28812SJohnny Huang info_cb.conf_info = a1_conf_info; 23083cb28812SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a1_conf_info); 23093cb28812SJohnny Huang info_cb.strap_info = a1_strap_info; 23103cb28812SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a1_strap_info); 23119a4fe690SJohnny Huang info_cb.key_info = a1_key_type; 23129a4fe690SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a1_key_type); 23130dae9d52SJohnny Huang break; 23140dae9d52SJohnny Huang case OTP_AST2600A2: 23155fdde29fSJohnny Huang info_cb.version = OTP_AST2600A2; 23165fdde29fSJohnny Huang info_cb.conf_info = a2_conf_info; 23175fdde29fSJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info); 23185fdde29fSJohnny Huang info_cb.strap_info = a2_strap_info; 23195fdde29fSJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info); 23205fdde29fSJohnny Huang info_cb.key_info = a2_key_type; 23215fdde29fSJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a2_key_type); 23220dae9d52SJohnny Huang break; 232364b66712SJohnny Huang case OTP_AST2600A3: 232464b66712SJohnny Huang info_cb.version = OTP_AST2600A3; 232564b66712SJohnny Huang info_cb.conf_info = a2_conf_info; 232664b66712SJohnny Huang info_cb.conf_info_len = ARRAY_SIZE(a2_conf_info); 232764b66712SJohnny Huang info_cb.strap_info = a2_strap_info; 232864b66712SJohnny Huang info_cb.strap_info_len = ARRAY_SIZE(a2_strap_info); 2329181f72d8SJohnny Huang info_cb.key_info = a3_key_type; 2330181f72d8SJohnny Huang info_cb.key_info_len = ARRAY_SIZE(a3_key_type); 233164b66712SJohnny Huang break; 23320dae9d52SJohnny Huang default: 2333f1be5099SJohnny Huang printf("SOC is not supported\n"); 23340dae9d52SJohnny Huang return CMD_RET_FAILURE; 23359a4fe690SJohnny Huang } 23369a4fe690SJohnny Huang 2337e14b073cSJohnny Huang ret = cp->cmd(cmdtp, flag, argc, argv); 2338e14b073cSJohnny Huang writel(1, OTP_PROTECT_KEY); //password 2339e14b073cSJohnny Huang 2340e14b073cSJohnny Huang return ret; 234169d5fd8fSJohnny Huang } 234269d5fd8fSJohnny Huang 2343a219f6deSJohnny Huang U_BOOT_CMD(otp, 7, 0, do_ast_otp, 234469d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 2345f67375f7SJohnny Huang "version\n" 2346f67375f7SJohnny Huang "otp read conf|data <otp_dw_offset> <dw_count>\n" 23472a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 23482d4b0742SJohnny Huang "otp info strap [v]\n" 23492d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2350de6b0cc4SJohnny Huang "otp prog [o] <addr>\n" 2351ed071a2bSJohnny Huang "otp pb conf|data [o] <otp_dw_offset> <bit_offset> <value>\n" 2352ed071a2bSJohnny Huang "otp pb strap [o] <bit_offset> <value>\n" 2353ed071a2bSJohnny Huang "otp protect [o] <bit_offset>\n" 2354e14b073cSJohnny Huang "otp rprotect [o] <bit_offset>\n" 2355*794e27ecSJohnny Huang "otp update [o] <revision_id>\n" 2356*794e27ecSJohnny Huang "otp rid\n" 235769d5fd8fSJohnny Huang ); 2358