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 28*7332532cSJohnny Huang #define OTP_REGION_STRAP BIT(0) 29*7332532cSJohnny Huang #define OTP_REGION_CONF BIT(1) 30*7332532cSJohnny Huang #define OTP_REGION_DATA BIT(2) 3169d5fd8fSJohnny Huang 322a856b9aSJohnny Huang #define OTP_USAGE -1 332a856b9aSJohnny Huang #define OTP_FAILURE -2 342a856b9aSJohnny Huang #define OTP_SUCCESS 0 352a856b9aSJohnny Huang 36a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 37a6af4a17SJohnny Huang 38a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 39b458cd62SJohnny Huang #define OTP_REG_VALUE -2 40b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4176d13988SJohnny Huang 424c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 434c1c9b35SJohnny Huang #define PBWIDTH 60 444c1c9b35SJohnny Huang 4566f2f8e5SJohnny Huang struct otpstrap_status { 4669d5fd8fSJohnny Huang int value; 4769d5fd8fSJohnny Huang int option_array[7]; 4869d5fd8fSJohnny Huang int remain_times; 4969d5fd8fSJohnny Huang int writeable_option; 5069d5fd8fSJohnny Huang int protected; 5169d5fd8fSJohnny Huang }; 5269d5fd8fSJohnny Huang 5366f2f8e5SJohnny Huang struct otpconf_parse { 5466f2f8e5SJohnny Huang int dw_offset; 5566f2f8e5SJohnny Huang int bit; 5666f2f8e5SJohnny Huang int length; 5766f2f8e5SJohnny Huang int value; 5866f2f8e5SJohnny Huang int keep; 5966f2f8e5SJohnny Huang char status[80]; 6066f2f8e5SJohnny Huang }; 6166f2f8e5SJohnny Huang 62a8bd6d8cSJohnny Huang struct otpstrap_info { 63a8bd6d8cSJohnny Huang uint32_t bit_offset; 64a8bd6d8cSJohnny Huang uint32_t length; 6576d13988SJohnny Huang int value; 66a8bd6d8cSJohnny Huang char information[80]; 67a8bd6d8cSJohnny Huang }; 68a8bd6d8cSJohnny Huang 69a8bd6d8cSJohnny Huang struct otpconf_info { 70a8bd6d8cSJohnny Huang uint32_t dw_offset; 71a8bd6d8cSJohnny Huang uint32_t bit_offset; 72a8bd6d8cSJohnny Huang uint32_t length; 73a8bd6d8cSJohnny Huang int value; 74a8bd6d8cSJohnny Huang char information[80]; 75a8bd6d8cSJohnny Huang }; 76a8bd6d8cSJohnny Huang 77a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 78a8bd6d8cSJohnny Huang { 79a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 80a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 81a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 82a8bd6d8cSJohnny Huang char buffer[256]; 83a8bd6d8cSJohnny Huang va_list aptr; 84a8bd6d8cSJohnny Huang 85a8bd6d8cSJohnny Huang va_start(aptr, format); 86a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 87a8bd6d8cSJohnny Huang va_end(aptr); 88a8bd6d8cSJohnny Huang 89a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 90a8bd6d8cSJohnny Huang if (numerator == denominator) 91a8bd6d8cSJohnny Huang printf("\n"); 92a8bd6d8cSJohnny Huang } 93a8bd6d8cSJohnny Huang 94a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 95a8bd6d8cSJohnny Huang { 96a8bd6d8cSJohnny Huang 0, 1, 0, "Disable secure boot" 97a8bd6d8cSJohnny Huang }, { 98a8bd6d8cSJohnny Huang 0, 1, 1, "Enable secure boot" 99a8bd6d8cSJohnny Huang }, { 100a8bd6d8cSJohnny Huang 1, 1, 0, "Disable boot from eMMC" 101a8bd6d8cSJohnny Huang }, { 102a8bd6d8cSJohnny Huang 1, 1, 1, "Enable boot from eMMC" 103a8bd6d8cSJohnny Huang }, { 104a8bd6d8cSJohnny Huang 2, 1, 0, "Disable Boot from debug SPI" 105a8bd6d8cSJohnny Huang }, { 106a8bd6d8cSJohnny Huang 2, 1, 1, "Enable Boot from debug SPI" 107a8bd6d8cSJohnny Huang }, { 108a8bd6d8cSJohnny Huang 3, 1, 0, "Enable ARM CM3" 109a8bd6d8cSJohnny Huang }, { 110a8bd6d8cSJohnny Huang 3, 1, 1, "Disable ARM CM3" 111a8bd6d8cSJohnny Huang }, { 112a8bd6d8cSJohnny Huang 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" 113a8bd6d8cSJohnny Huang }, { 114a8bd6d8cSJohnny Huang 4, 1, 1, "Enable dedicated VGA BIOS ROM" 115a8bd6d8cSJohnny Huang }, { 116a8bd6d8cSJohnny Huang 5, 1, 0, "MAC 1 : RMII/NCSI" 117a8bd6d8cSJohnny Huang }, { 118a8bd6d8cSJohnny Huang 5, 1, 1, "MAC 1 : RGMII" 119a8bd6d8cSJohnny Huang }, { 120a8bd6d8cSJohnny Huang 6, 1, 0, "MAC 2 : RMII/NCSI" 121a8bd6d8cSJohnny Huang }, { 122a8bd6d8cSJohnny Huang 6, 1, 1, "MAC 2 : RGMII" 123a8bd6d8cSJohnny Huang }, { 124a8bd6d8cSJohnny Huang 7, 3, 0, "CPU Frequency : 1GHz" 125a8bd6d8cSJohnny Huang }, { 126a8bd6d8cSJohnny Huang 7, 3, 1, "CPU Frequency : 800MHz" 127a8bd6d8cSJohnny Huang }, { 128a8bd6d8cSJohnny Huang 7, 3, 2, "CPU Frequency : 1.2GHz" 129a8bd6d8cSJohnny Huang }, { 130a8bd6d8cSJohnny Huang 7, 3, 3, "CPU Frequency : 1.4GHz" 131a8bd6d8cSJohnny Huang }, { 132a8bd6d8cSJohnny Huang 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" 133a8bd6d8cSJohnny Huang }, { 134a8bd6d8cSJohnny Huang 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" 135a8bd6d8cSJohnny Huang }, { 136a8bd6d8cSJohnny Huang 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" 137a8bd6d8cSJohnny Huang }, { 138a8bd6d8cSJohnny Huang 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" 139a8bd6d8cSJohnny Huang }, { 140a8bd6d8cSJohnny Huang 12, 2, 0, "VGA memory size : 8MB" 141a8bd6d8cSJohnny Huang }, { 142a8bd6d8cSJohnny Huang 12, 2, 1, "VGA memory size : 16MB" 143a8bd6d8cSJohnny Huang }, { 144a8bd6d8cSJohnny Huang 12, 2, 2, "VGA memory size : 32MB" 145a8bd6d8cSJohnny Huang }, { 146a8bd6d8cSJohnny Huang 12, 2, 3, "VGA memory size : 64MB" 147a8bd6d8cSJohnny Huang }, { 148a8bd6d8cSJohnny Huang 14, 3, OTP_REG_RESERVED, "" 149a8bd6d8cSJohnny Huang }, { 150a8bd6d8cSJohnny Huang 17, 1, 0, "VGA class code : Class Code for video device" 151a8bd6d8cSJohnny Huang }, { 152a8bd6d8cSJohnny Huang 17, 1, 1, "VGA class code : Class Code for VGA device" 153a8bd6d8cSJohnny Huang }, { 154a8bd6d8cSJohnny Huang 18, 1, 0, "Enable debug interfaces 0" 155a8bd6d8cSJohnny Huang }, { 156a8bd6d8cSJohnny Huang 18, 1, 1, "Disable debug interfaces 0" 157a8bd6d8cSJohnny Huang }, { 158a8bd6d8cSJohnny Huang 19, 1, 0, "Boot from emmc mode : High eMMC speed" 159a8bd6d8cSJohnny Huang }, { 160a8bd6d8cSJohnny Huang 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" 161a8bd6d8cSJohnny Huang }, { 162a8bd6d8cSJohnny Huang 20, 1, 0, "Enable Pcie EHCI device" 163a8bd6d8cSJohnny Huang }, { 164a8bd6d8cSJohnny Huang 20, 1, 1, "Disable Pcie EHCI device" 165a8bd6d8cSJohnny Huang }, { 166a8bd6d8cSJohnny Huang 21, 1, 0, "Enable VGA XDMA function" 167a8bd6d8cSJohnny Huang }, { 168a8bd6d8cSJohnny Huang 21, 1, 1, "Disable VGA XDMA function" 169a8bd6d8cSJohnny Huang }, { 170a8bd6d8cSJohnny Huang 22, 1, 0, "Normal BMC mode" 171a8bd6d8cSJohnny Huang }, { 172a8bd6d8cSJohnny Huang 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" 173a8bd6d8cSJohnny Huang }, { 174a8bd6d8cSJohnny Huang 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" 175a8bd6d8cSJohnny Huang }, { 176a8bd6d8cSJohnny Huang 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" 177a8bd6d8cSJohnny Huang }, { 178*7332532cSJohnny Huang 24, 1, 0, "DRAM types : DDR4" 179a8bd6d8cSJohnny Huang }, { 180*7332532cSJohnny Huang 24, 1, 1, "DRAM types : DDR3" 181a8bd6d8cSJohnny Huang }, { 182a8bd6d8cSJohnny Huang 25, 5, OTP_REG_RESERVED, "" 183a8bd6d8cSJohnny Huang }, { 184a8bd6d8cSJohnny Huang 30, 2, OTP_REG_RESERVED, "" 185a8bd6d8cSJohnny Huang }, { 186a8bd6d8cSJohnny Huang 32, 1, 0, "MAC 3 : RMII/NCSI" 187a8bd6d8cSJohnny Huang }, { 188a8bd6d8cSJohnny Huang 32, 1, 1, "MAC 3 : RGMII" 189a8bd6d8cSJohnny Huang }, { 190a8bd6d8cSJohnny Huang 33, 1, 0, "MAC 4 : RMII/NCSI" 191a8bd6d8cSJohnny Huang }, { 192a8bd6d8cSJohnny Huang 33, 1, 1, "MAC 4 : RGMII" 193a8bd6d8cSJohnny Huang }, { 194a8bd6d8cSJohnny Huang 34, 1, 0, "SuperIO configuration address : 0x2E" 195a8bd6d8cSJohnny Huang }, { 196a8bd6d8cSJohnny Huang 34, 1, 1, "SuperIO configuration address : 0x4E" 197a8bd6d8cSJohnny Huang }, { 198a8bd6d8cSJohnny Huang 35, 1, 0, "Enable LPC to decode SuperIO" 199a8bd6d8cSJohnny Huang }, { 200a8bd6d8cSJohnny Huang 35, 1, 1, "Disable LPC to decode SuperIO" 201a8bd6d8cSJohnny Huang }, { 202a8bd6d8cSJohnny Huang 36, 1, 0, "Enable debug interfaces 1" 203a8bd6d8cSJohnny Huang }, { 204a8bd6d8cSJohnny Huang 36, 1, 1, "Disable debug interfaces 1" 205a8bd6d8cSJohnny Huang }, { 206a8bd6d8cSJohnny Huang 37, 1, 0, "Disable ACPI function" 207a8bd6d8cSJohnny Huang }, { 208a8bd6d8cSJohnny Huang 37, 1, 1, "Enable ACPI function" 209a8bd6d8cSJohnny Huang }, { 210a8bd6d8cSJohnny Huang 38, 1, 0, "Enable eSPI mode" 211a8bd6d8cSJohnny Huang }, { 212a8bd6d8cSJohnny Huang 38, 1, 1, "Enable LPC mode" 213a8bd6d8cSJohnny Huang }, { 214a8bd6d8cSJohnny Huang 39, 1, 0, "Enable SAFS mode" 215a8bd6d8cSJohnny Huang }, { 216a8bd6d8cSJohnny Huang 39, 1, 1, "Enable SAFS mode" 217a8bd6d8cSJohnny Huang }, { 218a8bd6d8cSJohnny Huang 40, 2, OTP_REG_RESERVED, "" 219a8bd6d8cSJohnny Huang }, { 220a8bd6d8cSJohnny Huang 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" 221a8bd6d8cSJohnny Huang }, { 222a8bd6d8cSJohnny Huang 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" 223a8bd6d8cSJohnny Huang }, { 224a8bd6d8cSJohnny Huang 43, 1, 0, "Disable boot SPI ABR" 225a8bd6d8cSJohnny Huang }, { 226a8bd6d8cSJohnny Huang 43, 1, 1, "Enable boot SPI ABR" 227a8bd6d8cSJohnny Huang }, { 228a8bd6d8cSJohnny Huang 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" 229a8bd6d8cSJohnny Huang }, { 230a8bd6d8cSJohnny Huang 44, 1, 1, "Boot SPI ABR mode : single SPI flash" 231a8bd6d8cSJohnny Huang }, { 232a8bd6d8cSJohnny Huang 45, 3, 0, "Boot SPI flash size : no define size" 233a8bd6d8cSJohnny Huang }, { 234a8bd6d8cSJohnny Huang 45, 3, 1, "Boot SPI flash size : 2MB" 235a8bd6d8cSJohnny Huang }, { 236a8bd6d8cSJohnny Huang 45, 3, 2, "Boot SPI flash size : 4MB" 237a8bd6d8cSJohnny Huang }, { 238a8bd6d8cSJohnny Huang 45, 3, 3, "Boot SPI flash size : 8MB" 239a8bd6d8cSJohnny Huang }, { 240a8bd6d8cSJohnny Huang 45, 3, 4, "Boot SPI flash size : 16MB" 241a8bd6d8cSJohnny Huang }, { 242a8bd6d8cSJohnny Huang 45, 3, 5, "Boot SPI flash size : 32MB" 243a8bd6d8cSJohnny Huang }, { 244a8bd6d8cSJohnny Huang 45, 3, 6, "Boot SPI flash size : 64MB" 245a8bd6d8cSJohnny Huang }, { 246a8bd6d8cSJohnny Huang 45, 3, 7, "Boot SPI flash size : 128MB" 247a8bd6d8cSJohnny Huang }, { 248a8bd6d8cSJohnny Huang 48, 1, 0, "Disable host SPI ABR" 249a8bd6d8cSJohnny Huang }, { 250a8bd6d8cSJohnny Huang 48, 1, 1, "Enable host SPI ABR" 251a8bd6d8cSJohnny Huang }, { 252a8bd6d8cSJohnny Huang 49, 1, 0, "Disable host SPI ABR mode select pin" 253a8bd6d8cSJohnny Huang }, { 254a8bd6d8cSJohnny Huang 49, 1, 1, "Enable host SPI ABR mode select pin" 255a8bd6d8cSJohnny Huang }, { 256a8bd6d8cSJohnny Huang 50, 1, 0, "Host SPI ABR mode : dual SPI flash" 257a8bd6d8cSJohnny Huang }, { 258a8bd6d8cSJohnny Huang 50, 1, 1, "Host SPI ABR mode : single SPI flash" 259a8bd6d8cSJohnny Huang }, { 260a8bd6d8cSJohnny Huang 51, 3, 0, "Host SPI flash size : no define size" 261a8bd6d8cSJohnny Huang }, { 262a8bd6d8cSJohnny Huang 51, 3, 1, "Host SPI flash size : 2MB" 263a8bd6d8cSJohnny Huang }, { 264a8bd6d8cSJohnny Huang 51, 3, 2, "Host SPI flash size : 4MB" 265a8bd6d8cSJohnny Huang }, { 266a8bd6d8cSJohnny Huang 51, 3, 3, "Host SPI flash size : 8MB" 267a8bd6d8cSJohnny Huang }, { 268a8bd6d8cSJohnny Huang 51, 3, 4, "Host SPI flash size : 16MB" 269a8bd6d8cSJohnny Huang }, { 270a8bd6d8cSJohnny Huang 51, 3, 5, "Host SPI flash size : 32MB" 271a8bd6d8cSJohnny Huang }, { 272a8bd6d8cSJohnny Huang 51, 3, 6, "Host SPI flash size : 64MB" 273a8bd6d8cSJohnny Huang }, { 274a8bd6d8cSJohnny Huang 51, 3, 7, "Host SPI flash size : 128MB" 275a8bd6d8cSJohnny Huang }, { 276a8bd6d8cSJohnny Huang 54, 1, 0, "Disable boot SPI auxiliary control pins" 277a8bd6d8cSJohnny Huang }, { 278a8bd6d8cSJohnny Huang 54, 1, 1, "Enable boot SPI auxiliary control pins" 279a8bd6d8cSJohnny Huang }, { 280a8bd6d8cSJohnny Huang 55, 2, 0, "Boot SPI CRTM size : disable CRTM" 281a8bd6d8cSJohnny Huang }, { 282a8bd6d8cSJohnny Huang 55, 2, 1, "Boot SPI CRTM size : 256KB" 283a8bd6d8cSJohnny Huang }, { 284a8bd6d8cSJohnny Huang 55, 2, 2, "Boot SPI CRTM size : 512KB" 285a8bd6d8cSJohnny Huang }, { 286a8bd6d8cSJohnny Huang 55, 2, 3, "Boot SPI CRTM size : 1MB" 287a8bd6d8cSJohnny Huang }, { 288a8bd6d8cSJohnny Huang 57, 2, 0, "Host SPI CRTM size : disable CRTM" 289a8bd6d8cSJohnny Huang }, { 290a8bd6d8cSJohnny Huang 57, 2, 1, "Host SPI CRTM size : 256KB" 291a8bd6d8cSJohnny Huang }, { 292a8bd6d8cSJohnny Huang 57, 2, 2, "Host SPI CRTM size : 512KB" 293a8bd6d8cSJohnny Huang }, { 294a8bd6d8cSJohnny Huang 57, 2, 3, "Host SPI CRTM size : 1MB" 295a8bd6d8cSJohnny Huang }, { 296a8bd6d8cSJohnny Huang 59, 1, 0, "Disable host SPI auxiliary control pins" 297a8bd6d8cSJohnny Huang }, { 298a8bd6d8cSJohnny Huang 59, 1, 1, "Enable host SPI auxiliary control pins" 299a8bd6d8cSJohnny Huang }, { 300a8bd6d8cSJohnny Huang 60, 1, 0, "Disable GPIO pass through" 301a8bd6d8cSJohnny Huang }, { 302a8bd6d8cSJohnny Huang 60, 1, 1, "Enable GPIO pass through" 303a8bd6d8cSJohnny Huang }, { 304a8bd6d8cSJohnny Huang 61, 1, 0, "Enable low security secure boot key" 305a8bd6d8cSJohnny Huang }, { 306a8bd6d8cSJohnny Huang 61, 1, 1, "Disable low security secure boot key" 307a8bd6d8cSJohnny Huang }, { 308a8bd6d8cSJohnny Huang 62, 1, 0, "Disable dedicate GPIO strap pins" 309a8bd6d8cSJohnny Huang }, { 310a8bd6d8cSJohnny Huang 62, 1, 1, "Enable dedicate GPIO strap pins" 311b458cd62SJohnny Huang }, { 312b458cd62SJohnny Huang 63, 1, OTP_REG_RESERVED, "" 313a8bd6d8cSJohnny Huang } 31476d13988SJohnny Huang }; 315b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 316b458cd62SJohnny Huang { 317b458cd62SJohnny Huang 0, 0, 1, 0, "Enable Secure Region programming" 318b458cd62SJohnny Huang }, { 319b458cd62SJohnny Huang 0, 0, 1, 1, "Disable Secure Region programming" 320b458cd62SJohnny Huang }, { 321b458cd62SJohnny Huang 0, 1, 1, 0, "Disable Secure Boot" 322b458cd62SJohnny Huang }, { 323b458cd62SJohnny Huang 0, 1, 1, 1, "Enable Secure Boot" 324b458cd62SJohnny Huang }, { 325b458cd62SJohnny Huang 0, 2, 1, 0, "Initialization programming not done" 326b458cd62SJohnny Huang }, { 327b458cd62SJohnny Huang 0, 2, 1, 1, "Initialization programming done" 328b458cd62SJohnny Huang }, { 329b458cd62SJohnny Huang 0, 3, 1, 0, "User region ECC disable" 330b458cd62SJohnny Huang }, { 331b458cd62SJohnny Huang 0, 3, 1, 1, "User region ECC enable" 332b458cd62SJohnny Huang }, { 333b458cd62SJohnny Huang 0, 4, 1, 0, "Secure Region ECC disable" 334b458cd62SJohnny Huang }, { 335b458cd62SJohnny Huang 0, 4, 1, 1, "Secure Region ECC enable" 336b458cd62SJohnny Huang }, { 337b458cd62SJohnny Huang 0, 5, 1, 0, "Enable low security key" 338b458cd62SJohnny Huang }, { 339b458cd62SJohnny Huang 0, 5, 1, 1, "Disable low security key" 340b458cd62SJohnny Huang }, { 341b458cd62SJohnny Huang 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" 342b458cd62SJohnny Huang }, { 343b458cd62SJohnny Huang 0, 6, 1, 1, "Ignore Secure Boot hardware strap" 344b458cd62SJohnny Huang }, { 345*7332532cSJohnny Huang 0, 7, 1, 0, "Secure Boot Mode: 1" 346b458cd62SJohnny Huang }, { 347*7332532cSJohnny Huang 0, 7, 1, 1, "Secure Boot Mode: 2" 348b458cd62SJohnny Huang }, { 349b458cd62SJohnny Huang 0, 8, 2, 0, "Single cell mode (recommended)" 350b458cd62SJohnny Huang }, { 351b458cd62SJohnny Huang 0, 8, 2, 1, "Differnetial mode" 352b458cd62SJohnny Huang }, { 353b458cd62SJohnny Huang 0, 8, 2, 2, "Differential-redundant mode" 354b458cd62SJohnny Huang }, { 355b458cd62SJohnny Huang 0, 10, 2, 0, "RSA mode : RSA1024" 356b458cd62SJohnny Huang }, { 357b458cd62SJohnny Huang 0, 10, 2, 1, "RSA mode : RSA2048" 358b458cd62SJohnny Huang }, { 359b458cd62SJohnny Huang 0, 10, 2, 2, "RSA mode : RSA3072" 360b458cd62SJohnny Huang }, { 361b458cd62SJohnny Huang 0, 10, 2, 3, "RSA mode : RSA4096" 362b458cd62SJohnny Huang }, { 363b458cd62SJohnny Huang 0, 12, 2, 0, "SHA mode : SHA224" 364b458cd62SJohnny Huang }, { 365b458cd62SJohnny Huang 0, 12, 2, 1, "SHA mode : SHA256" 366b458cd62SJohnny Huang }, { 367b458cd62SJohnny Huang 0, 12, 2, 2, "SHA mode : SHA384" 368b458cd62SJohnny Huang }, { 369b458cd62SJohnny Huang 0, 12, 2, 3, "SHA mode : SHA512" 370b458cd62SJohnny Huang }, { 371b458cd62SJohnny Huang 0, 14, 2, OTP_REG_RESERVED, "" 372b458cd62SJohnny Huang }, { 373b458cd62SJohnny Huang 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" 374b458cd62SJohnny Huang }, { 375b458cd62SJohnny Huang 0, 22, 1, 0, "Secure Region : Writable" 376b458cd62SJohnny Huang }, { 377b458cd62SJohnny Huang 0, 22, 1, 1, "Secure Region : Write Protect" 378b458cd62SJohnny Huang }, { 379b458cd62SJohnny Huang 0, 23, 1, 0, "User Region : Writable" 380b458cd62SJohnny Huang }, { 381b458cd62SJohnny Huang 0, 23, 1, 1, "User Region : Write Protect" 382b458cd62SJohnny Huang }, { 383b458cd62SJohnny Huang 0, 24, 1, 0, "Configure Region : Writable" 384b458cd62SJohnny Huang }, { 385b458cd62SJohnny Huang 0, 24, 1, 1, "Configure Region : Write Protect" 386b458cd62SJohnny Huang }, { 387b458cd62SJohnny Huang 0, 25, 1, 0, "OTP strap Region : Writable" 388b458cd62SJohnny Huang }, { 389b458cd62SJohnny Huang 0, 25, 1, 1, "OTP strap Region : Write Protect" 390b458cd62SJohnny Huang }, { 391b458cd62SJohnny Huang 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" 392b458cd62SJohnny Huang }, { 393b458cd62SJohnny Huang 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" 394b458cd62SJohnny Huang }, { 395b458cd62SJohnny Huang 0, 27, 1, 0, "Disable image encryption" 396b458cd62SJohnny Huang }, { 397b458cd62SJohnny Huang 0, 27, 1, 1, "Enable image encryption" 398b458cd62SJohnny Huang }, { 399b458cd62SJohnny Huang 0, 28, 1, OTP_REG_RESERVED, "" 400b458cd62SJohnny Huang }, { 401b458cd62SJohnny Huang 0, 29, 1, 0, "OTP key retire Region : Writable" 402b458cd62SJohnny Huang }, { 403b458cd62SJohnny Huang 0, 29, 1, 1, "OTP key retire Region : Write Protect" 404b458cd62SJohnny Huang }, { 405b458cd62SJohnny Huang 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" 406b458cd62SJohnny Huang }, { 407b458cd62SJohnny Huang 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" 408b458cd62SJohnny Huang }, { 409b458cd62SJohnny Huang 0, 31, 1, 0, "SIPROM Mlock memory lock disable" 410b458cd62SJohnny Huang }, { 411b458cd62SJohnny Huang 0, 31, 1, 1, "SIPROM Mlock memory lock enable" 412b458cd62SJohnny Huang }, { 413b458cd62SJohnny Huang 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" 414b458cd62SJohnny Huang }, { 415b458cd62SJohnny Huang 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" 416b458cd62SJohnny Huang }, { 417b458cd62SJohnny Huang 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" 418b458cd62SJohnny Huang }, { 419b458cd62SJohnny Huang 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %d" 420b458cd62SJohnny Huang }, { 421b458cd62SJohnny Huang 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %d" 422b458cd62SJohnny Huang }, { 423b458cd62SJohnny Huang 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" 424b458cd62SJohnny Huang }, { 425b458cd62SJohnny Huang 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" 426b458cd62SJohnny Huang }, { 42707baa4e8SJohnny Huang 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" 42807baa4e8SJohnny Huang }, { 42907baa4e8SJohnny Huang 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" 43007baa4e8SJohnny Huang }, { 43107baa4e8SJohnny Huang 7, 1, 1, 0, "Force enable UART5 debug port function" 43207baa4e8SJohnny Huang }, { 43307baa4e8SJohnny Huang 7, 1, 1, 1, "Force disable UART5 debug port function" 43407baa4e8SJohnny Huang }, { 43507baa4e8SJohnny Huang 7, 2, 1, 0, "Force enable XDMA function" 43607baa4e8SJohnny Huang }, { 43707baa4e8SJohnny Huang 7, 2, 1, 1, "Force disable XDMA function" 43807baa4e8SJohnny Huang }, { 43907baa4e8SJohnny Huang 7, 3, 1, 0, "Force enable APB to PCIE device bridge" 44007baa4e8SJohnny Huang }, { 44107baa4e8SJohnny Huang 7, 3, 1, 1, "Force disable APB to PCIE device bridge" 44207baa4e8SJohnny Huang }, { 44307baa4e8SJohnny Huang 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" 44407baa4e8SJohnny Huang }, { 44507baa4e8SJohnny Huang 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" 44607baa4e8SJohnny Huang }, { 44707baa4e8SJohnny Huang 7, 5, 1, 0, "Force enable PCIE bus trace buffer" 44807baa4e8SJohnny Huang }, { 44907baa4e8SJohnny Huang 7, 5, 1, 1, "Force disable PCIE bus trace buffer" 45007baa4e8SJohnny Huang }, { 45107baa4e8SJohnny Huang 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" 45207baa4e8SJohnny Huang }, { 45307baa4e8SJohnny Huang 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" 45407baa4e8SJohnny Huang }, { 45507baa4e8SJohnny Huang 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" 45607baa4e8SJohnny Huang }, { 45707baa4e8SJohnny Huang 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" 45807baa4e8SJohnny Huang }, { 45907baa4e8SJohnny Huang 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" 46007baa4e8SJohnny Huang }, { 46107baa4e8SJohnny Huang 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" 46207baa4e8SJohnny Huang }, { 46307baa4e8SJohnny Huang 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" 46407baa4e8SJohnny Huang }, { 46507baa4e8SJohnny Huang 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" 46607baa4e8SJohnny Huang }, { 46707baa4e8SJohnny Huang 7, 19, 1, 0, "Force enable UART1 debug port function" 46807baa4e8SJohnny Huang }, { 46907baa4e8SJohnny Huang 7, 19, 1, 1, "Force disable UART1 debug port function" 47007baa4e8SJohnny Huang }, { 47107baa4e8SJohnny Huang 7, 31, 1, 0, "Disable chip security setting" 47207baa4e8SJohnny Huang }, { 47307baa4e8SJohnny Huang 7, 31, 1, 1, "Enable chip security setting" 47407baa4e8SJohnny Huang }, { 475b458cd62SJohnny Huang 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" 476b458cd62SJohnny Huang }, { 477b458cd62SJohnny Huang 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" 478b458cd62SJohnny Huang }, { 479b458cd62SJohnny Huang 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" 480b458cd62SJohnny Huang } 481b458cd62SJohnny Huang }; 4822a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 48369d5fd8fSJohnny Huang { 48469d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 48569d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 48669d5fd8fSJohnny Huang udelay(2); 48769d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 48869d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 48969d5fd8fSJohnny Huang } 49069d5fd8fSJohnny Huang 4912a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 49269d5fd8fSJohnny Huang { 49369d5fd8fSJohnny Huang int config_offset; 49469d5fd8fSJohnny Huang 49569d5fd8fSJohnny Huang config_offset = 0x800; 49669d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 49769d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 49869d5fd8fSJohnny Huang 49969d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 50069d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 50169d5fd8fSJohnny Huang udelay(2); 50269d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 50369d5fd8fSJohnny Huang } 50469d5fd8fSJohnny Huang 50569d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 50669d5fd8fSJohnny Huang { 50769d5fd8fSJohnny Huang int i; 50869d5fd8fSJohnny Huang uint32_t ret[1]; 50969d5fd8fSJohnny Huang 51069d5fd8fSJohnny Huang if (offset + dw_count > 32) 5112a856b9aSJohnny Huang return OTP_USAGE; 51269d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 51369d5fd8fSJohnny Huang otp_read_config(i, ret); 514a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 51569d5fd8fSJohnny Huang } 51669d5fd8fSJohnny Huang printf("\n"); 5172a856b9aSJohnny Huang return OTP_SUCCESS; 51869d5fd8fSJohnny Huang } 51969d5fd8fSJohnny Huang 52069d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 52169d5fd8fSJohnny Huang { 52269d5fd8fSJohnny Huang int i; 52369d5fd8fSJohnny Huang uint32_t ret[2]; 52469d5fd8fSJohnny Huang 52569d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5262a856b9aSJohnny Huang return OTP_USAGE; 52769d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 52869d5fd8fSJohnny Huang otp_read_data(i, ret); 52969d5fd8fSJohnny Huang if (i % 4 == 0) 53069d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 53169d5fd8fSJohnny Huang else 53269d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 53369d5fd8fSJohnny Huang 53469d5fd8fSJohnny Huang } 53569d5fd8fSJohnny Huang printf("\n"); 5362a856b9aSJohnny Huang return OTP_SUCCESS; 53769d5fd8fSJohnny Huang } 53869d5fd8fSJohnny Huang 53969d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 54069d5fd8fSJohnny Huang { 54169d5fd8fSJohnny Huang uint32_t ret; 54269d5fd8fSJohnny Huang uint32_t *buf; 54369d5fd8fSJohnny Huang 54469d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 54569d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 54669d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 54769d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 54869d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 54969d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 55069d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 55169d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 55269d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 55369d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 55469d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 55569d5fd8fSJohnny Huang udelay(10); 55669d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 55769d5fd8fSJohnny Huang if (ret & 0x1) 55869d5fd8fSJohnny Huang return 0; 55969d5fd8fSJohnny Huang else 56069d5fd8fSJohnny Huang return -1; 56169d5fd8fSJohnny Huang } 56269d5fd8fSJohnny Huang 56369d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 56469d5fd8fSJohnny Huang { 56569d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 56669d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 56769d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 56869d5fd8fSJohnny Huang udelay(100); 56969d5fd8fSJohnny Huang } 57069d5fd8fSJohnny Huang 57169d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 57269d5fd8fSJohnny Huang { 57369d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 57469d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 57569d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 57669d5fd8fSJohnny Huang udelay(85); 57769d5fd8fSJohnny Huang } 57869d5fd8fSJohnny Huang 579a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 58069d5fd8fSJohnny Huang { 58169d5fd8fSJohnny Huang int ret; 58269d5fd8fSJohnny Huang 58369d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 58469d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 58569d5fd8fSJohnny Huang udelay(2); 58669d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 587a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 58869d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 58969d5fd8fSJohnny Huang return 0; 59069d5fd8fSJohnny Huang else 59169d5fd8fSJohnny Huang return -1; 59269d5fd8fSJohnny Huang } 59369d5fd8fSJohnny Huang 594d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 5954c1c9b35SJohnny Huang { 5964c1c9b35SJohnny Huang uint32_t ret[2]; 5974c1c9b35SJohnny Huang 5984c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 5994c1c9b35SJohnny Huang 6004c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6014c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 6024c1c9b35SJohnny Huang else 6034c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 6044c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 6054c1c9b35SJohnny Huang udelay(2); 6064c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 6074c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 6084c1c9b35SJohnny Huang if (size == 1) { 6094c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6104c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 611d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6124c1c9b35SJohnny Huang compare[0] = 0; 6134c1c9b35SJohnny Huang return 0; 6144c1c9b35SJohnny Huang } else { 6154c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6164c1c9b35SJohnny Huang return -1; 6174c1c9b35SJohnny Huang } 6184c1c9b35SJohnny Huang 6194c1c9b35SJohnny Huang } else { 6204c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 621d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 6224c1c9b35SJohnny Huang compare[0] = ~0; 6234c1c9b35SJohnny Huang return 0; 6244c1c9b35SJohnny Huang } else { 625d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 6264c1c9b35SJohnny Huang return -1; 6274c1c9b35SJohnny Huang } 6284c1c9b35SJohnny Huang } 6294c1c9b35SJohnny Huang } else if (size == 2) { 6304c1c9b35SJohnny Huang // otp_addr should be even 631d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 6324c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 6334c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 6344c1c9b35SJohnny Huang compare[0] = 0; 6354c1c9b35SJohnny Huang compare[1] = ~0; 6364c1c9b35SJohnny Huang return 0; 6374c1c9b35SJohnny Huang } else { 6384c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 6394c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 6404c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6414c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 6424c1c9b35SJohnny Huang return -1; 6434c1c9b35SJohnny Huang } 6444c1c9b35SJohnny Huang } else { 6454c1c9b35SJohnny Huang return -1; 6464c1c9b35SJohnny Huang } 6474c1c9b35SJohnny Huang } 6484c1c9b35SJohnny Huang 6497e22f42dSJohnny Huang static void otp_soak(int soak) 650d90825e2SJohnny Huang { 651d90825e2SJohnny Huang if (soak) { 652d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 653d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 654d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 655d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 656d90825e2SJohnny Huang } else { 657d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 658d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 659d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 660d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 661d90825e2SJohnny Huang } 662d90825e2SJohnny Huang } 663d90825e2SJohnny Huang 664d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 665d90825e2SJohnny Huang { 666d90825e2SJohnny Huang int j, bit_value, prog_bit; 667d90825e2SJohnny Huang 668d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 669d90825e2SJohnny Huang if ((keep >> j) & 0x1) 670d90825e2SJohnny Huang continue; 671d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 672d90825e2SJohnny Huang if (prog_address % 2 == 0) { 673d90825e2SJohnny Huang if (bit_value) 674d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 675d90825e2SJohnny Huang else 676d90825e2SJohnny Huang continue; 677d90825e2SJohnny Huang } else { 678d90825e2SJohnny Huang prog_address |= 1 << 15; 679d90825e2SJohnny Huang if (bit_value) 680d90825e2SJohnny Huang continue; 681d90825e2SJohnny Huang else 682d90825e2SJohnny Huang prog_bit = 0x1 << j; 683d90825e2SJohnny Huang } 684d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 685d90825e2SJohnny Huang } 686d90825e2SJohnny Huang } 687d90825e2SJohnny Huang 68876d13988SJohnny Huang 68976d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 69076d13988SJohnny Huang { 69176d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 69276d13988SJohnny Huang int i, j; 69376d13988SJohnny Huang 69476d13988SJohnny Huang for (j = 0; j < 64; j++) { 69576d13988SJohnny Huang otpstrap[j].value = 0; 69676d13988SJohnny Huang otpstrap[j].remain_times = 7; 69776d13988SJohnny Huang otpstrap[j].writeable_option = -1; 69876d13988SJohnny Huang otpstrap[j].protected = 0; 69976d13988SJohnny Huang } 70076d13988SJohnny Huang 70176d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 70276d13988SJohnny Huang int option = (i - 16) / 2; 70376d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 70476d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 70576d13988SJohnny Huang for (j = 0; j < 32; j++) { 70676d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 70776d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 70876d13988SJohnny Huang otpstrap[j].writeable_option = option; 70976d13988SJohnny Huang } 71076d13988SJohnny Huang if (bit_value == 1) 71176d13988SJohnny Huang otpstrap[j].remain_times --; 71276d13988SJohnny Huang otpstrap[j].value ^= bit_value; 71376d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 71476d13988SJohnny Huang } 71576d13988SJohnny Huang for (j = 32; j < 64; j++) { 71676d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 71776d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 71876d13988SJohnny Huang otpstrap[j].writeable_option = option; 71976d13988SJohnny Huang } 72076d13988SJohnny Huang if (bit_value == 1) 72176d13988SJohnny Huang otpstrap[j].remain_times --; 72276d13988SJohnny Huang otpstrap[j].value ^= bit_value; 72376d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 72476d13988SJohnny Huang } 72576d13988SJohnny Huang } 72676d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 72776d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 72876d13988SJohnny Huang for (j = 0; j < 32; j++) { 72976d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 73076d13988SJohnny Huang otpstrap[j].protected = 1; 73176d13988SJohnny Huang } 73276d13988SJohnny Huang for (j = 32; j < 64; j++) { 73376d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 73476d13988SJohnny Huang otpstrap[j].protected = 1; 73576d13988SJohnny Huang } 73676d13988SJohnny Huang } 73776d13988SJohnny Huang 738b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 73969d5fd8fSJohnny Huang { 740442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 741b458cd62SJohnny Huang uint32_t mask; 742b458cd62SJohnny Huang uint32_t dw_offset; 743b458cd62SJohnny Huang uint32_t bit_offset; 744b458cd62SJohnny Huang uint32_t otp_value; 745b458cd62SJohnny Huang uint32_t otp_keep; 746b458cd62SJohnny Huang int fail = 0; 747b458cd62SJohnny Huang int valid_bit = 0; 74866f2f8e5SJohnny Huang int i; 74966f2f8e5SJohnny Huang 750737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 75166f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 752b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 753b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 754b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 755b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 756b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 757b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 758b458cd62SJohnny Huang 759b458cd62SJohnny Huang if (otp_keep == mask) { 760b458cd62SJohnny Huang continue; 761b458cd62SJohnny Huang } else if (otp_keep != 0) { 762b458cd62SJohnny Huang fail = 1; 763b458cd62SJohnny Huang } 764b458cd62SJohnny Huang 765b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 766b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 767b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 768b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 769b458cd62SJohnny Huang continue; 770b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 771b458cd62SJohnny Huang 772b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 773b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 77466f2f8e5SJohnny Huang } else { 775b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 776b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 777b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 77866f2f8e5SJohnny Huang } 779b458cd62SJohnny Huang printf("0x%-10x", otp_value); 780b458cd62SJohnny Huang 781b458cd62SJohnny Huang if (fail) { 782b458cd62SJohnny Huang printf("Keep mask error\n"); 783b458cd62SJohnny Huang } else { 784b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 785b458cd62SJohnny Huang printf("Reserved\n"); 786b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 787b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 788b458cd62SJohnny Huang printf("\n"); 789b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 790b458cd62SJohnny Huang if (otp_value != 0) { 791b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 792b458cd62SJohnny Huang if (otp_value == (1 << i)) { 793b458cd62SJohnny Huang valid_bit = i + 1; 79466f2f8e5SJohnny Huang } 795b458cd62SJohnny Huang } 796b458cd62SJohnny Huang } else { 797b458cd62SJohnny Huang valid_bit = 0; 798b458cd62SJohnny Huang } 799b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 800b458cd62SJohnny Huang printf("\n"); 801b458cd62SJohnny Huang } else { 802b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 803b458cd62SJohnny Huang } 804b458cd62SJohnny Huang } 805b458cd62SJohnny Huang } 806b458cd62SJohnny Huang 807b458cd62SJohnny Huang if (fail) 808b458cd62SJohnny Huang return OTP_FAILURE; 809b458cd62SJohnny Huang 81066f2f8e5SJohnny Huang return OTP_SUCCESS; 81166f2f8e5SJohnny Huang } 81266f2f8e5SJohnny Huang 8132d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 81466f2f8e5SJohnny Huang { 815b458cd62SJohnny Huang uint32_t OTPCFG[12]; 816b458cd62SJohnny Huang uint32_t mask; 817b458cd62SJohnny Huang uint32_t dw_offset; 818b458cd62SJohnny Huang uint32_t bit_offset; 819b458cd62SJohnny Huang uint32_t otp_value; 820b458cd62SJohnny Huang int valid_bit = 0; 82166f2f8e5SJohnny Huang int i; 82266f2f8e5SJohnny Huang 82366f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 82466f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 82566f2f8e5SJohnny Huang 82666f2f8e5SJohnny Huang 827b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 828b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 829b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 8302d4b0742SJohnny Huang if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset) 8312d4b0742SJohnny Huang continue; 832b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 833b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 834b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 835b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 836b458cd62SJohnny Huang 837b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 838b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 839b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 840b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 841b458cd62SJohnny Huang continue; 842b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 843b458cd62SJohnny Huang 844b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 845b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 846b458cd62SJohnny Huang } else { 847b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 848b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 849b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 850b458cd62SJohnny Huang } 851b458cd62SJohnny Huang printf("0x%-10x", otp_value); 852b458cd62SJohnny Huang 853b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 854b458cd62SJohnny Huang printf("Reserved\n"); 855b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 856b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 857b458cd62SJohnny Huang printf("\n"); 858b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 859b458cd62SJohnny Huang if (otp_value != 0) { 860b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 861b458cd62SJohnny Huang if (otp_value == (1 << i)) { 862b458cd62SJohnny Huang valid_bit = i + 1; 863b458cd62SJohnny Huang } 864b458cd62SJohnny Huang } 865b458cd62SJohnny Huang } else { 866b458cd62SJohnny Huang valid_bit = 0; 867b458cd62SJohnny Huang } 868b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 869b458cd62SJohnny Huang printf("\n"); 870b458cd62SJohnny Huang } else { 871b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 872b458cd62SJohnny Huang } 873b458cd62SJohnny Huang } 874b458cd62SJohnny Huang return OTP_SUCCESS; 87566f2f8e5SJohnny Huang } 87666f2f8e5SJohnny Huang 877b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 87876d13988SJohnny Huang { 879a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 880a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 88176d13988SJohnny Huang int i; 882a8bd6d8cSJohnny Huang int fail = 0; 883a8bd6d8cSJohnny Huang uint32_t bit_offset; 884a8bd6d8cSJohnny Huang uint32_t dw_offset; 885a8bd6d8cSJohnny Huang uint32_t mask; 886a8bd6d8cSJohnny Huang uint32_t otp_value; 887a8bd6d8cSJohnny Huang uint32_t otp_protect; 888a8bd6d8cSJohnny Huang uint32_t otp_keep; 88976d13988SJohnny Huang 890a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 891a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 892b458cd62SJohnny Huang 893a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 894a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 895a8bd6d8cSJohnny Huang dw_offset = 1; 896a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 897a8bd6d8cSJohnny Huang } else { 898a8bd6d8cSJohnny Huang dw_offset = 0; 899a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 900a8bd6d8cSJohnny Huang } 90176d13988SJohnny Huang 902a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 903a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 904a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 905a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 906a8bd6d8cSJohnny Huang 907a8bd6d8cSJohnny Huang if (otp_keep == mask) { 908a8bd6d8cSJohnny Huang continue; 909a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 910a8bd6d8cSJohnny Huang fail = 1; 911a8bd6d8cSJohnny Huang } 912a8bd6d8cSJohnny Huang 913a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 914a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 915a8bd6d8cSJohnny Huang continue; 916a8bd6d8cSJohnny Huang 917a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 918b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 919a8bd6d8cSJohnny Huang } else { 920b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 921a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 922a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 923a8bd6d8cSJohnny Huang } 924a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 925a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 926a8bd6d8cSJohnny Huang 927a8bd6d8cSJohnny Huang if (fail) { 928a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 929a8bd6d8cSJohnny Huang } else { 930a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 931a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 932a8bd6d8cSJohnny Huang else 933a8bd6d8cSJohnny Huang printf("Reserved\n"); 934a8bd6d8cSJohnny Huang } 935a8bd6d8cSJohnny Huang } 936a8bd6d8cSJohnny Huang 937a8bd6d8cSJohnny Huang if (fail) 93876d13988SJohnny Huang return OTP_FAILURE; 93976d13988SJohnny Huang 94076d13988SJohnny Huang return OTP_SUCCESS; 94176d13988SJohnny Huang } 94276d13988SJohnny Huang 943b458cd62SJohnny Huang static int otp_print_strap_info(int view) 94476d13988SJohnny Huang { 94576d13988SJohnny Huang struct otpstrap_status strap_status[64]; 94607baa4e8SJohnny Huang int i, j; 947b458cd62SJohnny Huang int fail = 0; 948b458cd62SJohnny Huang uint32_t bit_offset; 949b458cd62SJohnny Huang uint32_t length; 950b458cd62SJohnny Huang uint32_t otp_value; 951b458cd62SJohnny Huang uint32_t otp_protect; 95276d13988SJohnny Huang 95376d13988SJohnny Huang otp_strp_status(strap_status); 95476d13988SJohnny Huang 955b458cd62SJohnny Huang if (view) { 95607baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 95707baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 95807baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 95907baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 960b458cd62SJohnny Huang } else { 961b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 962b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 96376d13988SJohnny Huang } 964b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 965b458cd62SJohnny Huang otp_value = 0; 966b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 967b458cd62SJohnny Huang length = a0_strap_info[i].length; 968b458cd62SJohnny Huang for (j = 0; j < length; j++) { 969c947ef08SJohnny Huang otp_value |= strap_status[bit_offset + j].value << j; 970c947ef08SJohnny Huang otp_protect |= strap_status[bit_offset + j].protected << j; 971b458cd62SJohnny Huang } 972b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 973b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 974b458cd62SJohnny Huang continue; 975b458cd62SJohnny Huang if (view) { 976b458cd62SJohnny Huang for (j = 0; j < length; j++) { 977b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 978b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 97907baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 980b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 981b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 982b458cd62SJohnny Huang printf(" Reserved\n"); 983b458cd62SJohnny Huang continue; 984b458cd62SJohnny Huang } 985b458cd62SJohnny Huang if (length == 1) { 986b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 987b458cd62SJohnny Huang continue; 98876d13988SJohnny Huang } 98976d13988SJohnny Huang 990b458cd62SJohnny Huang if (j == 0) 991b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 992b458cd62SJohnny Huang else if (j == length - 1) 993b458cd62SJohnny Huang printf("\\ \"\n"); 994b458cd62SJohnny Huang else 995b458cd62SJohnny Huang printf("| \"\n"); 99676d13988SJohnny Huang } 997b458cd62SJohnny Huang } else { 998c947ef08SJohnny Huang if (length == 1) { 999b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 1000b458cd62SJohnny Huang } else { 1001b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1002b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1003b458cd62SJohnny Huang } 1004b458cd62SJohnny Huang 1005b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1006b458cd62SJohnny Huang 1007b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 1008b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 1009b458cd62SJohnny Huang else 1010b458cd62SJohnny Huang printf("Reserved\n"); 1011b458cd62SJohnny Huang } 1012b458cd62SJohnny Huang } 1013b458cd62SJohnny Huang 1014b458cd62SJohnny Huang if (fail) 1015b458cd62SJohnny Huang return OTP_FAILURE; 1016b458cd62SJohnny Huang 1017b458cd62SJohnny Huang return OTP_SUCCESS; 1018b458cd62SJohnny Huang } 1019b458cd62SJohnny Huang 102069d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 102169d5fd8fSJohnny Huang { 102269d5fd8fSJohnny Huang int i; 102369d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 102469d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 102569d5fd8fSJohnny Huang if (i % 16 == 0) { 102669d5fd8fSJohnny Huang printf("%04X: ", i); 102769d5fd8fSJohnny Huang } 102869d5fd8fSJohnny Huang printf("%02X ", buf[i]); 102969d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 103069d5fd8fSJohnny Huang printf("\n"); 103169d5fd8fSJohnny Huang } 103269d5fd8fSJohnny Huang } 103369d5fd8fSJohnny Huang } 103469d5fd8fSJohnny Huang 10357f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 103669d5fd8fSJohnny Huang { 103769d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 103869d5fd8fSJohnny Huang char *byte_buf; 103969d5fd8fSJohnny Huang int i = 0, len = 0; 104069d5fd8fSJohnny Huang byte_buf = (char *)buf; 104169d5fd8fSJohnny Huang while (1) { 104269d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 104369d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 104469d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 104569d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 104669d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 104769d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 10487f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 104969d5fd8fSJohnny Huang printf("Key Type: "); 105069d5fd8fSJohnny Huang switch (key_type) { 105169d5fd8fSJohnny Huang case 0: 105269d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 105369d5fd8fSJohnny Huang break; 105469d5fd8fSJohnny Huang case 1: 105569d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 105669d5fd8fSJohnny Huang break; 105769d5fd8fSJohnny Huang case 4: 105869d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 105969d5fd8fSJohnny Huang break; 106069d5fd8fSJohnny Huang case 8: 106169d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 106269d5fd8fSJohnny Huang break; 106369d5fd8fSJohnny Huang case 9: 106469d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 106569d5fd8fSJohnny Huang break; 106669d5fd8fSJohnny Huang case 10: 106769d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 106869d5fd8fSJohnny Huang break; 106969d5fd8fSJohnny Huang case 13: 107069d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 107169d5fd8fSJohnny Huang break; 107269d5fd8fSJohnny Huang case 14: 107369d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 107469d5fd8fSJohnny Huang break; 107569d5fd8fSJohnny Huang default: 107669d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 107769d5fd8fSJohnny Huang return -1; 107869d5fd8fSJohnny Huang } 107969d5fd8fSJohnny Huang if (key_type == 4) { 108069d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 108169d5fd8fSJohnny Huang switch (key_length) { 108269d5fd8fSJohnny Huang case 0: 108369d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 108469d5fd8fSJohnny Huang break; 108569d5fd8fSJohnny Huang case 1: 108669d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 108769d5fd8fSJohnny Huang break; 108869d5fd8fSJohnny Huang case 2: 108969d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 109069d5fd8fSJohnny Huang break; 109169d5fd8fSJohnny Huang case 3: 109269d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 109369d5fd8fSJohnny Huang break; 109469d5fd8fSJohnny Huang } 1095cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 109669d5fd8fSJohnny Huang printf("RSA SHA Type: "); 109769d5fd8fSJohnny Huang switch (key_length) { 109869d5fd8fSJohnny Huang case 0: 109969d5fd8fSJohnny Huang printf("RSA1024\n"); 110069d5fd8fSJohnny Huang len = 0x100; 110169d5fd8fSJohnny Huang break; 110269d5fd8fSJohnny Huang case 1: 110369d5fd8fSJohnny Huang printf("RSA2048\n"); 110469d5fd8fSJohnny Huang len = 0x200; 110569d5fd8fSJohnny Huang break; 110669d5fd8fSJohnny Huang case 2: 110769d5fd8fSJohnny Huang printf("RSA3072\n"); 110869d5fd8fSJohnny Huang len = 0x300; 110969d5fd8fSJohnny Huang break; 111069d5fd8fSJohnny Huang case 3: 111169d5fd8fSJohnny Huang printf("RSA4096\n"); 111269d5fd8fSJohnny Huang len = 0x400; 111369d5fd8fSJohnny Huang break; 111469d5fd8fSJohnny Huang } 111569d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 111669d5fd8fSJohnny Huang } 111769d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 111869d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 111969d5fd8fSJohnny Huang printf("Key Value:\n"); 112069d5fd8fSJohnny Huang if (key_type == 4) { 112169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 112269d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 112369d5fd8fSJohnny Huang printf("AES Key:\n"); 112469d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 112569d5fd8fSJohnny Huang printf("AES IV:\n"); 112669d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 112769d5fd8fSJohnny Huang 112869d5fd8fSJohnny Huang } else { 112969d5fd8fSJohnny Huang printf("RSA mod:\n"); 113069d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 113169d5fd8fSJohnny Huang printf("RSA exp:\n"); 113269d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 113369d5fd8fSJohnny Huang } 113469d5fd8fSJohnny Huang if (last) 113569d5fd8fSJohnny Huang break; 113669d5fd8fSJohnny Huang i++; 113769d5fd8fSJohnny Huang } 113869d5fd8fSJohnny Huang return 0; 113969d5fd8fSJohnny Huang } 114069d5fd8fSJohnny Huang 1141a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 114269d5fd8fSJohnny Huang { 1143a6d0d645SJohnny Huang int i, k; 1144d90825e2SJohnny Huang int pass = 0; 1145d90825e2SJohnny Huang int soak = 0; 1146a6d0d645SJohnny Huang uint32_t prog_address; 1147a6d0d645SJohnny Huang uint32_t data[12]; 1148a6d0d645SJohnny Huang uint32_t compare[2]; 1149d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1150d90825e2SJohnny Huang uint32_t data_masked; 1151d90825e2SJohnny Huang uint32_t buf_masked; 115269d5fd8fSJohnny Huang 1153a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1154a6d0d645SJohnny Huang 1155a6d0d645SJohnny Huang printProgress(0, 12, ""); 1156a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1157a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 115869d5fd8fSJohnny Huang prog_address = 0x800; 1159a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1160a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1161a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1162a6d0d645SJohnny Huang } 1163a6d0d645SJohnny Huang 1164a6d0d645SJohnny Huang printf("Check writable...\n"); 1165a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1166d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1167d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1168d90825e2SJohnny Huang if (data_masked == buf_masked) 116969d5fd8fSJohnny Huang continue; 1170d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1171a6d0d645SJohnny Huang continue; 1172a6d0d645SJohnny Huang } else { 1173a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1174a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1175a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1176a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 11772a856b9aSJohnny Huang return OTP_FAILURE; 1178a6d0d645SJohnny Huang } 1179a6d0d645SJohnny Huang } 1180a6d0d645SJohnny Huang 1181a6d0d645SJohnny Huang printf("Start Programing...\n"); 1182a6d0d645SJohnny Huang printProgress(0, 12, ""); 1183d90825e2SJohnny Huang otp_soak(0); 1184a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1185d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1186d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1187a6d0d645SJohnny Huang prog_address = 0x800; 1188a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1189a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1190d90825e2SJohnny Huang if (data_masked == buf_masked) { 1191a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1192a6d0d645SJohnny Huang continue; 1193a6d0d645SJohnny Huang } 1194d90825e2SJohnny Huang if (soak) { 1195d90825e2SJohnny Huang soak = 0; 1196d90825e2SJohnny Huang otp_soak(0); 1197d90825e2SJohnny Huang } 1198a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1199a6d0d645SJohnny Huang 1200d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1201a6d0d645SJohnny Huang 120269d5fd8fSJohnny Huang pass = 0; 120369d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1204d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1205d90825e2SJohnny Huang if (soak == 0) { 1206d90825e2SJohnny Huang soak = 1; 1207d90825e2SJohnny Huang otp_soak(1); 1208d90825e2SJohnny Huang } 1209a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1210a6d0d645SJohnny Huang } else { 121169d5fd8fSJohnny Huang pass = 1; 121269d5fd8fSJohnny Huang break; 121369d5fd8fSJohnny Huang } 121469d5fd8fSJohnny Huang } 1215a6d0d645SJohnny Huang } 1216a6d0d645SJohnny Huang 121769d5fd8fSJohnny Huang if (!pass) 12182a856b9aSJohnny Huang return OTP_FAILURE; 1219a6d0d645SJohnny Huang 12202a856b9aSJohnny Huang return OTP_SUCCESS; 1221d90825e2SJohnny Huang 122269d5fd8fSJohnny Huang } 122369d5fd8fSJohnny Huang 122469d5fd8fSJohnny Huang 122576d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 122669d5fd8fSJohnny Huang { 122769d5fd8fSJohnny Huang int i; 122869d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 122969d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 123069d5fd8fSJohnny Huang int bit, pbit, kbit; 123169d5fd8fSJohnny Huang int fail = 0; 1232a6af4a17SJohnny Huang int skip = -1; 123366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 123469d5fd8fSJohnny Huang 123569d5fd8fSJohnny Huang otp_strp_status(otpstrap); 123669d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 123769d5fd8fSJohnny Huang if (i < 32) { 123869d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 123969d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 124069d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 124169d5fd8fSJohnny Huang } else { 124269d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 124369d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 124469d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 124569d5fd8fSJohnny Huang } 124669d5fd8fSJohnny Huang 124769d5fd8fSJohnny Huang if (kbit == 1) { 124869d5fd8fSJohnny Huang continue; 124969d5fd8fSJohnny Huang } else { 1250a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 125169d5fd8fSJohnny Huang } 125269d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 125369d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1254a6af4a17SJohnny Huang if (skip == -1) 1255a6af4a17SJohnny Huang skip = 1; 125669d5fd8fSJohnny Huang continue; 1257a6af4a17SJohnny Huang } else { 1258a6af4a17SJohnny Huang skip = 0; 125969d5fd8fSJohnny Huang } 126069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 126169d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 126269d5fd8fSJohnny Huang fail = 1; 126369d5fd8fSJohnny Huang continue; 126469d5fd8fSJohnny Huang } 126569d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1266a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 126769d5fd8fSJohnny Huang fail = 1; 126869d5fd8fSJohnny Huang continue; 126969d5fd8fSJohnny Huang } 127069d5fd8fSJohnny Huang if (pbit == 1) { 127169d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 127269d5fd8fSJohnny Huang } 1273a6af4a17SJohnny 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); 127469d5fd8fSJohnny Huang } 127569d5fd8fSJohnny Huang if (fail == 1) 1276a6af4a17SJohnny Huang return OTP_FAILURE; 1277a6af4a17SJohnny Huang else if (skip == 1) 1278a6af4a17SJohnny Huang return OTP_PROG_SKIP; 12797e22f42dSJohnny Huang 12807e22f42dSJohnny Huang return 0; 128169d5fd8fSJohnny Huang } 128269d5fd8fSJohnny Huang 12832a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 128469d5fd8fSJohnny Huang { 128569d5fd8fSJohnny Huang int i, j; 128666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 128769d5fd8fSJohnny Huang 12882a856b9aSJohnny Huang if (start < 0 || start > 64) 12892a856b9aSJohnny Huang return OTP_USAGE; 12902a856b9aSJohnny Huang 12912a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 12922a856b9aSJohnny Huang return OTP_USAGE; 12932a856b9aSJohnny Huang 129469d5fd8fSJohnny Huang otp_strp_status(otpstrap); 129569d5fd8fSJohnny Huang 129607baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1297a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1298737ed20bSJohnny Huang 1299cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 130007baa4e8SJohnny Huang printf("0x%-8X", i); 1301737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1302737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1303737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1304737ed20bSJohnny Huang printf(" "); 130569d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1306737ed20bSJohnny Huang printf("protected and not writable"); 130769d5fd8fSJohnny Huang } else { 1308737ed20bSJohnny Huang printf("not protected "); 130969d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1310737ed20bSJohnny Huang printf("and no remaining times to write."); 131169d5fd8fSJohnny Huang } else { 1312737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 131369d5fd8fSJohnny Huang } 131469d5fd8fSJohnny Huang } 1315737ed20bSJohnny Huang printf("\n"); 131669d5fd8fSJohnny Huang } 13172a856b9aSJohnny Huang 13182a856b9aSJohnny Huang return OTP_SUCCESS; 131969d5fd8fSJohnny Huang } 132069d5fd8fSJohnny Huang 132169d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 132269d5fd8fSJohnny Huang { 132369d5fd8fSJohnny Huang int i, j; 132469d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 132569d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 132669d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 132769d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 132869d5fd8fSJohnny Huang int fail = 0; 13297e22f42dSJohnny Huang int pass = 0; 13307e22f42dSJohnny Huang int soak = 0; 133166f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 133269d5fd8fSJohnny Huang 13337f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 133469d5fd8fSJohnny Huang otp_strp_status(otpstrap); 133569d5fd8fSJohnny Huang 13367f795e57SJohnny Huang printf("Check writable...\n"); 13377f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 13387f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 13397f795e57SJohnny Huang return OTP_FAILURE; 13407f795e57SJohnny Huang } 13417e22f42dSJohnny Huang 13427f795e57SJohnny Huang otp_soak(0); 134369d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 13444c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 134569d5fd8fSJohnny Huang prog_address = 0x800; 134669d5fd8fSJohnny Huang if (i < 32) { 134769d5fd8fSJohnny Huang offset = i; 134869d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 134969d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 135069d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 135169d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 135269d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 135369d5fd8fSJohnny Huang 135469d5fd8fSJohnny Huang } else { 135569d5fd8fSJohnny Huang offset = (i - 32); 135669d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 135769d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 135869d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 135969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 136069d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 136169d5fd8fSJohnny Huang } 136269d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 136369d5fd8fSJohnny Huang 136469d5fd8fSJohnny Huang if (kbit == 1) { 136569d5fd8fSJohnny Huang continue; 136669d5fd8fSJohnny Huang } 136769d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 136869d5fd8fSJohnny Huang continue; 136969d5fd8fSJohnny Huang } 137069d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 137169d5fd8fSJohnny Huang fail = 1; 137269d5fd8fSJohnny Huang continue; 137369d5fd8fSJohnny Huang } 137469d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 137569d5fd8fSJohnny Huang fail = 1; 137669d5fd8fSJohnny Huang continue; 137769d5fd8fSJohnny Huang } 13787e22f42dSJohnny Huang 13797e22f42dSJohnny Huang if (soak) { 138069d5fd8fSJohnny Huang soak = 0; 13817e22f42dSJohnny Huang otp_soak(0); 13827e22f42dSJohnny Huang } 13837e22f42dSJohnny Huang 13847e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 13857e22f42dSJohnny Huang 13867e22f42dSJohnny Huang pass = 0; 13877e22f42dSJohnny Huang 138869d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1389a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 139069d5fd8fSJohnny Huang pass = 1; 139169d5fd8fSJohnny Huang break; 139269d5fd8fSJohnny Huang } 13937e22f42dSJohnny Huang if (soak == 0) { 139469d5fd8fSJohnny Huang soak = 1; 13957e22f42dSJohnny Huang otp_soak(1); 13964b65a65dSJohnny Huang } 139769d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 139869d5fd8fSJohnny Huang } 139969d5fd8fSJohnny Huang if (!pass) 14002a856b9aSJohnny Huang return OTP_FAILURE; 140169d5fd8fSJohnny Huang 140269d5fd8fSJohnny Huang if (pbit == 0) 140369d5fd8fSJohnny Huang continue; 140469d5fd8fSJohnny Huang prog_address = 0x800; 140569d5fd8fSJohnny Huang if (i < 32) 140669d5fd8fSJohnny Huang prog_address |= 0x60c; 140769d5fd8fSJohnny Huang else 140869d5fd8fSJohnny Huang prog_address |= 0x60e; 140969d5fd8fSJohnny Huang 14107e22f42dSJohnny Huang 14117e22f42dSJohnny Huang if (soak) { 14127e22f42dSJohnny Huang soak = 0; 14137e22f42dSJohnny Huang otp_soak(0); 14147e22f42dSJohnny Huang } 14157e22f42dSJohnny Huang 14167e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14177e22f42dSJohnny Huang 14187e22f42dSJohnny Huang pass = 0; 14197e22f42dSJohnny Huang 142069d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 14217e22f42dSJohnny Huang 1422a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 142369d5fd8fSJohnny Huang pass = 1; 142469d5fd8fSJohnny Huang break; 142569d5fd8fSJohnny Huang } 14267e22f42dSJohnny Huang if (soak == 0) { 142769d5fd8fSJohnny Huang soak = 1; 14287e22f42dSJohnny Huang otp_soak(1); 142969d5fd8fSJohnny Huang } 143069d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 143169d5fd8fSJohnny Huang } 143269d5fd8fSJohnny Huang if (!pass) 14332a856b9aSJohnny Huang return OTP_FAILURE; 143469d5fd8fSJohnny Huang 143569d5fd8fSJohnny Huang } 143669d5fd8fSJohnny Huang if (fail == 1) 14372a856b9aSJohnny Huang return OTP_FAILURE; 143869d5fd8fSJohnny Huang else 14392a856b9aSJohnny Huang return OTP_SUCCESS; 144069d5fd8fSJohnny Huang 144169d5fd8fSJohnny Huang } 144269d5fd8fSJohnny Huang 1443cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1444cd1610b4SJohnny Huang { 1445cd1610b4SJohnny Huang int prog_bit; 1446cd1610b4SJohnny Huang 14477e22f42dSJohnny Huang otp_soak(soak); 14487e22f42dSJohnny Huang 1449cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1450cd1610b4SJohnny Huang if (value) 1451cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1452cd1610b4SJohnny Huang else 1453cd1610b4SJohnny Huang return; 1454cd1610b4SJohnny Huang } else { 1455cd1610b4SJohnny Huang prog_address |= 1 << 15; 1456cd1610b4SJohnny Huang if (!value) 1457cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1458cd1610b4SJohnny Huang else 1459cd1610b4SJohnny Huang return; 1460cd1610b4SJohnny Huang } 1461cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1462cd1610b4SJohnny Huang } 1463cd1610b4SJohnny Huang 1464d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 14654c1c9b35SJohnny Huang { 14664c1c9b35SJohnny Huang int i, k; 14674c1c9b35SJohnny Huang int pass; 1468d90825e2SJohnny Huang int soak = 0; 14694c1c9b35SJohnny Huang uint32_t prog_address; 1470d90825e2SJohnny Huang uint32_t data[2048]; 14714c1c9b35SJohnny Huang uint32_t compare[2]; 1472d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 14734c1c9b35SJohnny Huang 1474d90825e2SJohnny Huang uint32_t data0_masked; 1475d90825e2SJohnny Huang uint32_t data1_masked; 1476d90825e2SJohnny Huang uint32_t buf0_masked; 1477d90825e2SJohnny Huang uint32_t buf1_masked; 14784c1c9b35SJohnny Huang 14794c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 14804c1c9b35SJohnny Huang 1481d90825e2SJohnny Huang printProgress(0, 2048, ""); 1482d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1483d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1484d90825e2SJohnny Huang otp_read_data(i, &data[i]); 14854c1c9b35SJohnny Huang } 1486d90825e2SJohnny Huang 14874c1c9b35SJohnny Huang 14884c1c9b35SJohnny Huang printf("Check writable...\n"); 1489d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1490d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1491d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1492d90825e2SJohnny Huang if (data0_masked == buf0_masked) 14934c1c9b35SJohnny Huang continue; 1494d90825e2SJohnny Huang if (i % 2 == 0) { 1495d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 14964c1c9b35SJohnny Huang continue; 14974c1c9b35SJohnny Huang } else { 14984c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1499d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 15004c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1501d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15022a856b9aSJohnny Huang return OTP_FAILURE; 150369d5fd8fSJohnny Huang } 1504d90825e2SJohnny Huang } else { 1505d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1506d90825e2SJohnny Huang continue; 1507d90825e2SJohnny Huang } else { 1508d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1509d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1510d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1511d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15122a856b9aSJohnny Huang return OTP_FAILURE; 1513d90825e2SJohnny Huang } 1514d90825e2SJohnny Huang } 1515d90825e2SJohnny Huang } 151669d5fd8fSJohnny Huang 1517d90825e2SJohnny Huang printf("Start Programing...\n"); 1518d90825e2SJohnny Huang printProgress(0, 2048, ""); 1519d90825e2SJohnny Huang 1520d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1521d90825e2SJohnny Huang prog_address = i; 1522d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1523d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1524d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1525d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1526d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1527d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1528d90825e2SJohnny Huang continue; 1529d90825e2SJohnny Huang } 1530d90825e2SJohnny Huang if (soak) { 1531d90825e2SJohnny Huang soak = 0; 1532d90825e2SJohnny Huang otp_soak(0); 1533d90825e2SJohnny Huang } 1534d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1535d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1536d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1537d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1538d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1539d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1540d90825e2SJohnny Huang } else { 1541d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1542d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1543d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1544d90825e2SJohnny Huang } 1545d90825e2SJohnny Huang 1546d90825e2SJohnny Huang pass = 0; 1547d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1548d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1549d90825e2SJohnny Huang if (soak == 0) { 1550d90825e2SJohnny Huang soak = 1; 1551d90825e2SJohnny Huang otp_soak(1); 1552d90825e2SJohnny Huang } 1553d90825e2SJohnny Huang if (compare[0] != 0) { 1554d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1555d90825e2SJohnny Huang } 1556d90825e2SJohnny Huang if (compare[1] != ~0) { 1557d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1558d90825e2SJohnny Huang } 1559d90825e2SJohnny Huang } else { 1560d90825e2SJohnny Huang pass = 1; 1561d90825e2SJohnny Huang break; 1562d90825e2SJohnny Huang } 1563d90825e2SJohnny Huang } 1564d90825e2SJohnny Huang 1565d90825e2SJohnny Huang if (!pass) 15662a856b9aSJohnny Huang return OTP_FAILURE; 1567d90825e2SJohnny Huang } 15682a856b9aSJohnny Huang return OTP_SUCCESS; 1569d90825e2SJohnny Huang 1570d90825e2SJohnny Huang } 1571d90825e2SJohnny Huang 1572d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 157369d5fd8fSJohnny Huang { 157469d5fd8fSJohnny Huang int ret; 1575*7332532cSJohnny Huang int mode = 0; 157669d5fd8fSJohnny Huang uint32_t *buf; 1577d90825e2SJohnny Huang uint32_t *data_region = NULL; 1578d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1579d90825e2SJohnny Huang uint32_t *strap_region = NULL; 158069d5fd8fSJohnny Huang 1581d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 158269d5fd8fSJohnny Huang if (!buf) { 158369d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 15842a856b9aSJohnny Huang return OTP_FAILURE; 158569d5fd8fSJohnny Huang } 1586d90825e2SJohnny Huang 1587d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 1588*7332532cSJohnny Huang mode |= OTP_REGION_DATA; 1589*7332532cSJohnny Huang data_region = &buf[36]; 1590d90825e2SJohnny Huang } 1591d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 1592*7332532cSJohnny Huang mode |= OTP_REGION_CONF; 1593*7332532cSJohnny Huang conf_region = &buf[12]; 1594d90825e2SJohnny Huang } 1595d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 1596*7332532cSJohnny Huang mode |= OTP_REGION_STRAP; 1597*7332532cSJohnny Huang strap_region = &buf[4]; 1598d90825e2SJohnny Huang } 1599*7332532cSJohnny Huang 160069d5fd8fSJohnny Huang if (!nconfirm) { 1601*7332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 16027f795e57SJohnny Huang printf("\nOTP data region :\n"); 16037f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 160469d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16052a856b9aSJohnny Huang return OTP_FAILURE; 160669d5fd8fSJohnny Huang } 160769d5fd8fSJohnny Huang } 1608*7332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 1609*7332532cSJohnny Huang printf("\nOTP strap region :\n"); 1610*7332532cSJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 1611*7332532cSJohnny Huang printf("OTP strap error, please check.\n"); 1612*7332532cSJohnny Huang return OTP_FAILURE; 1613*7332532cSJohnny Huang } 1614*7332532cSJohnny Huang } 1615*7332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 1616*7332532cSJohnny Huang printf("\nOTP configuration region :\n"); 1617*7332532cSJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 1618*7332532cSJohnny Huang printf("OTP config error, please check.\n"); 1619*7332532cSJohnny Huang return OTP_FAILURE; 1620*7332532cSJohnny Huang } 1621*7332532cSJohnny Huang } 1622*7332532cSJohnny Huang 162369d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 162469d5fd8fSJohnny Huang if (!confirm_yesno()) { 162569d5fd8fSJohnny Huang printf(" Aborting\n"); 16262a856b9aSJohnny Huang return OTP_FAILURE; 162769d5fd8fSJohnny Huang } 162869d5fd8fSJohnny Huang } 1629*7332532cSJohnny Huang 1630*7332532cSJohnny Huang if (mode & OTP_REGION_DATA) { 1631*7332532cSJohnny Huang printf("programing data region ...\n"); 1632d90825e2SJohnny Huang ret = otp_prog_data(data_region); 16332a856b9aSJohnny Huang if (ret != 0) { 163469d5fd8fSJohnny Huang printf("Error\n"); 163569d5fd8fSJohnny Huang return ret; 163669d5fd8fSJohnny Huang } else { 163769d5fd8fSJohnny Huang printf("Done\n"); 163869d5fd8fSJohnny Huang } 1639*7332532cSJohnny Huang } 1640*7332532cSJohnny Huang if (mode & OTP_REGION_STRAP) { 1641*7332532cSJohnny Huang printf("programing strap region ...\n"); 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 } 1649*7332532cSJohnny Huang } 1650*7332532cSJohnny Huang if (mode & OTP_REGION_CONF) { 1651*7332532cSJohnny Huang printf("programing configuration region ...\n"); 1652d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 16532a856b9aSJohnny Huang if (ret != 0) { 165469d5fd8fSJohnny Huang printf("Error\n"); 165569d5fd8fSJohnny Huang return ret; 165669d5fd8fSJohnny Huang } 165769d5fd8fSJohnny Huang printf("Done\n"); 165869d5fd8fSJohnny Huang } 1659cd1610b4SJohnny Huang 1660*7332532cSJohnny Huang return OTP_SUCCESS; 16612a856b9aSJohnny Huang } 16622a856b9aSJohnny Huang 16632a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1664cd1610b4SJohnny Huang { 1665a6af4a17SJohnny Huang uint32_t read[2]; 1666cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1667d90825e2SJohnny Huang uint32_t prog_address = 0; 166866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1669cd1610b4SJohnny Huang int otp_bit; 1670cd1610b4SJohnny Huang int i; 1671cd1610b4SJohnny Huang int pass; 1672a6af4a17SJohnny Huang int ret; 1673cd1610b4SJohnny Huang 1674cd1610b4SJohnny Huang switch (mode) { 1675a6d0d645SJohnny Huang case OTP_REGION_CONF: 1676a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1677cd1610b4SJohnny Huang prog_address = 0x800; 1678cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1679cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1680a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1681cd1610b4SJohnny Huang if (otp_bit == value) { 1682a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1683cd1610b4SJohnny Huang printf("No need to program\n"); 16842a856b9aSJohnny Huang return OTP_SUCCESS; 1685cd1610b4SJohnny Huang } 1686cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1687a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1688cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 16892a856b9aSJohnny Huang return OTP_FAILURE; 1690cd1610b4SJohnny Huang } 1691a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1692cd1610b4SJohnny Huang break; 1693a6d0d645SJohnny Huang case OTP_REGION_DATA: 1694cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1695cd1610b4SJohnny Huang 1696cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1697a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1698a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1699cd1610b4SJohnny Huang } else { 1700a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1701a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1702cd1610b4SJohnny Huang } 1703cd1610b4SJohnny Huang if (otp_bit == value) { 1704a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1705cd1610b4SJohnny Huang printf("No need to program\n"); 17062a856b9aSJohnny Huang return OTP_SUCCESS; 1707cd1610b4SJohnny Huang } 1708cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1709a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1710cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17112a856b9aSJohnny Huang return OTP_FAILURE; 1712cd1610b4SJohnny Huang } 1713a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1714cd1610b4SJohnny Huang break; 1715a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1716cd1610b4SJohnny Huang otp_strp_status(otpstrap); 1717cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1718cd1610b4SJohnny Huang if (bit_offset < 32) { 1719cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1720cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1721cd1610b4SJohnny Huang strap_buf[3] = ~0; 1722cd1610b4SJohnny Huang strap_buf[5] = 0; 17232a856b9aSJohnny Huang // if (protect) 17242a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 17252a856b9aSJohnny Huang // else 17262a856b9aSJohnny Huang // strap_buf[4] = 0; 1727cd1610b4SJohnny Huang } else { 1728cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1729cd1610b4SJohnny Huang strap_buf[2] = ~0; 1730cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1731cd1610b4SJohnny Huang strap_buf[4] = 0; 17322a856b9aSJohnny Huang // if (protect) 17332a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 17342a856b9aSJohnny Huang // else 17352a856b9aSJohnny Huang // strap_buf[5] = 0; 1736cd1610b4SJohnny Huang } 173776d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1738a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 17392a856b9aSJohnny Huang return OTP_FAILURE; 1740a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1741a6af4a17SJohnny Huang return OTP_SUCCESS; 1742a6af4a17SJohnny Huang 1743cd1610b4SJohnny Huang break; 1744cd1610b4SJohnny Huang } 1745cd1610b4SJohnny Huang 1746cd1610b4SJohnny Huang if (!nconfirm) { 1747cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1748cd1610b4SJohnny Huang if (!confirm_yesno()) { 1749cd1610b4SJohnny Huang printf(" Aborting\n"); 17502a856b9aSJohnny Huang return OTP_FAILURE; 1751cd1610b4SJohnny Huang } 1752cd1610b4SJohnny Huang } 1753cd1610b4SJohnny Huang 1754cd1610b4SJohnny Huang switch (mode) { 1755a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1756cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1757a6d0d645SJohnny Huang case OTP_REGION_CONF: 1758a6d0d645SJohnny Huang case OTP_REGION_DATA: 1759cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1760cd1610b4SJohnny Huang pass = -1; 1761cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1762a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1763cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1764cd1610b4SJohnny Huang } else { 1765cd1610b4SJohnny Huang pass = 0; 1766cd1610b4SJohnny Huang break; 1767cd1610b4SJohnny Huang } 1768cd1610b4SJohnny Huang } 17692a856b9aSJohnny Huang if (pass == 0) 17702a856b9aSJohnny Huang return OTP_SUCCESS; 1771cd1610b4SJohnny Huang } 1772cd1610b4SJohnny Huang 17732a856b9aSJohnny Huang return OTP_USAGE; 1774cd1610b4SJohnny Huang } 1775cd1610b4SJohnny Huang 17762a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 177769d5fd8fSJohnny Huang { 17782a856b9aSJohnny Huang uint32_t offset, count; 17792a856b9aSJohnny Huang int ret; 178069d5fd8fSJohnny Huang 17812a856b9aSJohnny Huang if (argc == 4) { 17822a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17832a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 17842a856b9aSJohnny Huang } else if (argc == 3) { 17852a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 17862a856b9aSJohnny Huang count = 1; 17872a856b9aSJohnny Huang } else { 178869d5fd8fSJohnny Huang return CMD_RET_USAGE; 178969d5fd8fSJohnny Huang } 179069d5fd8fSJohnny Huang 179169d5fd8fSJohnny Huang 17922a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 179369d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17942a856b9aSJohnny Huang ret = otp_print_config(offset, count); 17952a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 17962a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 17972a856b9aSJohnny Huang ret = otp_print_data(offset, count); 17982a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 17992a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18002a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 18012a856b9aSJohnny Huang } else { 18022a856b9aSJohnny Huang return CMD_RET_USAGE; 180369d5fd8fSJohnny Huang } 180469d5fd8fSJohnny Huang 18052a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18062a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18072a856b9aSJohnny Huang else 18082a856b9aSJohnny Huang return CMD_RET_USAGE; 18092a856b9aSJohnny Huang 18102a856b9aSJohnny Huang } 18112a856b9aSJohnny Huang 18122a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18132a856b9aSJohnny Huang { 18142a856b9aSJohnny Huang phys_addr_t addr; 18152a856b9aSJohnny Huang uint32_t byte_size; 18162a856b9aSJohnny Huang int ret; 18172a856b9aSJohnny Huang 18182a856b9aSJohnny Huang if (argc == 4) { 18192a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 18202a856b9aSJohnny Huang return CMD_RET_USAGE; 18212a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 18222a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 182369d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18242a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 18252a856b9aSJohnny Huang } else if (argc == 3) { 18262a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 18272a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 18282a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18292a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 18302a856b9aSJohnny Huang } else { 18312a856b9aSJohnny Huang return CMD_RET_USAGE; 18322a856b9aSJohnny Huang } 18332a856b9aSJohnny Huang 18342a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18352a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18362a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18372a856b9aSJohnny Huang return CMD_RET_FAILURE; 18382a856b9aSJohnny Huang else 18392a856b9aSJohnny Huang return CMD_RET_USAGE; 18402a856b9aSJohnny Huang } 18412a856b9aSJohnny Huang 18422a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18432a856b9aSJohnny Huang { 18442a856b9aSJohnny Huang int mode = 0; 18452a856b9aSJohnny Huang int nconfirm = 0; 18462a856b9aSJohnny Huang int otp_addr = 0; 18472a856b9aSJohnny Huang int bit_offset; 18482a856b9aSJohnny Huang int value; 18492a856b9aSJohnny Huang int ret; 18502a856b9aSJohnny Huang 18512a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 18522a856b9aSJohnny Huang return CMD_RET_USAGE; 18532a856b9aSJohnny Huang 18542a856b9aSJohnny Huang /* Drop the pb cmd */ 18552a856b9aSJohnny Huang argc--; 18562a856b9aSJohnny Huang argv++; 18572a856b9aSJohnny Huang 18582a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1859a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 18602a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1861a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 18622a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1863a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1864cd1610b4SJohnny Huang else 18652a856b9aSJohnny Huang return CMD_RET_USAGE; 18662a856b9aSJohnny Huang 18672a856b9aSJohnny Huang /* Drop the region cmd */ 18682a856b9aSJohnny Huang argc--; 18692a856b9aSJohnny Huang argv++; 18702a856b9aSJohnny Huang 18712a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1872cd1610b4SJohnny Huang nconfirm = 1; 18732a856b9aSJohnny Huang /* Drop the force option */ 18742a856b9aSJohnny Huang argc--; 18752a856b9aSJohnny Huang argv++; 18762a856b9aSJohnny Huang } 1877cd1610b4SJohnny Huang 1878a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 18792a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 18802a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1881cd1610b4SJohnny Huang if (bit_offset >= 64) 18822a856b9aSJohnny Huang return CMD_RET_USAGE; 1883cd1610b4SJohnny Huang } else { 18842a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 18852a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 18862a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1887cd1610b4SJohnny Huang if (bit_offset >= 32) 18882a856b9aSJohnny Huang return CMD_RET_USAGE; 1889cd1610b4SJohnny Huang } 1890cd1610b4SJohnny Huang if (value != 0 && value != 1) 18912a856b9aSJohnny Huang return CMD_RET_USAGE; 1892cd1610b4SJohnny Huang 1893cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18942a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 18952a856b9aSJohnny Huang 18962a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18972a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18982a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18992a856b9aSJohnny Huang return CMD_RET_FAILURE; 19002a856b9aSJohnny Huang else 19012a856b9aSJohnny Huang return CMD_RET_USAGE; 19022a856b9aSJohnny Huang } 19032a856b9aSJohnny Huang 19042a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19052a856b9aSJohnny Huang { 19062a856b9aSJohnny Huang phys_addr_t addr; 19072a856b9aSJohnny Huang int otp_addr = 0; 19082a856b9aSJohnny Huang 19092a856b9aSJohnny Huang if (argc != 3) 19102a856b9aSJohnny Huang return CMD_RET_USAGE; 19112a856b9aSJohnny Huang 191269d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19132a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19142a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 19152a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 191669d5fd8fSJohnny Huang printf("Compare pass\n"); 19172a856b9aSJohnny Huang return CMD_RET_SUCCESS; 191869d5fd8fSJohnny Huang } else { 191969d5fd8fSJohnny Huang printf("Compare fail\n"); 19202a856b9aSJohnny Huang return CMD_RET_FAILURE; 192169d5fd8fSJohnny Huang } 192269d5fd8fSJohnny Huang } 192369d5fd8fSJohnny Huang 192466f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 192566f2f8e5SJohnny Huang { 1926a8bd6d8cSJohnny Huang int view = 0; 19272d4b0742SJohnny Huang int input; 1928a8bd6d8cSJohnny Huang 1929a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 193066f2f8e5SJohnny Huang return CMD_RET_USAGE; 193166f2f8e5SJohnny Huang 19322d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 193366f2f8e5SJohnny Huang 19342d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19352d4b0742SJohnny Huang if (argc == 3) { 19362d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 19372d4b0742SJohnny Huang otp_print_conf_info(input); 19382d4b0742SJohnny Huang } else { 19392d4b0742SJohnny Huang otp_print_conf_info(-1); 19402d4b0742SJohnny Huang } 19412d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19422d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 1943a8bd6d8cSJohnny Huang view = 1; 1944a8bd6d8cSJohnny Huang /* Drop the view option */ 1945a8bd6d8cSJohnny Huang argc--; 1946a8bd6d8cSJohnny Huang argv++; 1947a8bd6d8cSJohnny Huang } 194866f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1949b458cd62SJohnny Huang otp_print_strap_info(view); 195066f2f8e5SJohnny Huang } else { 195166f2f8e5SJohnny Huang return CMD_RET_USAGE; 195266f2f8e5SJohnny Huang } 19532d4b0742SJohnny Huang 195466f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 195566f2f8e5SJohnny Huang } 195666f2f8e5SJohnny Huang 1957737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 1958737ed20bSJohnny Huang { 1959737ed20bSJohnny Huang int input; 1960737ed20bSJohnny Huang int bit_offset; 1961737ed20bSJohnny Huang int prog_address; 1962737ed20bSJohnny Huang int pass; 1963737ed20bSJohnny Huang int i; 1964737ed20bSJohnny Huang if (argc != 3 && argc != 2) 1965737ed20bSJohnny Huang return CMD_RET_USAGE; 1966737ed20bSJohnny Huang 1967737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 1968737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 1969737ed20bSJohnny Huang } else { 1970737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 1971737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 1972737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1973737ed20bSJohnny Huang if (!confirm_yesno()) { 1974737ed20bSJohnny Huang printf(" Aborting\n"); 1975737ed20bSJohnny Huang return CMD_RET_FAILURE; 1976737ed20bSJohnny Huang } 1977737ed20bSJohnny Huang } 1978737ed20bSJohnny Huang 1979737ed20bSJohnny Huang prog_address = 0x800; 1980737ed20bSJohnny Huang if (input < 32) { 1981737ed20bSJohnny Huang bit_offset = input; 1982737ed20bSJohnny Huang prog_address |= 0x60c; 1983737ed20bSJohnny Huang } else if (input < 64) { 1984737ed20bSJohnny Huang bit_offset = input - 32; 1985737ed20bSJohnny Huang prog_address |= 0x60e; 1986737ed20bSJohnny Huang } else { 1987737ed20bSJohnny Huang return CMD_RET_USAGE; 1988737ed20bSJohnny Huang } 1989737ed20bSJohnny Huang 1990737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 1991737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 1992737ed20bSJohnny Huang } 1993737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 1994737ed20bSJohnny Huang pass = -1; 1995737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 1996737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 1997737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 1998737ed20bSJohnny Huang } else { 1999737ed20bSJohnny Huang pass = 0; 2000737ed20bSJohnny Huang break; 2001737ed20bSJohnny Huang } 2002737ed20bSJohnny Huang } 2003737ed20bSJohnny Huang if (pass == 0) { 2004737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2005737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2006737ed20bSJohnny Huang } 2007737ed20bSJohnny Huang 2008737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2009737ed20bSJohnny Huang return CMD_RET_FAILURE; 2010737ed20bSJohnny Huang 2011737ed20bSJohnny Huang } 20122a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 20132a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2014a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 20152a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 20162a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2017737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 20182a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 20192a856b9aSJohnny Huang }; 20202a856b9aSJohnny Huang 20212a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20222a856b9aSJohnny Huang { 20232a856b9aSJohnny Huang cmd_tbl_t *cp; 20242a856b9aSJohnny Huang 20252a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 20262a856b9aSJohnny Huang 2027737ed20bSJohnny Huang /* Drop the otp command */ 20282a856b9aSJohnny Huang argc--; 20292a856b9aSJohnny Huang argv++; 20302a856b9aSJohnny Huang 20312a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 20322a856b9aSJohnny Huang return CMD_RET_USAGE; 20332a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 20342a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20352a856b9aSJohnny Huang 20362a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 203769d5fd8fSJohnny Huang } 203869d5fd8fSJohnny Huang 203969d5fd8fSJohnny Huang U_BOOT_CMD( 204069d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 204169d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 20422a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 20432a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 20442d4b0742SJohnny Huang "otp info strap [v]\n" 20452d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2046d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2047cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2048737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2049737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 20502a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 205169d5fd8fSJohnny Huang ); 2052