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 40b458cd62SJohnny Huang #define OTP_REG_VALUE -2 41b458cd62SJohnny 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" 312b458cd62SJohnny Huang }, { 313b458cd62SJohnny Huang 63, 1, OTP_REG_RESERVED, "" 314a8bd6d8cSJohnny Huang } 31576d13988SJohnny Huang }; 316b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 317b458cd62SJohnny Huang { 318b458cd62SJohnny Huang 0, 0, 1, 0, "Enable Secure Region programming" 319b458cd62SJohnny Huang }, { 320b458cd62SJohnny Huang 0, 0, 1, 1, "Disable Secure Region programming" 321b458cd62SJohnny Huang }, { 322b458cd62SJohnny Huang 0, 1, 1, 0, "Disable Secure Boot" 323b458cd62SJohnny Huang }, { 324b458cd62SJohnny Huang 0, 1, 1, 1, "Enable Secure Boot" 325b458cd62SJohnny Huang }, { 326b458cd62SJohnny Huang 0, 2, 1, 0, "Initialization programming not done" 327b458cd62SJohnny Huang }, { 328b458cd62SJohnny Huang 0, 2, 1, 1, "Initialization programming done" 329b458cd62SJohnny Huang }, { 330b458cd62SJohnny Huang 0, 3, 1, 0, "User region ECC disable" 331b458cd62SJohnny Huang }, { 332b458cd62SJohnny Huang 0, 3, 1, 1, "User region ECC enable" 333b458cd62SJohnny Huang }, { 334b458cd62SJohnny Huang 0, 4, 1, 0, "Secure Region ECC disable" 335b458cd62SJohnny Huang }, { 336b458cd62SJohnny Huang 0, 4, 1, 1, "Secure Region ECC enable" 337b458cd62SJohnny Huang }, { 338b458cd62SJohnny Huang 0, 5, 1, 0, "Enable low security key" 339b458cd62SJohnny Huang }, { 340b458cd62SJohnny Huang 0, 5, 1, 1, "Disable low security key" 341b458cd62SJohnny Huang }, { 342b458cd62SJohnny Huang 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" 343b458cd62SJohnny Huang }, { 344b458cd62SJohnny Huang 0, 6, 1, 1, "Ignore Secure Boot hardware strap" 345b458cd62SJohnny Huang }, { 346b458cd62SJohnny Huang 0, 7, 1, 0, "Secure Boot Mode: 2" 347b458cd62SJohnny Huang }, { 348b458cd62SJohnny Huang 0, 7, 1, 1, "Secure Boot Mode: 1" 349b458cd62SJohnny Huang }, { 350b458cd62SJohnny Huang 0, 8, 2, 0, "Single cell mode (recommended)" 351b458cd62SJohnny Huang }, { 352b458cd62SJohnny Huang 0, 8, 2, 1, "Differnetial mode" 353b458cd62SJohnny Huang }, { 354b458cd62SJohnny Huang 0, 8, 2, 2, "Differential-redundant mode" 355b458cd62SJohnny Huang }, { 356b458cd62SJohnny Huang 0, 10, 2, 0, "RSA mode : RSA1024" 357b458cd62SJohnny Huang }, { 358b458cd62SJohnny Huang 0, 10, 2, 1, "RSA mode : RSA2048" 359b458cd62SJohnny Huang }, { 360b458cd62SJohnny Huang 0, 10, 2, 2, "RSA mode : RSA3072" 361b458cd62SJohnny Huang }, { 362b458cd62SJohnny Huang 0, 10, 2, 3, "RSA mode : RSA4096" 363b458cd62SJohnny Huang }, { 364b458cd62SJohnny Huang 0, 12, 2, 0, "SHA mode : SHA224" 365b458cd62SJohnny Huang }, { 366b458cd62SJohnny Huang 0, 12, 2, 1, "SHA mode : SHA256" 367b458cd62SJohnny Huang }, { 368b458cd62SJohnny Huang 0, 12, 2, 2, "SHA mode : SHA384" 369b458cd62SJohnny Huang }, { 370b458cd62SJohnny Huang 0, 12, 2, 3, "SHA mode : SHA512" 371b458cd62SJohnny Huang }, { 372b458cd62SJohnny Huang 0, 14, 2, OTP_REG_RESERVED, "" 373b458cd62SJohnny Huang }, { 374b458cd62SJohnny Huang 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" 375b458cd62SJohnny Huang }, { 376b458cd62SJohnny Huang 0, 22, 1, 0, "Secure Region : Writable" 377b458cd62SJohnny Huang }, { 378b458cd62SJohnny Huang 0, 22, 1, 1, "Secure Region : Write Protect" 379b458cd62SJohnny Huang }, { 380b458cd62SJohnny Huang 0, 23, 1, 0, "User Region : Writable" 381b458cd62SJohnny Huang }, { 382b458cd62SJohnny Huang 0, 23, 1, 1, "User Region : Write Protect" 383b458cd62SJohnny Huang }, { 384b458cd62SJohnny Huang 0, 24, 1, 0, "Configure Region : Writable" 385b458cd62SJohnny Huang }, { 386b458cd62SJohnny Huang 0, 24, 1, 1, "Configure Region : Write Protect" 387b458cd62SJohnny Huang }, { 388b458cd62SJohnny Huang 0, 25, 1, 0, "OTP strap Region : Writable" 389b458cd62SJohnny Huang }, { 390b458cd62SJohnny Huang 0, 25, 1, 1, "OTP strap Region : Write Protect" 391b458cd62SJohnny Huang }, { 392b458cd62SJohnny Huang 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" 393b458cd62SJohnny Huang }, { 394b458cd62SJohnny Huang 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" 395b458cd62SJohnny Huang }, { 396b458cd62SJohnny Huang 0, 27, 1, 0, "Disable image encryption" 397b458cd62SJohnny Huang }, { 398b458cd62SJohnny Huang 0, 27, 1, 1, "Enable image encryption" 399b458cd62SJohnny Huang }, { 400b458cd62SJohnny Huang 0, 28, 1, OTP_REG_RESERVED, "" 401b458cd62SJohnny Huang }, { 402b458cd62SJohnny Huang 0, 29, 1, 0, "OTP key retire Region : Writable" 403b458cd62SJohnny Huang }, { 404b458cd62SJohnny Huang 0, 29, 1, 1, "OTP key retire Region : Write Protect" 405b458cd62SJohnny Huang }, { 406b458cd62SJohnny Huang 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" 407b458cd62SJohnny Huang }, { 408b458cd62SJohnny Huang 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" 409b458cd62SJohnny Huang }, { 410b458cd62SJohnny Huang 0, 31, 1, 0, "SIPROM Mlock memory lock disable" 411b458cd62SJohnny Huang }, { 412b458cd62SJohnny Huang 0, 31, 1, 1, "SIPROM Mlock memory lock enable" 413b458cd62SJohnny Huang }, { 414b458cd62SJohnny Huang 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" 415b458cd62SJohnny Huang }, { 416b458cd62SJohnny Huang 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" 417b458cd62SJohnny Huang }, { 418b458cd62SJohnny Huang 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" 419b458cd62SJohnny Huang }, { 420b458cd62SJohnny Huang 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %d" 421b458cd62SJohnny Huang }, { 422b458cd62SJohnny Huang 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %d" 423b458cd62SJohnny Huang }, { 424b458cd62SJohnny Huang 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" 425b458cd62SJohnny Huang }, { 426b458cd62SJohnny Huang 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" 427b458cd62SJohnny Huang }, { 428b458cd62SJohnny Huang 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" 429b458cd62SJohnny Huang }, { 430b458cd62SJohnny Huang 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" 431b458cd62SJohnny Huang }, { 432b458cd62SJohnny Huang 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" 433b458cd62SJohnny Huang } 434b458cd62SJohnny 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 691b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 69269d5fd8fSJohnny Huang { 693442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 694b458cd62SJohnny Huang uint32_t mask; 695b458cd62SJohnny Huang uint32_t dw_offset; 696b458cd62SJohnny Huang uint32_t bit_offset; 697b458cd62SJohnny Huang uint32_t otp_value; 698b458cd62SJohnny Huang uint32_t otp_keep; 699b458cd62SJohnny Huang int fail = 0; 700b458cd62SJohnny Huang int valid_bit = 0; 70166f2f8e5SJohnny Huang int i; 70266f2f8e5SJohnny Huang 703737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 70466f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 705b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 706b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 707b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 708b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 709b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 710b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 711b458cd62SJohnny Huang 712b458cd62SJohnny Huang if (otp_keep == mask) { 713b458cd62SJohnny Huang continue; 714b458cd62SJohnny Huang } else if (otp_keep != 0) { 715b458cd62SJohnny Huang fail = 1; 716b458cd62SJohnny Huang } 717b458cd62SJohnny Huang 718b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 719b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 720b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 721b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 722b458cd62SJohnny Huang continue; 723b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 724b458cd62SJohnny Huang 725b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 726b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 72766f2f8e5SJohnny Huang } else { 728b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 729b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 730b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 73166f2f8e5SJohnny Huang } 732b458cd62SJohnny Huang printf("0x%-10x", otp_value); 733b458cd62SJohnny Huang 734b458cd62SJohnny Huang if (fail) { 735b458cd62SJohnny Huang printf("Keep mask error\n"); 736b458cd62SJohnny Huang } else { 737b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 738b458cd62SJohnny Huang printf("Reserved\n"); 739b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 740b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 741b458cd62SJohnny Huang printf("\n"); 742b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 743b458cd62SJohnny Huang if (otp_value != 0) { 744b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 745b458cd62SJohnny Huang if (otp_value == (1 << i)) { 746b458cd62SJohnny Huang valid_bit = i + 1; 74766f2f8e5SJohnny Huang } 748b458cd62SJohnny Huang } 749b458cd62SJohnny Huang } else { 750b458cd62SJohnny Huang valid_bit = 0; 751b458cd62SJohnny Huang } 752b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 753b458cd62SJohnny Huang printf("\n"); 754b458cd62SJohnny Huang } else { 755b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 756b458cd62SJohnny Huang } 757b458cd62SJohnny Huang } 758b458cd62SJohnny Huang } 759b458cd62SJohnny Huang 760b458cd62SJohnny Huang if (fail) 761b458cd62SJohnny Huang return OTP_FAILURE; 762b458cd62SJohnny Huang 76366f2f8e5SJohnny Huang return OTP_SUCCESS; 76466f2f8e5SJohnny Huang } 76566f2f8e5SJohnny Huang 766*2d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 76766f2f8e5SJohnny Huang { 768b458cd62SJohnny Huang uint32_t OTPCFG[12]; 769b458cd62SJohnny Huang uint32_t mask; 770b458cd62SJohnny Huang uint32_t dw_offset; 771b458cd62SJohnny Huang uint32_t bit_offset; 772b458cd62SJohnny Huang uint32_t otp_value; 773b458cd62SJohnny 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 780b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 781b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 782b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 783*2d4b0742SJohnny Huang if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset) 784*2d4b0742SJohnny Huang continue; 785b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 786b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 787b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 788b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 789b458cd62SJohnny Huang 790b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 791b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 792b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 793b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 794b458cd62SJohnny Huang continue; 795b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 796b458cd62SJohnny Huang 797b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 798b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 799b458cd62SJohnny Huang } else { 800b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 801b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 802b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 803b458cd62SJohnny Huang } 804b458cd62SJohnny Huang printf("0x%-10x", otp_value); 805b458cd62SJohnny Huang 806b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 807b458cd62SJohnny Huang printf("Reserved\n"); 808b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 809b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 810b458cd62SJohnny Huang printf("\n"); 811b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 812b458cd62SJohnny Huang if (otp_value != 0) { 813b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 814b458cd62SJohnny Huang if (otp_value == (1 << i)) { 815b458cd62SJohnny Huang valid_bit = i + 1; 816b458cd62SJohnny Huang } 817b458cd62SJohnny Huang } 818b458cd62SJohnny Huang } else { 819b458cd62SJohnny Huang valid_bit = 0; 820b458cd62SJohnny Huang } 821b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 822b458cd62SJohnny Huang printf("\n"); 823b458cd62SJohnny Huang } else { 824b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 825b458cd62SJohnny Huang } 826b458cd62SJohnny Huang } 827b458cd62SJohnny Huang return OTP_SUCCESS; 82866f2f8e5SJohnny Huang } 82966f2f8e5SJohnny Huang 830b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 83176d13988SJohnny Huang { 832a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 833a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 83476d13988SJohnny Huang int i; 835a8bd6d8cSJohnny Huang int fail = 0; 836a8bd6d8cSJohnny Huang uint32_t bit_offset; 837a8bd6d8cSJohnny Huang uint32_t dw_offset; 838a8bd6d8cSJohnny Huang uint32_t mask; 839a8bd6d8cSJohnny Huang uint32_t otp_value; 840a8bd6d8cSJohnny Huang uint32_t otp_protect; 841a8bd6d8cSJohnny Huang uint32_t otp_keep; 84276d13988SJohnny Huang 843a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 844a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 845b458cd62SJohnny Huang 846a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 847a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 848a8bd6d8cSJohnny Huang dw_offset = 1; 849a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 850a8bd6d8cSJohnny Huang } else { 851a8bd6d8cSJohnny Huang dw_offset = 0; 852a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 853a8bd6d8cSJohnny Huang } 85476d13988SJohnny Huang 855a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 856a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 857a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 858a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 859a8bd6d8cSJohnny Huang 860a8bd6d8cSJohnny Huang if (otp_keep == mask) { 861a8bd6d8cSJohnny Huang continue; 862a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 863a8bd6d8cSJohnny Huang fail = 1; 864a8bd6d8cSJohnny Huang } 865a8bd6d8cSJohnny Huang 866a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 867a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 868a8bd6d8cSJohnny Huang continue; 869a8bd6d8cSJohnny Huang 870a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 871b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 872a8bd6d8cSJohnny Huang } else { 873b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 874a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 875a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 876a8bd6d8cSJohnny Huang } 877a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 878a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 879a8bd6d8cSJohnny Huang 880a8bd6d8cSJohnny Huang if (fail) { 881a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 882a8bd6d8cSJohnny Huang } else { 883a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 884a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 885a8bd6d8cSJohnny Huang else 886a8bd6d8cSJohnny Huang printf("Reserved\n"); 887a8bd6d8cSJohnny Huang } 888a8bd6d8cSJohnny Huang } 889a8bd6d8cSJohnny Huang 890a8bd6d8cSJohnny Huang if (fail) 89176d13988SJohnny Huang return OTP_FAILURE; 89276d13988SJohnny Huang 89376d13988SJohnny Huang return OTP_SUCCESS; 89476d13988SJohnny Huang } 89576d13988SJohnny Huang 896b458cd62SJohnny Huang static int otp_print_strap_info(int view) 89776d13988SJohnny Huang { 89876d13988SJohnny Huang struct otpstrap_status strap_status[64]; 899b458cd62SJohnny Huang int i, j, k; 900b458cd62SJohnny Huang int fail = 0; 901b458cd62SJohnny Huang uint32_t bit_offset; 902b458cd62SJohnny Huang uint32_t length; 903b458cd62SJohnny Huang uint32_t otp_value; 904b458cd62SJohnny Huang uint32_t otp_protect; 90576d13988SJohnny Huang 90676d13988SJohnny Huang otp_strp_status(strap_status); 90776d13988SJohnny Huang 908b458cd62SJohnny Huang if (view) { 909b458cd62SJohnny Huang printf("BIT(hex) Value Option Protect Description\n"); 910b458cd62SJohnny Huang printf(" 0 1 2 3 4 5 6\n"); 911b458cd62SJohnny Huang printf("_________________________________________________________________________________________________________\n"); 912b458cd62SJohnny Huang } else { 913b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 914b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 91576d13988SJohnny Huang } 916b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 917b458cd62SJohnny Huang otp_value = 0; 918b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 919b458cd62SJohnny Huang length = a0_strap_info[i].length; 920b458cd62SJohnny Huang for (j = 0; j < length; j++) { 921b458cd62SJohnny Huang otp_value |= strap_status[bit_offset].value << j; 922b458cd62SJohnny Huang otp_protect |= strap_status[bit_offset].protected << j; 923b458cd62SJohnny Huang } 924b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 925b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 926b458cd62SJohnny Huang continue; 927b458cd62SJohnny Huang if (view) { 928b458cd62SJohnny Huang for (j = 0; j < length; j++) { 929b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 930b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 931b458cd62SJohnny Huang for (k = 0; k < 7; k++) { 932b458cd62SJohnny Huang printf("%X ", strap_status[bit_offset + j].option_array[k]); 933b458cd62SJohnny Huang } 934b458cd62SJohnny Huang printf(" "); 935b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 936b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 937b458cd62SJohnny Huang printf(" Reserved\n"); 938b458cd62SJohnny Huang continue; 939b458cd62SJohnny Huang } 940b458cd62SJohnny Huang if (length == 1) { 941b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 942b458cd62SJohnny Huang continue; 94376d13988SJohnny Huang } 94476d13988SJohnny Huang 945b458cd62SJohnny Huang if (j == 0) 946b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 947b458cd62SJohnny Huang else if (j == length - 1) 948b458cd62SJohnny Huang printf("\\ \"\n"); 949b458cd62SJohnny Huang else 950b458cd62SJohnny Huang printf("| \"\n"); 95176d13988SJohnny Huang } 952b458cd62SJohnny Huang } else { 953b458cd62SJohnny Huang if (a0_strap_info[i].length == 1) { 954b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 955b458cd62SJohnny Huang } else { 956b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 957b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 958b458cd62SJohnny Huang } 959b458cd62SJohnny Huang 960b458cd62SJohnny Huang printf("0x%-10X", otp_value); 961b458cd62SJohnny Huang 962b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 963b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 964b458cd62SJohnny Huang else 965b458cd62SJohnny Huang printf("Reserved\n"); 966b458cd62SJohnny Huang } 967b458cd62SJohnny Huang } 968b458cd62SJohnny Huang 969b458cd62SJohnny Huang if (fail) 970b458cd62SJohnny Huang return OTP_FAILURE; 971b458cd62SJohnny Huang 972b458cd62SJohnny Huang return OTP_SUCCESS; 973b458cd62SJohnny Huang } 974b458cd62SJohnny Huang 975b458cd62SJohnny Huang // static void otp_info_strap(int view) 976b458cd62SJohnny Huang // { 977b458cd62SJohnny Huang // struct otpstrap_status strap_status[64]; 978b458cd62SJohnny Huang // uint32_t OTPSTRAP[6]; 979b458cd62SJohnny Huang // int i; 980b458cd62SJohnny Huang 981b458cd62SJohnny Huang 982b458cd62SJohnny Huang // otp_strp_status(strap_status); 983b458cd62SJohnny Huang 984b458cd62SJohnny Huang // for (i = 0; i < 6; i++) 985b458cd62SJohnny Huang // OTPSTRAP[i] = 0; 986b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 987b458cd62SJohnny Huang // OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i; 988b458cd62SJohnny Huang // OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i; 989b458cd62SJohnny Huang // } 990b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 991b458cd62SJohnny Huang // OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i; 992b458cd62SJohnny Huang // OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i; 993b458cd62SJohnny Huang // } 994b458cd62SJohnny Huang 995b458cd62SJohnny Huang // otp_print_strap_info(OTPSTRAP, view); 996b458cd62SJohnny Huang // } 99776d13988SJohnny Huang 99869d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 99969d5fd8fSJohnny Huang { 100069d5fd8fSJohnny Huang int i; 100169d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 100269d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 100369d5fd8fSJohnny Huang if (i % 16 == 0) { 100469d5fd8fSJohnny Huang printf("%04X: ", i); 100569d5fd8fSJohnny Huang } 100669d5fd8fSJohnny Huang printf("%02X ", buf[i]); 100769d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 100869d5fd8fSJohnny Huang printf("\n"); 100969d5fd8fSJohnny Huang } 101069d5fd8fSJohnny Huang } 101169d5fd8fSJohnny Huang } 101269d5fd8fSJohnny Huang 10137f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 101469d5fd8fSJohnny Huang { 101569d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 101669d5fd8fSJohnny Huang char *byte_buf; 101769d5fd8fSJohnny Huang int i = 0, len = 0; 101869d5fd8fSJohnny Huang byte_buf = (char *)buf; 101969d5fd8fSJohnny Huang while (1) { 102069d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 102169d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 102269d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 102369d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 102469d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 102569d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 10267f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 102769d5fd8fSJohnny Huang printf("Key Type: "); 102869d5fd8fSJohnny Huang switch (key_type) { 102969d5fd8fSJohnny Huang case 0: 103069d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 103169d5fd8fSJohnny Huang break; 103269d5fd8fSJohnny Huang case 1: 103369d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 103469d5fd8fSJohnny Huang break; 103569d5fd8fSJohnny Huang case 4: 103669d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 103769d5fd8fSJohnny Huang break; 103869d5fd8fSJohnny Huang case 8: 103969d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 104069d5fd8fSJohnny Huang break; 104169d5fd8fSJohnny Huang case 9: 104269d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 104369d5fd8fSJohnny Huang break; 104469d5fd8fSJohnny Huang case 10: 104569d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 104669d5fd8fSJohnny Huang break; 104769d5fd8fSJohnny Huang case 13: 104869d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 104969d5fd8fSJohnny Huang break; 105069d5fd8fSJohnny Huang case 14: 105169d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 105269d5fd8fSJohnny Huang break; 105369d5fd8fSJohnny Huang default: 105469d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 105569d5fd8fSJohnny Huang return -1; 105669d5fd8fSJohnny Huang } 105769d5fd8fSJohnny Huang if (key_type == 4) { 105869d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 105969d5fd8fSJohnny Huang switch (key_length) { 106069d5fd8fSJohnny Huang case 0: 106169d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 106269d5fd8fSJohnny Huang break; 106369d5fd8fSJohnny Huang case 1: 106469d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 106569d5fd8fSJohnny Huang break; 106669d5fd8fSJohnny Huang case 2: 106769d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 106869d5fd8fSJohnny Huang break; 106969d5fd8fSJohnny Huang case 3: 107069d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 107169d5fd8fSJohnny Huang break; 107269d5fd8fSJohnny Huang } 1073cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 107469d5fd8fSJohnny Huang printf("RSA SHA Type: "); 107569d5fd8fSJohnny Huang switch (key_length) { 107669d5fd8fSJohnny Huang case 0: 107769d5fd8fSJohnny Huang printf("RSA1024\n"); 107869d5fd8fSJohnny Huang len = 0x100; 107969d5fd8fSJohnny Huang break; 108069d5fd8fSJohnny Huang case 1: 108169d5fd8fSJohnny Huang printf("RSA2048\n"); 108269d5fd8fSJohnny Huang len = 0x200; 108369d5fd8fSJohnny Huang break; 108469d5fd8fSJohnny Huang case 2: 108569d5fd8fSJohnny Huang printf("RSA3072\n"); 108669d5fd8fSJohnny Huang len = 0x300; 108769d5fd8fSJohnny Huang break; 108869d5fd8fSJohnny Huang case 3: 108969d5fd8fSJohnny Huang printf("RSA4096\n"); 109069d5fd8fSJohnny Huang len = 0x400; 109169d5fd8fSJohnny Huang break; 109269d5fd8fSJohnny Huang } 109369d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 109469d5fd8fSJohnny Huang } 109569d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 109669d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 109769d5fd8fSJohnny Huang printf("Key Value:\n"); 109869d5fd8fSJohnny Huang if (key_type == 4) { 109969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 110069d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 110169d5fd8fSJohnny Huang printf("AES Key:\n"); 110269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 110369d5fd8fSJohnny Huang printf("AES IV:\n"); 110469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 110569d5fd8fSJohnny Huang 110669d5fd8fSJohnny Huang } else { 110769d5fd8fSJohnny Huang printf("RSA mod:\n"); 110869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 110969d5fd8fSJohnny Huang printf("RSA exp:\n"); 111069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 111169d5fd8fSJohnny Huang } 111269d5fd8fSJohnny Huang if (last) 111369d5fd8fSJohnny Huang break; 111469d5fd8fSJohnny Huang i++; 111569d5fd8fSJohnny Huang } 111669d5fd8fSJohnny Huang return 0; 111769d5fd8fSJohnny Huang } 111869d5fd8fSJohnny Huang 1119a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 112069d5fd8fSJohnny Huang { 1121a6d0d645SJohnny Huang int i, k; 1122d90825e2SJohnny Huang int pass = 0; 1123d90825e2SJohnny Huang int soak = 0; 1124a6d0d645SJohnny Huang uint32_t prog_address; 1125a6d0d645SJohnny Huang uint32_t data[12]; 1126a6d0d645SJohnny Huang uint32_t compare[2]; 1127d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1128d90825e2SJohnny Huang uint32_t data_masked; 1129d90825e2SJohnny Huang uint32_t buf_masked; 113069d5fd8fSJohnny Huang 1131a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1132a6d0d645SJohnny Huang 1133a6d0d645SJohnny Huang printProgress(0, 12, ""); 1134a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1135a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 113669d5fd8fSJohnny Huang prog_address = 0x800; 1137a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1138a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1139a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1140a6d0d645SJohnny Huang } 1141a6d0d645SJohnny Huang 1142a6d0d645SJohnny Huang printf("Check writable...\n"); 1143a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1144d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1145d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1146d90825e2SJohnny Huang if (data_masked == buf_masked) 114769d5fd8fSJohnny Huang continue; 1148d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1149a6d0d645SJohnny Huang continue; 1150a6d0d645SJohnny Huang } else { 1151a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1152a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1153a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1154a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 11552a856b9aSJohnny Huang return OTP_FAILURE; 1156a6d0d645SJohnny Huang } 1157a6d0d645SJohnny Huang } 1158a6d0d645SJohnny Huang 1159a6d0d645SJohnny Huang printf("Start Programing...\n"); 1160a6d0d645SJohnny Huang printProgress(0, 12, ""); 1161d90825e2SJohnny Huang otp_soak(0); 1162a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1163d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1164d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1165a6d0d645SJohnny Huang prog_address = 0x800; 1166a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1167a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1168d90825e2SJohnny Huang if (data_masked == buf_masked) { 1169a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1170a6d0d645SJohnny Huang continue; 1171a6d0d645SJohnny Huang } 1172d90825e2SJohnny Huang if (soak) { 1173d90825e2SJohnny Huang soak = 0; 1174d90825e2SJohnny Huang otp_soak(0); 1175d90825e2SJohnny Huang } 1176a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1177a6d0d645SJohnny Huang 1178d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1179a6d0d645SJohnny Huang 118069d5fd8fSJohnny Huang pass = 0; 118169d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1182d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1183d90825e2SJohnny Huang if (soak == 0) { 1184d90825e2SJohnny Huang soak = 1; 1185d90825e2SJohnny Huang otp_soak(1); 1186d90825e2SJohnny Huang } 1187a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1188a6d0d645SJohnny Huang } else { 118969d5fd8fSJohnny Huang pass = 1; 119069d5fd8fSJohnny Huang break; 119169d5fd8fSJohnny Huang } 119269d5fd8fSJohnny Huang } 1193a6d0d645SJohnny Huang } 1194a6d0d645SJohnny Huang 119569d5fd8fSJohnny Huang if (!pass) 11962a856b9aSJohnny Huang return OTP_FAILURE; 1197a6d0d645SJohnny Huang 11982a856b9aSJohnny Huang return OTP_SUCCESS; 1199d90825e2SJohnny Huang 120069d5fd8fSJohnny Huang } 120169d5fd8fSJohnny Huang 120269d5fd8fSJohnny Huang 120376d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 120469d5fd8fSJohnny Huang { 120569d5fd8fSJohnny Huang int i; 120669d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 120769d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 120869d5fd8fSJohnny Huang int bit, pbit, kbit; 120969d5fd8fSJohnny Huang int fail = 0; 1210a6af4a17SJohnny Huang int skip = -1; 121166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 121269d5fd8fSJohnny Huang 121369d5fd8fSJohnny Huang otp_strp_status(otpstrap); 121469d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 121569d5fd8fSJohnny Huang if (i < 32) { 121669d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 121769d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 121869d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 121969d5fd8fSJohnny Huang } else { 122069d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 122169d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 122269d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 122369d5fd8fSJohnny Huang } 122469d5fd8fSJohnny Huang 122569d5fd8fSJohnny Huang if (kbit == 1) { 122669d5fd8fSJohnny Huang continue; 122769d5fd8fSJohnny Huang } else { 1228a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 122969d5fd8fSJohnny Huang } 123069d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 123169d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1232a6af4a17SJohnny Huang if (skip == -1) 1233a6af4a17SJohnny Huang skip = 1; 123469d5fd8fSJohnny Huang continue; 1235a6af4a17SJohnny Huang } else { 1236a6af4a17SJohnny Huang skip = 0; 123769d5fd8fSJohnny Huang } 123869d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 123969d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 124069d5fd8fSJohnny Huang fail = 1; 124169d5fd8fSJohnny Huang continue; 124269d5fd8fSJohnny Huang } 124369d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1244a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 124569d5fd8fSJohnny Huang fail = 1; 124669d5fd8fSJohnny Huang continue; 124769d5fd8fSJohnny Huang } 124869d5fd8fSJohnny Huang if (pbit == 1) { 124969d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 125069d5fd8fSJohnny Huang } 1251a6af4a17SJohnny 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); 125269d5fd8fSJohnny Huang } 125369d5fd8fSJohnny Huang if (fail == 1) 1254a6af4a17SJohnny Huang return OTP_FAILURE; 1255a6af4a17SJohnny Huang else if (skip == 1) 1256a6af4a17SJohnny Huang return OTP_PROG_SKIP; 12577e22f42dSJohnny Huang 12587e22f42dSJohnny Huang return 0; 125969d5fd8fSJohnny Huang } 126069d5fd8fSJohnny Huang 12612a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 126269d5fd8fSJohnny Huang { 126369d5fd8fSJohnny Huang int i, j; 126466f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 126569d5fd8fSJohnny Huang 12662a856b9aSJohnny Huang if (start < 0 || start > 64) 12672a856b9aSJohnny Huang return OTP_USAGE; 12682a856b9aSJohnny Huang 12692a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 12702a856b9aSJohnny Huang return OTP_USAGE; 12712a856b9aSJohnny Huang 127269d5fd8fSJohnny Huang otp_strp_status(otpstrap); 127369d5fd8fSJohnny Huang 1274a8bd6d8cSJohnny Huang printf("BIT(hex) Value Avaliable Status\n"); 1275a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1276737ed20bSJohnny Huang 1277cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 1278a8bd6d8cSJohnny Huang printf("%-10X", i); 1279737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1280737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1281737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1282737ed20bSJohnny Huang printf(" "); 128369d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1284737ed20bSJohnny Huang printf("protected and not writable"); 128569d5fd8fSJohnny Huang } else { 1286737ed20bSJohnny Huang printf("not protected "); 128769d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1288737ed20bSJohnny Huang printf("and no remaining times to write."); 128969d5fd8fSJohnny Huang } else { 1290737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 129169d5fd8fSJohnny Huang } 129269d5fd8fSJohnny Huang } 1293737ed20bSJohnny Huang printf("\n"); 129469d5fd8fSJohnny Huang } 12952a856b9aSJohnny Huang 12962a856b9aSJohnny Huang return OTP_SUCCESS; 129769d5fd8fSJohnny Huang } 129869d5fd8fSJohnny Huang 129969d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 130069d5fd8fSJohnny Huang { 130169d5fd8fSJohnny Huang int i, j; 130269d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 130369d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 130469d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 130569d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 130669d5fd8fSJohnny Huang int fail = 0; 13077e22f42dSJohnny Huang int pass = 0; 13087e22f42dSJohnny Huang int soak = 0; 130966f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 131069d5fd8fSJohnny Huang 13117f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 131269d5fd8fSJohnny Huang otp_strp_status(otpstrap); 131369d5fd8fSJohnny Huang 13147f795e57SJohnny Huang printf("Check writable...\n"); 13157f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 13167f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 13177f795e57SJohnny Huang return OTP_FAILURE; 13187f795e57SJohnny Huang } 13197e22f42dSJohnny Huang 13207f795e57SJohnny Huang otp_soak(0); 132169d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 13224c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 132369d5fd8fSJohnny Huang prog_address = 0x800; 132469d5fd8fSJohnny Huang if (i < 32) { 132569d5fd8fSJohnny Huang offset = i; 132669d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 132769d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 132869d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 132969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 133069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 133169d5fd8fSJohnny Huang 133269d5fd8fSJohnny Huang } else { 133369d5fd8fSJohnny Huang offset = (i - 32); 133469d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 133569d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 133669d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 133769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 133869d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 133969d5fd8fSJohnny Huang } 134069d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 134169d5fd8fSJohnny Huang 134269d5fd8fSJohnny Huang if (kbit == 1) { 134369d5fd8fSJohnny Huang continue; 134469d5fd8fSJohnny Huang } 134569d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 134669d5fd8fSJohnny Huang continue; 134769d5fd8fSJohnny Huang } 134869d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 134969d5fd8fSJohnny Huang fail = 1; 135069d5fd8fSJohnny Huang continue; 135169d5fd8fSJohnny Huang } 135269d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 135369d5fd8fSJohnny Huang fail = 1; 135469d5fd8fSJohnny Huang continue; 135569d5fd8fSJohnny Huang } 13567e22f42dSJohnny Huang 13577e22f42dSJohnny Huang if (soak) { 135869d5fd8fSJohnny Huang soak = 0; 13597e22f42dSJohnny Huang otp_soak(0); 13607e22f42dSJohnny Huang } 13617e22f42dSJohnny Huang 13627e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 13637e22f42dSJohnny Huang 13647e22f42dSJohnny Huang pass = 0; 13657e22f42dSJohnny Huang 136669d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1367a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 136869d5fd8fSJohnny Huang pass = 1; 136969d5fd8fSJohnny Huang break; 137069d5fd8fSJohnny Huang } 13717e22f42dSJohnny Huang if (soak == 0) { 137269d5fd8fSJohnny Huang soak = 1; 13737e22f42dSJohnny Huang otp_soak(1); 13744b65a65dSJohnny Huang } 137569d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 137669d5fd8fSJohnny Huang } 137769d5fd8fSJohnny Huang if (!pass) 13782a856b9aSJohnny Huang return OTP_FAILURE; 137969d5fd8fSJohnny Huang 138069d5fd8fSJohnny Huang if (pbit == 0) 138169d5fd8fSJohnny Huang continue; 138269d5fd8fSJohnny Huang prog_address = 0x800; 138369d5fd8fSJohnny Huang if (i < 32) 138469d5fd8fSJohnny Huang prog_address |= 0x60c; 138569d5fd8fSJohnny Huang else 138669d5fd8fSJohnny Huang prog_address |= 0x60e; 138769d5fd8fSJohnny Huang 13887e22f42dSJohnny Huang 13897e22f42dSJohnny Huang if (soak) { 13907e22f42dSJohnny Huang soak = 0; 13917e22f42dSJohnny Huang otp_soak(0); 13927e22f42dSJohnny Huang } 13937e22f42dSJohnny Huang 13947e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 13957e22f42dSJohnny Huang 13967e22f42dSJohnny Huang pass = 0; 13977e22f42dSJohnny Huang 139869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 13997e22f42dSJohnny Huang 1400a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 140169d5fd8fSJohnny Huang pass = 1; 140269d5fd8fSJohnny Huang break; 140369d5fd8fSJohnny Huang } 14047e22f42dSJohnny Huang if (soak == 0) { 140569d5fd8fSJohnny Huang soak = 1; 14067e22f42dSJohnny Huang otp_soak(1); 140769d5fd8fSJohnny Huang } 140869d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 140969d5fd8fSJohnny Huang } 141069d5fd8fSJohnny Huang if (!pass) 14112a856b9aSJohnny Huang return OTP_FAILURE; 141269d5fd8fSJohnny Huang 141369d5fd8fSJohnny Huang } 141469d5fd8fSJohnny Huang if (fail == 1) 14152a856b9aSJohnny Huang return OTP_FAILURE; 141669d5fd8fSJohnny Huang else 14172a856b9aSJohnny Huang return OTP_SUCCESS; 141869d5fd8fSJohnny Huang 141969d5fd8fSJohnny Huang } 142069d5fd8fSJohnny Huang 1421cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1422cd1610b4SJohnny Huang { 1423cd1610b4SJohnny Huang int prog_bit; 1424cd1610b4SJohnny Huang 14257e22f42dSJohnny Huang otp_soak(soak); 14267e22f42dSJohnny Huang 1427cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1428cd1610b4SJohnny Huang if (value) 1429cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1430cd1610b4SJohnny Huang else 1431cd1610b4SJohnny Huang return; 1432cd1610b4SJohnny Huang } else { 1433cd1610b4SJohnny Huang prog_address |= 1 << 15; 1434cd1610b4SJohnny Huang if (!value) 1435cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1436cd1610b4SJohnny Huang else 1437cd1610b4SJohnny Huang return; 1438cd1610b4SJohnny Huang } 1439cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1440cd1610b4SJohnny Huang } 1441cd1610b4SJohnny Huang 1442d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 14434c1c9b35SJohnny Huang { 14444c1c9b35SJohnny Huang int i, k; 14454c1c9b35SJohnny Huang int pass; 1446d90825e2SJohnny Huang int soak = 0; 14474c1c9b35SJohnny Huang uint32_t prog_address; 1448d90825e2SJohnny Huang uint32_t data[2048]; 14494c1c9b35SJohnny Huang uint32_t compare[2]; 1450d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 14514c1c9b35SJohnny Huang 1452d90825e2SJohnny Huang uint32_t data0_masked; 1453d90825e2SJohnny Huang uint32_t data1_masked; 1454d90825e2SJohnny Huang uint32_t buf0_masked; 1455d90825e2SJohnny Huang uint32_t buf1_masked; 14564c1c9b35SJohnny Huang 14574c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 14584c1c9b35SJohnny Huang 1459d90825e2SJohnny Huang printProgress(0, 2048, ""); 1460d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1461d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1462d90825e2SJohnny Huang otp_read_data(i, &data[i]); 14634c1c9b35SJohnny Huang } 1464d90825e2SJohnny Huang 14654c1c9b35SJohnny Huang 14664c1c9b35SJohnny Huang printf("Check writable...\n"); 1467d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1468d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1469d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1470d90825e2SJohnny Huang if (data0_masked == buf0_masked) 14714c1c9b35SJohnny Huang continue; 1472d90825e2SJohnny Huang if (i % 2 == 0) { 1473d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 14744c1c9b35SJohnny Huang continue; 14754c1c9b35SJohnny Huang } else { 14764c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1477d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 14784c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1479d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 14802a856b9aSJohnny Huang return OTP_FAILURE; 148169d5fd8fSJohnny Huang } 1482d90825e2SJohnny Huang } else { 1483d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1484d90825e2SJohnny Huang continue; 1485d90825e2SJohnny Huang } else { 1486d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1487d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1488d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1489d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 14902a856b9aSJohnny Huang return OTP_FAILURE; 1491d90825e2SJohnny Huang } 1492d90825e2SJohnny Huang } 1493d90825e2SJohnny Huang } 149469d5fd8fSJohnny Huang 1495d90825e2SJohnny Huang printf("Start Programing...\n"); 1496d90825e2SJohnny Huang printProgress(0, 2048, ""); 1497d90825e2SJohnny Huang 1498d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1499d90825e2SJohnny Huang prog_address = i; 1500d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1501d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1502d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1503d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1504d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1505d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1506d90825e2SJohnny Huang continue; 1507d90825e2SJohnny Huang } 1508d90825e2SJohnny Huang if (soak) { 1509d90825e2SJohnny Huang soak = 0; 1510d90825e2SJohnny Huang otp_soak(0); 1511d90825e2SJohnny Huang } 1512d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1513d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1514d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1515d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1516d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1517d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1518d90825e2SJohnny Huang } else { 1519d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1520d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1521d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1522d90825e2SJohnny Huang } 1523d90825e2SJohnny Huang 1524d90825e2SJohnny Huang pass = 0; 1525d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1526d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1527d90825e2SJohnny Huang if (soak == 0) { 1528d90825e2SJohnny Huang soak = 1; 1529d90825e2SJohnny Huang otp_soak(1); 1530d90825e2SJohnny Huang } 1531d90825e2SJohnny Huang if (compare[0] != 0) { 1532d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1533d90825e2SJohnny Huang } 1534d90825e2SJohnny Huang if (compare[1] != ~0) { 1535d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1536d90825e2SJohnny Huang } 1537d90825e2SJohnny Huang } else { 1538d90825e2SJohnny Huang pass = 1; 1539d90825e2SJohnny Huang break; 1540d90825e2SJohnny Huang } 1541d90825e2SJohnny Huang } 1542d90825e2SJohnny Huang 1543d90825e2SJohnny Huang if (!pass) 15442a856b9aSJohnny Huang return OTP_FAILURE; 1545d90825e2SJohnny Huang } 15462a856b9aSJohnny Huang return OTP_SUCCESS; 1547d90825e2SJohnny Huang 1548d90825e2SJohnny Huang } 1549d90825e2SJohnny Huang 1550d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 155169d5fd8fSJohnny Huang { 155269d5fd8fSJohnny Huang int ret; 1553d90825e2SJohnny Huang int mode; 155469d5fd8fSJohnny Huang uint32_t *buf; 1555d90825e2SJohnny Huang uint32_t *data_region = NULL; 1556d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1557d90825e2SJohnny Huang uint32_t *strap_region = NULL; 155869d5fd8fSJohnny Huang 1559d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 156069d5fd8fSJohnny Huang if (!buf) { 156169d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 15622a856b9aSJohnny Huang return OTP_FAILURE; 156369d5fd8fSJohnny Huang } 1564d90825e2SJohnny Huang 1565d90825e2SJohnny Huang if (((buf[0] >> 29) & 0x7) == 0x7) { 1566d90825e2SJohnny Huang mode = OTP_REGION_ALL; 1567d90825e2SJohnny Huang conf_region = &buf[1]; 1568d90825e2SJohnny Huang strap_region = &buf[25]; 1569d90825e2SJohnny Huang data_region = &buf[31]; 1570d90825e2SJohnny Huang } else { 1571d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 1572d90825e2SJohnny Huang mode = OTP_REGION_DATA; 1573d90825e2SJohnny Huang data_region = &buf[31]; 1574d90825e2SJohnny Huang } 1575d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 1576d90825e2SJohnny Huang mode = OTP_REGION_CONF; 1577d90825e2SJohnny Huang strap_region = &buf[25]; 1578d90825e2SJohnny Huang } 1579d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 1580d90825e2SJohnny Huang mode = OTP_REGION_STRAP; 1581d90825e2SJohnny Huang conf_region = &buf[1]; 1582d90825e2SJohnny Huang } 1583d90825e2SJohnny Huang } 158469d5fd8fSJohnny Huang if (!nconfirm) { 1585a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 15867f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1587b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 158869d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 15892a856b9aSJohnny Huang return OTP_FAILURE; 159069d5fd8fSJohnny Huang } 1591a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 15927f795e57SJohnny Huang printf("\nOTP data region :\n"); 15937f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 159469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 15952a856b9aSJohnny Huang return OTP_FAILURE; 159669d5fd8fSJohnny Huang } 1597a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 15987f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1599b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 160069d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 16012a856b9aSJohnny Huang return OTP_FAILURE; 160269d5fd8fSJohnny Huang } 1603a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 16047f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1605b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 160669d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 16072a856b9aSJohnny Huang return OTP_FAILURE; 160869d5fd8fSJohnny Huang } 16097f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1610b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 161169d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 16122a856b9aSJohnny Huang return OTP_FAILURE; 161369d5fd8fSJohnny Huang } 16147f795e57SJohnny Huang printf("\nOTP data region :\n"); 16157f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 161669d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16172a856b9aSJohnny Huang return OTP_FAILURE; 161869d5fd8fSJohnny Huang } 161969d5fd8fSJohnny Huang } 162069d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 162169d5fd8fSJohnny Huang if (!confirm_yesno()) { 162269d5fd8fSJohnny Huang printf(" Aborting\n"); 16232a856b9aSJohnny Huang return OTP_FAILURE; 162469d5fd8fSJohnny Huang } 162569d5fd8fSJohnny Huang } 1626a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 1627d90825e2SJohnny Huang return otp_prog_conf(conf_region); 1628a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 1629d90825e2SJohnny Huang return otp_prog_strap(strap_region); 1630a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 1631d90825e2SJohnny Huang return otp_prog_data(data_region); 1632a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 163369d5fd8fSJohnny Huang printf("programing data region ... "); 1634d90825e2SJohnny Huang ret = otp_prog_data(data_region); 16352a856b9aSJohnny Huang if (ret != 0) { 163669d5fd8fSJohnny Huang printf("Error\n"); 163769d5fd8fSJohnny Huang return ret; 163869d5fd8fSJohnny Huang } else { 163969d5fd8fSJohnny Huang printf("Done\n"); 164069d5fd8fSJohnny Huang } 164169d5fd8fSJohnny Huang printf("programing strap region ... "); 1642d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 16432a856b9aSJohnny Huang if (ret != 0) { 164469d5fd8fSJohnny Huang printf("Error\n"); 164569d5fd8fSJohnny Huang return ret; 164669d5fd8fSJohnny Huang } else { 164769d5fd8fSJohnny Huang printf("Done\n"); 164869d5fd8fSJohnny Huang } 164969d5fd8fSJohnny Huang printf("programing configuration region ... "); 1650d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 16512a856b9aSJohnny Huang if (ret != 0) { 165269d5fd8fSJohnny Huang printf("Error\n"); 165369d5fd8fSJohnny Huang return ret; 165469d5fd8fSJohnny Huang } 165569d5fd8fSJohnny Huang printf("Done\n"); 16562a856b9aSJohnny Huang return OTP_SUCCESS; 165769d5fd8fSJohnny Huang } 1658cd1610b4SJohnny Huang 16592a856b9aSJohnny Huang return OTP_USAGE; 16602a856b9aSJohnny Huang } 16612a856b9aSJohnny Huang 16622a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1663cd1610b4SJohnny Huang { 1664a6af4a17SJohnny Huang uint32_t read[2]; 1665cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1666d90825e2SJohnny Huang uint32_t prog_address = 0; 166766f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1668cd1610b4SJohnny Huang int otp_bit; 1669cd1610b4SJohnny Huang int i; 1670cd1610b4SJohnny Huang int pass; 1671a6af4a17SJohnny Huang int ret; 1672cd1610b4SJohnny Huang 1673cd1610b4SJohnny Huang switch (mode) { 1674a6d0d645SJohnny Huang case OTP_REGION_CONF: 1675a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1676cd1610b4SJohnny Huang prog_address = 0x800; 1677cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1678cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1679a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1680cd1610b4SJohnny Huang if (otp_bit == value) { 1681a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1682cd1610b4SJohnny Huang printf("No need to program\n"); 16832a856b9aSJohnny Huang return OTP_SUCCESS; 1684cd1610b4SJohnny Huang } 1685cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1686a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1687cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 16882a856b9aSJohnny Huang return OTP_FAILURE; 1689cd1610b4SJohnny Huang } 1690a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1691cd1610b4SJohnny Huang break; 1692a6d0d645SJohnny Huang case OTP_REGION_DATA: 1693cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1694cd1610b4SJohnny Huang 1695cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1696a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1697a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1698cd1610b4SJohnny Huang } else { 1699a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1700a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1701cd1610b4SJohnny Huang } 1702cd1610b4SJohnny Huang if (otp_bit == value) { 1703a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1704cd1610b4SJohnny Huang printf("No need to program\n"); 17052a856b9aSJohnny Huang return OTP_SUCCESS; 1706cd1610b4SJohnny Huang } 1707cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1708a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1709cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17102a856b9aSJohnny Huang return OTP_FAILURE; 1711cd1610b4SJohnny Huang } 1712a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1713cd1610b4SJohnny Huang break; 1714a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1715cd1610b4SJohnny Huang otp_strp_status(otpstrap); 1716cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1717cd1610b4SJohnny Huang if (bit_offset < 32) { 1718cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1719cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1720cd1610b4SJohnny Huang strap_buf[3] = ~0; 1721cd1610b4SJohnny Huang strap_buf[5] = 0; 17222a856b9aSJohnny Huang // if (protect) 17232a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 17242a856b9aSJohnny Huang // else 17252a856b9aSJohnny Huang // strap_buf[4] = 0; 1726cd1610b4SJohnny Huang } else { 1727cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1728cd1610b4SJohnny Huang strap_buf[2] = ~0; 1729cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1730cd1610b4SJohnny Huang strap_buf[4] = 0; 17312a856b9aSJohnny Huang // if (protect) 17322a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 17332a856b9aSJohnny Huang // else 17342a856b9aSJohnny Huang // strap_buf[5] = 0; 1735cd1610b4SJohnny Huang } 173676d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1737a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 17382a856b9aSJohnny Huang return OTP_FAILURE; 1739a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1740a6af4a17SJohnny Huang return OTP_SUCCESS; 1741a6af4a17SJohnny Huang 1742cd1610b4SJohnny Huang break; 1743cd1610b4SJohnny Huang } 1744cd1610b4SJohnny Huang 1745cd1610b4SJohnny Huang if (!nconfirm) { 1746cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1747cd1610b4SJohnny Huang if (!confirm_yesno()) { 1748cd1610b4SJohnny Huang printf(" Aborting\n"); 17492a856b9aSJohnny Huang return OTP_FAILURE; 1750cd1610b4SJohnny Huang } 1751cd1610b4SJohnny Huang } 1752cd1610b4SJohnny Huang 1753cd1610b4SJohnny Huang switch (mode) { 1754a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1755cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1756a6d0d645SJohnny Huang case OTP_REGION_CONF: 1757a6d0d645SJohnny Huang case OTP_REGION_DATA: 1758cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1759cd1610b4SJohnny Huang pass = -1; 1760cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1761a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1762cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1763cd1610b4SJohnny Huang } else { 1764cd1610b4SJohnny Huang pass = 0; 1765cd1610b4SJohnny Huang break; 1766cd1610b4SJohnny Huang } 1767cd1610b4SJohnny Huang } 17682a856b9aSJohnny Huang if (pass == 0) 17692a856b9aSJohnny Huang return OTP_SUCCESS; 1770cd1610b4SJohnny Huang } 1771cd1610b4SJohnny Huang 17722a856b9aSJohnny Huang return OTP_USAGE; 1773cd1610b4SJohnny Huang } 1774cd1610b4SJohnny Huang 17752a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 177669d5fd8fSJohnny Huang { 17772a856b9aSJohnny Huang uint32_t offset, count; 17782a856b9aSJohnny Huang int ret; 177969d5fd8fSJohnny Huang 17802a856b9aSJohnny Huang if (argc == 4) { 17812a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17822a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 17832a856b9aSJohnny Huang } else if (argc == 3) { 17842a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17852a856b9aSJohnny Huang count = 1; 17862a856b9aSJohnny Huang } else { 178769d5fd8fSJohnny Huang return CMD_RET_USAGE; 178869d5fd8fSJohnny Huang } 178969d5fd8fSJohnny Huang 179069d5fd8fSJohnny Huang 17912a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 179269d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17932a856b9aSJohnny Huang ret = otp_print_config(offset, count); 17942a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 17952a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17962a856b9aSJohnny Huang ret = otp_print_data(offset, count); 17972a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 17982a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17992a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 18002a856b9aSJohnny Huang } else { 18012a856b9aSJohnny Huang return CMD_RET_USAGE; 180269d5fd8fSJohnny Huang } 180369d5fd8fSJohnny Huang 18042a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18052a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18062a856b9aSJohnny Huang else 18072a856b9aSJohnny Huang return CMD_RET_USAGE; 18082a856b9aSJohnny Huang 18092a856b9aSJohnny Huang } 18102a856b9aSJohnny Huang 18112a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18122a856b9aSJohnny Huang { 18132a856b9aSJohnny Huang phys_addr_t addr; 18142a856b9aSJohnny Huang uint32_t byte_size; 18152a856b9aSJohnny Huang int ret; 18162a856b9aSJohnny Huang 18172a856b9aSJohnny Huang if (argc == 4) { 18182a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 18192a856b9aSJohnny Huang return CMD_RET_USAGE; 18202a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 18212a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 182269d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18232a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 18242a856b9aSJohnny Huang } else if (argc == 3) { 18252a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 18262a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 18272a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18282a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 18292a856b9aSJohnny Huang } else { 18302a856b9aSJohnny Huang return CMD_RET_USAGE; 18312a856b9aSJohnny Huang } 18322a856b9aSJohnny Huang 18332a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18342a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18352a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18362a856b9aSJohnny Huang return CMD_RET_FAILURE; 18372a856b9aSJohnny Huang else 18382a856b9aSJohnny Huang return CMD_RET_USAGE; 18392a856b9aSJohnny Huang } 18402a856b9aSJohnny Huang 18412a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18422a856b9aSJohnny Huang { 18432a856b9aSJohnny Huang int mode = 0; 18442a856b9aSJohnny Huang int nconfirm = 0; 18452a856b9aSJohnny Huang int otp_addr = 0; 18462a856b9aSJohnny Huang int bit_offset; 18472a856b9aSJohnny Huang int value; 18482a856b9aSJohnny Huang int ret; 18492a856b9aSJohnny Huang 18502a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 18512a856b9aSJohnny Huang return CMD_RET_USAGE; 18522a856b9aSJohnny Huang 18532a856b9aSJohnny Huang /* Drop the pb cmd */ 18542a856b9aSJohnny Huang argc--; 18552a856b9aSJohnny Huang argv++; 18562a856b9aSJohnny Huang 18572a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1858a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 18592a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1860a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 18612a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1862a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1863cd1610b4SJohnny Huang else 18642a856b9aSJohnny Huang return CMD_RET_USAGE; 18652a856b9aSJohnny Huang 18662a856b9aSJohnny Huang /* Drop the region cmd */ 18672a856b9aSJohnny Huang argc--; 18682a856b9aSJohnny Huang argv++; 18692a856b9aSJohnny Huang 18702a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1871cd1610b4SJohnny Huang nconfirm = 1; 18722a856b9aSJohnny Huang /* Drop the force option */ 18732a856b9aSJohnny Huang argc--; 18742a856b9aSJohnny Huang argv++; 18752a856b9aSJohnny Huang } 1876cd1610b4SJohnny Huang 1877a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 18782a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 18792a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1880cd1610b4SJohnny Huang if (bit_offset >= 64) 18812a856b9aSJohnny Huang return CMD_RET_USAGE; 1882cd1610b4SJohnny Huang } else { 18832a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 18842a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 18852a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1886cd1610b4SJohnny Huang if (bit_offset >= 32) 18872a856b9aSJohnny Huang return CMD_RET_USAGE; 1888cd1610b4SJohnny Huang } 1889cd1610b4SJohnny Huang if (value != 0 && value != 1) 18902a856b9aSJohnny Huang return CMD_RET_USAGE; 1891cd1610b4SJohnny Huang 1892cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18932a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 18942a856b9aSJohnny Huang 18952a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18962a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18972a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18982a856b9aSJohnny Huang return CMD_RET_FAILURE; 18992a856b9aSJohnny Huang else 19002a856b9aSJohnny Huang return CMD_RET_USAGE; 19012a856b9aSJohnny Huang } 19022a856b9aSJohnny Huang 19032a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19042a856b9aSJohnny Huang { 19052a856b9aSJohnny Huang phys_addr_t addr; 19062a856b9aSJohnny Huang int otp_addr = 0; 19072a856b9aSJohnny Huang 19082a856b9aSJohnny Huang if (argc != 3) 19092a856b9aSJohnny Huang return CMD_RET_USAGE; 19102a856b9aSJohnny Huang 191169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19122a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19132a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 19142a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 191569d5fd8fSJohnny Huang printf("Compare pass\n"); 19162a856b9aSJohnny Huang return CMD_RET_SUCCESS; 191769d5fd8fSJohnny Huang } else { 191869d5fd8fSJohnny Huang printf("Compare fail\n"); 19192a856b9aSJohnny Huang return CMD_RET_FAILURE; 192069d5fd8fSJohnny Huang } 192169d5fd8fSJohnny Huang } 192269d5fd8fSJohnny Huang 192366f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 192466f2f8e5SJohnny Huang { 1925a8bd6d8cSJohnny Huang int view = 0; 1926*2d4b0742SJohnny Huang int input; 1927a8bd6d8cSJohnny Huang 1928a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 192966f2f8e5SJohnny Huang return CMD_RET_USAGE; 193066f2f8e5SJohnny Huang 1931*2d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 193266f2f8e5SJohnny Huang 1933*2d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1934*2d4b0742SJohnny Huang if (argc == 3) { 1935*2d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1936*2d4b0742SJohnny Huang otp_print_conf_info(input); 1937*2d4b0742SJohnny Huang } else { 1938*2d4b0742SJohnny Huang otp_print_conf_info(-1); 1939*2d4b0742SJohnny Huang } 1940*2d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 1941*2d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 1942a8bd6d8cSJohnny Huang view = 1; 1943a8bd6d8cSJohnny Huang /* Drop the view option */ 1944a8bd6d8cSJohnny Huang argc--; 1945a8bd6d8cSJohnny Huang argv++; 1946a8bd6d8cSJohnny Huang } 194766f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1948b458cd62SJohnny Huang otp_print_strap_info(view); 194966f2f8e5SJohnny Huang } else { 195066f2f8e5SJohnny Huang return CMD_RET_USAGE; 195166f2f8e5SJohnny Huang } 1952*2d4b0742SJohnny Huang 195366f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 195466f2f8e5SJohnny Huang } 195566f2f8e5SJohnny Huang 1956737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 1957737ed20bSJohnny Huang { 1958737ed20bSJohnny Huang int input; 1959737ed20bSJohnny Huang int bit_offset; 1960737ed20bSJohnny Huang int prog_address; 1961737ed20bSJohnny Huang int pass; 1962737ed20bSJohnny Huang int i; 1963737ed20bSJohnny Huang if (argc != 3 && argc != 2) 1964737ed20bSJohnny Huang return CMD_RET_USAGE; 1965737ed20bSJohnny Huang 1966737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 1967737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1968737ed20bSJohnny Huang } else { 1969737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 1970737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 1971737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1972737ed20bSJohnny Huang if (!confirm_yesno()) { 1973737ed20bSJohnny Huang printf(" Aborting\n"); 1974737ed20bSJohnny Huang return CMD_RET_FAILURE; 1975737ed20bSJohnny Huang } 1976737ed20bSJohnny Huang } 1977737ed20bSJohnny Huang 1978737ed20bSJohnny Huang prog_address = 0x800; 1979737ed20bSJohnny Huang if (input < 32) { 1980737ed20bSJohnny Huang bit_offset = input; 1981737ed20bSJohnny Huang prog_address |= 0x60c; 1982737ed20bSJohnny Huang } else if (input < 64) { 1983737ed20bSJohnny Huang bit_offset = input - 32; 1984737ed20bSJohnny Huang prog_address |= 0x60e; 1985737ed20bSJohnny Huang } else { 1986737ed20bSJohnny Huang return CMD_RET_USAGE; 1987737ed20bSJohnny Huang } 1988737ed20bSJohnny Huang 1989737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 1990737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 1991737ed20bSJohnny Huang } 1992737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 1993737ed20bSJohnny Huang pass = -1; 1994737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 1995737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 1996737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 1997737ed20bSJohnny Huang } else { 1998737ed20bSJohnny Huang pass = 0; 1999737ed20bSJohnny Huang break; 2000737ed20bSJohnny Huang } 2001737ed20bSJohnny Huang } 2002737ed20bSJohnny Huang if (pass == 0) { 2003737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2004737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2005737ed20bSJohnny Huang } 2006737ed20bSJohnny Huang 2007737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2008737ed20bSJohnny Huang return CMD_RET_FAILURE; 2009737ed20bSJohnny Huang 2010737ed20bSJohnny Huang } 20112a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 20122a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2013a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 20142a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 20152a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2016737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 20172a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 20182a856b9aSJohnny Huang }; 20192a856b9aSJohnny Huang 20202a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20212a856b9aSJohnny Huang { 20222a856b9aSJohnny Huang cmd_tbl_t *cp; 20232a856b9aSJohnny Huang 20242a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 20252a856b9aSJohnny Huang 2026737ed20bSJohnny Huang /* Drop the otp command */ 20272a856b9aSJohnny Huang argc--; 20282a856b9aSJohnny Huang argv++; 20292a856b9aSJohnny Huang 20302a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 20312a856b9aSJohnny Huang return CMD_RET_USAGE; 20322a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 20332a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20342a856b9aSJohnny Huang 20352a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 203669d5fd8fSJohnny Huang } 203769d5fd8fSJohnny Huang 203869d5fd8fSJohnny Huang U_BOOT_CMD( 203969d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 204069d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 20412a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 20422a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 2043*2d4b0742SJohnny Huang "otp info strap [v]\n" 2044*2d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2045d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2046cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2047737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2048737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 20492a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 205069d5fd8fSJohnny Huang ); 2051