169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 28a6d0d645SJohnny Huang #define OTP_REGION_STRAP 1 29a6d0d645SJohnny Huang #define OTP_REGION_CONF 2 30a6d0d645SJohnny Huang #define OTP_REGION_DATA 3 31a6d0d645SJohnny Huang #define OTP_REGION_ALL 4 3269d5fd8fSJohnny Huang 332a856b9aSJohnny Huang #define OTP_USAGE -1 342a856b9aSJohnny Huang #define OTP_FAILURE -2 352a856b9aSJohnny Huang #define OTP_SUCCESS 0 362a856b9aSJohnny Huang 37a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 38a6af4a17SJohnny Huang 39a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 40*b458cd62SJohnny Huang #define OTP_REG_VALUE -2 41*b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4276d13988SJohnny Huang 434c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 444c1c9b35SJohnny Huang #define PBWIDTH 60 454c1c9b35SJohnny Huang 4666f2f8e5SJohnny Huang struct otpstrap_status { 4769d5fd8fSJohnny Huang int value; 4869d5fd8fSJohnny Huang int option_array[7]; 4969d5fd8fSJohnny Huang int remain_times; 5069d5fd8fSJohnny Huang int writeable_option; 5169d5fd8fSJohnny Huang int protected; 5269d5fd8fSJohnny Huang }; 5369d5fd8fSJohnny Huang 5466f2f8e5SJohnny Huang struct otpconf_parse { 5566f2f8e5SJohnny Huang int dw_offset; 5666f2f8e5SJohnny Huang int bit; 5766f2f8e5SJohnny Huang int length; 5866f2f8e5SJohnny Huang int value; 5966f2f8e5SJohnny Huang int keep; 6066f2f8e5SJohnny Huang char status[80]; 6166f2f8e5SJohnny Huang }; 6266f2f8e5SJohnny Huang 63a8bd6d8cSJohnny Huang struct otpstrap_info { 64a8bd6d8cSJohnny Huang uint32_t bit_offset; 65a8bd6d8cSJohnny Huang uint32_t length; 6676d13988SJohnny Huang int value; 67a8bd6d8cSJohnny Huang char information[80]; 68a8bd6d8cSJohnny Huang }; 69a8bd6d8cSJohnny Huang 70a8bd6d8cSJohnny Huang struct otpconf_info { 71a8bd6d8cSJohnny Huang uint32_t dw_offset; 72a8bd6d8cSJohnny Huang uint32_t bit_offset; 73a8bd6d8cSJohnny Huang uint32_t length; 74a8bd6d8cSJohnny Huang int value; 75a8bd6d8cSJohnny Huang char information[80]; 76a8bd6d8cSJohnny Huang }; 77a8bd6d8cSJohnny Huang 78a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 79a8bd6d8cSJohnny Huang { 80a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 81a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 82a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 83a8bd6d8cSJohnny Huang char buffer[256]; 84a8bd6d8cSJohnny Huang va_list aptr; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang va_start(aptr, format); 87a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 88a8bd6d8cSJohnny Huang va_end(aptr); 89a8bd6d8cSJohnny Huang 90a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 91a8bd6d8cSJohnny Huang if (numerator == denominator) 92a8bd6d8cSJohnny Huang printf("\n"); 93a8bd6d8cSJohnny Huang } 94a8bd6d8cSJohnny Huang 95a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 96a8bd6d8cSJohnny Huang { 97a8bd6d8cSJohnny Huang 0, 1, 0, "Disable secure boot" 98a8bd6d8cSJohnny Huang }, { 99a8bd6d8cSJohnny Huang 0, 1, 1, "Enable secure boot" 100a8bd6d8cSJohnny Huang }, { 101a8bd6d8cSJohnny Huang 1, 1, 0, "Disable boot from eMMC" 102a8bd6d8cSJohnny Huang }, { 103a8bd6d8cSJohnny Huang 1, 1, 1, "Enable boot from eMMC" 104a8bd6d8cSJohnny Huang }, { 105a8bd6d8cSJohnny Huang 2, 1, 0, "Disable Boot from debug SPI" 106a8bd6d8cSJohnny Huang }, { 107a8bd6d8cSJohnny Huang 2, 1, 1, "Enable Boot from debug SPI" 108a8bd6d8cSJohnny Huang }, { 109a8bd6d8cSJohnny Huang 3, 1, 0, "Enable ARM CM3" 110a8bd6d8cSJohnny Huang }, { 111a8bd6d8cSJohnny Huang 3, 1, 1, "Disable ARM CM3" 112a8bd6d8cSJohnny Huang }, { 113a8bd6d8cSJohnny Huang 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" 114a8bd6d8cSJohnny Huang }, { 115a8bd6d8cSJohnny Huang 4, 1, 1, "Enable dedicated VGA BIOS ROM" 116a8bd6d8cSJohnny Huang }, { 117a8bd6d8cSJohnny Huang 5, 1, 0, "MAC 1 : RMII/NCSI" 118a8bd6d8cSJohnny Huang }, { 119a8bd6d8cSJohnny Huang 5, 1, 1, "MAC 1 : RGMII" 120a8bd6d8cSJohnny Huang }, { 121a8bd6d8cSJohnny Huang 6, 1, 0, "MAC 2 : RMII/NCSI" 122a8bd6d8cSJohnny Huang }, { 123a8bd6d8cSJohnny Huang 6, 1, 1, "MAC 2 : RGMII" 124a8bd6d8cSJohnny Huang }, { 125a8bd6d8cSJohnny Huang 7, 3, 0, "CPU Frequency : 1GHz" 126a8bd6d8cSJohnny Huang }, { 127a8bd6d8cSJohnny Huang 7, 3, 1, "CPU Frequency : 800MHz" 128a8bd6d8cSJohnny Huang }, { 129a8bd6d8cSJohnny Huang 7, 3, 2, "CPU Frequency : 1.2GHz" 130a8bd6d8cSJohnny Huang }, { 131a8bd6d8cSJohnny Huang 7, 3, 3, "CPU Frequency : 1.4GHz" 132a8bd6d8cSJohnny Huang }, { 133a8bd6d8cSJohnny Huang 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" 134a8bd6d8cSJohnny Huang }, { 135a8bd6d8cSJohnny Huang 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" 136a8bd6d8cSJohnny Huang }, { 137a8bd6d8cSJohnny Huang 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" 138a8bd6d8cSJohnny Huang }, { 139a8bd6d8cSJohnny Huang 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" 140a8bd6d8cSJohnny Huang }, { 141a8bd6d8cSJohnny Huang 12, 2, 0, "VGA memory size : 8MB" 142a8bd6d8cSJohnny Huang }, { 143a8bd6d8cSJohnny Huang 12, 2, 1, "VGA memory size : 16MB" 144a8bd6d8cSJohnny Huang }, { 145a8bd6d8cSJohnny Huang 12, 2, 2, "VGA memory size : 32MB" 146a8bd6d8cSJohnny Huang }, { 147a8bd6d8cSJohnny Huang 12, 2, 3, "VGA memory size : 64MB" 148a8bd6d8cSJohnny Huang }, { 149a8bd6d8cSJohnny Huang 14, 3, OTP_REG_RESERVED, "" 150a8bd6d8cSJohnny Huang }, { 151a8bd6d8cSJohnny Huang 17, 1, 0, "VGA class code : Class Code for video device" 152a8bd6d8cSJohnny Huang }, { 153a8bd6d8cSJohnny Huang 17, 1, 1, "VGA class code : Class Code for VGA device" 154a8bd6d8cSJohnny Huang }, { 155a8bd6d8cSJohnny Huang 18, 1, 0, "Enable debug interfaces 0" 156a8bd6d8cSJohnny Huang }, { 157a8bd6d8cSJohnny Huang 18, 1, 1, "Disable debug interfaces 0" 158a8bd6d8cSJohnny Huang }, { 159a8bd6d8cSJohnny Huang 19, 1, 0, "Boot from emmc mode : High eMMC speed" 160a8bd6d8cSJohnny Huang }, { 161a8bd6d8cSJohnny Huang 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" 162a8bd6d8cSJohnny Huang }, { 163a8bd6d8cSJohnny Huang 20, 1, 0, "Enable Pcie EHCI device" 164a8bd6d8cSJohnny Huang }, { 165a8bd6d8cSJohnny Huang 20, 1, 1, "Disable Pcie EHCI device" 166a8bd6d8cSJohnny Huang }, { 167a8bd6d8cSJohnny Huang 21, 1, 0, "Enable VGA XDMA function" 168a8bd6d8cSJohnny Huang }, { 169a8bd6d8cSJohnny Huang 21, 1, 1, "Disable VGA XDMA function" 170a8bd6d8cSJohnny Huang }, { 171a8bd6d8cSJohnny Huang 22, 1, 0, "Normal BMC mode" 172a8bd6d8cSJohnny Huang }, { 173a8bd6d8cSJohnny Huang 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" 174a8bd6d8cSJohnny Huang }, { 175a8bd6d8cSJohnny Huang 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" 176a8bd6d8cSJohnny Huang }, { 177a8bd6d8cSJohnny Huang 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" 178a8bd6d8cSJohnny Huang }, { 179a8bd6d8cSJohnny Huang 24, 1, 0, "DRAM types : DDR3" 180a8bd6d8cSJohnny Huang }, { 181a8bd6d8cSJohnny Huang 24, 1, 1, "DRAM types : DDR4" 182a8bd6d8cSJohnny Huang }, { 183a8bd6d8cSJohnny Huang 25, 5, OTP_REG_RESERVED, "" 184a8bd6d8cSJohnny Huang }, { 185a8bd6d8cSJohnny Huang 30, 2, OTP_REG_RESERVED, "" 186a8bd6d8cSJohnny Huang }, { 187a8bd6d8cSJohnny Huang 32, 1, 0, "MAC 3 : RMII/NCSI" 188a8bd6d8cSJohnny Huang }, { 189a8bd6d8cSJohnny Huang 32, 1, 1, "MAC 3 : RGMII" 190a8bd6d8cSJohnny Huang }, { 191a8bd6d8cSJohnny Huang 33, 1, 0, "MAC 4 : RMII/NCSI" 192a8bd6d8cSJohnny Huang }, { 193a8bd6d8cSJohnny Huang 33, 1, 1, "MAC 4 : RGMII" 194a8bd6d8cSJohnny Huang }, { 195a8bd6d8cSJohnny Huang 34, 1, 0, "SuperIO configuration address : 0x2E" 196a8bd6d8cSJohnny Huang }, { 197a8bd6d8cSJohnny Huang 34, 1, 1, "SuperIO configuration address : 0x4E" 198a8bd6d8cSJohnny Huang }, { 199a8bd6d8cSJohnny Huang 35, 1, 0, "Enable LPC to decode SuperIO" 200a8bd6d8cSJohnny Huang }, { 201a8bd6d8cSJohnny Huang 35, 1, 1, "Disable LPC to decode SuperIO" 202a8bd6d8cSJohnny Huang }, { 203a8bd6d8cSJohnny Huang 36, 1, 0, "Enable debug interfaces 1" 204a8bd6d8cSJohnny Huang }, { 205a8bd6d8cSJohnny Huang 36, 1, 1, "Disable debug interfaces 1" 206a8bd6d8cSJohnny Huang }, { 207a8bd6d8cSJohnny Huang 37, 1, 0, "Disable ACPI function" 208a8bd6d8cSJohnny Huang }, { 209a8bd6d8cSJohnny Huang 37, 1, 1, "Enable ACPI function" 210a8bd6d8cSJohnny Huang }, { 211a8bd6d8cSJohnny Huang 38, 1, 0, "Enable eSPI mode" 212a8bd6d8cSJohnny Huang }, { 213a8bd6d8cSJohnny Huang 38, 1, 1, "Enable LPC mode" 214a8bd6d8cSJohnny Huang }, { 215a8bd6d8cSJohnny Huang 39, 1, 0, "Enable SAFS mode" 216a8bd6d8cSJohnny Huang }, { 217a8bd6d8cSJohnny Huang 39, 1, 1, "Enable SAFS mode" 218a8bd6d8cSJohnny Huang }, { 219a8bd6d8cSJohnny Huang 40, 2, OTP_REG_RESERVED, "" 220a8bd6d8cSJohnny Huang }, { 221a8bd6d8cSJohnny Huang 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" 222a8bd6d8cSJohnny Huang }, { 223a8bd6d8cSJohnny Huang 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" 224a8bd6d8cSJohnny Huang }, { 225a8bd6d8cSJohnny Huang 43, 1, 0, "Disable boot SPI ABR" 226a8bd6d8cSJohnny Huang }, { 227a8bd6d8cSJohnny Huang 43, 1, 1, "Enable boot SPI ABR" 228a8bd6d8cSJohnny Huang }, { 229a8bd6d8cSJohnny Huang 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" 230a8bd6d8cSJohnny Huang }, { 231a8bd6d8cSJohnny Huang 44, 1, 1, "Boot SPI ABR mode : single SPI flash" 232a8bd6d8cSJohnny Huang }, { 233a8bd6d8cSJohnny Huang 45, 3, 0, "Boot SPI flash size : no define size" 234a8bd6d8cSJohnny Huang }, { 235a8bd6d8cSJohnny Huang 45, 3, 1, "Boot SPI flash size : 2MB" 236a8bd6d8cSJohnny Huang }, { 237a8bd6d8cSJohnny Huang 45, 3, 2, "Boot SPI flash size : 4MB" 238a8bd6d8cSJohnny Huang }, { 239a8bd6d8cSJohnny Huang 45, 3, 3, "Boot SPI flash size : 8MB" 240a8bd6d8cSJohnny Huang }, { 241a8bd6d8cSJohnny Huang 45, 3, 4, "Boot SPI flash size : 16MB" 242a8bd6d8cSJohnny Huang }, { 243a8bd6d8cSJohnny Huang 45, 3, 5, "Boot SPI flash size : 32MB" 244a8bd6d8cSJohnny Huang }, { 245a8bd6d8cSJohnny Huang 45, 3, 6, "Boot SPI flash size : 64MB" 246a8bd6d8cSJohnny Huang }, { 247a8bd6d8cSJohnny Huang 45, 3, 7, "Boot SPI flash size : 128MB" 248a8bd6d8cSJohnny Huang }, { 249a8bd6d8cSJohnny Huang 48, 1, 0, "Disable host SPI ABR" 250a8bd6d8cSJohnny Huang }, { 251a8bd6d8cSJohnny Huang 48, 1, 1, "Enable host SPI ABR" 252a8bd6d8cSJohnny Huang }, { 253a8bd6d8cSJohnny Huang 49, 1, 0, "Disable host SPI ABR mode select pin" 254a8bd6d8cSJohnny Huang }, { 255a8bd6d8cSJohnny Huang 49, 1, 1, "Enable host SPI ABR mode select pin" 256a8bd6d8cSJohnny Huang }, { 257a8bd6d8cSJohnny Huang 50, 1, 0, "Host SPI ABR mode : dual SPI flash" 258a8bd6d8cSJohnny Huang }, { 259a8bd6d8cSJohnny Huang 50, 1, 1, "Host SPI ABR mode : single SPI flash" 260a8bd6d8cSJohnny Huang }, { 261a8bd6d8cSJohnny Huang 51, 3, 0, "Host SPI flash size : no define size" 262a8bd6d8cSJohnny Huang }, { 263a8bd6d8cSJohnny Huang 51, 3, 1, "Host SPI flash size : 2MB" 264a8bd6d8cSJohnny Huang }, { 265a8bd6d8cSJohnny Huang 51, 3, 2, "Host SPI flash size : 4MB" 266a8bd6d8cSJohnny Huang }, { 267a8bd6d8cSJohnny Huang 51, 3, 3, "Host SPI flash size : 8MB" 268a8bd6d8cSJohnny Huang }, { 269a8bd6d8cSJohnny Huang 51, 3, 4, "Host SPI flash size : 16MB" 270a8bd6d8cSJohnny Huang }, { 271a8bd6d8cSJohnny Huang 51, 3, 5, "Host SPI flash size : 32MB" 272a8bd6d8cSJohnny Huang }, { 273a8bd6d8cSJohnny Huang 51, 3, 6, "Host SPI flash size : 64MB" 274a8bd6d8cSJohnny Huang }, { 275a8bd6d8cSJohnny Huang 51, 3, 7, "Host SPI flash size : 128MB" 276a8bd6d8cSJohnny Huang }, { 277a8bd6d8cSJohnny Huang 54, 1, 0, "Disable boot SPI auxiliary control pins" 278a8bd6d8cSJohnny Huang }, { 279a8bd6d8cSJohnny Huang 54, 1, 1, "Enable boot SPI auxiliary control pins" 280a8bd6d8cSJohnny Huang }, { 281a8bd6d8cSJohnny Huang 55, 2, 0, "Boot SPI CRTM size : disable CRTM" 282a8bd6d8cSJohnny Huang }, { 283a8bd6d8cSJohnny Huang 55, 2, 1, "Boot SPI CRTM size : 256KB" 284a8bd6d8cSJohnny Huang }, { 285a8bd6d8cSJohnny Huang 55, 2, 2, "Boot SPI CRTM size : 512KB" 286a8bd6d8cSJohnny Huang }, { 287a8bd6d8cSJohnny Huang 55, 2, 3, "Boot SPI CRTM size : 1MB" 288a8bd6d8cSJohnny Huang }, { 289a8bd6d8cSJohnny Huang 57, 2, 0, "Host SPI CRTM size : disable CRTM" 290a8bd6d8cSJohnny Huang }, { 291a8bd6d8cSJohnny Huang 57, 2, 1, "Host SPI CRTM size : 256KB" 292a8bd6d8cSJohnny Huang }, { 293a8bd6d8cSJohnny Huang 57, 2, 2, "Host SPI CRTM size : 512KB" 294a8bd6d8cSJohnny Huang }, { 295a8bd6d8cSJohnny Huang 57, 2, 3, "Host SPI CRTM size : 1MB" 296a8bd6d8cSJohnny Huang }, { 297a8bd6d8cSJohnny Huang 59, 1, 0, "Disable host SPI auxiliary control pins" 298a8bd6d8cSJohnny Huang }, { 299a8bd6d8cSJohnny Huang 59, 1, 1, "Enable host SPI auxiliary control pins" 300a8bd6d8cSJohnny Huang }, { 301a8bd6d8cSJohnny Huang 60, 1, 0, "Disable GPIO pass through" 302a8bd6d8cSJohnny Huang }, { 303a8bd6d8cSJohnny Huang 60, 1, 1, "Enable GPIO pass through" 304a8bd6d8cSJohnny Huang }, { 305a8bd6d8cSJohnny Huang 61, 1, 0, "Enable low security secure boot key" 306a8bd6d8cSJohnny Huang }, { 307a8bd6d8cSJohnny Huang 61, 1, 1, "Disable low security secure boot key" 308a8bd6d8cSJohnny Huang }, { 309a8bd6d8cSJohnny Huang 62, 1, 0, "Disable dedicate GPIO strap pins" 310a8bd6d8cSJohnny Huang }, { 311a8bd6d8cSJohnny Huang 62, 1, 1, "Enable dedicate GPIO strap pins" 312*b458cd62SJohnny Huang }, { 313*b458cd62SJohnny Huang 63, 1, OTP_REG_RESERVED, "" 314a8bd6d8cSJohnny Huang } 31576d13988SJohnny Huang }; 316*b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 317*b458cd62SJohnny Huang { 318*b458cd62SJohnny Huang 0, 0, 1, 0, "Enable Secure Region programming" 319*b458cd62SJohnny Huang }, { 320*b458cd62SJohnny Huang 0, 0, 1, 1, "Disable Secure Region programming" 321*b458cd62SJohnny Huang }, { 322*b458cd62SJohnny Huang 0, 1, 1, 0, "Disable Secure Boot" 323*b458cd62SJohnny Huang }, { 324*b458cd62SJohnny Huang 0, 1, 1, 1, "Enable Secure Boot" 325*b458cd62SJohnny Huang }, { 326*b458cd62SJohnny Huang 0, 2, 1, 0, "Initialization programming not done" 327*b458cd62SJohnny Huang }, { 328*b458cd62SJohnny Huang 0, 2, 1, 1, "Initialization programming done" 329*b458cd62SJohnny Huang }, { 330*b458cd62SJohnny Huang 0, 3, 1, 0, "User region ECC disable" 331*b458cd62SJohnny Huang }, { 332*b458cd62SJohnny Huang 0, 3, 1, 1, "User region ECC enable" 333*b458cd62SJohnny Huang }, { 334*b458cd62SJohnny Huang 0, 4, 1, 0, "Secure Region ECC disable" 335*b458cd62SJohnny Huang }, { 336*b458cd62SJohnny Huang 0, 4, 1, 1, "Secure Region ECC enable" 337*b458cd62SJohnny Huang }, { 338*b458cd62SJohnny Huang 0, 5, 1, 0, "Enable low security key" 339*b458cd62SJohnny Huang }, { 340*b458cd62SJohnny Huang 0, 5, 1, 1, "Disable low security key" 341*b458cd62SJohnny Huang }, { 342*b458cd62SJohnny Huang 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" 343*b458cd62SJohnny Huang }, { 344*b458cd62SJohnny Huang 0, 6, 1, 1, "Ignore Secure Boot hardware strap" 345*b458cd62SJohnny Huang }, { 346*b458cd62SJohnny Huang 0, 7, 1, 0, "Secure Boot Mode: 2" 347*b458cd62SJohnny Huang }, { 348*b458cd62SJohnny Huang 0, 7, 1, 1, "Secure Boot Mode: 1" 349*b458cd62SJohnny Huang }, { 350*b458cd62SJohnny Huang 0, 8, 2, 0, "Single cell mode (recommended)" 351*b458cd62SJohnny Huang }, { 352*b458cd62SJohnny Huang 0, 8, 2, 1, "Differnetial mode" 353*b458cd62SJohnny Huang }, { 354*b458cd62SJohnny Huang 0, 8, 2, 2, "Differential-redundant mode" 355*b458cd62SJohnny Huang }, { 356*b458cd62SJohnny Huang 0, 10, 2, 0, "RSA mode : RSA1024" 357*b458cd62SJohnny Huang }, { 358*b458cd62SJohnny Huang 0, 10, 2, 1, "RSA mode : RSA2048" 359*b458cd62SJohnny Huang }, { 360*b458cd62SJohnny Huang 0, 10, 2, 2, "RSA mode : RSA3072" 361*b458cd62SJohnny Huang }, { 362*b458cd62SJohnny Huang 0, 10, 2, 3, "RSA mode : RSA4096" 363*b458cd62SJohnny Huang }, { 364*b458cd62SJohnny Huang 0, 12, 2, 0, "SHA mode : SHA224" 365*b458cd62SJohnny Huang }, { 366*b458cd62SJohnny Huang 0, 12, 2, 1, "SHA mode : SHA256" 367*b458cd62SJohnny Huang }, { 368*b458cd62SJohnny Huang 0, 12, 2, 2, "SHA mode : SHA384" 369*b458cd62SJohnny Huang }, { 370*b458cd62SJohnny Huang 0, 12, 2, 3, "SHA mode : SHA512" 371*b458cd62SJohnny Huang }, { 372*b458cd62SJohnny Huang 0, 14, 2, OTP_REG_RESERVED, "" 373*b458cd62SJohnny Huang }, { 374*b458cd62SJohnny Huang 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" 375*b458cd62SJohnny Huang }, { 376*b458cd62SJohnny Huang 0, 22, 1, 0, "Secure Region : Writable" 377*b458cd62SJohnny Huang }, { 378*b458cd62SJohnny Huang 0, 22, 1, 1, "Secure Region : Write Protect" 379*b458cd62SJohnny Huang }, { 380*b458cd62SJohnny Huang 0, 23, 1, 0, "User Region : Writable" 381*b458cd62SJohnny Huang }, { 382*b458cd62SJohnny Huang 0, 23, 1, 1, "User Region : Write Protect" 383*b458cd62SJohnny Huang }, { 384*b458cd62SJohnny Huang 0, 24, 1, 0, "Configure Region : Writable" 385*b458cd62SJohnny Huang }, { 386*b458cd62SJohnny Huang 0, 24, 1, 1, "Configure Region : Write Protect" 387*b458cd62SJohnny Huang }, { 388*b458cd62SJohnny Huang 0, 25, 1, 0, "OTP strap Region : Writable" 389*b458cd62SJohnny Huang }, { 390*b458cd62SJohnny Huang 0, 25, 1, 1, "OTP strap Region : Write Protect" 391*b458cd62SJohnny Huang }, { 392*b458cd62SJohnny Huang 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" 393*b458cd62SJohnny Huang }, { 394*b458cd62SJohnny Huang 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" 395*b458cd62SJohnny Huang }, { 396*b458cd62SJohnny Huang 0, 27, 1, 0, "Disable image encryption" 397*b458cd62SJohnny Huang }, { 398*b458cd62SJohnny Huang 0, 27, 1, 1, "Enable image encryption" 399*b458cd62SJohnny Huang }, { 400*b458cd62SJohnny Huang 0, 28, 1, OTP_REG_RESERVED, "" 401*b458cd62SJohnny Huang }, { 402*b458cd62SJohnny Huang 0, 29, 1, 0, "OTP key retire Region : Writable" 403*b458cd62SJohnny Huang }, { 404*b458cd62SJohnny Huang 0, 29, 1, 1, "OTP key retire Region : Write Protect" 405*b458cd62SJohnny Huang }, { 406*b458cd62SJohnny Huang 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" 407*b458cd62SJohnny Huang }, { 408*b458cd62SJohnny Huang 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" 409*b458cd62SJohnny Huang }, { 410*b458cd62SJohnny Huang 0, 31, 1, 0, "SIPROM Mlock memory lock disable" 411*b458cd62SJohnny Huang }, { 412*b458cd62SJohnny Huang 0, 31, 1, 1, "SIPROM Mlock memory lock enable" 413*b458cd62SJohnny Huang }, { 414*b458cd62SJohnny Huang 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" 415*b458cd62SJohnny Huang }, { 416*b458cd62SJohnny Huang 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" 417*b458cd62SJohnny Huang }, { 418*b458cd62SJohnny Huang 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" 419*b458cd62SJohnny Huang }, { 420*b458cd62SJohnny Huang 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %d" 421*b458cd62SJohnny Huang }, { 422*b458cd62SJohnny Huang 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %d" 423*b458cd62SJohnny Huang }, { 424*b458cd62SJohnny Huang 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" 425*b458cd62SJohnny Huang }, { 426*b458cd62SJohnny Huang 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" 427*b458cd62SJohnny Huang }, { 428*b458cd62SJohnny Huang 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" 429*b458cd62SJohnny Huang }, { 430*b458cd62SJohnny Huang 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" 431*b458cd62SJohnny Huang }, { 432*b458cd62SJohnny Huang 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" 433*b458cd62SJohnny Huang } 434*b458cd62SJohnny Huang }; 4352a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 43669d5fd8fSJohnny Huang { 43769d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 43869d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 43969d5fd8fSJohnny Huang udelay(2); 44069d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 44169d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 44269d5fd8fSJohnny Huang } 44369d5fd8fSJohnny Huang 4442a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 44569d5fd8fSJohnny Huang { 44669d5fd8fSJohnny Huang int config_offset; 44769d5fd8fSJohnny Huang 44869d5fd8fSJohnny Huang config_offset = 0x800; 44969d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 45069d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 45169d5fd8fSJohnny Huang 45269d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 45369d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 45469d5fd8fSJohnny Huang udelay(2); 45569d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 45669d5fd8fSJohnny Huang } 45769d5fd8fSJohnny Huang 45869d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 45969d5fd8fSJohnny Huang { 46069d5fd8fSJohnny Huang int i; 46169d5fd8fSJohnny Huang uint32_t ret[1]; 46269d5fd8fSJohnny Huang 46369d5fd8fSJohnny Huang if (offset + dw_count > 32) 4642a856b9aSJohnny Huang return OTP_USAGE; 46569d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 46669d5fd8fSJohnny Huang otp_read_config(i, ret); 467a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 46869d5fd8fSJohnny Huang } 46969d5fd8fSJohnny Huang printf("\n"); 4702a856b9aSJohnny Huang return OTP_SUCCESS; 47169d5fd8fSJohnny Huang } 47269d5fd8fSJohnny Huang 47369d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 47469d5fd8fSJohnny Huang { 47569d5fd8fSJohnny Huang int i; 47669d5fd8fSJohnny Huang uint32_t ret[2]; 47769d5fd8fSJohnny Huang 47869d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 4792a856b9aSJohnny Huang return OTP_USAGE; 48069d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 48169d5fd8fSJohnny Huang otp_read_data(i, ret); 48269d5fd8fSJohnny Huang if (i % 4 == 0) 48369d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 48469d5fd8fSJohnny Huang else 48569d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 48669d5fd8fSJohnny Huang 48769d5fd8fSJohnny Huang } 48869d5fd8fSJohnny Huang printf("\n"); 4892a856b9aSJohnny Huang return OTP_SUCCESS; 49069d5fd8fSJohnny Huang } 49169d5fd8fSJohnny Huang 49269d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 49369d5fd8fSJohnny Huang { 49469d5fd8fSJohnny Huang uint32_t ret; 49569d5fd8fSJohnny Huang uint32_t *buf; 49669d5fd8fSJohnny Huang 49769d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 49869d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 49969d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 50069d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 50169d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 50269d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 50369d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 50469d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 50569d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 50669d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 50769d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 50869d5fd8fSJohnny Huang udelay(10); 50969d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 51069d5fd8fSJohnny Huang if (ret & 0x1) 51169d5fd8fSJohnny Huang return 0; 51269d5fd8fSJohnny Huang else 51369d5fd8fSJohnny Huang return -1; 51469d5fd8fSJohnny Huang } 51569d5fd8fSJohnny Huang 51669d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 51769d5fd8fSJohnny Huang { 51869d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 51969d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 52069d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 52169d5fd8fSJohnny Huang udelay(100); 52269d5fd8fSJohnny Huang } 52369d5fd8fSJohnny Huang 52469d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 52569d5fd8fSJohnny Huang { 52669d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 52769d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 52869d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 52969d5fd8fSJohnny Huang udelay(85); 53069d5fd8fSJohnny Huang } 53169d5fd8fSJohnny Huang 532a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 53369d5fd8fSJohnny Huang { 53469d5fd8fSJohnny Huang int ret; 53569d5fd8fSJohnny Huang 53669d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 53769d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 53869d5fd8fSJohnny Huang udelay(2); 53969d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 540a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 54169d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 54269d5fd8fSJohnny Huang return 0; 54369d5fd8fSJohnny Huang else 54469d5fd8fSJohnny Huang return -1; 54569d5fd8fSJohnny Huang } 54669d5fd8fSJohnny Huang 547d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 5484c1c9b35SJohnny Huang { 5494c1c9b35SJohnny Huang uint32_t ret[2]; 5504c1c9b35SJohnny Huang 5514c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 5524c1c9b35SJohnny Huang 5534c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 5544c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 5554c1c9b35SJohnny Huang else 5564c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 5574c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 5584c1c9b35SJohnny Huang udelay(2); 5594c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 5604c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 5614c1c9b35SJohnny Huang if (size == 1) { 5624c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 5634c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 564d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 5654c1c9b35SJohnny Huang compare[0] = 0; 5664c1c9b35SJohnny Huang return 0; 5674c1c9b35SJohnny Huang } else { 5684c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 5694c1c9b35SJohnny Huang return -1; 5704c1c9b35SJohnny Huang } 5714c1c9b35SJohnny Huang 5724c1c9b35SJohnny Huang } else { 5734c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 574d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 5754c1c9b35SJohnny Huang compare[0] = ~0; 5764c1c9b35SJohnny Huang return 0; 5774c1c9b35SJohnny Huang } else { 578d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 5794c1c9b35SJohnny Huang return -1; 5804c1c9b35SJohnny Huang } 5814c1c9b35SJohnny Huang } 5824c1c9b35SJohnny Huang } else if (size == 2) { 5834c1c9b35SJohnny Huang // otp_addr should be even 584d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 5854c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 5864c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 5874c1c9b35SJohnny Huang compare[0] = 0; 5884c1c9b35SJohnny Huang compare[1] = ~0; 5894c1c9b35SJohnny Huang return 0; 5904c1c9b35SJohnny Huang } else { 5914c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 5924c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 5934c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 5944c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 5954c1c9b35SJohnny Huang return -1; 5964c1c9b35SJohnny Huang } 5974c1c9b35SJohnny Huang } else { 5984c1c9b35SJohnny Huang return -1; 5994c1c9b35SJohnny Huang } 6004c1c9b35SJohnny Huang } 6014c1c9b35SJohnny Huang 6027e22f42dSJohnny Huang static void otp_soak(int soak) 603d90825e2SJohnny Huang { 604d90825e2SJohnny Huang if (soak) { 605d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 606d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 607d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 608d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 609d90825e2SJohnny Huang } else { 610d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 611d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 612d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 613d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 614d90825e2SJohnny Huang } 615d90825e2SJohnny Huang } 616d90825e2SJohnny Huang 617d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 618d90825e2SJohnny Huang { 619d90825e2SJohnny Huang int j, bit_value, prog_bit; 620d90825e2SJohnny Huang 621d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 622d90825e2SJohnny Huang if ((keep >> j) & 0x1) 623d90825e2SJohnny Huang continue; 624d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 625d90825e2SJohnny Huang if (prog_address % 2 == 0) { 626d90825e2SJohnny Huang if (bit_value) 627d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 628d90825e2SJohnny Huang else 629d90825e2SJohnny Huang continue; 630d90825e2SJohnny Huang } else { 631d90825e2SJohnny Huang prog_address |= 1 << 15; 632d90825e2SJohnny Huang if (bit_value) 633d90825e2SJohnny Huang continue; 634d90825e2SJohnny Huang else 635d90825e2SJohnny Huang prog_bit = 0x1 << j; 636d90825e2SJohnny Huang } 637d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 638d90825e2SJohnny Huang } 639d90825e2SJohnny Huang } 640d90825e2SJohnny Huang 64176d13988SJohnny Huang 64276d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 64376d13988SJohnny Huang { 64476d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 64576d13988SJohnny Huang int i, j; 64676d13988SJohnny Huang 64776d13988SJohnny Huang for (j = 0; j < 64; j++) { 64876d13988SJohnny Huang otpstrap[j].value = 0; 64976d13988SJohnny Huang otpstrap[j].remain_times = 7; 65076d13988SJohnny Huang otpstrap[j].writeable_option = -1; 65176d13988SJohnny Huang otpstrap[j].protected = 0; 65276d13988SJohnny Huang } 65376d13988SJohnny Huang 65476d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 65576d13988SJohnny Huang int option = (i - 16) / 2; 65676d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 65776d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 65876d13988SJohnny Huang for (j = 0; j < 32; j++) { 65976d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 66076d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 66176d13988SJohnny Huang otpstrap[j].writeable_option = option; 66276d13988SJohnny Huang } 66376d13988SJohnny Huang if (bit_value == 1) 66476d13988SJohnny Huang otpstrap[j].remain_times --; 66576d13988SJohnny Huang otpstrap[j].value ^= bit_value; 66676d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 66776d13988SJohnny Huang } 66876d13988SJohnny Huang for (j = 32; j < 64; j++) { 66976d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 67076d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 67176d13988SJohnny Huang otpstrap[j].writeable_option = option; 67276d13988SJohnny Huang } 67376d13988SJohnny Huang if (bit_value == 1) 67476d13988SJohnny Huang otpstrap[j].remain_times --; 67576d13988SJohnny Huang otpstrap[j].value ^= bit_value; 67676d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 67776d13988SJohnny Huang } 67876d13988SJohnny Huang } 67976d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 68076d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 68176d13988SJohnny Huang for (j = 0; j < 32; j++) { 68276d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 68376d13988SJohnny Huang otpstrap[j].protected = 1; 68476d13988SJohnny Huang } 68576d13988SJohnny Huang for (j = 32; j < 64; j++) { 68676d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 68776d13988SJohnny Huang otpstrap[j].protected = 1; 68876d13988SJohnny Huang } 68976d13988SJohnny Huang } 69076d13988SJohnny Huang 691*b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 69269d5fd8fSJohnny Huang { 693442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 694*b458cd62SJohnny Huang uint32_t mask; 695*b458cd62SJohnny Huang uint32_t dw_offset; 696*b458cd62SJohnny Huang uint32_t bit_offset; 697*b458cd62SJohnny Huang uint32_t otp_value; 698*b458cd62SJohnny Huang uint32_t otp_keep; 699*b458cd62SJohnny Huang int fail = 0; 700*b458cd62SJohnny Huang int valid_bit = 0; 70166f2f8e5SJohnny Huang int i; 70266f2f8e5SJohnny Huang 703737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 70466f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 705*b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 706*b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 707*b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 708*b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 709*b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 710*b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 711*b458cd62SJohnny Huang 712*b458cd62SJohnny Huang if (otp_keep == mask) { 713*b458cd62SJohnny Huang continue; 714*b458cd62SJohnny Huang } else if (otp_keep != 0) { 715*b458cd62SJohnny Huang fail = 1; 716*b458cd62SJohnny Huang } 717*b458cd62SJohnny Huang 718*b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 719*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 720*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 721*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 722*b458cd62SJohnny Huang continue; 723*b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 724*b458cd62SJohnny Huang 725*b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 726*b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 72766f2f8e5SJohnny Huang } else { 728*b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 729*b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 730*b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 73166f2f8e5SJohnny Huang } 732*b458cd62SJohnny Huang printf("0x%-10x", otp_value); 733*b458cd62SJohnny Huang 734*b458cd62SJohnny Huang if (fail) { 735*b458cd62SJohnny Huang printf("Keep mask error\n"); 736*b458cd62SJohnny Huang } else { 737*b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 738*b458cd62SJohnny Huang printf("Reserved\n"); 739*b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 740*b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 741*b458cd62SJohnny Huang printf("\n"); 742*b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 743*b458cd62SJohnny Huang if (otp_value != 0) { 744*b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 745*b458cd62SJohnny Huang if (otp_value == (1 << i)) { 746*b458cd62SJohnny Huang valid_bit = i + 1; 74766f2f8e5SJohnny Huang } 748*b458cd62SJohnny Huang } 749*b458cd62SJohnny Huang } else { 750*b458cd62SJohnny Huang valid_bit = 0; 751*b458cd62SJohnny Huang } 752*b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 753*b458cd62SJohnny Huang printf("\n"); 754*b458cd62SJohnny Huang } else { 755*b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 756*b458cd62SJohnny Huang } 757*b458cd62SJohnny Huang } 758*b458cd62SJohnny Huang } 759*b458cd62SJohnny Huang 760*b458cd62SJohnny Huang if (fail) 761*b458cd62SJohnny Huang return OTP_FAILURE; 762*b458cd62SJohnny Huang 76366f2f8e5SJohnny Huang return OTP_SUCCESS; 76466f2f8e5SJohnny Huang } 76566f2f8e5SJohnny Huang 766*b458cd62SJohnny Huang static int otp_print_conf_info(int view) 76766f2f8e5SJohnny Huang { 768*b458cd62SJohnny Huang uint32_t OTPCFG[12]; 769*b458cd62SJohnny Huang uint32_t mask; 770*b458cd62SJohnny Huang uint32_t dw_offset; 771*b458cd62SJohnny Huang uint32_t bit_offset; 772*b458cd62SJohnny Huang uint32_t otp_value; 773*b458cd62SJohnny Huang int valid_bit = 0; 77466f2f8e5SJohnny Huang int i; 77566f2f8e5SJohnny Huang 77666f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 77766f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 77866f2f8e5SJohnny Huang 77966f2f8e5SJohnny Huang 780*b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 781*b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 782*b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 783*b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 784*b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 785*b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 786*b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 787*b458cd62SJohnny Huang 788*b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 789*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 790*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 791*b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 792*b458cd62SJohnny Huang continue; 793*b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 794*b458cd62SJohnny Huang 795*b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 796*b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 797*b458cd62SJohnny Huang } else { 798*b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 799*b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 800*b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 801*b458cd62SJohnny Huang } 802*b458cd62SJohnny Huang printf("0x%-10x", otp_value); 803*b458cd62SJohnny Huang 804*b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 805*b458cd62SJohnny Huang printf("Reserved\n"); 806*b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 807*b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 808*b458cd62SJohnny Huang printf("\n"); 809*b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 810*b458cd62SJohnny Huang if (otp_value != 0) { 811*b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 812*b458cd62SJohnny Huang if (otp_value == (1 << i)) { 813*b458cd62SJohnny Huang valid_bit = i + 1; 814*b458cd62SJohnny Huang } 815*b458cd62SJohnny Huang } 816*b458cd62SJohnny Huang } else { 817*b458cd62SJohnny Huang valid_bit = 0; 818*b458cd62SJohnny Huang } 819*b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 820*b458cd62SJohnny Huang printf("\n"); 821*b458cd62SJohnny Huang } else { 822*b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 823*b458cd62SJohnny Huang } 824*b458cd62SJohnny Huang } 825*b458cd62SJohnny Huang return OTP_SUCCESS; 82666f2f8e5SJohnny Huang } 82766f2f8e5SJohnny Huang 828*b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 82976d13988SJohnny Huang { 830a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 831a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 83276d13988SJohnny Huang int i; 833a8bd6d8cSJohnny Huang int fail = 0; 834a8bd6d8cSJohnny Huang uint32_t bit_offset; 835a8bd6d8cSJohnny Huang uint32_t dw_offset; 836a8bd6d8cSJohnny Huang uint32_t mask; 837a8bd6d8cSJohnny Huang uint32_t otp_value; 838a8bd6d8cSJohnny Huang uint32_t otp_protect; 839a8bd6d8cSJohnny Huang uint32_t otp_keep; 84076d13988SJohnny Huang 841a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 842a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 843*b458cd62SJohnny Huang 844a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 845a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 846a8bd6d8cSJohnny Huang dw_offset = 1; 847a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 848a8bd6d8cSJohnny Huang } else { 849a8bd6d8cSJohnny Huang dw_offset = 0; 850a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 851a8bd6d8cSJohnny Huang } 85276d13988SJohnny Huang 853a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 854a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 855a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 856a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 857a8bd6d8cSJohnny Huang 858a8bd6d8cSJohnny Huang if (otp_keep == mask) { 859a8bd6d8cSJohnny Huang continue; 860a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 861a8bd6d8cSJohnny Huang fail = 1; 862a8bd6d8cSJohnny Huang } 863a8bd6d8cSJohnny Huang 864a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 865a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 866a8bd6d8cSJohnny Huang continue; 867a8bd6d8cSJohnny Huang 868a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 869*b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 870a8bd6d8cSJohnny Huang } else { 871*b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 872a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 873a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 874a8bd6d8cSJohnny Huang } 875a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 876a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 877a8bd6d8cSJohnny Huang 878a8bd6d8cSJohnny Huang if (fail) { 879a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 880a8bd6d8cSJohnny Huang } else { 881a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 882a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 883a8bd6d8cSJohnny Huang else 884a8bd6d8cSJohnny Huang printf("Reserved\n"); 885a8bd6d8cSJohnny Huang } 886a8bd6d8cSJohnny Huang } 887a8bd6d8cSJohnny Huang 888a8bd6d8cSJohnny Huang if (fail) 88976d13988SJohnny Huang return OTP_FAILURE; 89076d13988SJohnny Huang 89176d13988SJohnny Huang return OTP_SUCCESS; 89276d13988SJohnny Huang } 89376d13988SJohnny Huang 894*b458cd62SJohnny Huang static int otp_print_strap_info(int view) 89576d13988SJohnny Huang { 89676d13988SJohnny Huang struct otpstrap_status strap_status[64]; 897*b458cd62SJohnny Huang int i, j, k; 898*b458cd62SJohnny Huang int fail = 0; 899*b458cd62SJohnny Huang uint32_t bit_offset; 900*b458cd62SJohnny Huang uint32_t length; 901*b458cd62SJohnny Huang uint32_t otp_value; 902*b458cd62SJohnny Huang uint32_t otp_protect; 90376d13988SJohnny Huang 90476d13988SJohnny Huang otp_strp_status(strap_status); 90576d13988SJohnny Huang 906*b458cd62SJohnny Huang if (view) { 907*b458cd62SJohnny Huang printf("BIT(hex) Value Option Protect Description\n"); 908*b458cd62SJohnny Huang printf(" 0 1 2 3 4 5 6\n"); 909*b458cd62SJohnny Huang printf("_________________________________________________________________________________________________________\n"); 910*b458cd62SJohnny Huang } else { 911*b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 912*b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 91376d13988SJohnny Huang } 914*b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 915*b458cd62SJohnny Huang otp_value = 0; 916*b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 917*b458cd62SJohnny Huang length = a0_strap_info[i].length; 918*b458cd62SJohnny Huang for (j = 0; j < length; j++) { 919*b458cd62SJohnny Huang otp_value |= strap_status[bit_offset].value << j; 920*b458cd62SJohnny Huang otp_protect |= strap_status[bit_offset].protected << j; 921*b458cd62SJohnny Huang } 922*b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 923*b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 924*b458cd62SJohnny Huang continue; 925*b458cd62SJohnny Huang if (view) { 926*b458cd62SJohnny Huang for (j = 0; j < length; j++) { 927*b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 928*b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 929*b458cd62SJohnny Huang for (k = 0; k < 7; k++) { 930*b458cd62SJohnny Huang printf("%X ", strap_status[bit_offset + j].option_array[k]); 931*b458cd62SJohnny Huang } 932*b458cd62SJohnny Huang printf(" "); 933*b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 934*b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 935*b458cd62SJohnny Huang printf(" Reserved\n"); 936*b458cd62SJohnny Huang continue; 937*b458cd62SJohnny Huang } 938*b458cd62SJohnny Huang if (length == 1) { 939*b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 940*b458cd62SJohnny Huang continue; 94176d13988SJohnny Huang } 94276d13988SJohnny Huang 943*b458cd62SJohnny Huang if (j == 0) 944*b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 945*b458cd62SJohnny Huang else if (j == length - 1) 946*b458cd62SJohnny Huang printf("\\ \"\n"); 947*b458cd62SJohnny Huang else 948*b458cd62SJohnny Huang printf("| \"\n"); 94976d13988SJohnny Huang } 950*b458cd62SJohnny Huang } else { 951*b458cd62SJohnny Huang if (a0_strap_info[i].length == 1) { 952*b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 953*b458cd62SJohnny Huang } else { 954*b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 955*b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 956*b458cd62SJohnny Huang } 957*b458cd62SJohnny Huang 958*b458cd62SJohnny Huang printf("0x%-10X", otp_value); 959*b458cd62SJohnny Huang 960*b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 961*b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 962*b458cd62SJohnny Huang else 963*b458cd62SJohnny Huang printf("Reserved\n"); 964*b458cd62SJohnny Huang } 965*b458cd62SJohnny Huang } 966*b458cd62SJohnny Huang 967*b458cd62SJohnny Huang if (fail) 968*b458cd62SJohnny Huang return OTP_FAILURE; 969*b458cd62SJohnny Huang 970*b458cd62SJohnny Huang return OTP_SUCCESS; 971*b458cd62SJohnny Huang } 972*b458cd62SJohnny Huang 973*b458cd62SJohnny Huang // static void otp_info_strap(int view) 974*b458cd62SJohnny Huang // { 975*b458cd62SJohnny Huang // struct otpstrap_status strap_status[64]; 976*b458cd62SJohnny Huang // uint32_t OTPSTRAP[6]; 977*b458cd62SJohnny Huang // int i; 978*b458cd62SJohnny Huang 979*b458cd62SJohnny Huang 980*b458cd62SJohnny Huang // otp_strp_status(strap_status); 981*b458cd62SJohnny Huang 982*b458cd62SJohnny Huang // for (i = 0; i < 6; i++) 983*b458cd62SJohnny Huang // OTPSTRAP[i] = 0; 984*b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 985*b458cd62SJohnny Huang // OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i; 986*b458cd62SJohnny Huang // OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i; 987*b458cd62SJohnny Huang // } 988*b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 989*b458cd62SJohnny Huang // OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i; 990*b458cd62SJohnny Huang // OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i; 991*b458cd62SJohnny Huang // } 992*b458cd62SJohnny Huang 993*b458cd62SJohnny Huang // otp_print_strap_info(OTPSTRAP, view); 994*b458cd62SJohnny Huang // } 99576d13988SJohnny Huang 99669d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 99769d5fd8fSJohnny Huang { 99869d5fd8fSJohnny Huang int i; 99969d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 100069d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 100169d5fd8fSJohnny Huang if (i % 16 == 0) { 100269d5fd8fSJohnny Huang printf("%04X: ", i); 100369d5fd8fSJohnny Huang } 100469d5fd8fSJohnny Huang printf("%02X ", buf[i]); 100569d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 100669d5fd8fSJohnny Huang printf("\n"); 100769d5fd8fSJohnny Huang } 100869d5fd8fSJohnny Huang } 100969d5fd8fSJohnny Huang } 101069d5fd8fSJohnny Huang 10117f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 101269d5fd8fSJohnny Huang { 101369d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 101469d5fd8fSJohnny Huang char *byte_buf; 101569d5fd8fSJohnny Huang int i = 0, len = 0; 101669d5fd8fSJohnny Huang byte_buf = (char *)buf; 101769d5fd8fSJohnny Huang while (1) { 101869d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 101969d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 102069d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 102169d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 102269d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 102369d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 10247f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 102569d5fd8fSJohnny Huang printf("Key Type: "); 102669d5fd8fSJohnny Huang switch (key_type) { 102769d5fd8fSJohnny Huang case 0: 102869d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 102969d5fd8fSJohnny Huang break; 103069d5fd8fSJohnny Huang case 1: 103169d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 103269d5fd8fSJohnny Huang break; 103369d5fd8fSJohnny Huang case 4: 103469d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 103569d5fd8fSJohnny Huang break; 103669d5fd8fSJohnny Huang case 8: 103769d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 103869d5fd8fSJohnny Huang break; 103969d5fd8fSJohnny Huang case 9: 104069d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 104169d5fd8fSJohnny Huang break; 104269d5fd8fSJohnny Huang case 10: 104369d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 104469d5fd8fSJohnny Huang break; 104569d5fd8fSJohnny Huang case 13: 104669d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 104769d5fd8fSJohnny Huang break; 104869d5fd8fSJohnny Huang case 14: 104969d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 105069d5fd8fSJohnny Huang break; 105169d5fd8fSJohnny Huang default: 105269d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 105369d5fd8fSJohnny Huang return -1; 105469d5fd8fSJohnny Huang } 105569d5fd8fSJohnny Huang if (key_type == 4) { 105669d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 105769d5fd8fSJohnny Huang switch (key_length) { 105869d5fd8fSJohnny Huang case 0: 105969d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 106069d5fd8fSJohnny Huang break; 106169d5fd8fSJohnny Huang case 1: 106269d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 106369d5fd8fSJohnny Huang break; 106469d5fd8fSJohnny Huang case 2: 106569d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 106669d5fd8fSJohnny Huang break; 106769d5fd8fSJohnny Huang case 3: 106869d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 106969d5fd8fSJohnny Huang break; 107069d5fd8fSJohnny Huang } 1071cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 107269d5fd8fSJohnny Huang printf("RSA SHA Type: "); 107369d5fd8fSJohnny Huang switch (key_length) { 107469d5fd8fSJohnny Huang case 0: 107569d5fd8fSJohnny Huang printf("RSA1024\n"); 107669d5fd8fSJohnny Huang len = 0x100; 107769d5fd8fSJohnny Huang break; 107869d5fd8fSJohnny Huang case 1: 107969d5fd8fSJohnny Huang printf("RSA2048\n"); 108069d5fd8fSJohnny Huang len = 0x200; 108169d5fd8fSJohnny Huang break; 108269d5fd8fSJohnny Huang case 2: 108369d5fd8fSJohnny Huang printf("RSA3072\n"); 108469d5fd8fSJohnny Huang len = 0x300; 108569d5fd8fSJohnny Huang break; 108669d5fd8fSJohnny Huang case 3: 108769d5fd8fSJohnny Huang printf("RSA4096\n"); 108869d5fd8fSJohnny Huang len = 0x400; 108969d5fd8fSJohnny Huang break; 109069d5fd8fSJohnny Huang } 109169d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 109269d5fd8fSJohnny Huang } 109369d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 109469d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 109569d5fd8fSJohnny Huang printf("Key Value:\n"); 109669d5fd8fSJohnny Huang if (key_type == 4) { 109769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 109869d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 109969d5fd8fSJohnny Huang printf("AES Key:\n"); 110069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 110169d5fd8fSJohnny Huang printf("AES IV:\n"); 110269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 110369d5fd8fSJohnny Huang 110469d5fd8fSJohnny Huang } else { 110569d5fd8fSJohnny Huang printf("RSA mod:\n"); 110669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 110769d5fd8fSJohnny Huang printf("RSA exp:\n"); 110869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 110969d5fd8fSJohnny Huang } 111069d5fd8fSJohnny Huang if (last) 111169d5fd8fSJohnny Huang break; 111269d5fd8fSJohnny Huang i++; 111369d5fd8fSJohnny Huang } 111469d5fd8fSJohnny Huang return 0; 111569d5fd8fSJohnny Huang } 111669d5fd8fSJohnny Huang 1117a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 111869d5fd8fSJohnny Huang { 1119a6d0d645SJohnny Huang int i, k; 1120d90825e2SJohnny Huang int pass = 0; 1121d90825e2SJohnny Huang int soak = 0; 1122a6d0d645SJohnny Huang uint32_t prog_address; 1123a6d0d645SJohnny Huang uint32_t data[12]; 1124a6d0d645SJohnny Huang uint32_t compare[2]; 1125d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1126d90825e2SJohnny Huang uint32_t data_masked; 1127d90825e2SJohnny Huang uint32_t buf_masked; 112869d5fd8fSJohnny Huang 1129a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1130a6d0d645SJohnny Huang 1131a6d0d645SJohnny Huang printProgress(0, 12, ""); 1132a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1133a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 113469d5fd8fSJohnny Huang prog_address = 0x800; 1135a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1136a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1137a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1138a6d0d645SJohnny Huang } 1139a6d0d645SJohnny Huang 1140a6d0d645SJohnny Huang printf("Check writable...\n"); 1141a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1142d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1143d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1144d90825e2SJohnny Huang if (data_masked == buf_masked) 114569d5fd8fSJohnny Huang continue; 1146d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1147a6d0d645SJohnny Huang continue; 1148a6d0d645SJohnny Huang } else { 1149a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1150a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1151a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1152a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 11532a856b9aSJohnny Huang return OTP_FAILURE; 1154a6d0d645SJohnny Huang } 1155a6d0d645SJohnny Huang } 1156a6d0d645SJohnny Huang 1157a6d0d645SJohnny Huang printf("Start Programing...\n"); 1158a6d0d645SJohnny Huang printProgress(0, 12, ""); 1159d90825e2SJohnny Huang otp_soak(0); 1160a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1161d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1162d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1163a6d0d645SJohnny Huang prog_address = 0x800; 1164a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1165a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1166d90825e2SJohnny Huang if (data_masked == buf_masked) { 1167a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1168a6d0d645SJohnny Huang continue; 1169a6d0d645SJohnny Huang } 1170d90825e2SJohnny Huang if (soak) { 1171d90825e2SJohnny Huang soak = 0; 1172d90825e2SJohnny Huang otp_soak(0); 1173d90825e2SJohnny Huang } 1174a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1175a6d0d645SJohnny Huang 1176d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1177a6d0d645SJohnny Huang 117869d5fd8fSJohnny Huang pass = 0; 117969d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1180d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1181d90825e2SJohnny Huang if (soak == 0) { 1182d90825e2SJohnny Huang soak = 1; 1183d90825e2SJohnny Huang otp_soak(1); 1184d90825e2SJohnny Huang } 1185a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1186a6d0d645SJohnny Huang } else { 118769d5fd8fSJohnny Huang pass = 1; 118869d5fd8fSJohnny Huang break; 118969d5fd8fSJohnny Huang } 119069d5fd8fSJohnny Huang } 1191a6d0d645SJohnny Huang } 1192a6d0d645SJohnny Huang 119369d5fd8fSJohnny Huang if (!pass) 11942a856b9aSJohnny Huang return OTP_FAILURE; 1195a6d0d645SJohnny Huang 11962a856b9aSJohnny Huang return OTP_SUCCESS; 1197d90825e2SJohnny Huang 119869d5fd8fSJohnny Huang } 119969d5fd8fSJohnny Huang 120069d5fd8fSJohnny Huang 120176d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 120269d5fd8fSJohnny Huang { 120369d5fd8fSJohnny Huang int i; 120469d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 120569d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 120669d5fd8fSJohnny Huang int bit, pbit, kbit; 120769d5fd8fSJohnny Huang int fail = 0; 1208a6af4a17SJohnny Huang int skip = -1; 120966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 121069d5fd8fSJohnny Huang 121169d5fd8fSJohnny Huang otp_strp_status(otpstrap); 121269d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 121369d5fd8fSJohnny Huang if (i < 32) { 121469d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 121569d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 121669d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 121769d5fd8fSJohnny Huang } else { 121869d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 121969d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 122069d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 122169d5fd8fSJohnny Huang } 122269d5fd8fSJohnny Huang 122369d5fd8fSJohnny Huang if (kbit == 1) { 122469d5fd8fSJohnny Huang continue; 122569d5fd8fSJohnny Huang } else { 1226a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 122769d5fd8fSJohnny Huang } 122869d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 122969d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1230a6af4a17SJohnny Huang if (skip == -1) 1231a6af4a17SJohnny Huang skip = 1; 123269d5fd8fSJohnny Huang continue; 1233a6af4a17SJohnny Huang } else { 1234a6af4a17SJohnny Huang skip = 0; 123569d5fd8fSJohnny Huang } 123669d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 123769d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 123869d5fd8fSJohnny Huang fail = 1; 123969d5fd8fSJohnny Huang continue; 124069d5fd8fSJohnny Huang } 124169d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1242a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 124369d5fd8fSJohnny Huang fail = 1; 124469d5fd8fSJohnny Huang continue; 124569d5fd8fSJohnny Huang } 124669d5fd8fSJohnny Huang if (pbit == 1) { 124769d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 124869d5fd8fSJohnny Huang } 1249a6af4a17SJohnny 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); 125069d5fd8fSJohnny Huang } 125169d5fd8fSJohnny Huang if (fail == 1) 1252a6af4a17SJohnny Huang return OTP_FAILURE; 1253a6af4a17SJohnny Huang else if (skip == 1) 1254a6af4a17SJohnny Huang return OTP_PROG_SKIP; 12557e22f42dSJohnny Huang 12567e22f42dSJohnny Huang return 0; 125769d5fd8fSJohnny Huang } 125869d5fd8fSJohnny Huang 12592a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 126069d5fd8fSJohnny Huang { 126169d5fd8fSJohnny Huang int i, j; 126266f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 126369d5fd8fSJohnny Huang 12642a856b9aSJohnny Huang if (start < 0 || start > 64) 12652a856b9aSJohnny Huang return OTP_USAGE; 12662a856b9aSJohnny Huang 12672a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 12682a856b9aSJohnny Huang return OTP_USAGE; 12692a856b9aSJohnny Huang 127069d5fd8fSJohnny Huang otp_strp_status(otpstrap); 127169d5fd8fSJohnny Huang 1272a8bd6d8cSJohnny Huang printf("BIT(hex) Value Avaliable Status\n"); 1273a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1274737ed20bSJohnny Huang 1275cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 1276a8bd6d8cSJohnny Huang printf("%-10X", i); 1277737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1278737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1279737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1280737ed20bSJohnny Huang printf(" "); 128169d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1282737ed20bSJohnny Huang printf("protected and not writable"); 128369d5fd8fSJohnny Huang } else { 1284737ed20bSJohnny Huang printf("not protected "); 128569d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1286737ed20bSJohnny Huang printf("and no remaining times to write."); 128769d5fd8fSJohnny Huang } else { 1288737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 128969d5fd8fSJohnny Huang } 129069d5fd8fSJohnny Huang } 1291737ed20bSJohnny Huang printf("\n"); 129269d5fd8fSJohnny Huang } 12932a856b9aSJohnny Huang 12942a856b9aSJohnny Huang return OTP_SUCCESS; 129569d5fd8fSJohnny Huang } 129669d5fd8fSJohnny Huang 129769d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 129869d5fd8fSJohnny Huang { 129969d5fd8fSJohnny Huang int i, j; 130069d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 130169d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 130269d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 130369d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 130469d5fd8fSJohnny Huang int fail = 0; 13057e22f42dSJohnny Huang int pass = 0; 13067e22f42dSJohnny Huang int soak = 0; 130766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 130869d5fd8fSJohnny Huang 13097f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 131069d5fd8fSJohnny Huang otp_strp_status(otpstrap); 131169d5fd8fSJohnny Huang 13127f795e57SJohnny Huang printf("Check writable...\n"); 13137f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 13147f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 13157f795e57SJohnny Huang return OTP_FAILURE; 13167f795e57SJohnny Huang } 13177e22f42dSJohnny Huang 13187f795e57SJohnny Huang otp_soak(0); 131969d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 13204c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 132169d5fd8fSJohnny Huang prog_address = 0x800; 132269d5fd8fSJohnny Huang if (i < 32) { 132369d5fd8fSJohnny Huang offset = i; 132469d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 132569d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 132669d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 132769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 132869d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 132969d5fd8fSJohnny Huang 133069d5fd8fSJohnny Huang } else { 133169d5fd8fSJohnny Huang offset = (i - 32); 133269d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 133369d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 133469d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 133569d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 133669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 133769d5fd8fSJohnny Huang } 133869d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 133969d5fd8fSJohnny Huang 134069d5fd8fSJohnny Huang if (kbit == 1) { 134169d5fd8fSJohnny Huang continue; 134269d5fd8fSJohnny Huang } 134369d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 134469d5fd8fSJohnny Huang continue; 134569d5fd8fSJohnny Huang } 134669d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 134769d5fd8fSJohnny Huang fail = 1; 134869d5fd8fSJohnny Huang continue; 134969d5fd8fSJohnny Huang } 135069d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 135169d5fd8fSJohnny Huang fail = 1; 135269d5fd8fSJohnny Huang continue; 135369d5fd8fSJohnny Huang } 13547e22f42dSJohnny Huang 13557e22f42dSJohnny Huang if (soak) { 135669d5fd8fSJohnny Huang soak = 0; 13577e22f42dSJohnny Huang otp_soak(0); 13587e22f42dSJohnny Huang } 13597e22f42dSJohnny Huang 13607e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 13617e22f42dSJohnny Huang 13627e22f42dSJohnny Huang pass = 0; 13637e22f42dSJohnny Huang 136469d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1365a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 136669d5fd8fSJohnny Huang pass = 1; 136769d5fd8fSJohnny Huang break; 136869d5fd8fSJohnny Huang } 13697e22f42dSJohnny Huang if (soak == 0) { 137069d5fd8fSJohnny Huang soak = 1; 13717e22f42dSJohnny Huang otp_soak(1); 13724b65a65dSJohnny Huang } 137369d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 137469d5fd8fSJohnny Huang } 137569d5fd8fSJohnny Huang if (!pass) 13762a856b9aSJohnny Huang return OTP_FAILURE; 137769d5fd8fSJohnny Huang 137869d5fd8fSJohnny Huang if (pbit == 0) 137969d5fd8fSJohnny Huang continue; 138069d5fd8fSJohnny Huang prog_address = 0x800; 138169d5fd8fSJohnny Huang if (i < 32) 138269d5fd8fSJohnny Huang prog_address |= 0x60c; 138369d5fd8fSJohnny Huang else 138469d5fd8fSJohnny Huang prog_address |= 0x60e; 138569d5fd8fSJohnny Huang 13867e22f42dSJohnny Huang 13877e22f42dSJohnny Huang if (soak) { 13887e22f42dSJohnny Huang soak = 0; 13897e22f42dSJohnny Huang otp_soak(0); 13907e22f42dSJohnny Huang } 13917e22f42dSJohnny Huang 13927e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 13937e22f42dSJohnny Huang 13947e22f42dSJohnny Huang pass = 0; 13957e22f42dSJohnny Huang 139669d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 13977e22f42dSJohnny Huang 1398a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 139969d5fd8fSJohnny Huang pass = 1; 140069d5fd8fSJohnny Huang break; 140169d5fd8fSJohnny Huang } 14027e22f42dSJohnny Huang if (soak == 0) { 140369d5fd8fSJohnny Huang soak = 1; 14047e22f42dSJohnny Huang otp_soak(1); 140569d5fd8fSJohnny Huang } 140669d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 140769d5fd8fSJohnny Huang } 140869d5fd8fSJohnny Huang if (!pass) 14092a856b9aSJohnny Huang return OTP_FAILURE; 141069d5fd8fSJohnny Huang 141169d5fd8fSJohnny Huang } 141269d5fd8fSJohnny Huang if (fail == 1) 14132a856b9aSJohnny Huang return OTP_FAILURE; 141469d5fd8fSJohnny Huang else 14152a856b9aSJohnny Huang return OTP_SUCCESS; 141669d5fd8fSJohnny Huang 141769d5fd8fSJohnny Huang } 141869d5fd8fSJohnny Huang 1419cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1420cd1610b4SJohnny Huang { 1421cd1610b4SJohnny Huang int prog_bit; 1422cd1610b4SJohnny Huang 14237e22f42dSJohnny Huang otp_soak(soak); 14247e22f42dSJohnny Huang 1425cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1426cd1610b4SJohnny Huang if (value) 1427cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1428cd1610b4SJohnny Huang else 1429cd1610b4SJohnny Huang return; 1430cd1610b4SJohnny Huang } else { 1431cd1610b4SJohnny Huang prog_address |= 1 << 15; 1432cd1610b4SJohnny Huang if (!value) 1433cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1434cd1610b4SJohnny Huang else 1435cd1610b4SJohnny Huang return; 1436cd1610b4SJohnny Huang } 1437cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1438cd1610b4SJohnny Huang } 1439cd1610b4SJohnny Huang 1440d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 14414c1c9b35SJohnny Huang { 14424c1c9b35SJohnny Huang int i, k; 14434c1c9b35SJohnny Huang int pass; 1444d90825e2SJohnny Huang int soak = 0; 14454c1c9b35SJohnny Huang uint32_t prog_address; 1446d90825e2SJohnny Huang uint32_t data[2048]; 14474c1c9b35SJohnny Huang uint32_t compare[2]; 1448d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 14494c1c9b35SJohnny Huang 1450d90825e2SJohnny Huang uint32_t data0_masked; 1451d90825e2SJohnny Huang uint32_t data1_masked; 1452d90825e2SJohnny Huang uint32_t buf0_masked; 1453d90825e2SJohnny Huang uint32_t buf1_masked; 14544c1c9b35SJohnny Huang 14554c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 14564c1c9b35SJohnny Huang 1457d90825e2SJohnny Huang printProgress(0, 2048, ""); 1458d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1459d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1460d90825e2SJohnny Huang otp_read_data(i, &data[i]); 14614c1c9b35SJohnny Huang } 1462d90825e2SJohnny Huang 14634c1c9b35SJohnny Huang 14644c1c9b35SJohnny Huang printf("Check writable...\n"); 1465d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1466d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1467d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1468d90825e2SJohnny Huang if (data0_masked == buf0_masked) 14694c1c9b35SJohnny Huang continue; 1470d90825e2SJohnny Huang if (i % 2 == 0) { 1471d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 14724c1c9b35SJohnny Huang continue; 14734c1c9b35SJohnny Huang } else { 14744c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1475d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 14764c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1477d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 14782a856b9aSJohnny Huang return OTP_FAILURE; 147969d5fd8fSJohnny Huang } 1480d90825e2SJohnny Huang } else { 1481d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1482d90825e2SJohnny Huang continue; 1483d90825e2SJohnny Huang } else { 1484d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1485d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1486d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1487d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 14882a856b9aSJohnny Huang return OTP_FAILURE; 1489d90825e2SJohnny Huang } 1490d90825e2SJohnny Huang } 1491d90825e2SJohnny Huang } 149269d5fd8fSJohnny Huang 1493d90825e2SJohnny Huang printf("Start Programing...\n"); 1494d90825e2SJohnny Huang printProgress(0, 2048, ""); 1495d90825e2SJohnny Huang 1496d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1497d90825e2SJohnny Huang prog_address = i; 1498d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1499d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1500d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1501d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1502d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1503d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1504d90825e2SJohnny Huang continue; 1505d90825e2SJohnny Huang } 1506d90825e2SJohnny Huang if (soak) { 1507d90825e2SJohnny Huang soak = 0; 1508d90825e2SJohnny Huang otp_soak(0); 1509d90825e2SJohnny Huang } 1510d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1511d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1512d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1513d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1514d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1515d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1516d90825e2SJohnny Huang } else { 1517d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1518d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1519d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1520d90825e2SJohnny Huang } 1521d90825e2SJohnny Huang 1522d90825e2SJohnny Huang pass = 0; 1523d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1524d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1525d90825e2SJohnny Huang if (soak == 0) { 1526d90825e2SJohnny Huang soak = 1; 1527d90825e2SJohnny Huang otp_soak(1); 1528d90825e2SJohnny Huang } 1529d90825e2SJohnny Huang if (compare[0] != 0) { 1530d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1531d90825e2SJohnny Huang } 1532d90825e2SJohnny Huang if (compare[1] != ~0) { 1533d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1534d90825e2SJohnny Huang } 1535d90825e2SJohnny Huang } else { 1536d90825e2SJohnny Huang pass = 1; 1537d90825e2SJohnny Huang break; 1538d90825e2SJohnny Huang } 1539d90825e2SJohnny Huang } 1540d90825e2SJohnny Huang 1541d90825e2SJohnny Huang if (!pass) 15422a856b9aSJohnny Huang return OTP_FAILURE; 1543d90825e2SJohnny Huang } 15442a856b9aSJohnny Huang return OTP_SUCCESS; 1545d90825e2SJohnny Huang 1546d90825e2SJohnny Huang } 1547d90825e2SJohnny Huang 1548d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 154969d5fd8fSJohnny Huang { 155069d5fd8fSJohnny Huang int ret; 1551d90825e2SJohnny Huang int mode; 155269d5fd8fSJohnny Huang uint32_t *buf; 1553d90825e2SJohnny Huang uint32_t *data_region = NULL; 1554d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1555d90825e2SJohnny Huang uint32_t *strap_region = NULL; 155669d5fd8fSJohnny Huang 1557d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 155869d5fd8fSJohnny Huang if (!buf) { 155969d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 15602a856b9aSJohnny Huang return OTP_FAILURE; 156169d5fd8fSJohnny Huang } 1562d90825e2SJohnny Huang 1563d90825e2SJohnny Huang if (((buf[0] >> 29) & 0x7) == 0x7) { 1564d90825e2SJohnny Huang mode = OTP_REGION_ALL; 1565d90825e2SJohnny Huang conf_region = &buf[1]; 1566d90825e2SJohnny Huang strap_region = &buf[25]; 1567d90825e2SJohnny Huang data_region = &buf[31]; 1568d90825e2SJohnny Huang } else { 1569d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 1570d90825e2SJohnny Huang mode = OTP_REGION_DATA; 1571d90825e2SJohnny Huang data_region = &buf[31]; 1572d90825e2SJohnny Huang } 1573d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 1574d90825e2SJohnny Huang mode = OTP_REGION_CONF; 1575d90825e2SJohnny Huang strap_region = &buf[25]; 1576d90825e2SJohnny Huang } 1577d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 1578d90825e2SJohnny Huang mode = OTP_REGION_STRAP; 1579d90825e2SJohnny Huang conf_region = &buf[1]; 1580d90825e2SJohnny Huang } 1581d90825e2SJohnny Huang } 158269d5fd8fSJohnny Huang if (!nconfirm) { 1583a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 15847f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1585*b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 158669d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 15872a856b9aSJohnny Huang return OTP_FAILURE; 158869d5fd8fSJohnny Huang } 1589a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 15907f795e57SJohnny Huang printf("\nOTP data region :\n"); 15917f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 159269d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 15932a856b9aSJohnny Huang return OTP_FAILURE; 159469d5fd8fSJohnny Huang } 1595a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 15967f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1597*b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 159869d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 15992a856b9aSJohnny Huang return OTP_FAILURE; 160069d5fd8fSJohnny Huang } 1601a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 16027f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1603*b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 160469d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 16052a856b9aSJohnny Huang return OTP_FAILURE; 160669d5fd8fSJohnny Huang } 16077f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1608*b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 160969d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 16102a856b9aSJohnny Huang return OTP_FAILURE; 161169d5fd8fSJohnny Huang } 16127f795e57SJohnny Huang printf("\nOTP data region :\n"); 16137f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 161469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16152a856b9aSJohnny Huang return OTP_FAILURE; 161669d5fd8fSJohnny Huang } 161769d5fd8fSJohnny Huang } 161869d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 161969d5fd8fSJohnny Huang if (!confirm_yesno()) { 162069d5fd8fSJohnny Huang printf(" Aborting\n"); 16212a856b9aSJohnny Huang return OTP_FAILURE; 162269d5fd8fSJohnny Huang } 162369d5fd8fSJohnny Huang } 1624a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 1625d90825e2SJohnny Huang return otp_prog_conf(conf_region); 1626a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 1627d90825e2SJohnny Huang return otp_prog_strap(strap_region); 1628a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 1629d90825e2SJohnny Huang return otp_prog_data(data_region); 1630a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 163169d5fd8fSJohnny Huang printf("programing data region ... "); 1632d90825e2SJohnny Huang ret = otp_prog_data(data_region); 16332a856b9aSJohnny Huang if (ret != 0) { 163469d5fd8fSJohnny Huang printf("Error\n"); 163569d5fd8fSJohnny Huang return ret; 163669d5fd8fSJohnny Huang } else { 163769d5fd8fSJohnny Huang printf("Done\n"); 163869d5fd8fSJohnny Huang } 163969d5fd8fSJohnny Huang printf("programing strap region ... "); 1640d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 16412a856b9aSJohnny Huang if (ret != 0) { 164269d5fd8fSJohnny Huang printf("Error\n"); 164369d5fd8fSJohnny Huang return ret; 164469d5fd8fSJohnny Huang } else { 164569d5fd8fSJohnny Huang printf("Done\n"); 164669d5fd8fSJohnny Huang } 164769d5fd8fSJohnny Huang printf("programing configuration region ... "); 1648d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 16492a856b9aSJohnny Huang if (ret != 0) { 165069d5fd8fSJohnny Huang printf("Error\n"); 165169d5fd8fSJohnny Huang return ret; 165269d5fd8fSJohnny Huang } 165369d5fd8fSJohnny Huang printf("Done\n"); 16542a856b9aSJohnny Huang return OTP_SUCCESS; 165569d5fd8fSJohnny Huang } 1656cd1610b4SJohnny Huang 16572a856b9aSJohnny Huang return OTP_USAGE; 16582a856b9aSJohnny Huang } 16592a856b9aSJohnny Huang 16602a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1661cd1610b4SJohnny Huang { 1662a6af4a17SJohnny Huang uint32_t read[2]; 1663cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1664d90825e2SJohnny Huang uint32_t prog_address = 0; 166566f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1666cd1610b4SJohnny Huang int otp_bit; 1667cd1610b4SJohnny Huang int i; 1668cd1610b4SJohnny Huang int pass; 1669a6af4a17SJohnny Huang int ret; 1670cd1610b4SJohnny Huang 1671cd1610b4SJohnny Huang switch (mode) { 1672a6d0d645SJohnny Huang case OTP_REGION_CONF: 1673a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1674cd1610b4SJohnny Huang prog_address = 0x800; 1675cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1676cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1677a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1678cd1610b4SJohnny Huang if (otp_bit == value) { 1679a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1680cd1610b4SJohnny Huang printf("No need to program\n"); 16812a856b9aSJohnny Huang return OTP_SUCCESS; 1682cd1610b4SJohnny Huang } 1683cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1684a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1685cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 16862a856b9aSJohnny Huang return OTP_FAILURE; 1687cd1610b4SJohnny Huang } 1688a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1689cd1610b4SJohnny Huang break; 1690a6d0d645SJohnny Huang case OTP_REGION_DATA: 1691cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1692cd1610b4SJohnny Huang 1693cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1694a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1695a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1696cd1610b4SJohnny Huang } else { 1697a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1698a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1699cd1610b4SJohnny Huang } 1700cd1610b4SJohnny Huang if (otp_bit == value) { 1701a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1702cd1610b4SJohnny Huang printf("No need to program\n"); 17032a856b9aSJohnny Huang return OTP_SUCCESS; 1704cd1610b4SJohnny Huang } 1705cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1706a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1707cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17082a856b9aSJohnny Huang return OTP_FAILURE; 1709cd1610b4SJohnny Huang } 1710a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1711cd1610b4SJohnny Huang break; 1712a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1713cd1610b4SJohnny Huang otp_strp_status(otpstrap); 1714cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1715cd1610b4SJohnny Huang if (bit_offset < 32) { 1716cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1717cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1718cd1610b4SJohnny Huang strap_buf[3] = ~0; 1719cd1610b4SJohnny Huang strap_buf[5] = 0; 17202a856b9aSJohnny Huang // if (protect) 17212a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 17222a856b9aSJohnny Huang // else 17232a856b9aSJohnny Huang // strap_buf[4] = 0; 1724cd1610b4SJohnny Huang } else { 1725cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1726cd1610b4SJohnny Huang strap_buf[2] = ~0; 1727cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1728cd1610b4SJohnny Huang strap_buf[4] = 0; 17292a856b9aSJohnny Huang // if (protect) 17302a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 17312a856b9aSJohnny Huang // else 17322a856b9aSJohnny Huang // strap_buf[5] = 0; 1733cd1610b4SJohnny Huang } 173476d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1735a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 17362a856b9aSJohnny Huang return OTP_FAILURE; 1737a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1738a6af4a17SJohnny Huang return OTP_SUCCESS; 1739a6af4a17SJohnny Huang 1740cd1610b4SJohnny Huang break; 1741cd1610b4SJohnny Huang } 1742cd1610b4SJohnny Huang 1743cd1610b4SJohnny Huang if (!nconfirm) { 1744cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1745cd1610b4SJohnny Huang if (!confirm_yesno()) { 1746cd1610b4SJohnny Huang printf(" Aborting\n"); 17472a856b9aSJohnny Huang return OTP_FAILURE; 1748cd1610b4SJohnny Huang } 1749cd1610b4SJohnny Huang } 1750cd1610b4SJohnny Huang 1751cd1610b4SJohnny Huang switch (mode) { 1752a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1753cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1754a6d0d645SJohnny Huang case OTP_REGION_CONF: 1755a6d0d645SJohnny Huang case OTP_REGION_DATA: 1756cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1757cd1610b4SJohnny Huang pass = -1; 1758cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1759a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1760cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1761cd1610b4SJohnny Huang } else { 1762cd1610b4SJohnny Huang pass = 0; 1763cd1610b4SJohnny Huang break; 1764cd1610b4SJohnny Huang } 1765cd1610b4SJohnny Huang } 17662a856b9aSJohnny Huang if (pass == 0) 17672a856b9aSJohnny Huang return OTP_SUCCESS; 1768cd1610b4SJohnny Huang } 1769cd1610b4SJohnny Huang 17702a856b9aSJohnny Huang return OTP_USAGE; 1771cd1610b4SJohnny Huang } 1772cd1610b4SJohnny Huang 17732a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 177469d5fd8fSJohnny Huang { 17752a856b9aSJohnny Huang uint32_t offset, count; 17762a856b9aSJohnny Huang int ret; 177769d5fd8fSJohnny Huang 17782a856b9aSJohnny Huang if (argc == 4) { 17792a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17802a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 17812a856b9aSJohnny Huang } else if (argc == 3) { 17822a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17832a856b9aSJohnny Huang count = 1; 17842a856b9aSJohnny Huang } else { 178569d5fd8fSJohnny Huang return CMD_RET_USAGE; 178669d5fd8fSJohnny Huang } 178769d5fd8fSJohnny Huang 178869d5fd8fSJohnny Huang 17892a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 179069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17912a856b9aSJohnny Huang ret = otp_print_config(offset, count); 17922a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 17932a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17942a856b9aSJohnny Huang ret = otp_print_data(offset, count); 17952a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 17962a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17972a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 17982a856b9aSJohnny Huang } else { 17992a856b9aSJohnny Huang return CMD_RET_USAGE; 180069d5fd8fSJohnny Huang } 180169d5fd8fSJohnny Huang 18022a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18032a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18042a856b9aSJohnny Huang else 18052a856b9aSJohnny Huang return CMD_RET_USAGE; 18062a856b9aSJohnny Huang 18072a856b9aSJohnny Huang } 18082a856b9aSJohnny Huang 18092a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18102a856b9aSJohnny Huang { 18112a856b9aSJohnny Huang phys_addr_t addr; 18122a856b9aSJohnny Huang uint32_t byte_size; 18132a856b9aSJohnny Huang int ret; 18142a856b9aSJohnny Huang 18152a856b9aSJohnny Huang if (argc == 4) { 18162a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 18172a856b9aSJohnny Huang return CMD_RET_USAGE; 18182a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 18192a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 182069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18212a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 18222a856b9aSJohnny Huang } else if (argc == 3) { 18232a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 18242a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 18252a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18262a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 18272a856b9aSJohnny Huang } else { 18282a856b9aSJohnny Huang return CMD_RET_USAGE; 18292a856b9aSJohnny Huang } 18302a856b9aSJohnny Huang 18312a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18322a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18332a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18342a856b9aSJohnny Huang return CMD_RET_FAILURE; 18352a856b9aSJohnny Huang else 18362a856b9aSJohnny Huang return CMD_RET_USAGE; 18372a856b9aSJohnny Huang } 18382a856b9aSJohnny Huang 18392a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18402a856b9aSJohnny Huang { 18412a856b9aSJohnny Huang int mode = 0; 18422a856b9aSJohnny Huang int nconfirm = 0; 18432a856b9aSJohnny Huang int otp_addr = 0; 18442a856b9aSJohnny Huang int bit_offset; 18452a856b9aSJohnny Huang int value; 18462a856b9aSJohnny Huang int ret; 18472a856b9aSJohnny Huang 18482a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 18492a856b9aSJohnny Huang return CMD_RET_USAGE; 18502a856b9aSJohnny Huang 18512a856b9aSJohnny Huang /* Drop the pb cmd */ 18522a856b9aSJohnny Huang argc--; 18532a856b9aSJohnny Huang argv++; 18542a856b9aSJohnny Huang 18552a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1856a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 18572a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1858a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 18592a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1860a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1861cd1610b4SJohnny Huang else 18622a856b9aSJohnny Huang return CMD_RET_USAGE; 18632a856b9aSJohnny Huang 18642a856b9aSJohnny Huang /* Drop the region cmd */ 18652a856b9aSJohnny Huang argc--; 18662a856b9aSJohnny Huang argv++; 18672a856b9aSJohnny Huang 18682a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1869cd1610b4SJohnny Huang nconfirm = 1; 18702a856b9aSJohnny Huang /* Drop the force option */ 18712a856b9aSJohnny Huang argc--; 18722a856b9aSJohnny Huang argv++; 18732a856b9aSJohnny Huang } 1874cd1610b4SJohnny Huang 1875a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 18762a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 18772a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1878cd1610b4SJohnny Huang if (bit_offset >= 64) 18792a856b9aSJohnny Huang return CMD_RET_USAGE; 1880cd1610b4SJohnny Huang } else { 18812a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 18822a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 18832a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1884cd1610b4SJohnny Huang if (bit_offset >= 32) 18852a856b9aSJohnny Huang return CMD_RET_USAGE; 1886cd1610b4SJohnny Huang } 1887cd1610b4SJohnny Huang if (value != 0 && value != 1) 18882a856b9aSJohnny Huang return CMD_RET_USAGE; 1889cd1610b4SJohnny Huang 1890cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18912a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 18922a856b9aSJohnny Huang 18932a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18942a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18952a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18962a856b9aSJohnny Huang return CMD_RET_FAILURE; 18972a856b9aSJohnny Huang else 18982a856b9aSJohnny Huang return CMD_RET_USAGE; 18992a856b9aSJohnny Huang } 19002a856b9aSJohnny Huang 19012a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19022a856b9aSJohnny Huang { 19032a856b9aSJohnny Huang phys_addr_t addr; 19042a856b9aSJohnny Huang int otp_addr = 0; 19052a856b9aSJohnny Huang 19062a856b9aSJohnny Huang if (argc != 3) 19072a856b9aSJohnny Huang return CMD_RET_USAGE; 19082a856b9aSJohnny Huang 190969d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19102a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19112a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 19122a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 191369d5fd8fSJohnny Huang printf("Compare pass\n"); 19142a856b9aSJohnny Huang return CMD_RET_SUCCESS; 191569d5fd8fSJohnny Huang } else { 191669d5fd8fSJohnny Huang printf("Compare fail\n"); 19172a856b9aSJohnny Huang return CMD_RET_FAILURE; 191869d5fd8fSJohnny Huang } 191969d5fd8fSJohnny Huang } 192069d5fd8fSJohnny Huang 192166f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 192266f2f8e5SJohnny Huang { 1923a8bd6d8cSJohnny Huang int mode = 0; 1924a8bd6d8cSJohnny Huang int view = 0; 1925a8bd6d8cSJohnny Huang 1926a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 192766f2f8e5SJohnny Huang return CMD_RET_USAGE; 192866f2f8e5SJohnny Huang 1929a8bd6d8cSJohnny Huang /* Drop the info cmd */ 1930a8bd6d8cSJohnny Huang argc--; 1931a8bd6d8cSJohnny Huang argv++; 193266f2f8e5SJohnny Huang 1933a8bd6d8cSJohnny Huang if (!strcmp(argv[0], "conf")) 1934a8bd6d8cSJohnny Huang mode = OTP_REGION_CONF; 1935a8bd6d8cSJohnny Huang else if (!strcmp(argv[0], "strap")) 1936a8bd6d8cSJohnny Huang mode = OTP_REGION_STRAP; 1937a8bd6d8cSJohnny Huang else 1938a8bd6d8cSJohnny Huang return CMD_RET_USAGE; 1939a8bd6d8cSJohnny Huang 1940a8bd6d8cSJohnny Huang /* Drop the region cmd */ 1941a8bd6d8cSJohnny Huang argc--; 1942a8bd6d8cSJohnny Huang argv++; 1943a8bd6d8cSJohnny Huang 1944a8bd6d8cSJohnny Huang if (!strcmp(argv[0], "v")) { 1945a8bd6d8cSJohnny Huang view = 1; 1946a8bd6d8cSJohnny Huang /* Drop the view option */ 1947a8bd6d8cSJohnny Huang argc--; 1948a8bd6d8cSJohnny Huang argv++; 1949a8bd6d8cSJohnny Huang } 1950a8bd6d8cSJohnny Huang 1951a8bd6d8cSJohnny Huang if (mode == OTP_REGION_CONF) { 195266f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1953*b458cd62SJohnny Huang otp_print_conf_info(view); 1954a8bd6d8cSJohnny Huang } else if (mode == OTP_REGION_STRAP) { 195566f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1956*b458cd62SJohnny Huang otp_print_strap_info(view); 195766f2f8e5SJohnny Huang } else { 195866f2f8e5SJohnny Huang return CMD_RET_USAGE; 195966f2f8e5SJohnny Huang } 196066f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 196166f2f8e5SJohnny Huang } 196266f2f8e5SJohnny Huang 1963737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 1964737ed20bSJohnny Huang { 1965737ed20bSJohnny Huang int input; 1966737ed20bSJohnny Huang int bit_offset; 1967737ed20bSJohnny Huang int prog_address; 1968737ed20bSJohnny Huang int pass; 1969737ed20bSJohnny Huang int i; 1970737ed20bSJohnny Huang if (argc != 3 && argc != 2) 1971737ed20bSJohnny Huang return CMD_RET_USAGE; 1972737ed20bSJohnny Huang 1973737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 1974737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1975737ed20bSJohnny Huang } else { 1976737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 1977737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 1978737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1979737ed20bSJohnny Huang if (!confirm_yesno()) { 1980737ed20bSJohnny Huang printf(" Aborting\n"); 1981737ed20bSJohnny Huang return CMD_RET_FAILURE; 1982737ed20bSJohnny Huang } 1983737ed20bSJohnny Huang } 1984737ed20bSJohnny Huang 1985737ed20bSJohnny Huang prog_address = 0x800; 1986737ed20bSJohnny Huang if (input < 32) { 1987737ed20bSJohnny Huang bit_offset = input; 1988737ed20bSJohnny Huang prog_address |= 0x60c; 1989737ed20bSJohnny Huang } else if (input < 64) { 1990737ed20bSJohnny Huang bit_offset = input - 32; 1991737ed20bSJohnny Huang prog_address |= 0x60e; 1992737ed20bSJohnny Huang } else { 1993737ed20bSJohnny Huang return CMD_RET_USAGE; 1994737ed20bSJohnny Huang } 1995737ed20bSJohnny Huang 1996737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 1997737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 1998737ed20bSJohnny Huang } 1999737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 2000737ed20bSJohnny Huang pass = -1; 2001737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2002737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2003737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 2004737ed20bSJohnny Huang } else { 2005737ed20bSJohnny Huang pass = 0; 2006737ed20bSJohnny Huang break; 2007737ed20bSJohnny Huang } 2008737ed20bSJohnny Huang } 2009737ed20bSJohnny Huang if (pass == 0) { 2010737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2011737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2012737ed20bSJohnny Huang } 2013737ed20bSJohnny Huang 2014737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2015737ed20bSJohnny Huang return CMD_RET_FAILURE; 2016737ed20bSJohnny Huang 2017737ed20bSJohnny Huang } 20182a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 20192a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2020a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 20212a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 20222a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2023737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 20242a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 20252a856b9aSJohnny Huang }; 20262a856b9aSJohnny Huang 20272a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20282a856b9aSJohnny Huang { 20292a856b9aSJohnny Huang cmd_tbl_t *cp; 20302a856b9aSJohnny Huang 20312a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 20322a856b9aSJohnny Huang 2033737ed20bSJohnny Huang /* Drop the otp command */ 20342a856b9aSJohnny Huang argc--; 20352a856b9aSJohnny Huang argv++; 20362a856b9aSJohnny Huang 20372a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 20382a856b9aSJohnny Huang return CMD_RET_USAGE; 20392a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 20402a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20412a856b9aSJohnny Huang 20422a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 204369d5fd8fSJohnny Huang } 204469d5fd8fSJohnny Huang 204569d5fd8fSJohnny Huang U_BOOT_CMD( 204669d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 204769d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 20482a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 20492a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 2050a8bd6d8cSJohnny Huang "otp info conf|strap [v]\n" 2051d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2052cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2053737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2054737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 20552a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 205669d5fd8fSJohnny Huang ); 2057