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 287332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 297332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 307332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 38a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 39b458cd62SJohnny Huang #define OTP_REG_VALUE -2 40b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4176d13988SJohnny Huang 424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 434c1c9b35SJohnny Huang #define PBWIDTH 60 444c1c9b35SJohnny Huang 4566f2f8e5SJohnny Huang struct otpstrap_status { 4669d5fd8fSJohnny Huang int value; 4769d5fd8fSJohnny Huang int option_array[7]; 4869d5fd8fSJohnny Huang int remain_times; 4969d5fd8fSJohnny Huang int writeable_option; 5069d5fd8fSJohnny Huang int protected; 5169d5fd8fSJohnny Huang }; 5269d5fd8fSJohnny Huang 5366f2f8e5SJohnny Huang struct otpconf_parse { 5466f2f8e5SJohnny Huang int dw_offset; 5566f2f8e5SJohnny Huang int bit; 5666f2f8e5SJohnny Huang int length; 5766f2f8e5SJohnny Huang int value; 5866f2f8e5SJohnny Huang int keep; 5966f2f8e5SJohnny Huang char status[80]; 6066f2f8e5SJohnny Huang }; 6166f2f8e5SJohnny Huang 62a8bd6d8cSJohnny Huang struct otpstrap_info { 63a8bd6d8cSJohnny Huang uint32_t bit_offset; 64a8bd6d8cSJohnny Huang uint32_t length; 6576d13988SJohnny Huang int value; 66a8bd6d8cSJohnny Huang char information[80]; 67a8bd6d8cSJohnny Huang }; 68a8bd6d8cSJohnny Huang 69a8bd6d8cSJohnny Huang struct otpconf_info { 70a8bd6d8cSJohnny Huang uint32_t dw_offset; 71a8bd6d8cSJohnny Huang uint32_t bit_offset; 72a8bd6d8cSJohnny Huang uint32_t length; 73a8bd6d8cSJohnny Huang int value; 74a8bd6d8cSJohnny Huang char information[80]; 75a8bd6d8cSJohnny Huang }; 76a8bd6d8cSJohnny Huang 77a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 78a8bd6d8cSJohnny Huang { 79a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 80a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 81a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 82a8bd6d8cSJohnny Huang char buffer[256]; 83a8bd6d8cSJohnny Huang va_list aptr; 84a8bd6d8cSJohnny Huang 85a8bd6d8cSJohnny Huang va_start(aptr, format); 86a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 87a8bd6d8cSJohnny Huang va_end(aptr); 88a8bd6d8cSJohnny Huang 89a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 90a8bd6d8cSJohnny Huang if (numerator == denominator) 91a8bd6d8cSJohnny Huang printf("\n"); 92a8bd6d8cSJohnny Huang } 93a8bd6d8cSJohnny Huang 94a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 95*91448c03SJohnny Huang { 0, 1, 0, "Disable secure boot" }, 96*91448c03SJohnny Huang { 0, 1, 1, "Enable secure boot" }, 97*91448c03SJohnny Huang { 1, 1, 0, "Disable boot from eMMC" }, 98*91448c03SJohnny Huang { 1, 1, 1, "Enable boot from eMMC" }, 99*91448c03SJohnny Huang { 2, 1, 0, "Disable Boot from debug SPI" }, 100*91448c03SJohnny Huang { 2, 1, 1, "Enable Boot from debug SPI" }, 101*91448c03SJohnny Huang { 3, 1, 0, "Enable ARM CM3" }, 102*91448c03SJohnny Huang { 3, 1, 1, "Disable ARM CM3" }, 103*91448c03SJohnny Huang { 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" }, 104*91448c03SJohnny Huang { 4, 1, 1, "Enable dedicated VGA BIOS ROM" }, 105*91448c03SJohnny Huang { 5, 1, 0, "MAC 1 : RMII/NCSI" }, 106*91448c03SJohnny Huang { 5, 1, 1, "MAC 1 : RGMII" }, 107*91448c03SJohnny Huang { 6, 1, 0, "MAC 2 : RMII/NCSI" }, 108*91448c03SJohnny Huang { 6, 1, 1, "MAC 2 : RGMII" }, 109*91448c03SJohnny Huang { 7, 3, 0, "CPU Frequency : 1GHz" }, 110*91448c03SJohnny Huang { 7, 3, 1, "CPU Frequency : 800MHz" }, 111*91448c03SJohnny Huang { 7, 3, 2, "CPU Frequency : 1.2GHz" }, 112*91448c03SJohnny Huang { 7, 3, 3, "CPU Frequency : 1.4GHz" }, 113*91448c03SJohnny Huang { 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" }, 114*91448c03SJohnny Huang { 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" }, 115*91448c03SJohnny Huang { 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" }, 116*91448c03SJohnny Huang { 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" }, 117*91448c03SJohnny Huang { 12, 2, 0, "VGA memory size : 8MB" }, 118*91448c03SJohnny Huang { 12, 2, 1, "VGA memory size : 16MB" }, 119*91448c03SJohnny Huang { 12, 2, 2, "VGA memory size : 32MB" }, 120*91448c03SJohnny Huang { 12, 2, 3, "VGA memory size : 64MB" }, 121*91448c03SJohnny Huang { 14, 3, OTP_REG_RESERVED, "" }, 122*91448c03SJohnny Huang { 17, 1, 0, "VGA class code : Class Code for video device" }, 123*91448c03SJohnny Huang { 17, 1, 1, "VGA class code : Class Code for VGA device" }, 124*91448c03SJohnny Huang { 18, 1, 0, "Enable debug interfaces 0" }, 125*91448c03SJohnny Huang { 18, 1, 1, "Disable debug interfaces 0" }, 126*91448c03SJohnny Huang { 19, 1, 0, "Boot from emmc mode : High eMMC speed" }, 127*91448c03SJohnny Huang { 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" }, 128*91448c03SJohnny Huang { 20, 1, 0, "Enable Pcie EHCI device" }, 129*91448c03SJohnny Huang { 20, 1, 1, "Disable Pcie EHCI device" }, 130*91448c03SJohnny Huang { 21, 1, 0, "Enable VGA XDMA function" }, 131*91448c03SJohnny Huang { 21, 1, 1, "Disable VGA XDMA function" }, 132*91448c03SJohnny Huang { 22, 1, 0, "Normal BMC mode" }, 133*91448c03SJohnny Huang { 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" }, 134*91448c03SJohnny Huang { 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" }, 135*91448c03SJohnny Huang { 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" }, 136*91448c03SJohnny Huang { 24, 1, 0, "DRAM types : DDR4" }, 137*91448c03SJohnny Huang { 24, 1, 1, "DRAM types : DDR3" }, 138*91448c03SJohnny Huang { 25, 5, OTP_REG_RESERVED, "" }, 139*91448c03SJohnny Huang { 30, 2, OTP_REG_RESERVED, "" }, 140*91448c03SJohnny Huang { 32, 1, 0, "MAC 3 : RMII/NCSI" }, 141*91448c03SJohnny Huang { 32, 1, 1, "MAC 3 : RGMII" }, 142*91448c03SJohnny Huang { 33, 1, 0, "MAC 4 : RMII/NCSI" }, 143*91448c03SJohnny Huang { 33, 1, 1, "MAC 4 : RGMII" }, 144*91448c03SJohnny Huang { 34, 1, 0, "SuperIO configuration address : 0x2E" }, 145*91448c03SJohnny Huang { 34, 1, 1, "SuperIO configuration address : 0x4E" }, 146*91448c03SJohnny Huang { 35, 1, 0, "Enable LPC to decode SuperIO" }, 147*91448c03SJohnny Huang { 35, 1, 1, "Disable LPC to decode SuperIO" }, 148*91448c03SJohnny Huang { 36, 1, 0, "Enable debug interfaces 1" }, 149*91448c03SJohnny Huang { 36, 1, 1, "Disable debug interfaces 1" }, 150*91448c03SJohnny Huang { 37, 1, 0, "Disable ACPI function" }, 151*91448c03SJohnny Huang { 37, 1, 1, "Enable ACPI function" }, 152*91448c03SJohnny Huang { 38, 1, 0, "Enable eSPI mode" }, 153*91448c03SJohnny Huang { 38, 1, 1, "Enable LPC mode" }, 154*91448c03SJohnny Huang { 39, 1, 0, "Enable SAFS mode" }, 155*91448c03SJohnny Huang { 39, 1, 1, "Enable SAFS mode" }, 156*91448c03SJohnny Huang { 40, 2, OTP_REG_RESERVED, "" }, 157*91448c03SJohnny Huang { 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" }, 158*91448c03SJohnny Huang { 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" }, 159*91448c03SJohnny Huang { 43, 1, 0, "Disable boot SPI ABR" }, 160*91448c03SJohnny Huang { 43, 1, 1, "Enable boot SPI ABR" }, 161*91448c03SJohnny Huang { 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" }, 162*91448c03SJohnny Huang { 44, 1, 1, "Boot SPI ABR mode : single SPI flash" }, 163*91448c03SJohnny Huang { 45, 3, 0, "Boot SPI flash size : no define size" }, 164*91448c03SJohnny Huang { 45, 3, 1, "Boot SPI flash size : 2MB" }, 165*91448c03SJohnny Huang { 45, 3, 2, "Boot SPI flash size : 4MB" }, 166*91448c03SJohnny Huang { 45, 3, 3, "Boot SPI flash size : 8MB" }, 167*91448c03SJohnny Huang { 45, 3, 4, "Boot SPI flash size : 16MB" }, 168*91448c03SJohnny Huang { 45, 3, 5, "Boot SPI flash size : 32MB" }, 169*91448c03SJohnny Huang { 45, 3, 6, "Boot SPI flash size : 64MB" }, 170*91448c03SJohnny Huang { 45, 3, 7, "Boot SPI flash size : 128MB" }, 171*91448c03SJohnny Huang { 48, 1, 0, "Disable host SPI ABR" }, 172*91448c03SJohnny Huang { 48, 1, 1, "Enable host SPI ABR" }, 173*91448c03SJohnny Huang { 49, 1, 0, "Disable host SPI ABR mode select pin" }, 174*91448c03SJohnny Huang { 49, 1, 1, "Enable host SPI ABR mode select pin" }, 175*91448c03SJohnny Huang { 50, 1, 0, "Host SPI ABR mode : dual SPI flash" }, 176*91448c03SJohnny Huang { 50, 1, 1, "Host SPI ABR mode : single SPI flash" }, 177*91448c03SJohnny Huang { 51, 3, 0, "Host SPI flash size : no define size" }, 178*91448c03SJohnny Huang { 51, 3, 1, "Host SPI flash size : 2MB" }, 179*91448c03SJohnny Huang { 51, 3, 2, "Host SPI flash size : 4MB" }, 180*91448c03SJohnny Huang { 51, 3, 3, "Host SPI flash size : 8MB" }, 181*91448c03SJohnny Huang { 51, 3, 4, "Host SPI flash size : 16MB" }, 182*91448c03SJohnny Huang { 51, 3, 5, "Host SPI flash size : 32MB" }, 183*91448c03SJohnny Huang { 51, 3, 6, "Host SPI flash size : 64MB" }, 184*91448c03SJohnny Huang { 51, 3, 7, "Host SPI flash size : 128MB" }, 185*91448c03SJohnny Huang { 54, 1, 0, "Disable boot SPI auxiliary control pins" }, 186*91448c03SJohnny Huang { 54, 1, 1, "Enable boot SPI auxiliary control pins" }, 187*91448c03SJohnny Huang { 55, 2, 0, "Boot SPI CRTM size : disable CRTM" }, 188*91448c03SJohnny Huang { 55, 2, 1, "Boot SPI CRTM size : 256KB" }, 189*91448c03SJohnny Huang { 55, 2, 2, "Boot SPI CRTM size : 512KB" }, 190*91448c03SJohnny Huang { 55, 2, 3, "Boot SPI CRTM size : 1MB" }, 191*91448c03SJohnny Huang { 57, 2, 0, "Host SPI CRTM size : disable CRTM" }, 192*91448c03SJohnny Huang { 57, 2, 1, "Host SPI CRTM size : 256KB" }, 193*91448c03SJohnny Huang { 57, 2, 2, "Host SPI CRTM size : 512KB" }, 194*91448c03SJohnny Huang { 57, 2, 3, "Host SPI CRTM size : 1MB" }, 195*91448c03SJohnny Huang { 59, 1, 0, "Disable host SPI auxiliary control pins" }, 196*91448c03SJohnny Huang { 59, 1, 1, "Enable host SPI auxiliary control pins" }, 197*91448c03SJohnny Huang { 60, 1, 0, "Disable GPIO pass through" }, 198*91448c03SJohnny Huang { 60, 1, 1, "Enable GPIO pass through" }, 199*91448c03SJohnny Huang { 61, 1, 0, "Enable low security secure boot key" }, 200*91448c03SJohnny Huang { 61, 1, 1, "Disable low security secure boot key" }, 201*91448c03SJohnny Huang { 62, 1, 0, "Disable dedicate GPIO strap pins" }, 202*91448c03SJohnny Huang { 62, 1, 1, "Enable dedicate GPIO strap pins" }, 203*91448c03SJohnny Huang { 63, 1, OTP_REG_RESERVED, "" } 20476d13988SJohnny Huang }; 205b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 206*91448c03SJohnny Huang { 0, 0, 1, 0, "Enable Secure Region programming" }, 207*91448c03SJohnny Huang { 0, 0, 1, 1, "Disable Secure Region programming" }, 208*91448c03SJohnny Huang { 0, 1, 1, 0, "Disable Secure Boot" }, 209*91448c03SJohnny Huang { 0, 1, 1, 1, "Enable Secure Boot" }, 210*91448c03SJohnny Huang { 0, 2, 1, 0, "Initialization programming not done" }, 211*91448c03SJohnny Huang { 0, 2, 1, 1, "Initialization programming done" }, 212*91448c03SJohnny Huang { 0, 3, 1, 0, "User region ECC disable" }, 213*91448c03SJohnny Huang { 0, 3, 1, 1, "User region ECC enable" }, 214*91448c03SJohnny Huang { 0, 4, 1, 0, "Secure Region ECC disable" }, 215*91448c03SJohnny Huang { 0, 4, 1, 1, "Secure Region ECC enable" }, 216*91448c03SJohnny Huang { 0, 5, 1, 0, "Enable low security key" }, 217*91448c03SJohnny Huang { 0, 5, 1, 1, "Disable low security key" }, 218*91448c03SJohnny Huang { 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" }, 219*91448c03SJohnny Huang { 0, 6, 1, 1, "Ignore Secure Boot hardware strap" }, 220*91448c03SJohnny Huang { 0, 7, 1, 0, "Secure Boot Mode: 1" }, 221*91448c03SJohnny Huang { 0, 7, 1, 1, "Secure Boot Mode: 2" }, 222*91448c03SJohnny Huang { 0, 8, 2, 0, "Single cell mode (recommended)" }, 223*91448c03SJohnny Huang { 0, 8, 2, 1, "Differnetial mode" }, 224*91448c03SJohnny Huang { 0, 8, 2, 2, "Differential-redundant mode" }, 225*91448c03SJohnny Huang { 0, 10, 2, 0, "RSA mode : RSA1024" }, 226*91448c03SJohnny Huang { 0, 10, 2, 1, "RSA mode : RSA2048" }, 227*91448c03SJohnny Huang { 0, 10, 2, 2, "RSA mode : RSA3072" }, 228*91448c03SJohnny Huang { 0, 10, 2, 3, "RSA mode : RSA4096" }, 229*91448c03SJohnny Huang { 0, 12, 2, 0, "SHA mode : SHA224" }, 230*91448c03SJohnny Huang { 0, 12, 2, 1, "SHA mode : SHA256" }, 231*91448c03SJohnny Huang { 0, 12, 2, 2, "SHA mode : SHA384" }, 232*91448c03SJohnny Huang { 0, 12, 2, 3, "SHA mode : SHA512" }, 233*91448c03SJohnny Huang { 0, 14, 2, OTP_REG_RESERVED, "" }, 234*91448c03SJohnny Huang { 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" }, 235*91448c03SJohnny Huang { 0, 22, 1, 0, "Secure Region : Writable" }, 236*91448c03SJohnny Huang { 0, 22, 1, 1, "Secure Region : Write Protect" }, 237*91448c03SJohnny Huang { 0, 23, 1, 0, "User Region : Writable" }, 238*91448c03SJohnny Huang { 0, 23, 1, 1, "User Region : Write Protect" }, 239*91448c03SJohnny Huang { 0, 24, 1, 0, "Configure Region : Writable" }, 240*91448c03SJohnny Huang { 0, 24, 1, 1, "Configure Region : Write Protect" }, 241*91448c03SJohnny Huang { 0, 25, 1, 0, "OTP strap Region : Writable" }, 242*91448c03SJohnny Huang { 0, 25, 1, 1, "OTP strap Region : Write Protect" }, 243*91448c03SJohnny Huang { 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" }, 244*91448c03SJohnny Huang { 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" }, 245*91448c03SJohnny Huang { 0, 27, 1, 0, "Disable image encryption" }, 246*91448c03SJohnny Huang { 0, 27, 1, 1, "Enable image encryption" }, 247*91448c03SJohnny Huang { 0, 28, 1, OTP_REG_RESERVED, "" }, 248*91448c03SJohnny Huang { 0, 29, 1, 0, "OTP key retire Region : Writable" }, 249*91448c03SJohnny Huang { 0, 29, 1, 1, "OTP key retire Region : Write Protect" }, 250*91448c03SJohnny Huang { 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" }, 251*91448c03SJohnny Huang { 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" }, 252*91448c03SJohnny Huang { 0, 31, 1, 0, "SIPROM Mlock memory lock disable" }, 253*91448c03SJohnny Huang { 0, 31, 1, 1, "SIPROM Mlock memory lock enable" }, 254*91448c03SJohnny Huang { 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" }, 255*91448c03SJohnny Huang { 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" }, 256*91448c03SJohnny Huang { 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" }, 257*91448c03SJohnny Huang { 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %d" }, 258*91448c03SJohnny Huang { 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %d" }, 259*91448c03SJohnny Huang { 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" }, 260*91448c03SJohnny Huang { 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" }, 261*91448c03SJohnny Huang { 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" }, 262*91448c03SJohnny Huang { 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" }, 263*91448c03SJohnny Huang { 7, 1, 1, 0, "Force enable UART5 debug port function" }, 264*91448c03SJohnny Huang { 7, 1, 1, 1, "Force disable UART5 debug port function" }, 265*91448c03SJohnny Huang { 7, 2, 1, 0, "Force enable XDMA function" }, 266*91448c03SJohnny Huang { 7, 2, 1, 1, "Force disable XDMA function" }, 267*91448c03SJohnny Huang { 7, 3, 1, 0, "Force enable APB to PCIE device bridge" }, 268*91448c03SJohnny Huang { 7, 3, 1, 1, "Force disable APB to PCIE device bridge" }, 269*91448c03SJohnny Huang { 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" }, 270*91448c03SJohnny Huang { 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" }, 271*91448c03SJohnny Huang { 7, 5, 1, 0, "Force enable PCIE bus trace buffer" }, 272*91448c03SJohnny Huang { 7, 5, 1, 1, "Force disable PCIE bus trace buffer" }, 273*91448c03SJohnny Huang { 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" }, 274*91448c03SJohnny Huang { 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" }, 275*91448c03SJohnny Huang { 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" }, 276*91448c03SJohnny Huang { 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" }, 277*91448c03SJohnny Huang { 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" }, 278*91448c03SJohnny Huang { 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" }, 279*91448c03SJohnny Huang { 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" }, 280*91448c03SJohnny Huang { 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" }, 281*91448c03SJohnny Huang { 7, 19, 1, 0, "Force enable UART1 debug port function" }, 282*91448c03SJohnny Huang { 7, 19, 1, 1, "Force disable UART1 debug port function" }, 283*91448c03SJohnny Huang { 7, 31, 1, 0, "Disable chip security setting" }, 284*91448c03SJohnny Huang { 7, 31, 1, 1, "Enable chip security setting" }, 285*91448c03SJohnny Huang { 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" }, 286*91448c03SJohnny Huang { 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" }, 287*91448c03SJohnny Huang { 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" } 288b458cd62SJohnny Huang }; 2892a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 29069d5fd8fSJohnny Huang { 29169d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 29269d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 29369d5fd8fSJohnny Huang udelay(2); 29469d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 29569d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 29669d5fd8fSJohnny Huang } 29769d5fd8fSJohnny Huang 2982a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 29969d5fd8fSJohnny Huang { 30069d5fd8fSJohnny Huang int config_offset; 30169d5fd8fSJohnny Huang 30269d5fd8fSJohnny Huang config_offset = 0x800; 30369d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 30469d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 30569d5fd8fSJohnny Huang 30669d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 30769d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 30869d5fd8fSJohnny Huang udelay(2); 30969d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 31069d5fd8fSJohnny Huang } 31169d5fd8fSJohnny Huang 31269d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 31369d5fd8fSJohnny Huang { 31469d5fd8fSJohnny Huang int i; 31569d5fd8fSJohnny Huang uint32_t ret[1]; 31669d5fd8fSJohnny Huang 31769d5fd8fSJohnny Huang if (offset + dw_count > 32) 3182a856b9aSJohnny Huang return OTP_USAGE; 31969d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 32069d5fd8fSJohnny Huang otp_read_config(i, ret); 321a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 32269d5fd8fSJohnny Huang } 32369d5fd8fSJohnny Huang printf("\n"); 3242a856b9aSJohnny Huang return OTP_SUCCESS; 32569d5fd8fSJohnny Huang } 32669d5fd8fSJohnny Huang 32769d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 32869d5fd8fSJohnny Huang { 32969d5fd8fSJohnny Huang int i; 33069d5fd8fSJohnny Huang uint32_t ret[2]; 33169d5fd8fSJohnny Huang 33269d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 3332a856b9aSJohnny Huang return OTP_USAGE; 33469d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 33569d5fd8fSJohnny Huang otp_read_data(i, ret); 33669d5fd8fSJohnny Huang if (i % 4 == 0) 33769d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 33869d5fd8fSJohnny Huang else 33969d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 34069d5fd8fSJohnny Huang 34169d5fd8fSJohnny Huang } 34269d5fd8fSJohnny Huang printf("\n"); 3432a856b9aSJohnny Huang return OTP_SUCCESS; 34469d5fd8fSJohnny Huang } 34569d5fd8fSJohnny Huang 34669d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 34769d5fd8fSJohnny Huang { 34869d5fd8fSJohnny Huang uint32_t ret; 34969d5fd8fSJohnny Huang uint32_t *buf; 35069d5fd8fSJohnny Huang 35169d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 35269d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 35369d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 35469d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 35569d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 35669d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 35769d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 35869d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 35969d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 36069d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 36169d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 36269d5fd8fSJohnny Huang udelay(10); 36369d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 36469d5fd8fSJohnny Huang if (ret & 0x1) 36569d5fd8fSJohnny Huang return 0; 36669d5fd8fSJohnny Huang else 36769d5fd8fSJohnny Huang return -1; 36869d5fd8fSJohnny Huang } 36969d5fd8fSJohnny Huang 37069d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 37169d5fd8fSJohnny Huang { 37269d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 37369d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 37469d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 37569d5fd8fSJohnny Huang udelay(100); 37669d5fd8fSJohnny Huang } 37769d5fd8fSJohnny Huang 37869d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 37969d5fd8fSJohnny Huang { 38069d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 38169d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 38269d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 38369d5fd8fSJohnny Huang udelay(85); 38469d5fd8fSJohnny Huang } 38569d5fd8fSJohnny Huang 386a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 38769d5fd8fSJohnny Huang { 38869d5fd8fSJohnny Huang int ret; 38969d5fd8fSJohnny Huang 39069d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 39169d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 39269d5fd8fSJohnny Huang udelay(2); 39369d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 394a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 39569d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 39669d5fd8fSJohnny Huang return 0; 39769d5fd8fSJohnny Huang else 39869d5fd8fSJohnny Huang return -1; 39969d5fd8fSJohnny Huang } 40069d5fd8fSJohnny Huang 401d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 4024c1c9b35SJohnny Huang { 4034c1c9b35SJohnny Huang uint32_t ret[2]; 4044c1c9b35SJohnny Huang 4054c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 4064c1c9b35SJohnny Huang 4074c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 4084c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 4094c1c9b35SJohnny Huang else 4104c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 4114c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 4124c1c9b35SJohnny Huang udelay(2); 4134c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 4144c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 4154c1c9b35SJohnny Huang if (size == 1) { 4164c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 4174c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 418d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 4194c1c9b35SJohnny Huang compare[0] = 0; 4204c1c9b35SJohnny Huang return 0; 4214c1c9b35SJohnny Huang } else { 4224c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4234c1c9b35SJohnny Huang return -1; 4244c1c9b35SJohnny Huang } 4254c1c9b35SJohnny Huang 4264c1c9b35SJohnny Huang } else { 4274c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 428d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 4294c1c9b35SJohnny Huang compare[0] = ~0; 4304c1c9b35SJohnny Huang return 0; 4314c1c9b35SJohnny Huang } else { 432d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 4334c1c9b35SJohnny Huang return -1; 4344c1c9b35SJohnny Huang } 4354c1c9b35SJohnny Huang } 4364c1c9b35SJohnny Huang } else if (size == 2) { 4374c1c9b35SJohnny Huang // otp_addr should be even 438d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 4394c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4404c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4414c1c9b35SJohnny Huang compare[0] = 0; 4424c1c9b35SJohnny Huang compare[1] = ~0; 4434c1c9b35SJohnny Huang return 0; 4444c1c9b35SJohnny Huang } else { 4454c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 4464c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 4474c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 4484c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 4494c1c9b35SJohnny Huang return -1; 4504c1c9b35SJohnny Huang } 4514c1c9b35SJohnny Huang } else { 4524c1c9b35SJohnny Huang return -1; 4534c1c9b35SJohnny Huang } 4544c1c9b35SJohnny Huang } 4554c1c9b35SJohnny Huang 4567e22f42dSJohnny Huang static void otp_soak(int soak) 457d90825e2SJohnny Huang { 458d90825e2SJohnny Huang if (soak) { 459d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 460d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 461d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 462d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 463d90825e2SJohnny Huang } else { 464d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 465d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 466d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 467d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 468d90825e2SJohnny Huang } 469d90825e2SJohnny Huang } 470d90825e2SJohnny Huang 471d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 472d90825e2SJohnny Huang { 473d90825e2SJohnny Huang int j, bit_value, prog_bit; 474d90825e2SJohnny Huang 475d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 476d90825e2SJohnny Huang if ((keep >> j) & 0x1) 477d90825e2SJohnny Huang continue; 478d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 479d90825e2SJohnny Huang if (prog_address % 2 == 0) { 480d90825e2SJohnny Huang if (bit_value) 481d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 482d90825e2SJohnny Huang else 483d90825e2SJohnny Huang continue; 484d90825e2SJohnny Huang } else { 485d90825e2SJohnny Huang prog_address |= 1 << 15; 486d90825e2SJohnny Huang if (bit_value) 487d90825e2SJohnny Huang continue; 488d90825e2SJohnny Huang else 489d90825e2SJohnny Huang prog_bit = 0x1 << j; 490d90825e2SJohnny Huang } 491d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 492d90825e2SJohnny Huang } 493d90825e2SJohnny Huang } 494d90825e2SJohnny Huang 49576d13988SJohnny Huang 49676d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 49776d13988SJohnny Huang { 49876d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 49976d13988SJohnny Huang int i, j; 50076d13988SJohnny Huang 50176d13988SJohnny Huang for (j = 0; j < 64; j++) { 50276d13988SJohnny Huang otpstrap[j].value = 0; 50376d13988SJohnny Huang otpstrap[j].remain_times = 7; 50476d13988SJohnny Huang otpstrap[j].writeable_option = -1; 50576d13988SJohnny Huang otpstrap[j].protected = 0; 50676d13988SJohnny Huang } 50776d13988SJohnny Huang 50876d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 50976d13988SJohnny Huang int option = (i - 16) / 2; 51076d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 51176d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 51276d13988SJohnny Huang for (j = 0; j < 32; j++) { 51376d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 51476d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 51576d13988SJohnny Huang otpstrap[j].writeable_option = option; 51676d13988SJohnny Huang } 51776d13988SJohnny Huang if (bit_value == 1) 51876d13988SJohnny Huang otpstrap[j].remain_times --; 51976d13988SJohnny Huang otpstrap[j].value ^= bit_value; 52076d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 52176d13988SJohnny Huang } 52276d13988SJohnny Huang for (j = 32; j < 64; j++) { 52376d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 52476d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 52576d13988SJohnny Huang otpstrap[j].writeable_option = option; 52676d13988SJohnny Huang } 52776d13988SJohnny Huang if (bit_value == 1) 52876d13988SJohnny Huang otpstrap[j].remain_times --; 52976d13988SJohnny Huang otpstrap[j].value ^= bit_value; 53076d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 53176d13988SJohnny Huang } 53276d13988SJohnny Huang } 53376d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 53476d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 53576d13988SJohnny Huang for (j = 0; j < 32; j++) { 53676d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 53776d13988SJohnny Huang otpstrap[j].protected = 1; 53876d13988SJohnny Huang } 53976d13988SJohnny Huang for (j = 32; j < 64; j++) { 54076d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 54176d13988SJohnny Huang otpstrap[j].protected = 1; 54276d13988SJohnny Huang } 54376d13988SJohnny Huang } 54476d13988SJohnny Huang 545b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 54669d5fd8fSJohnny Huang { 547442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 548b458cd62SJohnny Huang uint32_t mask; 549b458cd62SJohnny Huang uint32_t dw_offset; 550b458cd62SJohnny Huang uint32_t bit_offset; 551b458cd62SJohnny Huang uint32_t otp_value; 552b458cd62SJohnny Huang uint32_t otp_keep; 553b458cd62SJohnny Huang int fail = 0; 554b458cd62SJohnny Huang int valid_bit = 0; 55566f2f8e5SJohnny Huang int i; 55666f2f8e5SJohnny Huang 557737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 55866f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 559b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 560b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 561b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 562b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 563b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 564b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 565b458cd62SJohnny Huang 566b458cd62SJohnny Huang if (otp_keep == mask) { 567b458cd62SJohnny Huang continue; 568b458cd62SJohnny Huang } else if (otp_keep != 0) { 569b458cd62SJohnny Huang fail = 1; 570b458cd62SJohnny Huang } 571b458cd62SJohnny Huang 572b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 573b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 574b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 575b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 576b458cd62SJohnny Huang continue; 577b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 578b458cd62SJohnny Huang 579b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 580b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 58166f2f8e5SJohnny Huang } else { 582b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 583b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 584b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 58566f2f8e5SJohnny Huang } 586b458cd62SJohnny Huang printf("0x%-10x", otp_value); 587b458cd62SJohnny Huang 588b458cd62SJohnny Huang if (fail) { 589b458cd62SJohnny Huang printf("Keep mask error\n"); 590b458cd62SJohnny Huang } else { 591b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 592b458cd62SJohnny Huang printf("Reserved\n"); 593b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 594b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 595b458cd62SJohnny Huang printf("\n"); 596b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 597b458cd62SJohnny Huang if (otp_value != 0) { 598b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 599b458cd62SJohnny Huang if (otp_value == (1 << i)) { 600b458cd62SJohnny Huang valid_bit = i + 1; 60166f2f8e5SJohnny Huang } 602b458cd62SJohnny Huang } 603b458cd62SJohnny Huang } else { 604b458cd62SJohnny Huang valid_bit = 0; 605b458cd62SJohnny Huang } 606b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 607b458cd62SJohnny Huang printf("\n"); 608b458cd62SJohnny Huang } else { 609b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 610b458cd62SJohnny Huang } 611b458cd62SJohnny Huang } 612b458cd62SJohnny Huang } 613b458cd62SJohnny Huang 614b458cd62SJohnny Huang if (fail) 615b458cd62SJohnny Huang return OTP_FAILURE; 616b458cd62SJohnny Huang 61766f2f8e5SJohnny Huang return OTP_SUCCESS; 61866f2f8e5SJohnny Huang } 61966f2f8e5SJohnny Huang 6202d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 62166f2f8e5SJohnny Huang { 622b458cd62SJohnny Huang uint32_t OTPCFG[12]; 623b458cd62SJohnny Huang uint32_t mask; 624b458cd62SJohnny Huang uint32_t dw_offset; 625b458cd62SJohnny Huang uint32_t bit_offset; 626b458cd62SJohnny Huang uint32_t otp_value; 627b458cd62SJohnny Huang int valid_bit = 0; 62866f2f8e5SJohnny Huang int i; 62966f2f8e5SJohnny Huang 63066f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 63166f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 63266f2f8e5SJohnny Huang 63366f2f8e5SJohnny Huang 634b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 635b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 636b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 6372d4b0742SJohnny Huang if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset) 6382d4b0742SJohnny Huang continue; 639b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 640b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 641b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 642b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 643b458cd62SJohnny Huang 644b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 645b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 646b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 647b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 648b458cd62SJohnny Huang continue; 649b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 650b458cd62SJohnny Huang 651b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 652b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 653b458cd62SJohnny Huang } else { 654b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 655b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 656b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 657b458cd62SJohnny Huang } 658b458cd62SJohnny Huang printf("0x%-10x", otp_value); 659b458cd62SJohnny Huang 660b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 661b458cd62SJohnny Huang printf("Reserved\n"); 662b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 663b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 664b458cd62SJohnny Huang printf("\n"); 665b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 666b458cd62SJohnny Huang if (otp_value != 0) { 667b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 668b458cd62SJohnny Huang if (otp_value == (1 << i)) { 669b458cd62SJohnny Huang valid_bit = i + 1; 670b458cd62SJohnny Huang } 671b458cd62SJohnny Huang } 672b458cd62SJohnny Huang } else { 673b458cd62SJohnny Huang valid_bit = 0; 674b458cd62SJohnny Huang } 675b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 676b458cd62SJohnny Huang printf("\n"); 677b458cd62SJohnny Huang } else { 678b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 679b458cd62SJohnny Huang } 680b458cd62SJohnny Huang } 681b458cd62SJohnny Huang return OTP_SUCCESS; 68266f2f8e5SJohnny Huang } 68366f2f8e5SJohnny Huang 684b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 68576d13988SJohnny Huang { 686a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 687a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 68876d13988SJohnny Huang int i; 689a8bd6d8cSJohnny Huang int fail = 0; 690a8bd6d8cSJohnny Huang uint32_t bit_offset; 691a8bd6d8cSJohnny Huang uint32_t dw_offset; 692a8bd6d8cSJohnny Huang uint32_t mask; 693a8bd6d8cSJohnny Huang uint32_t otp_value; 694a8bd6d8cSJohnny Huang uint32_t otp_protect; 695a8bd6d8cSJohnny Huang uint32_t otp_keep; 69676d13988SJohnny Huang 697a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 698a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 699b458cd62SJohnny Huang 700a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 701a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 702a8bd6d8cSJohnny Huang dw_offset = 1; 703a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 704a8bd6d8cSJohnny Huang } else { 705a8bd6d8cSJohnny Huang dw_offset = 0; 706a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 707a8bd6d8cSJohnny Huang } 70876d13988SJohnny Huang 709a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 710a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 711a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 712a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 713a8bd6d8cSJohnny Huang 714a8bd6d8cSJohnny Huang if (otp_keep == mask) { 715a8bd6d8cSJohnny Huang continue; 716a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 717a8bd6d8cSJohnny Huang fail = 1; 718a8bd6d8cSJohnny Huang } 719a8bd6d8cSJohnny Huang 720a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 721a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 722a8bd6d8cSJohnny Huang continue; 723a8bd6d8cSJohnny Huang 724a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 725b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 726a8bd6d8cSJohnny Huang } else { 727b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 728a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 729a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 730a8bd6d8cSJohnny Huang } 731a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 732a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 733a8bd6d8cSJohnny Huang 734a8bd6d8cSJohnny Huang if (fail) { 735a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 736a8bd6d8cSJohnny Huang } else { 737a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 738a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 739a8bd6d8cSJohnny Huang else 740a8bd6d8cSJohnny Huang printf("Reserved\n"); 741a8bd6d8cSJohnny Huang } 742a8bd6d8cSJohnny Huang } 743a8bd6d8cSJohnny Huang 744a8bd6d8cSJohnny Huang if (fail) 74576d13988SJohnny Huang return OTP_FAILURE; 74676d13988SJohnny Huang 74776d13988SJohnny Huang return OTP_SUCCESS; 74876d13988SJohnny Huang } 74976d13988SJohnny Huang 750b458cd62SJohnny Huang static int otp_print_strap_info(int view) 75176d13988SJohnny Huang { 75276d13988SJohnny Huang struct otpstrap_status strap_status[64]; 75307baa4e8SJohnny Huang int i, j; 754b458cd62SJohnny Huang int fail = 0; 755b458cd62SJohnny Huang uint32_t bit_offset; 756b458cd62SJohnny Huang uint32_t length; 757b458cd62SJohnny Huang uint32_t otp_value; 758b458cd62SJohnny Huang uint32_t otp_protect; 75976d13988SJohnny Huang 76076d13988SJohnny Huang otp_strp_status(strap_status); 76176d13988SJohnny Huang 762b458cd62SJohnny Huang if (view) { 76307baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 76407baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 76507baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 76607baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 767b458cd62SJohnny Huang } else { 768b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 769b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 77076d13988SJohnny Huang } 771b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 772b458cd62SJohnny Huang otp_value = 0; 773b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 774b458cd62SJohnny Huang length = a0_strap_info[i].length; 775b458cd62SJohnny Huang for (j = 0; j < length; j++) { 776c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 777c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 778b458cd62SJohnny Huang } 779b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 780b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 781b458cd62SJohnny Huang continue; 782b458cd62SJohnny Huang if (view) { 783b458cd62SJohnny Huang for (j = 0; j < length; j++) { 784b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 785b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 78607baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 787b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 788b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 789b458cd62SJohnny Huang printf(" Reserved\n"); 790b458cd62SJohnny Huang continue; 791b458cd62SJohnny Huang } 792b458cd62SJohnny Huang if (length == 1) { 793b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 794b458cd62SJohnny Huang continue; 79576d13988SJohnny Huang } 79676d13988SJohnny Huang 797b458cd62SJohnny Huang if (j == 0) 798b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 799b458cd62SJohnny Huang else if (j == length - 1) 800b458cd62SJohnny Huang printf("\\ \"\n"); 801b458cd62SJohnny Huang else 802b458cd62SJohnny Huang printf("| \"\n"); 80376d13988SJohnny Huang } 804b458cd62SJohnny Huang } else { 805c947ef08SJohnny Huang if (length == 1) { 806b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 807b458cd62SJohnny Huang } else { 808b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 809b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 810b458cd62SJohnny Huang } 811b458cd62SJohnny Huang 812b458cd62SJohnny Huang printf("0x%-10X", otp_value); 813b458cd62SJohnny Huang 814b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 815b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 816b458cd62SJohnny Huang else 817b458cd62SJohnny Huang printf("Reserved\n"); 818b458cd62SJohnny Huang } 819b458cd62SJohnny Huang } 820b458cd62SJohnny Huang 821b458cd62SJohnny Huang if (fail) 822b458cd62SJohnny Huang return OTP_FAILURE; 823b458cd62SJohnny Huang 824b458cd62SJohnny Huang return OTP_SUCCESS; 825b458cd62SJohnny Huang } 826b458cd62SJohnny Huang 82769d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 82869d5fd8fSJohnny Huang { 82969d5fd8fSJohnny Huang int i; 83069d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 83169d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 83269d5fd8fSJohnny Huang if (i % 16 == 0) { 83369d5fd8fSJohnny Huang printf("%04X: ", i); 83469d5fd8fSJohnny Huang } 83569d5fd8fSJohnny Huang printf("%02X ", buf[i]); 83669d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 83769d5fd8fSJohnny Huang printf("\n"); 83869d5fd8fSJohnny Huang } 83969d5fd8fSJohnny Huang } 84069d5fd8fSJohnny Huang } 84169d5fd8fSJohnny Huang 8427f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 84369d5fd8fSJohnny Huang { 84469d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 84569d5fd8fSJohnny Huang char *byte_buf; 84669d5fd8fSJohnny Huang int i = 0, len = 0; 84769d5fd8fSJohnny Huang byte_buf = (char *)buf; 84869d5fd8fSJohnny Huang while (1) { 84969d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 85069d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 85169d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 85269d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 85369d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 85469d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 8557f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 85669d5fd8fSJohnny Huang printf("Key Type: "); 85769d5fd8fSJohnny Huang switch (key_type) { 85869d5fd8fSJohnny Huang case 0: 85969d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 86069d5fd8fSJohnny Huang break; 86169d5fd8fSJohnny Huang case 1: 86269d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 86369d5fd8fSJohnny Huang break; 86469d5fd8fSJohnny Huang case 4: 86569d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 86669d5fd8fSJohnny Huang break; 86769d5fd8fSJohnny Huang case 8: 86869d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 86969d5fd8fSJohnny Huang break; 87069d5fd8fSJohnny Huang case 9: 87169d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 87269d5fd8fSJohnny Huang break; 87369d5fd8fSJohnny Huang case 10: 87469d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 87569d5fd8fSJohnny Huang break; 87669d5fd8fSJohnny Huang case 13: 87769d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 87869d5fd8fSJohnny Huang break; 87969d5fd8fSJohnny Huang case 14: 88069d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 88169d5fd8fSJohnny Huang break; 88269d5fd8fSJohnny Huang default: 88369d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 88469d5fd8fSJohnny Huang return -1; 88569d5fd8fSJohnny Huang } 88669d5fd8fSJohnny Huang if (key_type == 4) { 88769d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 88869d5fd8fSJohnny Huang switch (key_length) { 88969d5fd8fSJohnny Huang case 0: 89069d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 89169d5fd8fSJohnny Huang break; 89269d5fd8fSJohnny Huang case 1: 89369d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 89469d5fd8fSJohnny Huang break; 89569d5fd8fSJohnny Huang case 2: 89669d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 89769d5fd8fSJohnny Huang break; 89869d5fd8fSJohnny Huang case 3: 89969d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 90069d5fd8fSJohnny Huang break; 90169d5fd8fSJohnny Huang } 902cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 90369d5fd8fSJohnny Huang printf("RSA SHA Type: "); 90469d5fd8fSJohnny Huang switch (key_length) { 90569d5fd8fSJohnny Huang case 0: 90669d5fd8fSJohnny Huang printf("RSA1024\n"); 90769d5fd8fSJohnny Huang len = 0x100; 90869d5fd8fSJohnny Huang break; 90969d5fd8fSJohnny Huang case 1: 91069d5fd8fSJohnny Huang printf("RSA2048\n"); 91169d5fd8fSJohnny Huang len = 0x200; 91269d5fd8fSJohnny Huang break; 91369d5fd8fSJohnny Huang case 2: 91469d5fd8fSJohnny Huang printf("RSA3072\n"); 91569d5fd8fSJohnny Huang len = 0x300; 91669d5fd8fSJohnny Huang break; 91769d5fd8fSJohnny Huang case 3: 91869d5fd8fSJohnny Huang printf("RSA4096\n"); 91969d5fd8fSJohnny Huang len = 0x400; 92069d5fd8fSJohnny Huang break; 92169d5fd8fSJohnny Huang } 92269d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 92369d5fd8fSJohnny Huang } 92469d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 92569d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 92669d5fd8fSJohnny Huang printf("Key Value:\n"); 92769d5fd8fSJohnny Huang if (key_type == 4) { 92869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 92969d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 93069d5fd8fSJohnny Huang printf("AES Key:\n"); 93169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 93269d5fd8fSJohnny Huang printf("AES IV:\n"); 93369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 93469d5fd8fSJohnny Huang 93569d5fd8fSJohnny Huang } else { 93669d5fd8fSJohnny Huang printf("RSA mod:\n"); 93769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 93869d5fd8fSJohnny Huang printf("RSA exp:\n"); 93969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 94069d5fd8fSJohnny Huang } 94169d5fd8fSJohnny Huang if (last) 94269d5fd8fSJohnny Huang break; 94369d5fd8fSJohnny Huang i++; 94469d5fd8fSJohnny Huang } 94569d5fd8fSJohnny Huang return 0; 94669d5fd8fSJohnny Huang } 94769d5fd8fSJohnny Huang 948a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 94969d5fd8fSJohnny Huang { 950a6d0d645SJohnny Huang int i, k; 951d90825e2SJohnny Huang int pass = 0; 952d90825e2SJohnny Huang int soak = 0; 953a6d0d645SJohnny Huang uint32_t prog_address; 954a6d0d645SJohnny Huang uint32_t data[12]; 955a6d0d645SJohnny Huang uint32_t compare[2]; 956d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 957d90825e2SJohnny Huang uint32_t data_masked; 958d90825e2SJohnny Huang uint32_t buf_masked; 95969d5fd8fSJohnny Huang 960a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 961a6d0d645SJohnny Huang 962a6d0d645SJohnny Huang printProgress(0, 12, ""); 963a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 964a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 96569d5fd8fSJohnny Huang prog_address = 0x800; 966a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 967a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 968a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 969a6d0d645SJohnny Huang } 970a6d0d645SJohnny Huang 971a6d0d645SJohnny Huang printf("Check writable...\n"); 972a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 973d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 974d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 975d90825e2SJohnny Huang if (data_masked == buf_masked) 97669d5fd8fSJohnny Huang continue; 977d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 978a6d0d645SJohnny Huang continue; 979a6d0d645SJohnny Huang } else { 980a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 981a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 982a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 983a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 9842a856b9aSJohnny Huang return OTP_FAILURE; 985a6d0d645SJohnny Huang } 986a6d0d645SJohnny Huang } 987a6d0d645SJohnny Huang 988a6d0d645SJohnny Huang printf("Start Programing...\n"); 989a6d0d645SJohnny Huang printProgress(0, 12, ""); 990d90825e2SJohnny Huang otp_soak(0); 991a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 992d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 993d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 994a6d0d645SJohnny Huang prog_address = 0x800; 995a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 996a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 997d90825e2SJohnny Huang if (data_masked == buf_masked) { 998a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 999a6d0d645SJohnny Huang continue; 1000a6d0d645SJohnny Huang } 1001d90825e2SJohnny Huang if (soak) { 1002d90825e2SJohnny Huang soak = 0; 1003d90825e2SJohnny Huang otp_soak(0); 1004d90825e2SJohnny Huang } 1005a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1006a6d0d645SJohnny Huang 1007d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1008a6d0d645SJohnny Huang 100969d5fd8fSJohnny Huang pass = 0; 101069d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1011d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1012d90825e2SJohnny Huang if (soak == 0) { 1013d90825e2SJohnny Huang soak = 1; 1014d90825e2SJohnny Huang otp_soak(1); 1015d90825e2SJohnny Huang } 1016a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1017a6d0d645SJohnny Huang } else { 101869d5fd8fSJohnny Huang pass = 1; 101969d5fd8fSJohnny Huang break; 102069d5fd8fSJohnny Huang } 102169d5fd8fSJohnny Huang } 1022a6d0d645SJohnny Huang } 1023a6d0d645SJohnny Huang 102469d5fd8fSJohnny Huang if (!pass) 10252a856b9aSJohnny Huang return OTP_FAILURE; 1026a6d0d645SJohnny Huang 10272a856b9aSJohnny Huang return OTP_SUCCESS; 1028d90825e2SJohnny Huang 102969d5fd8fSJohnny Huang } 103069d5fd8fSJohnny Huang 103169d5fd8fSJohnny Huang 103276d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 103369d5fd8fSJohnny Huang { 103469d5fd8fSJohnny Huang int i; 103569d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 103669d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 103769d5fd8fSJohnny Huang int bit, pbit, kbit; 103869d5fd8fSJohnny Huang int fail = 0; 1039a6af4a17SJohnny Huang int skip = -1; 104066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 104169d5fd8fSJohnny Huang 104269d5fd8fSJohnny Huang otp_strp_status(otpstrap); 104369d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 104469d5fd8fSJohnny Huang if (i < 32) { 104569d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 104669d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 104769d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 104869d5fd8fSJohnny Huang } else { 104969d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 105069d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 105169d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 105269d5fd8fSJohnny Huang } 105369d5fd8fSJohnny Huang 105469d5fd8fSJohnny Huang if (kbit == 1) { 105569d5fd8fSJohnny Huang continue; 105669d5fd8fSJohnny Huang } else { 1057a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 105869d5fd8fSJohnny Huang } 105969d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 106069d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1061a6af4a17SJohnny Huang if (skip == -1) 1062a6af4a17SJohnny Huang skip = 1; 106369d5fd8fSJohnny Huang continue; 1064a6af4a17SJohnny Huang } else { 1065a6af4a17SJohnny Huang skip = 0; 106669d5fd8fSJohnny Huang } 106769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 106869d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 106969d5fd8fSJohnny Huang fail = 1; 107069d5fd8fSJohnny Huang continue; 107169d5fd8fSJohnny Huang } 107269d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1073a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 107469d5fd8fSJohnny Huang fail = 1; 107569d5fd8fSJohnny Huang continue; 107669d5fd8fSJohnny Huang } 107769d5fd8fSJohnny Huang if (pbit == 1) { 107869d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 107969d5fd8fSJohnny Huang } 1080a6af4a17SJohnny 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); 108169d5fd8fSJohnny Huang } 108269d5fd8fSJohnny Huang if (fail == 1) 1083a6af4a17SJohnny Huang return OTP_FAILURE; 1084a6af4a17SJohnny Huang else if (skip == 1) 1085a6af4a17SJohnny Huang return OTP_PROG_SKIP; 10867e22f42dSJohnny Huang 10877e22f42dSJohnny Huang return 0; 108869d5fd8fSJohnny Huang } 108969d5fd8fSJohnny Huang 10902a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 109169d5fd8fSJohnny Huang { 109269d5fd8fSJohnny Huang int i, j; 109366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 109469d5fd8fSJohnny Huang 10952a856b9aSJohnny Huang if (start < 0 || start > 64) 10962a856b9aSJohnny Huang return OTP_USAGE; 10972a856b9aSJohnny Huang 10982a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 10992a856b9aSJohnny Huang return OTP_USAGE; 11002a856b9aSJohnny Huang 110169d5fd8fSJohnny Huang otp_strp_status(otpstrap); 110269d5fd8fSJohnny Huang 110307baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1104a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1105737ed20bSJohnny Huang 1106cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 110707baa4e8SJohnny Huang printf("0x%-8X", i); 1108737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1109737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1110737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1111737ed20bSJohnny Huang printf(" "); 111269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1113737ed20bSJohnny Huang printf("protected and not writable"); 111469d5fd8fSJohnny Huang } else { 1115737ed20bSJohnny Huang printf("not protected "); 111669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1117737ed20bSJohnny Huang printf("and no remaining times to write."); 111869d5fd8fSJohnny Huang } else { 1119737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 112069d5fd8fSJohnny Huang } 112169d5fd8fSJohnny Huang } 1122737ed20bSJohnny Huang printf("\n"); 112369d5fd8fSJohnny Huang } 11242a856b9aSJohnny Huang 11252a856b9aSJohnny Huang return OTP_SUCCESS; 112669d5fd8fSJohnny Huang } 112769d5fd8fSJohnny Huang 112869d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 112969d5fd8fSJohnny Huang { 113069d5fd8fSJohnny Huang int i, j; 113169d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 113269d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 113369d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 113469d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 113569d5fd8fSJohnny Huang int fail = 0; 11367e22f42dSJohnny Huang int pass = 0; 11377e22f42dSJohnny Huang int soak = 0; 113866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 113969d5fd8fSJohnny Huang 11407f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 114169d5fd8fSJohnny Huang otp_strp_status(otpstrap); 114269d5fd8fSJohnny Huang 11437f795e57SJohnny Huang printf("Check writable...\n"); 11447f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 11457f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 11467f795e57SJohnny Huang return OTP_FAILURE; 11477f795e57SJohnny Huang } 11487e22f42dSJohnny Huang 11497f795e57SJohnny Huang otp_soak(0); 115069d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 11514c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 115269d5fd8fSJohnny Huang prog_address = 0x800; 115369d5fd8fSJohnny Huang if (i < 32) { 115469d5fd8fSJohnny Huang offset = i; 115569d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 115669d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 115769d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 115869d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 115969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 116069d5fd8fSJohnny Huang 116169d5fd8fSJohnny Huang } else { 116269d5fd8fSJohnny Huang offset = (i - 32); 116369d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 116469d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 116569d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 116669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 116769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 116869d5fd8fSJohnny Huang } 116969d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 117069d5fd8fSJohnny Huang 117169d5fd8fSJohnny Huang if (kbit == 1) { 117269d5fd8fSJohnny Huang continue; 117369d5fd8fSJohnny Huang } 117469d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 117569d5fd8fSJohnny Huang continue; 117669d5fd8fSJohnny Huang } 117769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 117869d5fd8fSJohnny Huang fail = 1; 117969d5fd8fSJohnny Huang continue; 118069d5fd8fSJohnny Huang } 118169d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 118269d5fd8fSJohnny Huang fail = 1; 118369d5fd8fSJohnny Huang continue; 118469d5fd8fSJohnny Huang } 11857e22f42dSJohnny Huang 11867e22f42dSJohnny Huang if (soak) { 118769d5fd8fSJohnny Huang soak = 0; 11887e22f42dSJohnny Huang otp_soak(0); 11897e22f42dSJohnny Huang } 11907e22f42dSJohnny Huang 11917e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 11927e22f42dSJohnny Huang 11937e22f42dSJohnny Huang pass = 0; 11947e22f42dSJohnny Huang 119569d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1196a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 119769d5fd8fSJohnny Huang pass = 1; 119869d5fd8fSJohnny Huang break; 119969d5fd8fSJohnny Huang } 12007e22f42dSJohnny Huang if (soak == 0) { 120169d5fd8fSJohnny Huang soak = 1; 12027e22f42dSJohnny Huang otp_soak(1); 12034b65a65dSJohnny Huang } 120469d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 120569d5fd8fSJohnny Huang } 120669d5fd8fSJohnny Huang if (!pass) 12072a856b9aSJohnny Huang return OTP_FAILURE; 120869d5fd8fSJohnny Huang 120969d5fd8fSJohnny Huang if (pbit == 0) 121069d5fd8fSJohnny Huang continue; 121169d5fd8fSJohnny Huang prog_address = 0x800; 121269d5fd8fSJohnny Huang if (i < 32) 121369d5fd8fSJohnny Huang prog_address |= 0x60c; 121469d5fd8fSJohnny Huang else 121569d5fd8fSJohnny Huang prog_address |= 0x60e; 121669d5fd8fSJohnny Huang 12177e22f42dSJohnny Huang 12187e22f42dSJohnny Huang if (soak) { 12197e22f42dSJohnny Huang soak = 0; 12207e22f42dSJohnny Huang otp_soak(0); 12217e22f42dSJohnny Huang } 12227e22f42dSJohnny Huang 12237e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 12247e22f42dSJohnny Huang 12257e22f42dSJohnny Huang pass = 0; 12267e22f42dSJohnny Huang 122769d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 12287e22f42dSJohnny Huang 1229a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 123069d5fd8fSJohnny Huang pass = 1; 123169d5fd8fSJohnny Huang break; 123269d5fd8fSJohnny Huang } 12337e22f42dSJohnny Huang if (soak == 0) { 123469d5fd8fSJohnny Huang soak = 1; 12357e22f42dSJohnny Huang otp_soak(1); 123669d5fd8fSJohnny Huang } 123769d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 123869d5fd8fSJohnny Huang } 123969d5fd8fSJohnny Huang if (!pass) 12402a856b9aSJohnny Huang return OTP_FAILURE; 124169d5fd8fSJohnny Huang 124269d5fd8fSJohnny Huang } 124369d5fd8fSJohnny Huang if (fail == 1) 12442a856b9aSJohnny Huang return OTP_FAILURE; 124569d5fd8fSJohnny Huang else 12462a856b9aSJohnny Huang return OTP_SUCCESS; 124769d5fd8fSJohnny Huang 124869d5fd8fSJohnny Huang } 124969d5fd8fSJohnny Huang 1250cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1251cd1610b4SJohnny Huang { 1252cd1610b4SJohnny Huang int prog_bit; 1253cd1610b4SJohnny Huang 12547e22f42dSJohnny Huang otp_soak(soak); 12557e22f42dSJohnny Huang 1256cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1257cd1610b4SJohnny Huang if (value) 1258cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1259cd1610b4SJohnny Huang else 1260cd1610b4SJohnny Huang return; 1261cd1610b4SJohnny Huang } else { 1262cd1610b4SJohnny Huang prog_address |= 1 << 15; 1263cd1610b4SJohnny Huang if (!value) 1264cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1265cd1610b4SJohnny Huang else 1266cd1610b4SJohnny Huang return; 1267cd1610b4SJohnny Huang } 1268cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1269cd1610b4SJohnny Huang } 1270cd1610b4SJohnny Huang 1271d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 12724c1c9b35SJohnny Huang { 12734c1c9b35SJohnny Huang int i, k; 12744c1c9b35SJohnny Huang int pass; 1275d90825e2SJohnny Huang int soak = 0; 12764c1c9b35SJohnny Huang uint32_t prog_address; 1277d90825e2SJohnny Huang uint32_t data[2048]; 12784c1c9b35SJohnny Huang uint32_t compare[2]; 1279d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 12804c1c9b35SJohnny Huang 1281d90825e2SJohnny Huang uint32_t data0_masked; 1282d90825e2SJohnny Huang uint32_t data1_masked; 1283d90825e2SJohnny Huang uint32_t buf0_masked; 1284d90825e2SJohnny Huang uint32_t buf1_masked; 12854c1c9b35SJohnny Huang 12864c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 12874c1c9b35SJohnny Huang 1288d90825e2SJohnny Huang printProgress(0, 2048, ""); 1289d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1290d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1291d90825e2SJohnny Huang otp_read_data(i, &data[i]); 12924c1c9b35SJohnny Huang } 1293d90825e2SJohnny Huang 12944c1c9b35SJohnny Huang 12954c1c9b35SJohnny Huang printf("Check writable...\n"); 1296d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1297d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1298d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1299d90825e2SJohnny Huang if (data0_masked == buf0_masked) 13004c1c9b35SJohnny Huang continue; 1301d90825e2SJohnny Huang if (i % 2 == 0) { 1302d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 13034c1c9b35SJohnny Huang continue; 13044c1c9b35SJohnny Huang } else { 13054c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1306d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 13074c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1308d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 13092a856b9aSJohnny Huang return OTP_FAILURE; 131069d5fd8fSJohnny Huang } 1311d90825e2SJohnny Huang } else { 1312d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1313d90825e2SJohnny Huang continue; 1314d90825e2SJohnny Huang } else { 1315d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1316d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1317d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1318d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 13192a856b9aSJohnny Huang return OTP_FAILURE; 1320d90825e2SJohnny Huang } 1321d90825e2SJohnny Huang } 1322d90825e2SJohnny Huang } 132369d5fd8fSJohnny Huang 1324d90825e2SJohnny Huang printf("Start Programing...\n"); 1325d90825e2SJohnny Huang printProgress(0, 2048, ""); 1326d90825e2SJohnny Huang 1327d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1328d90825e2SJohnny Huang prog_address = i; 1329d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1330d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1331d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1332d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1333d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1334d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1335d90825e2SJohnny Huang continue; 1336d90825e2SJohnny Huang } 1337d90825e2SJohnny Huang if (soak) { 1338d90825e2SJohnny Huang soak = 0; 1339d90825e2SJohnny Huang otp_soak(0); 1340d90825e2SJohnny Huang } 1341d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1342d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1343d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1344d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1345d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1346d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1347d90825e2SJohnny Huang } else { 1348d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1349d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1350d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1351d90825e2SJohnny Huang } 1352d90825e2SJohnny Huang 1353d90825e2SJohnny Huang pass = 0; 1354d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1355d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1356d90825e2SJohnny Huang if (soak == 0) { 1357d90825e2SJohnny Huang soak = 1; 1358d90825e2SJohnny Huang otp_soak(1); 1359d90825e2SJohnny Huang } 1360d90825e2SJohnny Huang if (compare[0] != 0) { 1361d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1362d90825e2SJohnny Huang } 1363d90825e2SJohnny Huang if (compare[1] != ~0) { 1364d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1365d90825e2SJohnny Huang } 1366d90825e2SJohnny Huang } else { 1367d90825e2SJohnny Huang pass = 1; 1368d90825e2SJohnny Huang break; 1369d90825e2SJohnny Huang } 1370d90825e2SJohnny Huang } 1371d90825e2SJohnny Huang 1372d90825e2SJohnny Huang if (!pass) 13732a856b9aSJohnny Huang return OTP_FAILURE; 1374d90825e2SJohnny Huang } 13752a856b9aSJohnny Huang return OTP_SUCCESS; 1376d90825e2SJohnny Huang 1377d90825e2SJohnny Huang } 1378d90825e2SJohnny Huang 1379d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 138069d5fd8fSJohnny Huang { 138169d5fd8fSJohnny Huang int ret; 13827332532cSJohnny Huang int mode = 0; 138369d5fd8fSJohnny Huang uint32_t *buf; 1384d90825e2SJohnny Huang uint32_t *data_region = NULL; 1385d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1386d90825e2SJohnny Huang uint32_t *strap_region = NULL; 138769d5fd8fSJohnny Huang 1388d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 138969d5fd8fSJohnny Huang if (!buf) { 139069d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 13912a856b9aSJohnny Huang return OTP_FAILURE; 139269d5fd8fSJohnny Huang } 1393d90825e2SJohnny Huang 1394d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 13957332532cSJohnny Huang mode |= OTP_REGION_DATA; 13967332532cSJohnny Huang data_region = &buf[36]; 1397d90825e2SJohnny Huang } 1398d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 13997332532cSJohnny Huang mode |= OTP_REGION_CONF; 14007332532cSJohnny Huang conf_region = &buf[12]; 1401d90825e2SJohnny Huang } 1402d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 14037332532cSJohnny Huang mode |= OTP_REGION_STRAP; 14047332532cSJohnny Huang strap_region = &buf[4]; 1405d90825e2SJohnny Huang } 14067332532cSJohnny Huang 140769d5fd8fSJohnny Huang if (!nconfirm) { 14087332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 14097f795e57SJohnny Huang printf("\nOTP data region :\n"); 14107f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 141169d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 14122a856b9aSJohnny Huang return OTP_FAILURE; 141369d5fd8fSJohnny Huang } 141469d5fd8fSJohnny Huang } 14157332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 14167332532cSJohnny Huang printf("\nOTP strap region :\n"); 14177332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 14187332532cSJohnny Huang printf("OTP strap error, please check.\n"); 14197332532cSJohnny Huang return OTP_FAILURE; 14207332532cSJohnny Huang } 14217332532cSJohnny Huang } 14227332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 14237332532cSJohnny Huang printf("\nOTP configuration region :\n"); 14247332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 14257332532cSJohnny Huang printf("OTP config error, please check.\n"); 14267332532cSJohnny Huang return OTP_FAILURE; 14277332532cSJohnny Huang } 14287332532cSJohnny Huang } 14297332532cSJohnny Huang 143069d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 143169d5fd8fSJohnny Huang if (!confirm_yesno()) { 143269d5fd8fSJohnny Huang printf(" Aborting\n"); 14332a856b9aSJohnny Huang return OTP_FAILURE; 143469d5fd8fSJohnny Huang } 143569d5fd8fSJohnny Huang } 14367332532cSJohnny Huang 14377332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 14387332532cSJohnny Huang printf("programing data region ...\n"); 1439d90825e2SJohnny Huang ret = otp_prog_data(data_region); 14402a856b9aSJohnny Huang if (ret != 0) { 144169d5fd8fSJohnny Huang printf("Error\n"); 144269d5fd8fSJohnny Huang return ret; 144369d5fd8fSJohnny Huang } else { 144469d5fd8fSJohnny Huang printf("Done\n"); 144569d5fd8fSJohnny Huang } 14467332532cSJohnny Huang } 14477332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 14487332532cSJohnny Huang printf("programing strap region ...\n"); 1449d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 14502a856b9aSJohnny Huang if (ret != 0) { 145169d5fd8fSJohnny Huang printf("Error\n"); 145269d5fd8fSJohnny Huang return ret; 145369d5fd8fSJohnny Huang } else { 145469d5fd8fSJohnny Huang printf("Done\n"); 145569d5fd8fSJohnny Huang } 14567332532cSJohnny Huang } 14577332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 14587332532cSJohnny Huang printf("programing configuration region ...\n"); 1459d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 14602a856b9aSJohnny Huang if (ret != 0) { 146169d5fd8fSJohnny Huang printf("Error\n"); 146269d5fd8fSJohnny Huang return ret; 146369d5fd8fSJohnny Huang } 146469d5fd8fSJohnny Huang printf("Done\n"); 146569d5fd8fSJohnny Huang } 1466cd1610b4SJohnny Huang 14677332532cSJohnny Huang return OTP_SUCCESS; 14682a856b9aSJohnny Huang } 14692a856b9aSJohnny Huang 14702a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1471cd1610b4SJohnny Huang { 1472a6af4a17SJohnny Huang uint32_t read[2]; 1473cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1474d90825e2SJohnny Huang uint32_t prog_address = 0; 147566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1476cd1610b4SJohnny Huang int otp_bit; 1477cd1610b4SJohnny Huang int i; 1478cd1610b4SJohnny Huang int pass; 1479a6af4a17SJohnny Huang int ret; 1480cd1610b4SJohnny Huang 1481cd1610b4SJohnny Huang switch (mode) { 1482a6d0d645SJohnny Huang case OTP_REGION_CONF: 1483a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1484cd1610b4SJohnny Huang prog_address = 0x800; 1485cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1486cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1487a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1488cd1610b4SJohnny Huang if (otp_bit == value) { 1489a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1490cd1610b4SJohnny Huang printf("No need to program\n"); 14912a856b9aSJohnny Huang return OTP_SUCCESS; 1492cd1610b4SJohnny Huang } 1493cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1494a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1495cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 14962a856b9aSJohnny Huang return OTP_FAILURE; 1497cd1610b4SJohnny Huang } 1498a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1499cd1610b4SJohnny Huang break; 1500a6d0d645SJohnny Huang case OTP_REGION_DATA: 1501cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1502cd1610b4SJohnny Huang 1503cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1504a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1505a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1506cd1610b4SJohnny Huang } else { 1507a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1508a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1509cd1610b4SJohnny Huang } 1510cd1610b4SJohnny Huang if (otp_bit == value) { 1511a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1512cd1610b4SJohnny Huang printf("No need to program\n"); 15132a856b9aSJohnny Huang return OTP_SUCCESS; 1514cd1610b4SJohnny Huang } 1515cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1516a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1517cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 15182a856b9aSJohnny Huang return OTP_FAILURE; 1519cd1610b4SJohnny Huang } 1520a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1521cd1610b4SJohnny Huang break; 1522a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1523cd1610b4SJohnny Huang otp_strp_status(otpstrap); 1524cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1525cd1610b4SJohnny Huang if (bit_offset < 32) { 1526cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1527cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1528cd1610b4SJohnny Huang strap_buf[3] = ~0; 1529cd1610b4SJohnny Huang strap_buf[5] = 0; 15302a856b9aSJohnny Huang // if (protect) 15312a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 15322a856b9aSJohnny Huang // else 15332a856b9aSJohnny Huang // strap_buf[4] = 0; 1534cd1610b4SJohnny Huang } else { 1535cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1536cd1610b4SJohnny Huang strap_buf[2] = ~0; 1537cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1538cd1610b4SJohnny Huang strap_buf[4] = 0; 15392a856b9aSJohnny Huang // if (protect) 15402a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 15412a856b9aSJohnny Huang // else 15422a856b9aSJohnny Huang // strap_buf[5] = 0; 1543cd1610b4SJohnny Huang } 154476d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1545a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 15462a856b9aSJohnny Huang return OTP_FAILURE; 1547a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1548a6af4a17SJohnny Huang return OTP_SUCCESS; 1549a6af4a17SJohnny Huang 1550cd1610b4SJohnny Huang break; 1551cd1610b4SJohnny Huang } 1552cd1610b4SJohnny Huang 1553cd1610b4SJohnny Huang if (!nconfirm) { 1554cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1555cd1610b4SJohnny Huang if (!confirm_yesno()) { 1556cd1610b4SJohnny Huang printf(" Aborting\n"); 15572a856b9aSJohnny Huang return OTP_FAILURE; 1558cd1610b4SJohnny Huang } 1559cd1610b4SJohnny Huang } 1560cd1610b4SJohnny Huang 1561cd1610b4SJohnny Huang switch (mode) { 1562a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1563cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1564a6d0d645SJohnny Huang case OTP_REGION_CONF: 1565a6d0d645SJohnny Huang case OTP_REGION_DATA: 1566cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1567cd1610b4SJohnny Huang pass = -1; 1568cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1569a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1570cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1571cd1610b4SJohnny Huang } else { 1572cd1610b4SJohnny Huang pass = 0; 1573cd1610b4SJohnny Huang break; 1574cd1610b4SJohnny Huang } 1575cd1610b4SJohnny Huang } 15762a856b9aSJohnny Huang if (pass == 0) 15772a856b9aSJohnny Huang return OTP_SUCCESS; 1578cd1610b4SJohnny Huang } 1579cd1610b4SJohnny Huang 15802a856b9aSJohnny Huang return OTP_USAGE; 1581cd1610b4SJohnny Huang } 1582cd1610b4SJohnny Huang 15832a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 158469d5fd8fSJohnny Huang { 15852a856b9aSJohnny Huang uint32_t offset, count; 15862a856b9aSJohnny Huang int ret; 158769d5fd8fSJohnny Huang 15882a856b9aSJohnny Huang if (argc == 4) { 15892a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 15902a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 15912a856b9aSJohnny Huang } else if (argc == 3) { 15922a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 15932a856b9aSJohnny Huang count = 1; 15942a856b9aSJohnny Huang } else { 159569d5fd8fSJohnny Huang return CMD_RET_USAGE; 159669d5fd8fSJohnny Huang } 159769d5fd8fSJohnny Huang 159869d5fd8fSJohnny Huang 15992a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 160069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16012a856b9aSJohnny Huang ret = otp_print_config(offset, count); 16022a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 16032a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16042a856b9aSJohnny Huang ret = otp_print_data(offset, count); 16052a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 16062a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16072a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 16082a856b9aSJohnny Huang } else { 16092a856b9aSJohnny Huang return CMD_RET_USAGE; 161069d5fd8fSJohnny Huang } 161169d5fd8fSJohnny Huang 16122a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 16132a856b9aSJohnny Huang return CMD_RET_SUCCESS; 16142a856b9aSJohnny Huang else 16152a856b9aSJohnny Huang return CMD_RET_USAGE; 16162a856b9aSJohnny Huang 16172a856b9aSJohnny Huang } 16182a856b9aSJohnny Huang 16192a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 16202a856b9aSJohnny Huang { 16212a856b9aSJohnny Huang phys_addr_t addr; 16222a856b9aSJohnny Huang uint32_t byte_size; 16232a856b9aSJohnny Huang int ret; 16242a856b9aSJohnny Huang 16252a856b9aSJohnny Huang if (argc == 4) { 16262a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 16272a856b9aSJohnny Huang return CMD_RET_USAGE; 16282a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 16292a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 163069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16312a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 16322a856b9aSJohnny Huang } else if (argc == 3) { 16332a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 16342a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 16352a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 16362a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 16372a856b9aSJohnny Huang } else { 16382a856b9aSJohnny Huang return CMD_RET_USAGE; 16392a856b9aSJohnny Huang } 16402a856b9aSJohnny Huang 16412a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 16422a856b9aSJohnny Huang return CMD_RET_SUCCESS; 16432a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 16442a856b9aSJohnny Huang return CMD_RET_FAILURE; 16452a856b9aSJohnny Huang else 16462a856b9aSJohnny Huang return CMD_RET_USAGE; 16472a856b9aSJohnny Huang } 16482a856b9aSJohnny Huang 16492a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 16502a856b9aSJohnny Huang { 16512a856b9aSJohnny Huang int mode = 0; 16522a856b9aSJohnny Huang int nconfirm = 0; 16532a856b9aSJohnny Huang int otp_addr = 0; 16542a856b9aSJohnny Huang int bit_offset; 16552a856b9aSJohnny Huang int value; 16562a856b9aSJohnny Huang int ret; 16572a856b9aSJohnny Huang 16582a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 16592a856b9aSJohnny Huang return CMD_RET_USAGE; 16602a856b9aSJohnny Huang 16612a856b9aSJohnny Huang /* Drop the pb cmd */ 16622a856b9aSJohnny Huang argc--; 16632a856b9aSJohnny Huang argv++; 16642a856b9aSJohnny Huang 16652a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1666a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 16672a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1668a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 16692a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1670a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1671cd1610b4SJohnny Huang else 16722a856b9aSJohnny Huang return CMD_RET_USAGE; 16732a856b9aSJohnny Huang 16742a856b9aSJohnny Huang /* Drop the region cmd */ 16752a856b9aSJohnny Huang argc--; 16762a856b9aSJohnny Huang argv++; 16772a856b9aSJohnny Huang 16782a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1679cd1610b4SJohnny Huang nconfirm = 1; 16802a856b9aSJohnny Huang /* Drop the force option */ 16812a856b9aSJohnny Huang argc--; 16822a856b9aSJohnny Huang argv++; 16832a856b9aSJohnny Huang } 1684cd1610b4SJohnny Huang 1685a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 16862a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 16872a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1688cd1610b4SJohnny Huang if (bit_offset >= 64) 16892a856b9aSJohnny Huang return CMD_RET_USAGE; 1690cd1610b4SJohnny Huang } else { 16912a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 16922a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 16932a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1694cd1610b4SJohnny Huang if (bit_offset >= 32) 16952a856b9aSJohnny Huang return CMD_RET_USAGE; 1696cd1610b4SJohnny Huang } 1697cd1610b4SJohnny Huang if (value != 0 && value != 1) 16982a856b9aSJohnny Huang return CMD_RET_USAGE; 1699cd1610b4SJohnny Huang 1700cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17012a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 17022a856b9aSJohnny Huang 17032a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 17042a856b9aSJohnny Huang return CMD_RET_SUCCESS; 17052a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 17062a856b9aSJohnny Huang return CMD_RET_FAILURE; 17072a856b9aSJohnny Huang else 17082a856b9aSJohnny Huang return CMD_RET_USAGE; 17092a856b9aSJohnny Huang } 17102a856b9aSJohnny Huang 17112a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 17122a856b9aSJohnny Huang { 17132a856b9aSJohnny Huang phys_addr_t addr; 17142a856b9aSJohnny Huang int otp_addr = 0; 17152a856b9aSJohnny Huang 17162a856b9aSJohnny Huang if (argc != 3) 17172a856b9aSJohnny Huang return CMD_RET_USAGE; 17182a856b9aSJohnny Huang 171969d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17202a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 17212a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 17222a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 172369d5fd8fSJohnny Huang printf("Compare pass\n"); 17242a856b9aSJohnny Huang return CMD_RET_SUCCESS; 172569d5fd8fSJohnny Huang } else { 172669d5fd8fSJohnny Huang printf("Compare fail\n"); 17272a856b9aSJohnny Huang return CMD_RET_FAILURE; 172869d5fd8fSJohnny Huang } 172969d5fd8fSJohnny Huang } 173069d5fd8fSJohnny Huang 173166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 173266f2f8e5SJohnny Huang { 1733a8bd6d8cSJohnny Huang int view = 0; 17342d4b0742SJohnny Huang int input; 1735a8bd6d8cSJohnny Huang 1736a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 173766f2f8e5SJohnny Huang return CMD_RET_USAGE; 173866f2f8e5SJohnny Huang 17392d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 174066f2f8e5SJohnny Huang 17412d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17422d4b0742SJohnny Huang if (argc == 3) { 17432d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 17442d4b0742SJohnny Huang otp_print_conf_info(input); 17452d4b0742SJohnny Huang } else { 17462d4b0742SJohnny Huang otp_print_conf_info(-1); 17472d4b0742SJohnny Huang } 17482d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 17492d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 1750a8bd6d8cSJohnny Huang view = 1; 1751a8bd6d8cSJohnny Huang /* Drop the view option */ 1752a8bd6d8cSJohnny Huang argc--; 1753a8bd6d8cSJohnny Huang argv++; 1754a8bd6d8cSJohnny Huang } 175566f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1756b458cd62SJohnny Huang otp_print_strap_info(view); 175766f2f8e5SJohnny Huang } else { 175866f2f8e5SJohnny Huang return CMD_RET_USAGE; 175966f2f8e5SJohnny Huang } 17602d4b0742SJohnny Huang 176166f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 176266f2f8e5SJohnny Huang } 176366f2f8e5SJohnny Huang 1764737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 1765737ed20bSJohnny Huang { 1766737ed20bSJohnny Huang int input; 1767737ed20bSJohnny Huang int bit_offset; 1768737ed20bSJohnny Huang int prog_address; 1769737ed20bSJohnny Huang int pass; 1770737ed20bSJohnny Huang int i; 1771737ed20bSJohnny Huang if (argc != 3 && argc != 2) 1772737ed20bSJohnny Huang return CMD_RET_USAGE; 1773737ed20bSJohnny Huang 1774737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 1775737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1776737ed20bSJohnny Huang } else { 1777737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 1778737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 1779737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1780737ed20bSJohnny Huang if (!confirm_yesno()) { 1781737ed20bSJohnny Huang printf(" Aborting\n"); 1782737ed20bSJohnny Huang return CMD_RET_FAILURE; 1783737ed20bSJohnny Huang } 1784737ed20bSJohnny Huang } 1785737ed20bSJohnny Huang 1786737ed20bSJohnny Huang prog_address = 0x800; 1787737ed20bSJohnny Huang if (input < 32) { 1788737ed20bSJohnny Huang bit_offset = input; 1789737ed20bSJohnny Huang prog_address |= 0x60c; 1790737ed20bSJohnny Huang } else if (input < 64) { 1791737ed20bSJohnny Huang bit_offset = input - 32; 1792737ed20bSJohnny Huang prog_address |= 0x60e; 1793737ed20bSJohnny Huang } else { 1794737ed20bSJohnny Huang return CMD_RET_USAGE; 1795737ed20bSJohnny Huang } 1796737ed20bSJohnny Huang 1797737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 1798737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 1799737ed20bSJohnny Huang } 1800737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 1801737ed20bSJohnny Huang pass = -1; 1802737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 1803737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 1804737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 1805737ed20bSJohnny Huang } else { 1806737ed20bSJohnny Huang pass = 0; 1807737ed20bSJohnny Huang break; 1808737ed20bSJohnny Huang } 1809737ed20bSJohnny Huang } 1810737ed20bSJohnny Huang if (pass == 0) { 1811737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 1812737ed20bSJohnny Huang return CMD_RET_SUCCESS; 1813737ed20bSJohnny Huang } 1814737ed20bSJohnny Huang 1815737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 1816737ed20bSJohnny Huang return CMD_RET_FAILURE; 1817737ed20bSJohnny Huang 1818737ed20bSJohnny Huang } 18192a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 18202a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 1821a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 18222a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 18232a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 1824737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 18252a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 18262a856b9aSJohnny Huang }; 18272a856b9aSJohnny Huang 18282a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18292a856b9aSJohnny Huang { 18302a856b9aSJohnny Huang cmd_tbl_t *cp; 18312a856b9aSJohnny Huang 18322a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 18332a856b9aSJohnny Huang 1834737ed20bSJohnny Huang /* Drop the otp command */ 18352a856b9aSJohnny Huang argc--; 18362a856b9aSJohnny Huang argv++; 18372a856b9aSJohnny Huang 18382a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 18392a856b9aSJohnny Huang return CMD_RET_USAGE; 18402a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 18412a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18422a856b9aSJohnny Huang 18432a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 184469d5fd8fSJohnny Huang } 184569d5fd8fSJohnny Huang 184669d5fd8fSJohnny Huang U_BOOT_CMD( 184769d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 184869d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 18492a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 18502a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 18512d4b0742SJohnny Huang "otp info strap [v]\n" 18522d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 1853d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 1854cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 1855737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 1856737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 18572a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 185869d5fd8fSJohnny Huang ); 1859