169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 28a6d0d645SJohnny Huang #define OTP_REGION_STRAP 1 29a6d0d645SJohnny Huang #define OTP_REGION_CONF 2 30a6d0d645SJohnny Huang #define OTP_REGION_DATA 3 31a6d0d645SJohnny Huang #define OTP_REGION_ALL 4 3269d5fd8fSJohnny Huang 332a856b9aSJohnny Huang #define OTP_USAGE -1 342a856b9aSJohnny Huang #define OTP_FAILURE -2 352a856b9aSJohnny Huang #define OTP_SUCCESS 0 362a856b9aSJohnny Huang 37a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 38a6af4a17SJohnny Huang 3966f2f8e5SJohnny Huang #define DISABLE_SECREG_PROG(x) (x & 0x1) 4066f2f8e5SJohnny Huang #define ENABLE_SEC_BOOT(x) ((x >> 1) & 0x1) 4166f2f8e5SJohnny Huang #define INIT_PROG_DONE(x) ((x >> 2) & 0x1) 4266f2f8e5SJohnny Huang #define ENABLE_USERREG_ECC(x) ((x >> 3) & 0x1) 4366f2f8e5SJohnny Huang #define ENABLE_SECREG_ECC(x) ((x >> 4) & 0x1) 4466f2f8e5SJohnny Huang #define DISABLE_LOW_SEC_KEY(x) ((x >> 5) & 0x1) 4566f2f8e5SJohnny Huang #define IGNORE_SEC_BOOT_HWSTRAP(x) ((x >> 6) & 0x1) 4666f2f8e5SJohnny Huang #define SEC_BOOT_MDOES(x) ((x >> 7) & 0x1) 47e1f9e54eSJohnny Huang #define SEC_MODE1 0x0 48e1f9e54eSJohnny Huang #define SEC_MODE2 0x1 49e1f9e54eSJohnny Huang #define OTP_BIT_CELL_MODES(x) ((x >> 8) & 0x3) 50e1f9e54eSJohnny Huang #define SINGLE_CELL_MODE 0x0 51e1f9e54eSJohnny Huang #define DIFFERENTIAL_MODE 0x1 52e1f9e54eSJohnny Huang #define DIFFERENTIAL_REDUDANT_MODE 0x2 53e1f9e54eSJohnny Huang #define CRYPTO_MODES(x) ((x >> 10) & 0x3) 54e1f9e54eSJohnny Huang #define CRYPTO_RSA1024 0x0 55e1f9e54eSJohnny Huang #define CRYPTO_RSA2048 0x1 56e1f9e54eSJohnny Huang #define CRYPTO_RSA3072 0x2 57e1f9e54eSJohnny Huang #define CRYPTO_RSA4096 0x3 58e1f9e54eSJohnny Huang #define HASH_MODES(x) ((x >> 12) & 0x3) 59e1f9e54eSJohnny Huang #define HASH_SAH224 0x0 60e1f9e54eSJohnny Huang #define HASH_SAH256 0x1 61e1f9e54eSJohnny Huang #define HASH_SAH384 0x2 62e1f9e54eSJohnny Huang #define HASH_SAH512 0x3 63e1f9e54eSJohnny Huang #define SECREG_SIZE(x) ((x >> 16) & 0x3f) 6466f2f8e5SJohnny Huang #define WRITE_PROTECT_SECREG(x) ((x >> 22) & 0x1) 6566f2f8e5SJohnny Huang #define WRITE_PROTECT_USERREG(x) ((x >> 23) & 0x1) 6666f2f8e5SJohnny Huang #define WRITE_PROTECT_CONFREG(x) ((x >> 24) & 0x1) 6766f2f8e5SJohnny Huang #define WRITE_PROTECT_STRAPREG(x) ((x >> 25) & 0x1) 6866f2f8e5SJohnny Huang #define ENABLE_COPY_TO_SRAM(x) ((x >> 26) & 0x1) 6966f2f8e5SJohnny Huang #define ENABLE_IMAGE_ENC(x) ((x >> 27) & 0x1) 7066f2f8e5SJohnny Huang #define WRITE_PROTECT_KEY_RETIRE(x) ((x >> 29) & 0x1) 7166f2f8e5SJohnny Huang #define ENABLE_SIPROM_RED(x) ((x >> 30) & 0x1) 7266f2f8e5SJohnny Huang #define ENABLE_SIPROM_MLOCK(x) ((x >> 31) & 0x1) 73e1f9e54eSJohnny Huang 74e1f9e54eSJohnny Huang #define VENDER_ID(x) (x & 0xFFFF) 75e1f9e54eSJohnny Huang #define KEY_REVISION(x) ((x >> 16) & 0xFFFF) 76e1f9e54eSJohnny Huang 77e1f9e54eSJohnny Huang #define SEC_BOOT_HEADER_OFFSET(x) (x & 0xFFFF) 78e1f9e54eSJohnny Huang 79e1f9e54eSJohnny Huang #define KEYS_VALID_BITS(x) (x & 0xff) 80e1f9e54eSJohnny Huang #define KEYS_RETIRE_BITS(x) ((x >> 16) & 0xff) 814c1c9b35SJohnny Huang 82*a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 8376d13988SJohnny Huang 844c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 854c1c9b35SJohnny Huang #define PBWIDTH 60 864c1c9b35SJohnny Huang 8766f2f8e5SJohnny Huang struct otpstrap_status { 8869d5fd8fSJohnny Huang int value; 8969d5fd8fSJohnny Huang int option_array[7]; 9069d5fd8fSJohnny Huang int remain_times; 9169d5fd8fSJohnny Huang int writeable_option; 9269d5fd8fSJohnny Huang int protected; 9369d5fd8fSJohnny Huang }; 9469d5fd8fSJohnny Huang 9566f2f8e5SJohnny Huang struct otpconf_parse { 9666f2f8e5SJohnny Huang int dw_offset; 9766f2f8e5SJohnny Huang int bit; 9866f2f8e5SJohnny Huang int length; 9966f2f8e5SJohnny Huang int value; 10066f2f8e5SJohnny Huang int keep; 10166f2f8e5SJohnny Huang char status[80]; 10266f2f8e5SJohnny Huang }; 10366f2f8e5SJohnny Huang 104*a8bd6d8cSJohnny Huang struct otpstrap_info { 105*a8bd6d8cSJohnny Huang uint32_t bit_offset; 106*a8bd6d8cSJohnny Huang uint32_t length; 10776d13988SJohnny Huang int value; 108*a8bd6d8cSJohnny Huang char information[80]; 109*a8bd6d8cSJohnny Huang }; 110*a8bd6d8cSJohnny Huang 111*a8bd6d8cSJohnny Huang struct otpconf_info { 112*a8bd6d8cSJohnny Huang uint32_t dw_offset; 113*a8bd6d8cSJohnny Huang uint32_t bit_offset; 114*a8bd6d8cSJohnny Huang uint32_t length; 115*a8bd6d8cSJohnny Huang int value; 116*a8bd6d8cSJohnny Huang char information[80]; 117*a8bd6d8cSJohnny Huang }; 118*a8bd6d8cSJohnny Huang 119*a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 120*a8bd6d8cSJohnny Huang { 121*a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 122*a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 123*a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 124*a8bd6d8cSJohnny Huang char buffer[256]; 125*a8bd6d8cSJohnny Huang va_list aptr; 126*a8bd6d8cSJohnny Huang 127*a8bd6d8cSJohnny Huang va_start(aptr, format); 128*a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 129*a8bd6d8cSJohnny Huang va_end(aptr); 130*a8bd6d8cSJohnny Huang 131*a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 132*a8bd6d8cSJohnny Huang if (numerator == denominator) 133*a8bd6d8cSJohnny Huang printf("\n"); 134*a8bd6d8cSJohnny Huang } 135*a8bd6d8cSJohnny Huang 136*a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 137*a8bd6d8cSJohnny Huang { 138*a8bd6d8cSJohnny Huang 0, 1, 0, "Disable secure boot" 139*a8bd6d8cSJohnny Huang }, { 140*a8bd6d8cSJohnny Huang 0, 1, 1, "Enable secure boot" 141*a8bd6d8cSJohnny Huang }, { 142*a8bd6d8cSJohnny Huang 1, 1, 0, "Disable boot from eMMC" 143*a8bd6d8cSJohnny Huang }, { 144*a8bd6d8cSJohnny Huang 1, 1, 1, "Enable boot from eMMC" 145*a8bd6d8cSJohnny Huang }, { 146*a8bd6d8cSJohnny Huang 2, 1, 0, "Disable Boot from debug SPI" 147*a8bd6d8cSJohnny Huang }, { 148*a8bd6d8cSJohnny Huang 2, 1, 1, "Enable Boot from debug SPI" 149*a8bd6d8cSJohnny Huang }, { 150*a8bd6d8cSJohnny Huang 3, 1, 0, "Enable ARM CM3" 151*a8bd6d8cSJohnny Huang }, { 152*a8bd6d8cSJohnny Huang 3, 1, 1, "Disable ARM CM3" 153*a8bd6d8cSJohnny Huang }, { 154*a8bd6d8cSJohnny Huang 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" 155*a8bd6d8cSJohnny Huang }, { 156*a8bd6d8cSJohnny Huang 4, 1, 1, "Enable dedicated VGA BIOS ROM" 157*a8bd6d8cSJohnny Huang }, { 158*a8bd6d8cSJohnny Huang 5, 1, 0, "MAC 1 : RMII/NCSI" 159*a8bd6d8cSJohnny Huang }, { 160*a8bd6d8cSJohnny Huang 5, 1, 1, "MAC 1 : RGMII" 161*a8bd6d8cSJohnny Huang }, { 162*a8bd6d8cSJohnny Huang 6, 1, 0, "MAC 2 : RMII/NCSI" 163*a8bd6d8cSJohnny Huang }, { 164*a8bd6d8cSJohnny Huang 6, 1, 1, "MAC 2 : RGMII" 165*a8bd6d8cSJohnny Huang }, { 166*a8bd6d8cSJohnny Huang 7, 3, 0, "CPU Frequency : 1GHz" 167*a8bd6d8cSJohnny Huang }, { 168*a8bd6d8cSJohnny Huang 7, 3, 1, "CPU Frequency : 800MHz" 169*a8bd6d8cSJohnny Huang }, { 170*a8bd6d8cSJohnny Huang 7, 3, 2, "CPU Frequency : 1.2GHz" 171*a8bd6d8cSJohnny Huang }, { 172*a8bd6d8cSJohnny Huang 7, 3, 3, "CPU Frequency : 1.4GHz" 173*a8bd6d8cSJohnny Huang }, { 174*a8bd6d8cSJohnny Huang 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" 175*a8bd6d8cSJohnny Huang }, { 176*a8bd6d8cSJohnny Huang 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" 177*a8bd6d8cSJohnny Huang }, { 178*a8bd6d8cSJohnny Huang 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" 179*a8bd6d8cSJohnny Huang }, { 180*a8bd6d8cSJohnny Huang 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" 181*a8bd6d8cSJohnny Huang }, { 182*a8bd6d8cSJohnny Huang 12, 2, 0, "VGA memory size : 8MB" 183*a8bd6d8cSJohnny Huang }, { 184*a8bd6d8cSJohnny Huang 12, 2, 1, "VGA memory size : 16MB" 185*a8bd6d8cSJohnny Huang }, { 186*a8bd6d8cSJohnny Huang 12, 2, 2, "VGA memory size : 32MB" 187*a8bd6d8cSJohnny Huang }, { 188*a8bd6d8cSJohnny Huang 12, 2, 3, "VGA memory size : 64MB" 189*a8bd6d8cSJohnny Huang }, { 190*a8bd6d8cSJohnny Huang 14, 3, OTP_REG_RESERVED, "" 191*a8bd6d8cSJohnny Huang }, { 192*a8bd6d8cSJohnny Huang 17, 1, 0, "VGA class code : Class Code for video device" 193*a8bd6d8cSJohnny Huang }, { 194*a8bd6d8cSJohnny Huang 17, 1, 1, "VGA class code : Class Code for VGA device" 195*a8bd6d8cSJohnny Huang }, { 196*a8bd6d8cSJohnny Huang 18, 1, 0, "Enable debug interfaces 0" 197*a8bd6d8cSJohnny Huang }, { 198*a8bd6d8cSJohnny Huang 18, 1, 1, "Disable debug interfaces 0" 199*a8bd6d8cSJohnny Huang }, { 200*a8bd6d8cSJohnny Huang 19, 1, 0, "Boot from emmc mode : High eMMC speed" 201*a8bd6d8cSJohnny Huang }, { 202*a8bd6d8cSJohnny Huang 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" 203*a8bd6d8cSJohnny Huang }, { 204*a8bd6d8cSJohnny Huang 20, 1, 0, "Enable Pcie EHCI device" 205*a8bd6d8cSJohnny Huang }, { 206*a8bd6d8cSJohnny Huang 20, 1, 1, "Disable Pcie EHCI device" 207*a8bd6d8cSJohnny Huang }, { 208*a8bd6d8cSJohnny Huang 21, 1, 0, "Enable VGA XDMA function" 209*a8bd6d8cSJohnny Huang }, { 210*a8bd6d8cSJohnny Huang 21, 1, 1, "Disable VGA XDMA function" 211*a8bd6d8cSJohnny Huang }, { 212*a8bd6d8cSJohnny Huang 22, 1, 0, "Normal BMC mode" 213*a8bd6d8cSJohnny Huang }, { 214*a8bd6d8cSJohnny Huang 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" 215*a8bd6d8cSJohnny Huang }, { 216*a8bd6d8cSJohnny Huang 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" 217*a8bd6d8cSJohnny Huang }, { 218*a8bd6d8cSJohnny Huang 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" 219*a8bd6d8cSJohnny Huang }, { 220*a8bd6d8cSJohnny Huang 24, 1, 0, "DRAM types : DDR3" 221*a8bd6d8cSJohnny Huang }, { 222*a8bd6d8cSJohnny Huang 24, 1, 1, "DRAM types : DDR4" 223*a8bd6d8cSJohnny Huang }, { 224*a8bd6d8cSJohnny Huang 25, 5, OTP_REG_RESERVED, "" 225*a8bd6d8cSJohnny Huang }, { 226*a8bd6d8cSJohnny Huang 30, 2, OTP_REG_RESERVED, "" 227*a8bd6d8cSJohnny Huang }, { 228*a8bd6d8cSJohnny Huang 32, 1, 0, "MAC 3 : RMII/NCSI" 229*a8bd6d8cSJohnny Huang }, { 230*a8bd6d8cSJohnny Huang 32, 1, 1, "MAC 3 : RGMII" 231*a8bd6d8cSJohnny Huang }, { 232*a8bd6d8cSJohnny Huang 33, 1, 0, "MAC 4 : RMII/NCSI" 233*a8bd6d8cSJohnny Huang }, { 234*a8bd6d8cSJohnny Huang 33, 1, 1, "MAC 4 : RGMII" 235*a8bd6d8cSJohnny Huang }, { 236*a8bd6d8cSJohnny Huang 34, 1, 0, "SuperIO configuration address : 0x2E" 237*a8bd6d8cSJohnny Huang }, { 238*a8bd6d8cSJohnny Huang 34, 1, 1, "SuperIO configuration address : 0x4E" 239*a8bd6d8cSJohnny Huang }, { 240*a8bd6d8cSJohnny Huang 35, 1, 0, "Enable LPC to decode SuperIO" 241*a8bd6d8cSJohnny Huang }, { 242*a8bd6d8cSJohnny Huang 35, 1, 1, "Disable LPC to decode SuperIO" 243*a8bd6d8cSJohnny Huang }, { 244*a8bd6d8cSJohnny Huang 36, 1, 0, "Enable debug interfaces 1" 245*a8bd6d8cSJohnny Huang }, { 246*a8bd6d8cSJohnny Huang 36, 1, 1, "Disable debug interfaces 1" 247*a8bd6d8cSJohnny Huang }, { 248*a8bd6d8cSJohnny Huang 37, 1, 0, "Disable ACPI function" 249*a8bd6d8cSJohnny Huang }, { 250*a8bd6d8cSJohnny Huang 37, 1, 1, "Enable ACPI function" 251*a8bd6d8cSJohnny Huang }, { 252*a8bd6d8cSJohnny Huang 38, 1, 0, "Enable eSPI mode" 253*a8bd6d8cSJohnny Huang }, { 254*a8bd6d8cSJohnny Huang 38, 1, 1, "Enable LPC mode" 255*a8bd6d8cSJohnny Huang }, { 256*a8bd6d8cSJohnny Huang 39, 1, 0, "Enable SAFS mode" 257*a8bd6d8cSJohnny Huang }, { 258*a8bd6d8cSJohnny Huang 39, 1, 1, "Enable SAFS mode" 259*a8bd6d8cSJohnny Huang }, { 260*a8bd6d8cSJohnny Huang 40, 2, OTP_REG_RESERVED, "" 261*a8bd6d8cSJohnny Huang }, { 262*a8bd6d8cSJohnny Huang 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" 263*a8bd6d8cSJohnny Huang }, { 264*a8bd6d8cSJohnny Huang 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" 265*a8bd6d8cSJohnny Huang }, { 266*a8bd6d8cSJohnny Huang 43, 1, 0, "Disable boot SPI ABR" 267*a8bd6d8cSJohnny Huang }, { 268*a8bd6d8cSJohnny Huang 43, 1, 1, "Enable boot SPI ABR" 269*a8bd6d8cSJohnny Huang }, { 270*a8bd6d8cSJohnny Huang 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" 271*a8bd6d8cSJohnny Huang }, { 272*a8bd6d8cSJohnny Huang 44, 1, 1, "Boot SPI ABR mode : single SPI flash" 273*a8bd6d8cSJohnny Huang }, { 274*a8bd6d8cSJohnny Huang 45, 3, 0, "Boot SPI flash size : no define size" 275*a8bd6d8cSJohnny Huang }, { 276*a8bd6d8cSJohnny Huang 45, 3, 1, "Boot SPI flash size : 2MB" 277*a8bd6d8cSJohnny Huang }, { 278*a8bd6d8cSJohnny Huang 45, 3, 2, "Boot SPI flash size : 4MB" 279*a8bd6d8cSJohnny Huang }, { 280*a8bd6d8cSJohnny Huang 45, 3, 3, "Boot SPI flash size : 8MB" 281*a8bd6d8cSJohnny Huang }, { 282*a8bd6d8cSJohnny Huang 45, 3, 4, "Boot SPI flash size : 16MB" 283*a8bd6d8cSJohnny Huang }, { 284*a8bd6d8cSJohnny Huang 45, 3, 5, "Boot SPI flash size : 32MB" 285*a8bd6d8cSJohnny Huang }, { 286*a8bd6d8cSJohnny Huang 45, 3, 6, "Boot SPI flash size : 64MB" 287*a8bd6d8cSJohnny Huang }, { 288*a8bd6d8cSJohnny Huang 45, 3, 7, "Boot SPI flash size : 128MB" 289*a8bd6d8cSJohnny Huang }, { 290*a8bd6d8cSJohnny Huang 48, 1, 0, "Disable host SPI ABR" 291*a8bd6d8cSJohnny Huang }, { 292*a8bd6d8cSJohnny Huang 48, 1, 1, "Enable host SPI ABR" 293*a8bd6d8cSJohnny Huang }, { 294*a8bd6d8cSJohnny Huang 49, 1, 0, "Disable host SPI ABR mode select pin" 295*a8bd6d8cSJohnny Huang }, { 296*a8bd6d8cSJohnny Huang 49, 1, 1, "Enable host SPI ABR mode select pin" 297*a8bd6d8cSJohnny Huang }, { 298*a8bd6d8cSJohnny Huang 50, 1, 0, "Host SPI ABR mode : dual SPI flash" 299*a8bd6d8cSJohnny Huang }, { 300*a8bd6d8cSJohnny Huang 50, 1, 1, "Host SPI ABR mode : single SPI flash" 301*a8bd6d8cSJohnny Huang }, { 302*a8bd6d8cSJohnny Huang 51, 3, 0, "Host SPI flash size : no define size" 303*a8bd6d8cSJohnny Huang }, { 304*a8bd6d8cSJohnny Huang 51, 3, 1, "Host SPI flash size : 2MB" 305*a8bd6d8cSJohnny Huang }, { 306*a8bd6d8cSJohnny Huang 51, 3, 2, "Host SPI flash size : 4MB" 307*a8bd6d8cSJohnny Huang }, { 308*a8bd6d8cSJohnny Huang 51, 3, 3, "Host SPI flash size : 8MB" 309*a8bd6d8cSJohnny Huang }, { 310*a8bd6d8cSJohnny Huang 51, 3, 4, "Host SPI flash size : 16MB" 311*a8bd6d8cSJohnny Huang }, { 312*a8bd6d8cSJohnny Huang 51, 3, 5, "Host SPI flash size : 32MB" 313*a8bd6d8cSJohnny Huang }, { 314*a8bd6d8cSJohnny Huang 51, 3, 6, "Host SPI flash size : 64MB" 315*a8bd6d8cSJohnny Huang }, { 316*a8bd6d8cSJohnny Huang 51, 3, 7, "Host SPI flash size : 128MB" 317*a8bd6d8cSJohnny Huang }, { 318*a8bd6d8cSJohnny Huang 54, 1, 0, "Disable boot SPI auxiliary control pins" 319*a8bd6d8cSJohnny Huang }, { 320*a8bd6d8cSJohnny Huang 54, 1, 1, "Enable boot SPI auxiliary control pins" 321*a8bd6d8cSJohnny Huang }, { 322*a8bd6d8cSJohnny Huang 55, 2, 0, "Boot SPI CRTM size : disable CRTM" 323*a8bd6d8cSJohnny Huang }, { 324*a8bd6d8cSJohnny Huang 55, 2, 1, "Boot SPI CRTM size : 256KB" 325*a8bd6d8cSJohnny Huang }, { 326*a8bd6d8cSJohnny Huang 55, 2, 2, "Boot SPI CRTM size : 512KB" 327*a8bd6d8cSJohnny Huang }, { 328*a8bd6d8cSJohnny Huang 55, 2, 3, "Boot SPI CRTM size : 1MB" 329*a8bd6d8cSJohnny Huang }, { 330*a8bd6d8cSJohnny Huang 57, 2, 0, "Host SPI CRTM size : disable CRTM" 331*a8bd6d8cSJohnny Huang }, { 332*a8bd6d8cSJohnny Huang 57, 2, 1, "Host SPI CRTM size : 256KB" 333*a8bd6d8cSJohnny Huang }, { 334*a8bd6d8cSJohnny Huang 57, 2, 2, "Host SPI CRTM size : 512KB" 335*a8bd6d8cSJohnny Huang }, { 336*a8bd6d8cSJohnny Huang 57, 2, 3, "Host SPI CRTM size : 1MB" 337*a8bd6d8cSJohnny Huang }, { 338*a8bd6d8cSJohnny Huang 59, 1, 0, "Disable host SPI auxiliary control pins" 339*a8bd6d8cSJohnny Huang }, { 340*a8bd6d8cSJohnny Huang 59, 1, 1, "Enable host SPI auxiliary control pins" 341*a8bd6d8cSJohnny Huang }, { 342*a8bd6d8cSJohnny Huang 60, 1, 0, "Disable GPIO pass through" 343*a8bd6d8cSJohnny Huang }, { 344*a8bd6d8cSJohnny Huang 60, 1, 1, "Enable GPIO pass through" 345*a8bd6d8cSJohnny Huang }, { 346*a8bd6d8cSJohnny Huang 61, 1, 0, "Enable low security secure boot key" 347*a8bd6d8cSJohnny Huang }, { 348*a8bd6d8cSJohnny Huang 61, 1, 1, "Disable low security secure boot key" 349*a8bd6d8cSJohnny Huang }, { 350*a8bd6d8cSJohnny Huang 62, 1, 0, "Disable dedicate GPIO strap pins" 351*a8bd6d8cSJohnny Huang }, { 352*a8bd6d8cSJohnny Huang 62, 1, 1, "Enable dedicate GPIO strap pins" 353*a8bd6d8cSJohnny Huang } 35476d13988SJohnny Huang }; 35576d13988SJohnny Huang 3562a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 35769d5fd8fSJohnny Huang { 35869d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 35969d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 36069d5fd8fSJohnny Huang udelay(2); 36169d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 36269d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 36369d5fd8fSJohnny Huang } 36469d5fd8fSJohnny Huang 3652a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 36669d5fd8fSJohnny Huang { 36769d5fd8fSJohnny Huang int config_offset; 36869d5fd8fSJohnny Huang 36969d5fd8fSJohnny Huang config_offset = 0x800; 37069d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 37169d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 37269d5fd8fSJohnny Huang 37369d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 37469d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 37569d5fd8fSJohnny Huang udelay(2); 37669d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 37769d5fd8fSJohnny Huang } 37869d5fd8fSJohnny Huang 37969d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 38069d5fd8fSJohnny Huang { 38169d5fd8fSJohnny Huang int i; 38269d5fd8fSJohnny Huang uint32_t ret[1]; 38369d5fd8fSJohnny Huang 38469d5fd8fSJohnny Huang if (offset + dw_count > 32) 3852a856b9aSJohnny Huang return OTP_USAGE; 38669d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 38769d5fd8fSJohnny Huang otp_read_config(i, ret); 388a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 38969d5fd8fSJohnny Huang } 39069d5fd8fSJohnny Huang printf("\n"); 3912a856b9aSJohnny Huang return OTP_SUCCESS; 39269d5fd8fSJohnny Huang } 39369d5fd8fSJohnny Huang 39469d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 39569d5fd8fSJohnny Huang { 39669d5fd8fSJohnny Huang int i; 39769d5fd8fSJohnny Huang uint32_t ret[2]; 39869d5fd8fSJohnny Huang 39969d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 4002a856b9aSJohnny Huang return OTP_USAGE; 40169d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 40269d5fd8fSJohnny Huang otp_read_data(i, ret); 40369d5fd8fSJohnny Huang if (i % 4 == 0) 40469d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 40569d5fd8fSJohnny Huang else 40669d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 40769d5fd8fSJohnny Huang 40869d5fd8fSJohnny Huang } 40969d5fd8fSJohnny Huang printf("\n"); 4102a856b9aSJohnny Huang return OTP_SUCCESS; 41169d5fd8fSJohnny Huang } 41269d5fd8fSJohnny Huang 41369d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 41469d5fd8fSJohnny Huang { 41569d5fd8fSJohnny Huang uint32_t ret; 41669d5fd8fSJohnny Huang uint32_t *buf; 41769d5fd8fSJohnny Huang 41869d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 41969d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 42069d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 42169d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 42269d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 42369d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 42469d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 42569d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 42669d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 42769d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 42869d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 42969d5fd8fSJohnny Huang udelay(10); 43069d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 43169d5fd8fSJohnny Huang if (ret & 0x1) 43269d5fd8fSJohnny Huang return 0; 43369d5fd8fSJohnny Huang else 43469d5fd8fSJohnny Huang return -1; 43569d5fd8fSJohnny Huang } 43669d5fd8fSJohnny Huang 43769d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 43869d5fd8fSJohnny Huang { 43969d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 44069d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 44169d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 44269d5fd8fSJohnny Huang udelay(100); 44369d5fd8fSJohnny Huang } 44469d5fd8fSJohnny Huang 44569d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 44669d5fd8fSJohnny Huang { 44769d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 44869d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 44969d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 45069d5fd8fSJohnny Huang udelay(85); 45169d5fd8fSJohnny Huang } 45269d5fd8fSJohnny Huang 453a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 45469d5fd8fSJohnny Huang { 45569d5fd8fSJohnny Huang int ret; 45669d5fd8fSJohnny Huang 45769d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 45869d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 45969d5fd8fSJohnny Huang udelay(2); 46069d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 461a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 46269d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 46369d5fd8fSJohnny Huang return 0; 46469d5fd8fSJohnny Huang else 46569d5fd8fSJohnny Huang return -1; 46669d5fd8fSJohnny Huang } 46769d5fd8fSJohnny Huang 468d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 4694c1c9b35SJohnny Huang { 4704c1c9b35SJohnny Huang uint32_t ret[2]; 4714c1c9b35SJohnny Huang 4724c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4734c1c9b35SJohnny Huang 4744c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4754c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 4764c1c9b35SJohnny Huang else 4774c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 4784c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 4794c1c9b35SJohnny Huang udelay(2); 4804c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 4814c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 4824c1c9b35SJohnny Huang if (size == 1) { 4834c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4844c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 485d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 4864c1c9b35SJohnny Huang compare[0] = 0; 4874c1c9b35SJohnny Huang return 0; 4884c1c9b35SJohnny Huang } else { 4894c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4904c1c9b35SJohnny Huang return -1; 4914c1c9b35SJohnny Huang } 4924c1c9b35SJohnny Huang 4934c1c9b35SJohnny Huang } else { 4944c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 495d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 4964c1c9b35SJohnny Huang compare[0] = ~0; 4974c1c9b35SJohnny Huang return 0; 4984c1c9b35SJohnny Huang } else { 499d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 5004c1c9b35SJohnny Huang return -1; 5014c1c9b35SJohnny Huang } 5024c1c9b35SJohnny Huang } 5034c1c9b35SJohnny Huang } else if (size == 2) { 5044c1c9b35SJohnny Huang // otp_addr should be even 505d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 5064c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 5074c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 5084c1c9b35SJohnny Huang compare[0] = 0; 5094c1c9b35SJohnny Huang compare[1] = ~0; 5104c1c9b35SJohnny Huang return 0; 5114c1c9b35SJohnny Huang } else { 5124c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 5134c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 5144c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 5154c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 5164c1c9b35SJohnny Huang return -1; 5174c1c9b35SJohnny Huang } 5184c1c9b35SJohnny Huang } else { 5194c1c9b35SJohnny Huang return -1; 5204c1c9b35SJohnny Huang } 5214c1c9b35SJohnny Huang } 5224c1c9b35SJohnny Huang 5237e22f42dSJohnny Huang static void otp_soak(int soak) 524d90825e2SJohnny Huang { 525d90825e2SJohnny Huang if (soak) { 526d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 527d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 528d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 529d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 530d90825e2SJohnny Huang } else { 531d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 532d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 533d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 534d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 535d90825e2SJohnny Huang } 536d90825e2SJohnny Huang } 537d90825e2SJohnny Huang 538d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 539d90825e2SJohnny Huang { 540d90825e2SJohnny Huang int j, bit_value, prog_bit; 541d90825e2SJohnny Huang 542d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 543d90825e2SJohnny Huang if ((keep >> j) & 0x1) 544d90825e2SJohnny Huang continue; 545d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 546d90825e2SJohnny Huang if (prog_address % 2 == 0) { 547d90825e2SJohnny Huang if (bit_value) 548d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 549d90825e2SJohnny Huang else 550d90825e2SJohnny Huang continue; 551d90825e2SJohnny Huang } else { 552d90825e2SJohnny Huang prog_address |= 1 << 15; 553d90825e2SJohnny Huang if (bit_value) 554d90825e2SJohnny Huang continue; 555d90825e2SJohnny Huang else 556d90825e2SJohnny Huang prog_bit = 0x1 << j; 557d90825e2SJohnny Huang } 558d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 559d90825e2SJohnny Huang } 560d90825e2SJohnny Huang } 561d90825e2SJohnny Huang 56276d13988SJohnny Huang 56376d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 56476d13988SJohnny Huang { 56576d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 56676d13988SJohnny Huang int i, j; 56776d13988SJohnny Huang 56876d13988SJohnny Huang for (j = 0; j < 64; j++) { 56976d13988SJohnny Huang otpstrap[j].value = 0; 57076d13988SJohnny Huang otpstrap[j].remain_times = 7; 57176d13988SJohnny Huang otpstrap[j].writeable_option = -1; 57276d13988SJohnny Huang otpstrap[j].protected = 0; 57376d13988SJohnny Huang } 57476d13988SJohnny Huang 57576d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 57676d13988SJohnny Huang int option = (i - 16) / 2; 57776d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 57876d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 57976d13988SJohnny Huang for (j = 0; j < 32; j++) { 58076d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 58176d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 58276d13988SJohnny Huang otpstrap[j].writeable_option = option; 58376d13988SJohnny Huang } 58476d13988SJohnny Huang if (bit_value == 1) 58576d13988SJohnny Huang otpstrap[j].remain_times --; 58676d13988SJohnny Huang otpstrap[j].value ^= bit_value; 58776d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 58876d13988SJohnny Huang } 58976d13988SJohnny Huang for (j = 32; j < 64; j++) { 59076d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 59176d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 59276d13988SJohnny Huang otpstrap[j].writeable_option = option; 59376d13988SJohnny Huang } 59476d13988SJohnny Huang if (bit_value == 1) 59576d13988SJohnny Huang otpstrap[j].remain_times --; 59676d13988SJohnny Huang otpstrap[j].value ^= bit_value; 59776d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 59876d13988SJohnny Huang } 59976d13988SJohnny Huang } 60076d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 60176d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 60276d13988SJohnny Huang for (j = 0; j < 32; j++) { 60376d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 60476d13988SJohnny Huang otpstrap[j].protected = 1; 60576d13988SJohnny Huang } 60676d13988SJohnny Huang for (j = 32; j < 64; j++) { 60776d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 60876d13988SJohnny Huang otpstrap[j].protected = 1; 60976d13988SJohnny Huang } 61076d13988SJohnny Huang } 61176d13988SJohnny Huang 61266f2f8e5SJohnny Huang static int otp_conf_parse(uint32_t *OTPCFG, struct otpconf_parse *conf_parse) 61369d5fd8fSJohnny Huang { 6144c1c9b35SJohnny Huang int tmp, i; 61566f2f8e5SJohnny Huang int k = 0; 6164c1c9b35SJohnny Huang int pass = 0; 617442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 61869d5fd8fSJohnny Huang 61966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 62066f2f8e5SJohnny Huang conf_parse[k].bit = 0; 62166f2f8e5SJohnny Huang conf_parse[k].length = 1; 62266f2f8e5SJohnny Huang conf_parse[k].value = DISABLE_SECREG_PROG(OTPCFG[0]); 62366f2f8e5SJohnny Huang if (DISABLE_SECREG_PROG(OTPCFG_KEEP[0])) { 62466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 62566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 626442839bbSJohnny Huang } else { 62766f2f8e5SJohnny Huang if (DISABLE_SECREG_PROG(OTPCFG[0])) 62866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 62966f2f8e5SJohnny Huang "Disable Secure Region programming"); 63069d5fd8fSJohnny Huang else 63166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 63266f2f8e5SJohnny Huang "Enable Secure Region programming"); 633442839bbSJohnny Huang } 634442839bbSJohnny Huang 63566f2f8e5SJohnny Huang k++; 63666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 63766f2f8e5SJohnny Huang conf_parse[k].bit = 1; 63866f2f8e5SJohnny Huang conf_parse[k].length = 1; 63966f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SEC_BOOT(OTPCFG[0]); 64066f2f8e5SJohnny Huang if (ENABLE_SEC_BOOT(OTPCFG_KEEP[0])) { 64166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 64266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 643442839bbSJohnny Huang } else { 64466f2f8e5SJohnny Huang if (ENABLE_SEC_BOOT(OTPCFG[0])) 64566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 64666f2f8e5SJohnny Huang "Enable Secure Boot"); 64769d5fd8fSJohnny Huang else 64866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 64966f2f8e5SJohnny Huang "Disable Secure Boot"); 650442839bbSJohnny Huang } 651442839bbSJohnny Huang 65266f2f8e5SJohnny Huang k++; 65366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 65466f2f8e5SJohnny Huang conf_parse[k].bit = 3; 65566f2f8e5SJohnny Huang conf_parse[k].length = 1; 65666f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_USERREG_ECC(OTPCFG[0]); 65766f2f8e5SJohnny Huang if (ENABLE_USERREG_ECC(OTPCFG_KEEP[0])) { 65866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 65966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 660442839bbSJohnny Huang } else { 66166f2f8e5SJohnny Huang if (ENABLE_USERREG_ECC(OTPCFG[0])) 66266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 66366f2f8e5SJohnny Huang "User region ECC enable"); 66469d5fd8fSJohnny Huang else 66566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 66666f2f8e5SJohnny Huang "User region ECC disable"); 667442839bbSJohnny Huang } 668442839bbSJohnny Huang 66966f2f8e5SJohnny Huang k++; 67066f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 67166f2f8e5SJohnny Huang conf_parse[k].bit = 4; 67266f2f8e5SJohnny Huang conf_parse[k].length = 1; 67366f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SECREG_ECC(OTPCFG[0]); 67466f2f8e5SJohnny Huang if (ENABLE_SECREG_ECC(OTPCFG_KEEP[0])) { 67566f2f8e5SJohnny Huang conf_parse[k].keep = 1; 67666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 677442839bbSJohnny Huang } else { 67866f2f8e5SJohnny Huang if (ENABLE_SECREG_ECC(OTPCFG[0])) 67966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 68066f2f8e5SJohnny Huang "Secure Region ECC enable"); 68169d5fd8fSJohnny Huang else 68266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 68366f2f8e5SJohnny Huang "Secure Region ECC disable"); 684442839bbSJohnny Huang } 685442839bbSJohnny Huang 68666f2f8e5SJohnny Huang k++; 68766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 68866f2f8e5SJohnny Huang conf_parse[k].bit = 5; 68966f2f8e5SJohnny Huang conf_parse[k].length = 1; 69066f2f8e5SJohnny Huang conf_parse[k].value = DISABLE_LOW_SEC_KEY(OTPCFG[0]); 69166f2f8e5SJohnny Huang if (DISABLE_LOW_SEC_KEY(OTPCFG_KEEP[0])) { 69266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 69366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 694442839bbSJohnny Huang } else { 69566f2f8e5SJohnny Huang if (DISABLE_LOW_SEC_KEY(OTPCFG[0])) 69666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 69766f2f8e5SJohnny Huang "Disable low security key"); 69869d5fd8fSJohnny Huang else 69966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 70066f2f8e5SJohnny Huang "Enable low security key"); 701442839bbSJohnny Huang } 702442839bbSJohnny Huang 70366f2f8e5SJohnny Huang k++; 70466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 70566f2f8e5SJohnny Huang conf_parse[k].bit = 6; 70666f2f8e5SJohnny Huang conf_parse[k].length = 1; 70766f2f8e5SJohnny Huang conf_parse[k].value = IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0]); 70866f2f8e5SJohnny Huang if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG_KEEP[0])) { 70966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 71066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 711442839bbSJohnny Huang } else { 71266f2f8e5SJohnny Huang if (IGNORE_SEC_BOOT_HWSTRAP(OTPCFG[0])) 71366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 71466f2f8e5SJohnny Huang "Ignore Secure Boot hardware strap"); 71569d5fd8fSJohnny Huang else 71666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 71766f2f8e5SJohnny Huang "Do not ignore Secure Boot hardware strap"); 718442839bbSJohnny Huang } 719442839bbSJohnny Huang 72066f2f8e5SJohnny Huang k++; 72166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 72266f2f8e5SJohnny Huang conf_parse[k].bit = 7; 72366f2f8e5SJohnny Huang conf_parse[k].length = 1; 72466f2f8e5SJohnny Huang conf_parse[k].value = SEC_BOOT_MDOES(OTPCFG[0]); 72566f2f8e5SJohnny Huang if (SEC_BOOT_MDOES(OTPCFG_KEEP[0])) { 72666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 72766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 728442839bbSJohnny Huang } else { 72966f2f8e5SJohnny Huang if (SEC_BOOT_MDOES(OTPCFG[0])) 73066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 73166f2f8e5SJohnny Huang "Secure Boot Mode: 1"); 732e1f9e54eSJohnny Huang else 73366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 73466f2f8e5SJohnny Huang "Secure Boot Mode: 2"); 735442839bbSJohnny Huang } 736442839bbSJohnny Huang 73766f2f8e5SJohnny Huang k++; 73866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 73966f2f8e5SJohnny Huang conf_parse[k].bit = 8; 74066f2f8e5SJohnny Huang conf_parse[k].length = 2; 74166f2f8e5SJohnny Huang conf_parse[k].value = OTP_BIT_CELL_MODES(OTPCFG[0]); 742442839bbSJohnny Huang if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0x3) { 74366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 74466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 74566f2f8e5SJohnny Huang } else if (OTP_BIT_CELL_MODES(OTPCFG_KEEP[0]) == 0) { 74666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "OTP bit cell mode : "); 74766f2f8e5SJohnny Huang if (conf_parse[k].value == SINGLE_CELL_MODE) { 74866f2f8e5SJohnny Huang strcat(conf_parse[k].status, 74966f2f8e5SJohnny Huang "Single cell mode (recommended)"); 75066f2f8e5SJohnny Huang } else if (conf_parse[k].value == DIFFERENTIAL_MODE) { 75166f2f8e5SJohnny Huang strcat(conf_parse[k].status, 75266f2f8e5SJohnny Huang "Differnetial mode"); 75366f2f8e5SJohnny Huang } else if (conf_parse[k].value == DIFFERENTIAL_REDUDANT_MODE) { 75466f2f8e5SJohnny Huang strcat(conf_parse[k].status, 75566f2f8e5SJohnny Huang "Differential-redundant mode"); 756442839bbSJohnny Huang } else { 75766f2f8e5SJohnny Huang strcat(conf_parse[k].status, 75866f2f8e5SJohnny Huang "Value error"); 75969d5fd8fSJohnny Huang return -1; 76069d5fd8fSJohnny Huang } 76166f2f8e5SJohnny Huang } else { 76266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 76366f2f8e5SJohnny Huang return -1; 764442839bbSJohnny Huang } 76566f2f8e5SJohnny Huang 76666f2f8e5SJohnny Huang k++; 76766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 76866f2f8e5SJohnny Huang conf_parse[k].bit = 10; 76966f2f8e5SJohnny Huang conf_parse[k].length = 2; 77066f2f8e5SJohnny Huang conf_parse[k].value = CRYPTO_MODES(OTPCFG[0]); 771442839bbSJohnny Huang if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0x3) { 77266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 77366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 77466f2f8e5SJohnny Huang } else if (CRYPTO_MODES(OTPCFG_KEEP[0]) == 0) { 77566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "RSA mode : "); 77666f2f8e5SJohnny Huang if (conf_parse[k].value == CRYPTO_RSA1024) { 77766f2f8e5SJohnny Huang strcat(conf_parse[k].status, 77866f2f8e5SJohnny Huang "RSA1024"); 77966f2f8e5SJohnny Huang } else if (conf_parse[k].value == CRYPTO_RSA2048) { 78066f2f8e5SJohnny Huang strcat(conf_parse[k].status, 78166f2f8e5SJohnny Huang "RSA2048"); 78266f2f8e5SJohnny Huang } else if (conf_parse[k].value == CRYPTO_RSA3072) { 78366f2f8e5SJohnny Huang strcat(conf_parse[k].status, 78466f2f8e5SJohnny Huang "RSA3072"); 785442839bbSJohnny Huang } else { 78666f2f8e5SJohnny Huang strcat(conf_parse[k].status, 78766f2f8e5SJohnny Huang "RSA4096"); 78866f2f8e5SJohnny Huang } 78969d5fd8fSJohnny Huang } else { 79066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 79166f2f8e5SJohnny Huang return -1; 79269d5fd8fSJohnny Huang } 79366f2f8e5SJohnny Huang 79466f2f8e5SJohnny Huang k++; 79566f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 79666f2f8e5SJohnny Huang conf_parse[k].bit = 12; 79766f2f8e5SJohnny Huang conf_parse[k].length = 2; 79866f2f8e5SJohnny Huang conf_parse[k].value = HASH_MODES(OTPCFG[0]); 799442839bbSJohnny Huang if (HASH_MODES(OTPCFG_KEEP[0]) == 0x3) { 80066f2f8e5SJohnny Huang conf_parse[k].keep = 1; 80166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 80266f2f8e5SJohnny Huang } else if (HASH_MODES(OTPCFG_KEEP[0]) == 0) { 80366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "SHA mode : "); 80466f2f8e5SJohnny Huang if (conf_parse[k].value == HASH_SAH224) { 80566f2f8e5SJohnny Huang strcat(conf_parse[k].status, 80666f2f8e5SJohnny Huang "SHA224"); 80766f2f8e5SJohnny Huang } else if (conf_parse[k].value == HASH_SAH256) { 80866f2f8e5SJohnny Huang strcat(conf_parse[k].status, 80966f2f8e5SJohnny Huang "SHA256"); 81066f2f8e5SJohnny Huang } else if (conf_parse[k].value == HASH_SAH384) { 81166f2f8e5SJohnny Huang strcat(conf_parse[k].status, 81266f2f8e5SJohnny Huang "SHA384"); 813442839bbSJohnny Huang } else { 81466f2f8e5SJohnny Huang strcat(conf_parse[k].status, 81566f2f8e5SJohnny Huang "SHA512"); 81669d5fd8fSJohnny Huang } 81766f2f8e5SJohnny Huang } else { 81866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 81966f2f8e5SJohnny Huang return -1; 820442839bbSJohnny Huang } 82169d5fd8fSJohnny Huang 82266f2f8e5SJohnny Huang k++; 82366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 82466f2f8e5SJohnny Huang conf_parse[k].bit = 16; 82566f2f8e5SJohnny Huang conf_parse[k].length = 6; 82666f2f8e5SJohnny Huang conf_parse[k].value = SECREG_SIZE(OTPCFG[0]); 827442839bbSJohnny Huang if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0x3f) { 82866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 82966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 83066f2f8e5SJohnny Huang } else if (SECREG_SIZE(OTPCFG_KEEP[0]) == 0) { 83166f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 83266f2f8e5SJohnny Huang "Secure Region size (DW): 0x%x", SECREG_SIZE(OTPCFG[0])); 833442839bbSJohnny Huang } else { 83466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 83566f2f8e5SJohnny Huang return -1; 836442839bbSJohnny Huang } 83769d5fd8fSJohnny Huang 83866f2f8e5SJohnny Huang k++; 83966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 84066f2f8e5SJohnny Huang conf_parse[k].bit = 22; 84166f2f8e5SJohnny Huang conf_parse[k].length = 1; 84266f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_SECREG(OTPCFG[0]); 84366f2f8e5SJohnny Huang if (WRITE_PROTECT_SECREG(OTPCFG_KEEP[0])) { 84466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 84566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 846442839bbSJohnny Huang } else { 84766f2f8e5SJohnny Huang if (WRITE_PROTECT_SECREG(OTPCFG[0])) 84866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 84966f2f8e5SJohnny Huang "Secure Region : Write Protect"); 85069d5fd8fSJohnny Huang else 85166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 85266f2f8e5SJohnny Huang "Secure Region : Writable"); 853442839bbSJohnny Huang } 854442839bbSJohnny Huang 85566f2f8e5SJohnny Huang k++; 85666f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 85766f2f8e5SJohnny Huang conf_parse[k].bit = 23; 85866f2f8e5SJohnny Huang conf_parse[k].length = 1; 85966f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_USERREG(OTPCFG[0]); 86066f2f8e5SJohnny Huang if (WRITE_PROTECT_USERREG(OTPCFG_KEEP[0])) { 86166f2f8e5SJohnny Huang conf_parse[k].keep = 1; 86266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 863442839bbSJohnny Huang } else { 86466f2f8e5SJohnny Huang if (WRITE_PROTECT_USERREG(OTPCFG[0])) 86566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 86666f2f8e5SJohnny Huang "User Region : Write Protect"); 86769d5fd8fSJohnny Huang else 86866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 86966f2f8e5SJohnny Huang "User Region : Writable"); 870442839bbSJohnny Huang } 871442839bbSJohnny Huang 87266f2f8e5SJohnny Huang k++; 87366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 87466f2f8e5SJohnny Huang conf_parse[k].bit = 24; 87566f2f8e5SJohnny Huang conf_parse[k].length = 1; 87666f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_CONFREG(OTPCFG[0]); 87766f2f8e5SJohnny Huang if (WRITE_PROTECT_CONFREG(OTPCFG_KEEP[0])) { 87866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 87966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 880442839bbSJohnny Huang } else { 88166f2f8e5SJohnny Huang if (WRITE_PROTECT_CONFREG(OTPCFG[0])) 88266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 88366f2f8e5SJohnny Huang "Configure Region : Write Protect"); 88469d5fd8fSJohnny Huang else 88566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 88666f2f8e5SJohnny Huang "Configure Region : Writable"); 887442839bbSJohnny Huang } 888442839bbSJohnny Huang 88966f2f8e5SJohnny Huang k++; 89066f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 89166f2f8e5SJohnny Huang conf_parse[k].bit = 25; 89266f2f8e5SJohnny Huang conf_parse[k].length = 1; 89366f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_STRAPREG(OTPCFG[0]); 89466f2f8e5SJohnny Huang if (WRITE_PROTECT_STRAPREG(OTPCFG_KEEP[0])) { 89566f2f8e5SJohnny Huang conf_parse[k].keep = 1; 89666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 897442839bbSJohnny Huang } else { 89866f2f8e5SJohnny Huang if (WRITE_PROTECT_STRAPREG(OTPCFG[0])) 89966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 90066f2f8e5SJohnny Huang "OTP strap Region : Write Protect"); 90169d5fd8fSJohnny Huang else 90266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 90366f2f8e5SJohnny Huang "OTP strap Region : Writable"); 904442839bbSJohnny Huang } 905442839bbSJohnny Huang 90666f2f8e5SJohnny Huang k++; 90766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 90866f2f8e5SJohnny Huang conf_parse[k].bit = 26; 90966f2f8e5SJohnny Huang conf_parse[k].length = 1; 91066f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_COPY_TO_SRAM(OTPCFG[0]); 91166f2f8e5SJohnny Huang if (ENABLE_COPY_TO_SRAM(OTPCFG_KEEP[0])) { 91266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 91366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 914442839bbSJohnny Huang } else { 91566f2f8e5SJohnny Huang if (ENABLE_COPY_TO_SRAM(OTPCFG[0])) 91666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 91766f2f8e5SJohnny Huang "Copy Boot Image to Internal SRAM"); 91869d5fd8fSJohnny Huang else 91966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 92066f2f8e5SJohnny Huang "Disable Copy Boot Image to Internal SRAM"); 921442839bbSJohnny Huang } 92266f2f8e5SJohnny Huang 92366f2f8e5SJohnny Huang k++; 92466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 92566f2f8e5SJohnny Huang conf_parse[k].bit = 27; 92666f2f8e5SJohnny Huang conf_parse[k].length = 1; 92766f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_IMAGE_ENC(OTPCFG[0]); 92866f2f8e5SJohnny Huang if (ENABLE_IMAGE_ENC(OTPCFG_KEEP[0])) { 92966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 93066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 931442839bbSJohnny Huang } else { 93266f2f8e5SJohnny Huang if (ENABLE_IMAGE_ENC(OTPCFG[0])) 93366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 93466f2f8e5SJohnny Huang "Enable image encryption"); 93569d5fd8fSJohnny Huang else 93666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 93766f2f8e5SJohnny Huang "Disable image encryption"); 938442839bbSJohnny Huang } 939442839bbSJohnny Huang 94066f2f8e5SJohnny Huang k++; 94166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 94266f2f8e5SJohnny Huang conf_parse[k].bit = 29; 94366f2f8e5SJohnny Huang conf_parse[k].length = 1; 94466f2f8e5SJohnny Huang conf_parse[k].value = WRITE_PROTECT_KEY_RETIRE(OTPCFG[0]); 94566f2f8e5SJohnny Huang if (WRITE_PROTECT_KEY_RETIRE(OTPCFG_KEEP[0])) { 94666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 94766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 948442839bbSJohnny Huang } else { 94966f2f8e5SJohnny Huang if (WRITE_PROTECT_KEY_RETIRE(OTPCFG[0])) 95066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 95166f2f8e5SJohnny Huang "OTP key retire Region : Write Protect"); 95269d5fd8fSJohnny Huang else 95366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 95466f2f8e5SJohnny Huang "OTP key retire Region : Writable"); 955442839bbSJohnny Huang } 956442839bbSJohnny Huang 95766f2f8e5SJohnny Huang k++; 95866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 95966f2f8e5SJohnny Huang conf_parse[k].bit = 30; 96066f2f8e5SJohnny Huang conf_parse[k].length = 1; 96166f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SIPROM_RED(OTPCFG[0]); 96266f2f8e5SJohnny Huang if (ENABLE_SIPROM_RED(OTPCFG_KEEP[0])) { 96366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 96466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 965442839bbSJohnny Huang } else { 96666f2f8e5SJohnny Huang if (ENABLE_SIPROM_RED(OTPCFG[0])) 96766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 96866f2f8e5SJohnny Huang "SIPROM RED_EN redundancy repair enable"); 96969d5fd8fSJohnny Huang else 97066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 97166f2f8e5SJohnny Huang "SIPROM RED_EN redundancy repair disable"); 972442839bbSJohnny Huang } 973442839bbSJohnny Huang 97466f2f8e5SJohnny Huang k++; 97566f2f8e5SJohnny Huang conf_parse[k].dw_offset = 0; 97666f2f8e5SJohnny Huang conf_parse[k].bit = 31; 97766f2f8e5SJohnny Huang conf_parse[k].length = 1; 97866f2f8e5SJohnny Huang conf_parse[k].value = ENABLE_SIPROM_MLOCK(OTPCFG[0]); 97966f2f8e5SJohnny Huang if (ENABLE_SIPROM_MLOCK(OTPCFG_KEEP[0])) { 98066f2f8e5SJohnny Huang conf_parse[k].keep = 1; 98166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 982442839bbSJohnny Huang } else { 98366f2f8e5SJohnny Huang if (ENABLE_SIPROM_MLOCK(OTPCFG[0])) 98466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 98566f2f8e5SJohnny Huang "SIPROM Mlock memory lock enable"); 98669d5fd8fSJohnny Huang else 98766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, 98866f2f8e5SJohnny Huang "SIPROM Mlock memory lock disable"); 989442839bbSJohnny Huang } 99069d5fd8fSJohnny Huang 99166f2f8e5SJohnny Huang k++; 99266f2f8e5SJohnny Huang conf_parse[k].dw_offset = 2; 99366f2f8e5SJohnny Huang conf_parse[k].bit = 0; 99466f2f8e5SJohnny Huang conf_parse[k].length = 16; 99566f2f8e5SJohnny Huang conf_parse[k].value = VENDER_ID(OTPCFG[2]); 99666f2f8e5SJohnny Huang if (VENDER_ID(OTPCFG_KEEP[2]) == 0xffff) { 99766f2f8e5SJohnny Huang conf_parse[k].keep = 1; 99866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 99966f2f8e5SJohnny Huang } else if (VENDER_ID(OTPCFG_KEEP[2]) == 0) { 100066f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 100166f2f8e5SJohnny Huang "Vender ID : 0x%x", VENDER_ID(OTPCFG[2])); 1002442839bbSJohnny Huang } else { 100366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 100466f2f8e5SJohnny Huang return -1; 1005442839bbSJohnny Huang } 100669d5fd8fSJohnny Huang 100766f2f8e5SJohnny Huang k++; 100866f2f8e5SJohnny Huang conf_parse[k].dw_offset = 2; 100966f2f8e5SJohnny Huang conf_parse[k].bit = 16; 101066f2f8e5SJohnny Huang conf_parse[k].length = 16; 101166f2f8e5SJohnny Huang conf_parse[k].value = KEY_REVISION(OTPCFG[2]); 101266f2f8e5SJohnny Huang if (KEY_REVISION(OTPCFG_KEEP[2]) == 0xffff) { 101366f2f8e5SJohnny Huang conf_parse[k].keep = 1; 101466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 101566f2f8e5SJohnny Huang } else if (KEY_REVISION(OTPCFG_KEEP[2]) == 0) { 101666f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 101766f2f8e5SJohnny Huang "Key Revision : 0x%x", KEY_REVISION(OTPCFG[2])); 1018442839bbSJohnny Huang } else { 101966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 102066f2f8e5SJohnny Huang return -1; 102166f2f8e5SJohnny Huang } 102266f2f8e5SJohnny Huang 102366f2f8e5SJohnny Huang k++; 102466f2f8e5SJohnny Huang conf_parse[k].dw_offset = 3; 102566f2f8e5SJohnny Huang conf_parse[k].bit = 0; 102666f2f8e5SJohnny Huang conf_parse[k].length = 16; 102766f2f8e5SJohnny Huang conf_parse[k].value = SEC_BOOT_HEADER_OFFSET(OTPCFG[3]); 102866f2f8e5SJohnny Huang if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0xffff) { 102966f2f8e5SJohnny Huang conf_parse[k].keep = 1; 103066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 103166f2f8e5SJohnny Huang } else if (SEC_BOOT_HEADER_OFFSET(OTPCFG_KEEP[3]) == 0) { 103266f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 103366f2f8e5SJohnny Huang "Secure boot header offset : 0x%x", 1034e1f9e54eSJohnny Huang SEC_BOOT_HEADER_OFFSET(OTPCFG[3])); 103566f2f8e5SJohnny Huang } else { 103666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 103766f2f8e5SJohnny Huang return -1; 1038442839bbSJohnny Huang } 103969d5fd8fSJohnny Huang 104066f2f8e5SJohnny Huang k++; 104166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 4; 104266f2f8e5SJohnny Huang conf_parse[k].bit = 0; 104366f2f8e5SJohnny Huang conf_parse[k].length = 8; 104466f2f8e5SJohnny Huang conf_parse[k].value = KEYS_VALID_BITS(OTPCFG[4]); 104566f2f8e5SJohnny Huang if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0xff) { 104666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 104766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 104866f2f8e5SJohnny Huang } else if (KEYS_VALID_BITS(OTPCFG_KEEP[4]) == 0) { 1049e1f9e54eSJohnny Huang tmp = KEYS_VALID_BITS(OTPCFG[4]); 1050e1f9e54eSJohnny Huang if (tmp != 0) { 105169d5fd8fSJohnny Huang for (i = 0; i < 7; i++) { 105269d5fd8fSJohnny Huang if (tmp == (1 << i)) { 1053e1f9e54eSJohnny Huang pass = i + 1; 105469d5fd8fSJohnny Huang } 105569d5fd8fSJohnny Huang } 1056e1f9e54eSJohnny Huang } else { 1057e1f9e54eSJohnny Huang pass = 0; 1058e1f9e54eSJohnny Huang } 105966f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 106066f2f8e5SJohnny Huang "Keys valid : %d", pass); 1061442839bbSJohnny Huang } else { 106266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 106366f2f8e5SJohnny Huang return -1; 106466f2f8e5SJohnny Huang } 106566f2f8e5SJohnny Huang 106666f2f8e5SJohnny Huang k++; 106766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 4; 106866f2f8e5SJohnny Huang conf_parse[k].bit = 16; 106966f2f8e5SJohnny Huang conf_parse[k].length = 8; 107066f2f8e5SJohnny Huang conf_parse[k].value = KEYS_RETIRE_BITS(OTPCFG[4]); 107166f2f8e5SJohnny Huang if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0xff) { 107266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 107366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 107466f2f8e5SJohnny Huang } else if (KEYS_RETIRE_BITS(OTPCFG_KEEP[4]) == 0) { 1075e1f9e54eSJohnny Huang tmp = KEYS_RETIRE_BITS(OTPCFG[4]); 1076e1f9e54eSJohnny Huang if (tmp != 0) { 107769d5fd8fSJohnny Huang for (i = 0; i < 7; i++) { 107869d5fd8fSJohnny Huang if (tmp == (1 << i)) { 1079e1f9e54eSJohnny Huang pass = i + 1; 108069d5fd8fSJohnny Huang } 108169d5fd8fSJohnny Huang } 1082e1f9e54eSJohnny Huang } else { 1083e1f9e54eSJohnny Huang pass = 0; 108469d5fd8fSJohnny Huang } 108566f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 108666f2f8e5SJohnny Huang "Keys Retire ID : %d", pass); 108766f2f8e5SJohnny Huang } else { 108866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 108966f2f8e5SJohnny Huang return -1; 1090442839bbSJohnny Huang } 109166f2f8e5SJohnny Huang 109266f2f8e5SJohnny Huang k++; 109366f2f8e5SJohnny Huang conf_parse[k].dw_offset = 5; 109466f2f8e5SJohnny Huang conf_parse[k].bit = 0; 109566f2f8e5SJohnny Huang conf_parse[k].length = 32; 109666f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[5]; 1097442839bbSJohnny Huang if (OTPCFG_KEEP[5] == 0xFFFFFFFF) { 109866f2f8e5SJohnny Huang conf_parse[k].keep = 1; 109966f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 110066f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[5] == 0) { 110166f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 110266f2f8e5SJohnny Huang "User define data, random number low : 0x%x", OTPCFG[5]); 1103442839bbSJohnny Huang } else { 110466f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 110566f2f8e5SJohnny Huang return -1; 1106442839bbSJohnny Huang } 110769d5fd8fSJohnny Huang 110866f2f8e5SJohnny Huang k++; 110966f2f8e5SJohnny Huang conf_parse[k].dw_offset = 6; 111066f2f8e5SJohnny Huang conf_parse[k].bit = 0; 111166f2f8e5SJohnny Huang conf_parse[k].length = 32; 111266f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[6]; 1113442839bbSJohnny Huang if (OTPCFG_KEEP[6] == 0xFFFFFFFF) { 111466f2f8e5SJohnny Huang conf_parse[k].keep = 1; 111566f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 111666f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[6] == 0) { 111766f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 111866f2f8e5SJohnny Huang "User define data, random number high : 0x%x", OTPCFG[6]); 1119442839bbSJohnny Huang } else { 112066f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 112166f2f8e5SJohnny Huang return -1; 1122442839bbSJohnny Huang } 112369d5fd8fSJohnny Huang 112466f2f8e5SJohnny Huang k++; 112566f2f8e5SJohnny Huang conf_parse[k].dw_offset = 8; 112666f2f8e5SJohnny Huang conf_parse[k].bit = 0; 112766f2f8e5SJohnny Huang conf_parse[k].length = 32; 112866f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[8]; 1129442839bbSJohnny Huang if (OTPCFG_KEEP[8] == 0xFFFFFFFF) { 113066f2f8e5SJohnny Huang conf_parse[k].keep = 1; 113166f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 113266f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[8] == 0) { 113366f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 113466f2f8e5SJohnny Huang "Redundancy Repair : 0x%x", OTPCFG[8]); 1135442839bbSJohnny Huang } else { 113666f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 113766f2f8e5SJohnny Huang return -1; 1138442839bbSJohnny Huang } 113969d5fd8fSJohnny Huang 114066f2f8e5SJohnny Huang k++; 114166f2f8e5SJohnny Huang conf_parse[k].dw_offset = 10; 114266f2f8e5SJohnny Huang conf_parse[k].bit = 0; 114366f2f8e5SJohnny Huang conf_parse[k].length = 32; 114466f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[10]; 1145442839bbSJohnny Huang if (OTPCFG_KEEP[10] == 0xFFFFFFFF) { 114666f2f8e5SJohnny Huang conf_parse[k].keep = 1; 114766f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 114866f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[10] == 0) { 114966f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 115066f2f8e5SJohnny Huang "Manifest ID low : 0x%x", OTPCFG[10]); 1151442839bbSJohnny Huang } else { 115266f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 115366f2f8e5SJohnny Huang return -1; 1154442839bbSJohnny Huang } 115569d5fd8fSJohnny Huang 115666f2f8e5SJohnny Huang k++; 115766f2f8e5SJohnny Huang conf_parse[k].dw_offset = 11; 115866f2f8e5SJohnny Huang conf_parse[k].bit = 0; 115966f2f8e5SJohnny Huang conf_parse[k].length = 32; 116066f2f8e5SJohnny Huang conf_parse[k].value = OTPCFG[11]; 1161442839bbSJohnny Huang if (OTPCFG_KEEP[11] == 0xFFFFFFFF) { 116266f2f8e5SJohnny Huang conf_parse[k].keep = 1; 116366f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Skip"); 116466f2f8e5SJohnny Huang } else if (OTPCFG_KEEP[11] == 0) { 116566f2f8e5SJohnny Huang sprintf(conf_parse[k].status, 116666f2f8e5SJohnny Huang "Manifest ID high : 0x%x", OTPCFG[11]); 1167442839bbSJohnny Huang } else { 116866f2f8e5SJohnny Huang strcpy(conf_parse[k].status, "Keep mask error!"); 116966f2f8e5SJohnny Huang return -1; 1170442839bbSJohnny Huang } 1171442839bbSJohnny Huang 117266f2f8e5SJohnny Huang return k + 1; 117369d5fd8fSJohnny Huang 117469d5fd8fSJohnny Huang } 117569d5fd8fSJohnny Huang 117666f2f8e5SJohnny Huang static int otp_print_conf_info(uint32_t *OTPCFG) 117766f2f8e5SJohnny Huang { 117866f2f8e5SJohnny Huang struct otpconf_parse conf_parse[60]; 117966f2f8e5SJohnny Huang int length; 118066f2f8e5SJohnny Huang int i; 118166f2f8e5SJohnny Huang 118266f2f8e5SJohnny Huang length = otp_conf_parse(OTPCFG, conf_parse); 118366f2f8e5SJohnny Huang 118466f2f8e5SJohnny Huang if (length <= 0) 118566f2f8e5SJohnny Huang return OTP_FAILURE; 118666f2f8e5SJohnny Huang 1187737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 118866f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 118966f2f8e5SJohnny Huang for (i = 0; i < length; i++) { 119066f2f8e5SJohnny Huang printf("%-4d", conf_parse[i].dw_offset); 119166f2f8e5SJohnny Huang if (conf_parse[i].length == 1) { 119266f2f8e5SJohnny Huang printf("%-8d", conf_parse[i].bit); 119366f2f8e5SJohnny Huang } else { 119466f2f8e5SJohnny Huang printf("%-2d:%-5d", 119566f2f8e5SJohnny Huang conf_parse[i].bit + conf_parse[i].length - 1, 119666f2f8e5SJohnny Huang conf_parse[i].bit); 119766f2f8e5SJohnny Huang } 119866f2f8e5SJohnny Huang printf("0x%-10x", conf_parse[i].value); 119966f2f8e5SJohnny Huang printf("%s\n", conf_parse[i].status); 120066f2f8e5SJohnny Huang } 120166f2f8e5SJohnny Huang return OTP_SUCCESS; 120266f2f8e5SJohnny Huang } 120366f2f8e5SJohnny Huang 120466f2f8e5SJohnny Huang static void otp_info_config(void) 120566f2f8e5SJohnny Huang { 120666f2f8e5SJohnny Huang uint32_t OTPCFG[24]; 120766f2f8e5SJohnny Huang int i; 120866f2f8e5SJohnny Huang 120966f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 121066f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 121166f2f8e5SJohnny Huang 121266f2f8e5SJohnny Huang for (i = 12; i < 24; i++) 121366f2f8e5SJohnny Huang OTPCFG[i] = 0; 121466f2f8e5SJohnny Huang 121566f2f8e5SJohnny Huang otp_print_conf_info(OTPCFG); 121666f2f8e5SJohnny Huang } 121766f2f8e5SJohnny Huang 1218*a8bd6d8cSJohnny Huang static int otp_print_strap_info(uint32_t *OTPSTRAP, int view) 121976d13988SJohnny Huang { 1220*a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 1221*a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 122276d13988SJohnny Huang int i; 1223*a8bd6d8cSJohnny Huang int fail = 0; 1224*a8bd6d8cSJohnny Huang uint32_t bit_offset; 1225*a8bd6d8cSJohnny Huang uint32_t dw_offset; 1226*a8bd6d8cSJohnny Huang uint32_t mask; 1227*a8bd6d8cSJohnny Huang uint32_t otp_value; 1228*a8bd6d8cSJohnny Huang uint32_t otp_protect; 1229*a8bd6d8cSJohnny Huang uint32_t otp_keep; 123076d13988SJohnny Huang 1231*a8bd6d8cSJohnny Huang if (view) { 1232*a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 1233*a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 1234*a8bd6d8cSJohnny Huang } else { 1235*a8bd6d8cSJohnny Huang printf("BIT(hex) Value Description\n"); 1236*a8bd6d8cSJohnny Huang printf("______________________________________________________________________________\n"); 1237*a8bd6d8cSJohnny Huang } 1238*a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 1239*a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 1240*a8bd6d8cSJohnny Huang dw_offset = 1; 1241*a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 1242*a8bd6d8cSJohnny Huang } else { 1243*a8bd6d8cSJohnny Huang dw_offset = 0; 1244*a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 1245*a8bd6d8cSJohnny Huang } 124676d13988SJohnny Huang 1247*a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 1248*a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 1249*a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 1250*a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 1251*a8bd6d8cSJohnny Huang 1252*a8bd6d8cSJohnny Huang if (otp_keep == mask) { 1253*a8bd6d8cSJohnny Huang continue; 1254*a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 1255*a8bd6d8cSJohnny Huang fail = 1; 1256*a8bd6d8cSJohnny Huang } 1257*a8bd6d8cSJohnny Huang 1258*a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 1259*a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 1260*a8bd6d8cSJohnny Huang continue; 1261*a8bd6d8cSJohnny Huang 1262*a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 1263*a8bd6d8cSJohnny Huang printf("%-9X", a0_strap_info[i].bit_offset); 1264*a8bd6d8cSJohnny Huang } else { 1265*a8bd6d8cSJohnny Huang printf("%-2X:%-6X", 1266*a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 1267*a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 1268*a8bd6d8cSJohnny Huang } 1269*a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 1270*a8bd6d8cSJohnny Huang if (view) 1271*a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 1272*a8bd6d8cSJohnny Huang 1273*a8bd6d8cSJohnny Huang if (fail) { 1274*a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 1275*a8bd6d8cSJohnny Huang } else { 1276*a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 1277*a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 1278*a8bd6d8cSJohnny Huang else 1279*a8bd6d8cSJohnny Huang printf("Reserved\n"); 1280*a8bd6d8cSJohnny Huang } 1281*a8bd6d8cSJohnny Huang } 1282*a8bd6d8cSJohnny Huang 1283*a8bd6d8cSJohnny Huang if (fail) 128476d13988SJohnny Huang return OTP_FAILURE; 128576d13988SJohnny Huang 128676d13988SJohnny Huang return OTP_SUCCESS; 128776d13988SJohnny Huang } 128876d13988SJohnny Huang 1289*a8bd6d8cSJohnny Huang static void otp_info_strap(int view) 129076d13988SJohnny Huang { 129176d13988SJohnny Huang struct otpstrap_status strap_status[64]; 129276d13988SJohnny Huang uint32_t OTPSTRAP[6]; 129376d13988SJohnny Huang int i; 129476d13988SJohnny Huang 129576d13988SJohnny Huang 129676d13988SJohnny Huang otp_strp_status(strap_status); 129776d13988SJohnny Huang 129876d13988SJohnny Huang for (i = 0; i < 6; i++) 129976d13988SJohnny Huang OTPSTRAP[i] = 0; 130076d13988SJohnny Huang for (i = 0; i < 32; i++) { 130176d13988SJohnny Huang OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i; 130276d13988SJohnny Huang OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i; 130376d13988SJohnny Huang } 130476d13988SJohnny Huang for (i = 0; i < 32; i++) { 130576d13988SJohnny Huang OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i; 130676d13988SJohnny Huang OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i; 130776d13988SJohnny Huang } 130876d13988SJohnny Huang 1309*a8bd6d8cSJohnny Huang otp_print_strap_info(OTPSTRAP, view); 131076d13988SJohnny Huang } 131176d13988SJohnny Huang 131269d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 131369d5fd8fSJohnny Huang { 131469d5fd8fSJohnny Huang int i; 131569d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 131669d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 131769d5fd8fSJohnny Huang if (i % 16 == 0) { 131869d5fd8fSJohnny Huang printf("%04X: ", i); 131969d5fd8fSJohnny Huang } 132069d5fd8fSJohnny Huang printf("%02X ", buf[i]); 132169d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 132269d5fd8fSJohnny Huang printf("\n"); 132369d5fd8fSJohnny Huang } 132469d5fd8fSJohnny Huang } 132569d5fd8fSJohnny Huang } 132669d5fd8fSJohnny Huang 13277f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 132869d5fd8fSJohnny Huang { 132969d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 133069d5fd8fSJohnny Huang char *byte_buf; 133169d5fd8fSJohnny Huang int i = 0, len = 0; 133269d5fd8fSJohnny Huang byte_buf = (char *)buf; 133369d5fd8fSJohnny Huang while (1) { 133469d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 133569d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 133669d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 133769d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 133869d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 133969d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 13407f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 134169d5fd8fSJohnny Huang printf("Key Type: "); 134269d5fd8fSJohnny Huang switch (key_type) { 134369d5fd8fSJohnny Huang case 0: 134469d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 134569d5fd8fSJohnny Huang break; 134669d5fd8fSJohnny Huang case 1: 134769d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 134869d5fd8fSJohnny Huang break; 134969d5fd8fSJohnny Huang case 4: 135069d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 135169d5fd8fSJohnny Huang break; 135269d5fd8fSJohnny Huang case 8: 135369d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 135469d5fd8fSJohnny Huang break; 135569d5fd8fSJohnny Huang case 9: 135669d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 135769d5fd8fSJohnny Huang break; 135869d5fd8fSJohnny Huang case 10: 135969d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 136069d5fd8fSJohnny Huang break; 136169d5fd8fSJohnny Huang case 13: 136269d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 136369d5fd8fSJohnny Huang break; 136469d5fd8fSJohnny Huang case 14: 136569d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 136669d5fd8fSJohnny Huang break; 136769d5fd8fSJohnny Huang default: 136869d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 136969d5fd8fSJohnny Huang return -1; 137069d5fd8fSJohnny Huang } 137169d5fd8fSJohnny Huang if (key_type == 4) { 137269d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 137369d5fd8fSJohnny Huang switch (key_length) { 137469d5fd8fSJohnny Huang case 0: 137569d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 137669d5fd8fSJohnny Huang break; 137769d5fd8fSJohnny Huang case 1: 137869d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 137969d5fd8fSJohnny Huang break; 138069d5fd8fSJohnny Huang case 2: 138169d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 138269d5fd8fSJohnny Huang break; 138369d5fd8fSJohnny Huang case 3: 138469d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 138569d5fd8fSJohnny Huang break; 138669d5fd8fSJohnny Huang } 1387cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 138869d5fd8fSJohnny Huang printf("RSA SHA Type: "); 138969d5fd8fSJohnny Huang switch (key_length) { 139069d5fd8fSJohnny Huang case 0: 139169d5fd8fSJohnny Huang printf("RSA1024\n"); 139269d5fd8fSJohnny Huang len = 0x100; 139369d5fd8fSJohnny Huang break; 139469d5fd8fSJohnny Huang case 1: 139569d5fd8fSJohnny Huang printf("RSA2048\n"); 139669d5fd8fSJohnny Huang len = 0x200; 139769d5fd8fSJohnny Huang break; 139869d5fd8fSJohnny Huang case 2: 139969d5fd8fSJohnny Huang printf("RSA3072\n"); 140069d5fd8fSJohnny Huang len = 0x300; 140169d5fd8fSJohnny Huang break; 140269d5fd8fSJohnny Huang case 3: 140369d5fd8fSJohnny Huang printf("RSA4096\n"); 140469d5fd8fSJohnny Huang len = 0x400; 140569d5fd8fSJohnny Huang break; 140669d5fd8fSJohnny Huang } 140769d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 140869d5fd8fSJohnny Huang } 140969d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 141069d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 141169d5fd8fSJohnny Huang printf("Key Value:\n"); 141269d5fd8fSJohnny Huang if (key_type == 4) { 141369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 141469d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 141569d5fd8fSJohnny Huang printf("AES Key:\n"); 141669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 141769d5fd8fSJohnny Huang printf("AES IV:\n"); 141869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 141969d5fd8fSJohnny Huang 142069d5fd8fSJohnny Huang } else { 142169d5fd8fSJohnny Huang printf("RSA mod:\n"); 142269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 142369d5fd8fSJohnny Huang printf("RSA exp:\n"); 142469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 142569d5fd8fSJohnny Huang } 142669d5fd8fSJohnny Huang if (last) 142769d5fd8fSJohnny Huang break; 142869d5fd8fSJohnny Huang i++; 142969d5fd8fSJohnny Huang } 143069d5fd8fSJohnny Huang return 0; 143169d5fd8fSJohnny Huang } 143269d5fd8fSJohnny Huang 1433a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 143469d5fd8fSJohnny Huang { 1435a6d0d645SJohnny Huang int i, k; 1436d90825e2SJohnny Huang int pass = 0; 1437d90825e2SJohnny Huang int soak = 0; 1438a6d0d645SJohnny Huang uint32_t prog_address; 1439a6d0d645SJohnny Huang uint32_t data[12]; 1440a6d0d645SJohnny Huang uint32_t compare[2]; 1441d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1442d90825e2SJohnny Huang uint32_t data_masked; 1443d90825e2SJohnny Huang uint32_t buf_masked; 144469d5fd8fSJohnny Huang 1445a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1446a6d0d645SJohnny Huang 1447a6d0d645SJohnny Huang printProgress(0, 12, ""); 1448a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1449a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 145069d5fd8fSJohnny Huang prog_address = 0x800; 1451a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1452a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1453a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1454a6d0d645SJohnny Huang } 1455a6d0d645SJohnny Huang 1456a6d0d645SJohnny Huang printf("Check writable...\n"); 1457a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1458d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1459d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1460d90825e2SJohnny Huang if (data_masked == buf_masked) 146169d5fd8fSJohnny Huang continue; 1462d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1463a6d0d645SJohnny Huang continue; 1464a6d0d645SJohnny Huang } else { 1465a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1466a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1467a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1468a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 14692a856b9aSJohnny Huang return OTP_FAILURE; 1470a6d0d645SJohnny Huang } 1471a6d0d645SJohnny Huang } 1472a6d0d645SJohnny Huang 1473a6d0d645SJohnny Huang printf("Start Programing...\n"); 1474a6d0d645SJohnny Huang printProgress(0, 12, ""); 1475d90825e2SJohnny Huang otp_soak(0); 1476a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1477d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1478d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1479a6d0d645SJohnny Huang prog_address = 0x800; 1480a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1481a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1482d90825e2SJohnny Huang if (data_masked == buf_masked) { 1483a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1484a6d0d645SJohnny Huang continue; 1485a6d0d645SJohnny Huang } 1486d90825e2SJohnny Huang if (soak) { 1487d90825e2SJohnny Huang soak = 0; 1488d90825e2SJohnny Huang otp_soak(0); 1489d90825e2SJohnny Huang } 1490a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1491a6d0d645SJohnny Huang 1492d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1493a6d0d645SJohnny Huang 149469d5fd8fSJohnny Huang pass = 0; 149569d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1496d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1497d90825e2SJohnny Huang if (soak == 0) { 1498d90825e2SJohnny Huang soak = 1; 1499d90825e2SJohnny Huang otp_soak(1); 1500d90825e2SJohnny Huang } 1501a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1502a6d0d645SJohnny Huang } else { 150369d5fd8fSJohnny Huang pass = 1; 150469d5fd8fSJohnny Huang break; 150569d5fd8fSJohnny Huang } 150669d5fd8fSJohnny Huang } 1507a6d0d645SJohnny Huang } 1508a6d0d645SJohnny Huang 150969d5fd8fSJohnny Huang if (!pass) 15102a856b9aSJohnny Huang return OTP_FAILURE; 1511a6d0d645SJohnny Huang 15122a856b9aSJohnny Huang return OTP_SUCCESS; 1513d90825e2SJohnny Huang 151469d5fd8fSJohnny Huang } 151569d5fd8fSJohnny Huang 151669d5fd8fSJohnny Huang 151776d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 151869d5fd8fSJohnny Huang { 151969d5fd8fSJohnny Huang int i; 152069d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 152169d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 152269d5fd8fSJohnny Huang int bit, pbit, kbit; 152369d5fd8fSJohnny Huang int fail = 0; 1524a6af4a17SJohnny Huang int skip = -1; 152566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 152669d5fd8fSJohnny Huang 152769d5fd8fSJohnny Huang otp_strp_status(otpstrap); 152869d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 152969d5fd8fSJohnny Huang if (i < 32) { 153069d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 153169d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 153269d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 153369d5fd8fSJohnny Huang } else { 153469d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 153569d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 153669d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 153769d5fd8fSJohnny Huang } 153869d5fd8fSJohnny Huang 153969d5fd8fSJohnny Huang if (kbit == 1) { 154069d5fd8fSJohnny Huang continue; 154169d5fd8fSJohnny Huang } else { 1542a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 154369d5fd8fSJohnny Huang } 154469d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 154569d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1546a6af4a17SJohnny Huang if (skip == -1) 1547a6af4a17SJohnny Huang skip = 1; 154869d5fd8fSJohnny Huang continue; 1549a6af4a17SJohnny Huang } else { 1550a6af4a17SJohnny Huang skip = 0; 155169d5fd8fSJohnny Huang } 155269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 155369d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 155469d5fd8fSJohnny Huang fail = 1; 155569d5fd8fSJohnny Huang continue; 155669d5fd8fSJohnny Huang } 155769d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1558a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 155969d5fd8fSJohnny Huang fail = 1; 156069d5fd8fSJohnny Huang continue; 156169d5fd8fSJohnny Huang } 156269d5fd8fSJohnny Huang if (pbit == 1) { 156369d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 156469d5fd8fSJohnny Huang } 1565a6af4a17SJohnny Huang printf(" Write 1 to OTPSTRAP[%X] OPTION[%X], that value becomes from %d to %d.\n", i, otpstrap[i].writeable_option + 1, otpstrap[i].value, otpstrap[i].value ^ 1); 156669d5fd8fSJohnny Huang } 156769d5fd8fSJohnny Huang if (fail == 1) 1568a6af4a17SJohnny Huang return OTP_FAILURE; 1569a6af4a17SJohnny Huang else if (skip == 1) 1570a6af4a17SJohnny Huang return OTP_PROG_SKIP; 15717e22f42dSJohnny Huang 15727e22f42dSJohnny Huang return 0; 157369d5fd8fSJohnny Huang } 157469d5fd8fSJohnny Huang 15752a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 157669d5fd8fSJohnny Huang { 157769d5fd8fSJohnny Huang int i, j; 157866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 157969d5fd8fSJohnny Huang 15802a856b9aSJohnny Huang if (start < 0 || start > 64) 15812a856b9aSJohnny Huang return OTP_USAGE; 15822a856b9aSJohnny Huang 15832a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 15842a856b9aSJohnny Huang return OTP_USAGE; 15852a856b9aSJohnny Huang 158669d5fd8fSJohnny Huang otp_strp_status(otpstrap); 158769d5fd8fSJohnny Huang 1588*a8bd6d8cSJohnny Huang printf("BIT(hex) Value Avaliable Status\n"); 1589*a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1590737ed20bSJohnny Huang 1591cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 1592*a8bd6d8cSJohnny Huang printf("%-10X", i); 1593737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1594737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1595737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1596737ed20bSJohnny Huang printf(" "); 159769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1598737ed20bSJohnny Huang printf("protected and not writable"); 159969d5fd8fSJohnny Huang } else { 1600737ed20bSJohnny Huang printf("not protected "); 160169d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1602737ed20bSJohnny Huang printf("and no remaining times to write."); 160369d5fd8fSJohnny Huang } else { 1604737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 160569d5fd8fSJohnny Huang } 160669d5fd8fSJohnny Huang } 1607737ed20bSJohnny Huang printf("\n"); 160869d5fd8fSJohnny Huang } 16092a856b9aSJohnny Huang 16102a856b9aSJohnny Huang return OTP_SUCCESS; 161169d5fd8fSJohnny Huang } 161269d5fd8fSJohnny Huang 161369d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 161469d5fd8fSJohnny Huang { 161569d5fd8fSJohnny Huang int i, j; 161669d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 161769d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 161869d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 161969d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 162069d5fd8fSJohnny Huang int fail = 0; 16217e22f42dSJohnny Huang int pass = 0; 16227e22f42dSJohnny Huang int soak = 0; 162366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 162469d5fd8fSJohnny Huang 16257f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 162669d5fd8fSJohnny Huang otp_strp_status(otpstrap); 162769d5fd8fSJohnny Huang 16287f795e57SJohnny Huang printf("Check writable...\n"); 16297f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 16307f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 16317f795e57SJohnny Huang return OTP_FAILURE; 16327f795e57SJohnny Huang } 16337e22f42dSJohnny Huang 16347f795e57SJohnny Huang otp_soak(0); 163569d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 16364c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 163769d5fd8fSJohnny Huang prog_address = 0x800; 163869d5fd8fSJohnny Huang if (i < 32) { 163969d5fd8fSJohnny Huang offset = i; 164069d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 164169d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 164269d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 164369d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 164469d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 164569d5fd8fSJohnny Huang 164669d5fd8fSJohnny Huang } else { 164769d5fd8fSJohnny Huang offset = (i - 32); 164869d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 164969d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 165069d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 165169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 165269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 165369d5fd8fSJohnny Huang } 165469d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 165569d5fd8fSJohnny Huang 165669d5fd8fSJohnny Huang if (kbit == 1) { 165769d5fd8fSJohnny Huang continue; 165869d5fd8fSJohnny Huang } 165969d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 166069d5fd8fSJohnny Huang continue; 166169d5fd8fSJohnny Huang } 166269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 166369d5fd8fSJohnny Huang fail = 1; 166469d5fd8fSJohnny Huang continue; 166569d5fd8fSJohnny Huang } 166669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 166769d5fd8fSJohnny Huang fail = 1; 166869d5fd8fSJohnny Huang continue; 166969d5fd8fSJohnny Huang } 16707e22f42dSJohnny Huang 16717e22f42dSJohnny Huang if (soak) { 167269d5fd8fSJohnny Huang soak = 0; 16737e22f42dSJohnny Huang otp_soak(0); 16747e22f42dSJohnny Huang } 16757e22f42dSJohnny Huang 16767e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 16777e22f42dSJohnny Huang 16787e22f42dSJohnny Huang pass = 0; 16797e22f42dSJohnny Huang 168069d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1681a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 168269d5fd8fSJohnny Huang pass = 1; 168369d5fd8fSJohnny Huang break; 168469d5fd8fSJohnny Huang } 16857e22f42dSJohnny Huang if (soak == 0) { 168669d5fd8fSJohnny Huang soak = 1; 16877e22f42dSJohnny Huang otp_soak(1); 16884b65a65dSJohnny Huang } 168969d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 169069d5fd8fSJohnny Huang } 169169d5fd8fSJohnny Huang if (!pass) 16922a856b9aSJohnny Huang return OTP_FAILURE; 169369d5fd8fSJohnny Huang 169469d5fd8fSJohnny Huang if (pbit == 0) 169569d5fd8fSJohnny Huang continue; 169669d5fd8fSJohnny Huang prog_address = 0x800; 169769d5fd8fSJohnny Huang if (i < 32) 169869d5fd8fSJohnny Huang prog_address |= 0x60c; 169969d5fd8fSJohnny Huang else 170069d5fd8fSJohnny Huang prog_address |= 0x60e; 170169d5fd8fSJohnny Huang 17027e22f42dSJohnny Huang 17037e22f42dSJohnny Huang if (soak) { 17047e22f42dSJohnny Huang soak = 0; 17057e22f42dSJohnny Huang otp_soak(0); 17067e22f42dSJohnny Huang } 17077e22f42dSJohnny Huang 17087e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 17097e22f42dSJohnny Huang 17107e22f42dSJohnny Huang pass = 0; 17117e22f42dSJohnny Huang 171269d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 17137e22f42dSJohnny Huang 1714a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 171569d5fd8fSJohnny Huang pass = 1; 171669d5fd8fSJohnny Huang break; 171769d5fd8fSJohnny Huang } 17187e22f42dSJohnny Huang if (soak == 0) { 171969d5fd8fSJohnny Huang soak = 1; 17207e22f42dSJohnny Huang otp_soak(1); 172169d5fd8fSJohnny Huang } 172269d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 172369d5fd8fSJohnny Huang } 172469d5fd8fSJohnny Huang if (!pass) 17252a856b9aSJohnny Huang return OTP_FAILURE; 172669d5fd8fSJohnny Huang 172769d5fd8fSJohnny Huang } 172869d5fd8fSJohnny Huang if (fail == 1) 17292a856b9aSJohnny Huang return OTP_FAILURE; 173069d5fd8fSJohnny Huang else 17312a856b9aSJohnny Huang return OTP_SUCCESS; 173269d5fd8fSJohnny Huang 173369d5fd8fSJohnny Huang } 173469d5fd8fSJohnny Huang 1735cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1736cd1610b4SJohnny Huang { 1737cd1610b4SJohnny Huang int prog_bit; 1738cd1610b4SJohnny Huang 17397e22f42dSJohnny Huang otp_soak(soak); 17407e22f42dSJohnny Huang 1741cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1742cd1610b4SJohnny Huang if (value) 1743cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1744cd1610b4SJohnny Huang else 1745cd1610b4SJohnny Huang return; 1746cd1610b4SJohnny Huang } else { 1747cd1610b4SJohnny Huang prog_address |= 1 << 15; 1748cd1610b4SJohnny Huang if (!value) 1749cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1750cd1610b4SJohnny Huang else 1751cd1610b4SJohnny Huang return; 1752cd1610b4SJohnny Huang } 1753cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1754cd1610b4SJohnny Huang } 1755cd1610b4SJohnny Huang 1756d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 17574c1c9b35SJohnny Huang { 17584c1c9b35SJohnny Huang int i, k; 17594c1c9b35SJohnny Huang int pass; 1760d90825e2SJohnny Huang int soak = 0; 17614c1c9b35SJohnny Huang uint32_t prog_address; 1762d90825e2SJohnny Huang uint32_t data[2048]; 17634c1c9b35SJohnny Huang uint32_t compare[2]; 1764d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 17654c1c9b35SJohnny Huang 1766d90825e2SJohnny Huang uint32_t data0_masked; 1767d90825e2SJohnny Huang uint32_t data1_masked; 1768d90825e2SJohnny Huang uint32_t buf0_masked; 1769d90825e2SJohnny Huang uint32_t buf1_masked; 17704c1c9b35SJohnny Huang 17714c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 17724c1c9b35SJohnny Huang 1773d90825e2SJohnny Huang printProgress(0, 2048, ""); 1774d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1775d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1776d90825e2SJohnny Huang otp_read_data(i, &data[i]); 17774c1c9b35SJohnny Huang } 1778d90825e2SJohnny Huang 17794c1c9b35SJohnny Huang 17804c1c9b35SJohnny Huang printf("Check writable...\n"); 1781d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1782d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1783d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1784d90825e2SJohnny Huang if (data0_masked == buf0_masked) 17854c1c9b35SJohnny Huang continue; 1786d90825e2SJohnny Huang if (i % 2 == 0) { 1787d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 17884c1c9b35SJohnny Huang continue; 17894c1c9b35SJohnny Huang } else { 17904c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1791d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 17924c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1793d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 17942a856b9aSJohnny Huang return OTP_FAILURE; 179569d5fd8fSJohnny Huang } 1796d90825e2SJohnny Huang } else { 1797d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1798d90825e2SJohnny Huang continue; 1799d90825e2SJohnny Huang } else { 1800d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1801d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1802d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1803d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 18042a856b9aSJohnny Huang return OTP_FAILURE; 1805d90825e2SJohnny Huang } 1806d90825e2SJohnny Huang } 1807d90825e2SJohnny Huang } 180869d5fd8fSJohnny Huang 1809d90825e2SJohnny Huang printf("Start Programing...\n"); 1810d90825e2SJohnny Huang printProgress(0, 2048, ""); 1811d90825e2SJohnny Huang 1812d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1813d90825e2SJohnny Huang prog_address = i; 1814d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1815d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1816d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1817d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1818d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1819d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1820d90825e2SJohnny Huang continue; 1821d90825e2SJohnny Huang } 1822d90825e2SJohnny Huang if (soak) { 1823d90825e2SJohnny Huang soak = 0; 1824d90825e2SJohnny Huang otp_soak(0); 1825d90825e2SJohnny Huang } 1826d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1827d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1828d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1829d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1830d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1831d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1832d90825e2SJohnny Huang } else { 1833d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1834d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1835d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1836d90825e2SJohnny Huang } 1837d90825e2SJohnny Huang 1838d90825e2SJohnny Huang pass = 0; 1839d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1840d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1841d90825e2SJohnny Huang if (soak == 0) { 1842d90825e2SJohnny Huang soak = 1; 1843d90825e2SJohnny Huang otp_soak(1); 1844d90825e2SJohnny Huang } 1845d90825e2SJohnny Huang if (compare[0] != 0) { 1846d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1847d90825e2SJohnny Huang } 1848d90825e2SJohnny Huang if (compare[1] != ~0) { 1849d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1850d90825e2SJohnny Huang } 1851d90825e2SJohnny Huang } else { 1852d90825e2SJohnny Huang pass = 1; 1853d90825e2SJohnny Huang break; 1854d90825e2SJohnny Huang } 1855d90825e2SJohnny Huang } 1856d90825e2SJohnny Huang 1857d90825e2SJohnny Huang if (!pass) 18582a856b9aSJohnny Huang return OTP_FAILURE; 1859d90825e2SJohnny Huang } 18602a856b9aSJohnny Huang return OTP_SUCCESS; 1861d90825e2SJohnny Huang 1862d90825e2SJohnny Huang } 1863d90825e2SJohnny Huang 1864d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 186569d5fd8fSJohnny Huang { 186669d5fd8fSJohnny Huang int ret; 1867d90825e2SJohnny Huang int mode; 186869d5fd8fSJohnny Huang uint32_t *buf; 1869d90825e2SJohnny Huang uint32_t *data_region = NULL; 1870d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1871d90825e2SJohnny Huang uint32_t *strap_region = NULL; 187269d5fd8fSJohnny Huang 1873d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 187469d5fd8fSJohnny Huang if (!buf) { 187569d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 18762a856b9aSJohnny Huang return OTP_FAILURE; 187769d5fd8fSJohnny Huang } 1878d90825e2SJohnny Huang 1879d90825e2SJohnny Huang if (((buf[0] >> 29) & 0x7) == 0x7) { 1880d90825e2SJohnny Huang mode = OTP_REGION_ALL; 1881d90825e2SJohnny Huang conf_region = &buf[1]; 1882d90825e2SJohnny Huang strap_region = &buf[25]; 1883d90825e2SJohnny Huang data_region = &buf[31]; 1884d90825e2SJohnny Huang } else { 1885d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 1886d90825e2SJohnny Huang mode = OTP_REGION_DATA; 1887d90825e2SJohnny Huang data_region = &buf[31]; 1888d90825e2SJohnny Huang } 1889d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 1890d90825e2SJohnny Huang mode = OTP_REGION_CONF; 1891d90825e2SJohnny Huang strap_region = &buf[25]; 1892d90825e2SJohnny Huang } 1893d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 1894d90825e2SJohnny Huang mode = OTP_REGION_STRAP; 1895d90825e2SJohnny Huang conf_region = &buf[1]; 1896d90825e2SJohnny Huang } 1897d90825e2SJohnny Huang } 189869d5fd8fSJohnny Huang if (!nconfirm) { 1899a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 19007f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 190166f2f8e5SJohnny Huang if (otp_print_conf_info(conf_region) < 0) { 190269d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 19032a856b9aSJohnny Huang return OTP_FAILURE; 190469d5fd8fSJohnny Huang } 1905a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 19067f795e57SJohnny Huang printf("\nOTP data region :\n"); 19077f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 190869d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 19092a856b9aSJohnny Huang return OTP_FAILURE; 191069d5fd8fSJohnny Huang } 1911a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 19127f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1913*a8bd6d8cSJohnny Huang if (otp_print_strap_info(strap_region, 1) < 0) { 191469d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 19152a856b9aSJohnny Huang return OTP_FAILURE; 191669d5fd8fSJohnny Huang } 1917a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 19187f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 191966f2f8e5SJohnny Huang if (otp_print_conf_info(conf_region) < 0) { 192069d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 19212a856b9aSJohnny Huang return OTP_FAILURE; 192269d5fd8fSJohnny Huang } 19237f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1924*a8bd6d8cSJohnny Huang if (otp_print_strap_info(strap_region, 1) < 0) { 192569d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 19262a856b9aSJohnny Huang return OTP_FAILURE; 192769d5fd8fSJohnny Huang } 19287f795e57SJohnny Huang printf("\nOTP data region :\n"); 19297f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 193069d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 19312a856b9aSJohnny Huang return OTP_FAILURE; 193269d5fd8fSJohnny Huang } 193369d5fd8fSJohnny Huang } 193469d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 193569d5fd8fSJohnny Huang if (!confirm_yesno()) { 193669d5fd8fSJohnny Huang printf(" Aborting\n"); 19372a856b9aSJohnny Huang return OTP_FAILURE; 193869d5fd8fSJohnny Huang } 193969d5fd8fSJohnny Huang } 1940a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 1941d90825e2SJohnny Huang return otp_prog_conf(conf_region); 1942a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 1943d90825e2SJohnny Huang return otp_prog_strap(strap_region); 1944a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 1945d90825e2SJohnny Huang return otp_prog_data(data_region); 1946a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 194769d5fd8fSJohnny Huang printf("programing data region ... "); 1948d90825e2SJohnny Huang ret = otp_prog_data(data_region); 19492a856b9aSJohnny Huang if (ret != 0) { 195069d5fd8fSJohnny Huang printf("Error\n"); 195169d5fd8fSJohnny Huang return ret; 195269d5fd8fSJohnny Huang } else { 195369d5fd8fSJohnny Huang printf("Done\n"); 195469d5fd8fSJohnny Huang } 195569d5fd8fSJohnny Huang printf("programing strap region ... "); 1956d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 19572a856b9aSJohnny Huang if (ret != 0) { 195869d5fd8fSJohnny Huang printf("Error\n"); 195969d5fd8fSJohnny Huang return ret; 196069d5fd8fSJohnny Huang } else { 196169d5fd8fSJohnny Huang printf("Done\n"); 196269d5fd8fSJohnny Huang } 196369d5fd8fSJohnny Huang printf("programing configuration region ... "); 1964d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 19652a856b9aSJohnny Huang if (ret != 0) { 196669d5fd8fSJohnny Huang printf("Error\n"); 196769d5fd8fSJohnny Huang return ret; 196869d5fd8fSJohnny Huang } 196969d5fd8fSJohnny Huang printf("Done\n"); 19702a856b9aSJohnny Huang return OTP_SUCCESS; 197169d5fd8fSJohnny Huang } 1972cd1610b4SJohnny Huang 19732a856b9aSJohnny Huang return OTP_USAGE; 19742a856b9aSJohnny Huang } 19752a856b9aSJohnny Huang 19762a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1977cd1610b4SJohnny Huang { 1978a6af4a17SJohnny Huang uint32_t read[2]; 1979cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1980d90825e2SJohnny Huang uint32_t prog_address = 0; 198166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1982cd1610b4SJohnny Huang int otp_bit; 1983cd1610b4SJohnny Huang int i; 1984cd1610b4SJohnny Huang int pass; 1985a6af4a17SJohnny Huang int ret; 1986cd1610b4SJohnny Huang 1987cd1610b4SJohnny Huang switch (mode) { 1988a6d0d645SJohnny Huang case OTP_REGION_CONF: 1989a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1990cd1610b4SJohnny Huang prog_address = 0x800; 1991cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1992cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1993a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1994cd1610b4SJohnny Huang if (otp_bit == value) { 1995a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1996cd1610b4SJohnny Huang printf("No need to program\n"); 19972a856b9aSJohnny Huang return OTP_SUCCESS; 1998cd1610b4SJohnny Huang } 1999cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2000a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 2001cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 20022a856b9aSJohnny Huang return OTP_FAILURE; 2003cd1610b4SJohnny Huang } 2004a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 2005cd1610b4SJohnny Huang break; 2006a6d0d645SJohnny Huang case OTP_REGION_DATA: 2007cd1610b4SJohnny Huang prog_address = otp_dw_offset; 2008cd1610b4SJohnny Huang 2009cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 2010a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 2011a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 2012cd1610b4SJohnny Huang } else { 2013a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 2014a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 2015cd1610b4SJohnny Huang } 2016cd1610b4SJohnny Huang if (otp_bit == value) { 2017a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 2018cd1610b4SJohnny Huang printf("No need to program\n"); 20192a856b9aSJohnny Huang return OTP_SUCCESS; 2020cd1610b4SJohnny Huang } 2021cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 2022a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 2023cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 20242a856b9aSJohnny Huang return OTP_FAILURE; 2025cd1610b4SJohnny Huang } 2026a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 2027cd1610b4SJohnny Huang break; 2028a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2029cd1610b4SJohnny Huang otp_strp_status(otpstrap); 2030cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 2031cd1610b4SJohnny Huang if (bit_offset < 32) { 2032cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 2033cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 2034cd1610b4SJohnny Huang strap_buf[3] = ~0; 2035cd1610b4SJohnny Huang strap_buf[5] = 0; 20362a856b9aSJohnny Huang // if (protect) 20372a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 20382a856b9aSJohnny Huang // else 20392a856b9aSJohnny Huang // strap_buf[4] = 0; 2040cd1610b4SJohnny Huang } else { 2041cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 2042cd1610b4SJohnny Huang strap_buf[2] = ~0; 2043cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 2044cd1610b4SJohnny Huang strap_buf[4] = 0; 20452a856b9aSJohnny Huang // if (protect) 20462a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 20472a856b9aSJohnny Huang // else 20482a856b9aSJohnny Huang // strap_buf[5] = 0; 2049cd1610b4SJohnny Huang } 205076d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 2051a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 20522a856b9aSJohnny Huang return OTP_FAILURE; 2053a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 2054a6af4a17SJohnny Huang return OTP_SUCCESS; 2055a6af4a17SJohnny Huang 2056cd1610b4SJohnny Huang break; 2057cd1610b4SJohnny Huang } 2058cd1610b4SJohnny Huang 2059cd1610b4SJohnny Huang if (!nconfirm) { 2060cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2061cd1610b4SJohnny Huang if (!confirm_yesno()) { 2062cd1610b4SJohnny Huang printf(" Aborting\n"); 20632a856b9aSJohnny Huang return OTP_FAILURE; 2064cd1610b4SJohnny Huang } 2065cd1610b4SJohnny Huang } 2066cd1610b4SJohnny Huang 2067cd1610b4SJohnny Huang switch (mode) { 2068a6d0d645SJohnny Huang case OTP_REGION_STRAP: 2069cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 2070a6d0d645SJohnny Huang case OTP_REGION_CONF: 2071a6d0d645SJohnny Huang case OTP_REGION_DATA: 2072cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 2073cd1610b4SJohnny Huang pass = -1; 2074cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 2075a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 2076cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 2077cd1610b4SJohnny Huang } else { 2078cd1610b4SJohnny Huang pass = 0; 2079cd1610b4SJohnny Huang break; 2080cd1610b4SJohnny Huang } 2081cd1610b4SJohnny Huang } 20822a856b9aSJohnny Huang if (pass == 0) 20832a856b9aSJohnny Huang return OTP_SUCCESS; 2084cd1610b4SJohnny Huang } 2085cd1610b4SJohnny Huang 20862a856b9aSJohnny Huang return OTP_USAGE; 2087cd1610b4SJohnny Huang } 2088cd1610b4SJohnny Huang 20892a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 209069d5fd8fSJohnny Huang { 20912a856b9aSJohnny Huang uint32_t offset, count; 20922a856b9aSJohnny Huang int ret; 209369d5fd8fSJohnny Huang 20942a856b9aSJohnny Huang if (argc == 4) { 20952a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 20962a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 20972a856b9aSJohnny Huang } else if (argc == 3) { 20982a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 20992a856b9aSJohnny Huang count = 1; 21002a856b9aSJohnny Huang } else { 210169d5fd8fSJohnny Huang return CMD_RET_USAGE; 210269d5fd8fSJohnny Huang } 210369d5fd8fSJohnny Huang 210469d5fd8fSJohnny Huang 21052a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 210669d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 21072a856b9aSJohnny Huang ret = otp_print_config(offset, count); 21082a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 21092a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 21102a856b9aSJohnny Huang ret = otp_print_data(offset, count); 21112a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 21122a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 21132a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 21142a856b9aSJohnny Huang } else { 21152a856b9aSJohnny Huang return CMD_RET_USAGE; 211669d5fd8fSJohnny Huang } 211769d5fd8fSJohnny Huang 21182a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 21192a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21202a856b9aSJohnny Huang else 21212a856b9aSJohnny Huang return CMD_RET_USAGE; 21222a856b9aSJohnny Huang 21232a856b9aSJohnny Huang } 21242a856b9aSJohnny Huang 21252a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21262a856b9aSJohnny Huang { 21272a856b9aSJohnny Huang phys_addr_t addr; 21282a856b9aSJohnny Huang uint32_t byte_size; 21292a856b9aSJohnny Huang int ret; 21302a856b9aSJohnny Huang 21312a856b9aSJohnny Huang if (argc == 4) { 21322a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 21332a856b9aSJohnny Huang return CMD_RET_USAGE; 21342a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 21352a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 213669d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 21372a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 21382a856b9aSJohnny Huang } else if (argc == 3) { 21392a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 21402a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 21412a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 21422a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 21432a856b9aSJohnny Huang } else { 21442a856b9aSJohnny Huang return CMD_RET_USAGE; 21452a856b9aSJohnny Huang } 21462a856b9aSJohnny Huang 21472a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 21482a856b9aSJohnny Huang return CMD_RET_SUCCESS; 21492a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 21502a856b9aSJohnny Huang return CMD_RET_FAILURE; 21512a856b9aSJohnny Huang else 21522a856b9aSJohnny Huang return CMD_RET_USAGE; 21532a856b9aSJohnny Huang } 21542a856b9aSJohnny Huang 21552a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 21562a856b9aSJohnny Huang { 21572a856b9aSJohnny Huang int mode = 0; 21582a856b9aSJohnny Huang int nconfirm = 0; 21592a856b9aSJohnny Huang int otp_addr = 0; 21602a856b9aSJohnny Huang int bit_offset; 21612a856b9aSJohnny Huang int value; 21622a856b9aSJohnny Huang int ret; 21632a856b9aSJohnny Huang 21642a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 21652a856b9aSJohnny Huang return CMD_RET_USAGE; 21662a856b9aSJohnny Huang 21672a856b9aSJohnny Huang /* Drop the pb cmd */ 21682a856b9aSJohnny Huang argc--; 21692a856b9aSJohnny Huang argv++; 21702a856b9aSJohnny Huang 21712a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 2172a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 21732a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 2174a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 21752a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 2176a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 2177cd1610b4SJohnny Huang else 21782a856b9aSJohnny Huang return CMD_RET_USAGE; 21792a856b9aSJohnny Huang 21802a856b9aSJohnny Huang /* Drop the region cmd */ 21812a856b9aSJohnny Huang argc--; 21822a856b9aSJohnny Huang argv++; 21832a856b9aSJohnny Huang 21842a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 2185cd1610b4SJohnny Huang nconfirm = 1; 21862a856b9aSJohnny Huang /* Drop the force option */ 21872a856b9aSJohnny Huang argc--; 21882a856b9aSJohnny Huang argv++; 21892a856b9aSJohnny Huang } 2190cd1610b4SJohnny Huang 2191a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 21922a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 21932a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 2194cd1610b4SJohnny Huang if (bit_offset >= 64) 21952a856b9aSJohnny Huang return CMD_RET_USAGE; 2196cd1610b4SJohnny Huang } else { 21972a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 21982a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 21992a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 2200cd1610b4SJohnny Huang if (bit_offset >= 32) 22012a856b9aSJohnny Huang return CMD_RET_USAGE; 2202cd1610b4SJohnny Huang } 2203cd1610b4SJohnny Huang if (value != 0 && value != 1) 22042a856b9aSJohnny Huang return CMD_RET_USAGE; 2205cd1610b4SJohnny Huang 2206cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 22072a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 22082a856b9aSJohnny Huang 22092a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 22102a856b9aSJohnny Huang return CMD_RET_SUCCESS; 22112a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 22122a856b9aSJohnny Huang return CMD_RET_FAILURE; 22132a856b9aSJohnny Huang else 22142a856b9aSJohnny Huang return CMD_RET_USAGE; 22152a856b9aSJohnny Huang } 22162a856b9aSJohnny Huang 22172a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 22182a856b9aSJohnny Huang { 22192a856b9aSJohnny Huang phys_addr_t addr; 22202a856b9aSJohnny Huang int otp_addr = 0; 22212a856b9aSJohnny Huang 22222a856b9aSJohnny Huang if (argc != 3) 22232a856b9aSJohnny Huang return CMD_RET_USAGE; 22242a856b9aSJohnny Huang 222569d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 22262a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 22272a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 22282a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 222969d5fd8fSJohnny Huang printf("Compare pass\n"); 22302a856b9aSJohnny Huang return CMD_RET_SUCCESS; 223169d5fd8fSJohnny Huang } else { 223269d5fd8fSJohnny Huang printf("Compare fail\n"); 22332a856b9aSJohnny Huang return CMD_RET_FAILURE; 223469d5fd8fSJohnny Huang } 223569d5fd8fSJohnny Huang } 223669d5fd8fSJohnny Huang 223766f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 223866f2f8e5SJohnny Huang { 2239*a8bd6d8cSJohnny Huang int mode = 0; 2240*a8bd6d8cSJohnny Huang int view = 0; 2241*a8bd6d8cSJohnny Huang 2242*a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 224366f2f8e5SJohnny Huang return CMD_RET_USAGE; 224466f2f8e5SJohnny Huang 2245*a8bd6d8cSJohnny Huang /* Drop the info cmd */ 2246*a8bd6d8cSJohnny Huang argc--; 2247*a8bd6d8cSJohnny Huang argv++; 224866f2f8e5SJohnny Huang 2249*a8bd6d8cSJohnny Huang if (!strcmp(argv[0], "conf")) 2250*a8bd6d8cSJohnny Huang mode = OTP_REGION_CONF; 2251*a8bd6d8cSJohnny Huang else if (!strcmp(argv[0], "strap")) 2252*a8bd6d8cSJohnny Huang mode = OTP_REGION_STRAP; 2253*a8bd6d8cSJohnny Huang else 2254*a8bd6d8cSJohnny Huang return CMD_RET_USAGE; 2255*a8bd6d8cSJohnny Huang 2256*a8bd6d8cSJohnny Huang /* Drop the region cmd */ 2257*a8bd6d8cSJohnny Huang argc--; 2258*a8bd6d8cSJohnny Huang argv++; 2259*a8bd6d8cSJohnny Huang 2260*a8bd6d8cSJohnny Huang if (!strcmp(argv[0], "v")) { 2261*a8bd6d8cSJohnny Huang view = 1; 2262*a8bd6d8cSJohnny Huang /* Drop the view option */ 2263*a8bd6d8cSJohnny Huang argc--; 2264*a8bd6d8cSJohnny Huang argv++; 2265*a8bd6d8cSJohnny Huang } 2266*a8bd6d8cSJohnny Huang 2267*a8bd6d8cSJohnny Huang if (mode == OTP_REGION_CONF) { 226866f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 226966f2f8e5SJohnny Huang otp_info_config(); 2270*a8bd6d8cSJohnny Huang } else if (mode == OTP_REGION_STRAP) { 227166f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 2272*a8bd6d8cSJohnny Huang otp_info_strap(view); 227366f2f8e5SJohnny Huang } else { 227466f2f8e5SJohnny Huang return CMD_RET_USAGE; 227566f2f8e5SJohnny Huang } 227666f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 227766f2f8e5SJohnny Huang } 227866f2f8e5SJohnny Huang 2279737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2280737ed20bSJohnny Huang { 2281737ed20bSJohnny Huang int input; 2282737ed20bSJohnny Huang int bit_offset; 2283737ed20bSJohnny Huang int prog_address; 2284737ed20bSJohnny Huang int pass; 2285737ed20bSJohnny Huang int i; 2286737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2287737ed20bSJohnny Huang return CMD_RET_USAGE; 2288737ed20bSJohnny Huang 2289737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 2290737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2291737ed20bSJohnny Huang } else { 2292737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2293737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2294737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2295737ed20bSJohnny Huang if (!confirm_yesno()) { 2296737ed20bSJohnny Huang printf(" Aborting\n"); 2297737ed20bSJohnny Huang return CMD_RET_FAILURE; 2298737ed20bSJohnny Huang } 2299737ed20bSJohnny Huang } 2300737ed20bSJohnny Huang 2301737ed20bSJohnny Huang prog_address = 0x800; 2302737ed20bSJohnny Huang if (input < 32) { 2303737ed20bSJohnny Huang bit_offset = input; 2304737ed20bSJohnny Huang prog_address |= 0x60c; 2305737ed20bSJohnny Huang } else if (input < 64) { 2306737ed20bSJohnny Huang bit_offset = input - 32; 2307737ed20bSJohnny Huang prog_address |= 0x60e; 2308737ed20bSJohnny Huang } else { 2309737ed20bSJohnny Huang return CMD_RET_USAGE; 2310737ed20bSJohnny Huang } 2311737ed20bSJohnny Huang 2312737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2313737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2314737ed20bSJohnny Huang } 2315737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 2316737ed20bSJohnny Huang pass = -1; 2317737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2318737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2319737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 2320737ed20bSJohnny Huang } else { 2321737ed20bSJohnny Huang pass = 0; 2322737ed20bSJohnny Huang break; 2323737ed20bSJohnny Huang } 2324737ed20bSJohnny Huang } 2325737ed20bSJohnny Huang if (pass == 0) { 2326737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2327737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2328737ed20bSJohnny Huang } 2329737ed20bSJohnny Huang 2330737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2331737ed20bSJohnny Huang return CMD_RET_FAILURE; 2332737ed20bSJohnny Huang 2333737ed20bSJohnny Huang } 23342a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 23352a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2336*a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 23372a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 23382a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2339737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 23402a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 23412a856b9aSJohnny Huang }; 23422a856b9aSJohnny Huang 23432a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 23442a856b9aSJohnny Huang { 23452a856b9aSJohnny Huang cmd_tbl_t *cp; 23462a856b9aSJohnny Huang 23472a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 23482a856b9aSJohnny Huang 2349737ed20bSJohnny Huang /* Drop the otp command */ 23502a856b9aSJohnny Huang argc--; 23512a856b9aSJohnny Huang argv++; 23522a856b9aSJohnny Huang 23532a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 23542a856b9aSJohnny Huang return CMD_RET_USAGE; 23552a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 23562a856b9aSJohnny Huang return CMD_RET_SUCCESS; 23572a856b9aSJohnny Huang 23582a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 235969d5fd8fSJohnny Huang } 236069d5fd8fSJohnny Huang 236169d5fd8fSJohnny Huang U_BOOT_CMD( 236269d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 236369d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 23642a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 23652a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 2366*a8bd6d8cSJohnny Huang "otp info conf|strap [v]\n" 2367d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2368cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2369737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2370737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 23712a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 237269d5fd8fSJohnny Huang ); 2373