169d5fd8fSJohnny Huang /* 269d5fd8fSJohnny Huang * This program is distributed in the hope that it will be useful, 369d5fd8fSJohnny Huang * but WITHOUT ANY WARRANTY; without even the implied warranty of 469d5fd8fSJohnny Huang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 569d5fd8fSJohnny Huang * GNU General Public License for more details. 669d5fd8fSJohnny Huang * 769d5fd8fSJohnny Huang * You should have received a copy of the GNU General Public License 869d5fd8fSJohnny Huang * along with this program; if not, write to the Free Software 969d5fd8fSJohnny Huang * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1069d5fd8fSJohnny Huang */ 114c1c9b35SJohnny Huang #include <stdlib.h> 1269d5fd8fSJohnny Huang #include <common.h> 1369d5fd8fSJohnny Huang #include <console.h> 1469d5fd8fSJohnny Huang #include <bootretry.h> 1569d5fd8fSJohnny Huang #include <cli.h> 1669d5fd8fSJohnny Huang #include <command.h> 1769d5fd8fSJohnny Huang #include <console.h> 184c1c9b35SJohnny Huang #include <malloc.h> 1969d5fd8fSJohnny Huang #include <inttypes.h> 2069d5fd8fSJohnny Huang #include <mapmem.h> 2169d5fd8fSJohnny Huang #include <asm/io.h> 2269d5fd8fSJohnny Huang #include <linux/compiler.h> 2369d5fd8fSJohnny Huang 2469d5fd8fSJohnny Huang DECLARE_GLOBAL_DATA_PTR; 2569d5fd8fSJohnny Huang 2669d5fd8fSJohnny Huang #define OTP_PASSWD 0x349fe38a 2769d5fd8fSJohnny Huang #define RETRY 3 28a6d0d645SJohnny Huang #define OTP_REGION_STRAP 1 29a6d0d645SJohnny Huang #define OTP_REGION_CONF 2 30a6d0d645SJohnny Huang #define OTP_REGION_DATA 3 31a6d0d645SJohnny Huang #define OTP_REGION_ALL 4 3269d5fd8fSJohnny Huang 332a856b9aSJohnny Huang #define OTP_USAGE -1 342a856b9aSJohnny Huang #define OTP_FAILURE -2 352a856b9aSJohnny Huang #define OTP_SUCCESS 0 362a856b9aSJohnny Huang 37a6af4a17SJohnny Huang #define OTP_PROG_SKIP 1 38a6af4a17SJohnny Huang 39a8bd6d8cSJohnny Huang #define OTP_REG_RESERVED -1 40b458cd62SJohnny Huang #define OTP_REG_VALUE -2 41b458cd62SJohnny Huang #define OTP_REG_VALID_BIT -3 4276d13988SJohnny Huang 434c1c9b35SJohnny Huang #define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" 444c1c9b35SJohnny Huang #define PBWIDTH 60 454c1c9b35SJohnny Huang 4666f2f8e5SJohnny Huang struct otpstrap_status { 4769d5fd8fSJohnny Huang int value; 4869d5fd8fSJohnny Huang int option_array[7]; 4969d5fd8fSJohnny Huang int remain_times; 5069d5fd8fSJohnny Huang int writeable_option; 5169d5fd8fSJohnny Huang int protected; 5269d5fd8fSJohnny Huang }; 5369d5fd8fSJohnny Huang 5466f2f8e5SJohnny Huang struct otpconf_parse { 5566f2f8e5SJohnny Huang int dw_offset; 5666f2f8e5SJohnny Huang int bit; 5766f2f8e5SJohnny Huang int length; 5866f2f8e5SJohnny Huang int value; 5966f2f8e5SJohnny Huang int keep; 6066f2f8e5SJohnny Huang char status[80]; 6166f2f8e5SJohnny Huang }; 6266f2f8e5SJohnny Huang 63a8bd6d8cSJohnny Huang struct otpstrap_info { 64a8bd6d8cSJohnny Huang uint32_t bit_offset; 65a8bd6d8cSJohnny Huang uint32_t length; 6676d13988SJohnny Huang int value; 67a8bd6d8cSJohnny Huang char information[80]; 68a8bd6d8cSJohnny Huang }; 69a8bd6d8cSJohnny Huang 70a8bd6d8cSJohnny Huang struct otpconf_info { 71a8bd6d8cSJohnny Huang uint32_t dw_offset; 72a8bd6d8cSJohnny Huang uint32_t bit_offset; 73a8bd6d8cSJohnny Huang uint32_t length; 74a8bd6d8cSJohnny Huang int value; 75a8bd6d8cSJohnny Huang char information[80]; 76a8bd6d8cSJohnny Huang }; 77a8bd6d8cSJohnny Huang 78a8bd6d8cSJohnny Huang void printProgress(int numerator, int denominator, char *format, ...) 79a8bd6d8cSJohnny Huang { 80a8bd6d8cSJohnny Huang int val = numerator * 100 / denominator; 81a8bd6d8cSJohnny Huang int lpad = numerator * PBWIDTH / denominator; 82a8bd6d8cSJohnny Huang int rpad = PBWIDTH - lpad; 83a8bd6d8cSJohnny Huang char buffer[256]; 84a8bd6d8cSJohnny Huang va_list aptr; 85a8bd6d8cSJohnny Huang 86a8bd6d8cSJohnny Huang va_start(aptr, format); 87a8bd6d8cSJohnny Huang vsprintf(buffer, format, aptr); 88a8bd6d8cSJohnny Huang va_end(aptr); 89a8bd6d8cSJohnny Huang 90a8bd6d8cSJohnny Huang printf("\r%3d%% [%.*s%*s] %s", val, lpad, PBSTR, rpad, "", buffer); 91a8bd6d8cSJohnny Huang if (numerator == denominator) 92a8bd6d8cSJohnny Huang printf("\n"); 93a8bd6d8cSJohnny Huang } 94a8bd6d8cSJohnny Huang 95a8bd6d8cSJohnny Huang struct otpstrap_info a0_strap_info[] = { 96a8bd6d8cSJohnny Huang { 97a8bd6d8cSJohnny Huang 0, 1, 0, "Disable secure boot" 98a8bd6d8cSJohnny Huang }, { 99a8bd6d8cSJohnny Huang 0, 1, 1, "Enable secure boot" 100a8bd6d8cSJohnny Huang }, { 101a8bd6d8cSJohnny Huang 1, 1, 0, "Disable boot from eMMC" 102a8bd6d8cSJohnny Huang }, { 103a8bd6d8cSJohnny Huang 1, 1, 1, "Enable boot from eMMC" 104a8bd6d8cSJohnny Huang }, { 105a8bd6d8cSJohnny Huang 2, 1, 0, "Disable Boot from debug SPI" 106a8bd6d8cSJohnny Huang }, { 107a8bd6d8cSJohnny Huang 2, 1, 1, "Enable Boot from debug SPI" 108a8bd6d8cSJohnny Huang }, { 109a8bd6d8cSJohnny Huang 3, 1, 0, "Enable ARM CM3" 110a8bd6d8cSJohnny Huang }, { 111a8bd6d8cSJohnny Huang 3, 1, 1, "Disable ARM CM3" 112a8bd6d8cSJohnny Huang }, { 113a8bd6d8cSJohnny Huang 4, 1, 0, "No VGA BISO ROM, VGA BIOS is merged in the system BIOS" 114a8bd6d8cSJohnny Huang }, { 115a8bd6d8cSJohnny Huang 4, 1, 1, "Enable dedicated VGA BIOS ROM" 116a8bd6d8cSJohnny Huang }, { 117a8bd6d8cSJohnny Huang 5, 1, 0, "MAC 1 : RMII/NCSI" 118a8bd6d8cSJohnny Huang }, { 119a8bd6d8cSJohnny Huang 5, 1, 1, "MAC 1 : RGMII" 120a8bd6d8cSJohnny Huang }, { 121a8bd6d8cSJohnny Huang 6, 1, 0, "MAC 2 : RMII/NCSI" 122a8bd6d8cSJohnny Huang }, { 123a8bd6d8cSJohnny Huang 6, 1, 1, "MAC 2 : RGMII" 124a8bd6d8cSJohnny Huang }, { 125a8bd6d8cSJohnny Huang 7, 3, 0, "CPU Frequency : 1GHz" 126a8bd6d8cSJohnny Huang }, { 127a8bd6d8cSJohnny Huang 7, 3, 1, "CPU Frequency : 800MHz" 128a8bd6d8cSJohnny Huang }, { 129a8bd6d8cSJohnny Huang 7, 3, 2, "CPU Frequency : 1.2GHz" 130a8bd6d8cSJohnny Huang }, { 131a8bd6d8cSJohnny Huang 7, 3, 3, "CPU Frequency : 1.4GHz" 132a8bd6d8cSJohnny Huang }, { 133a8bd6d8cSJohnny Huang 10, 2, 0, "HCLK ratio AXI:AHB = 2:1" 134a8bd6d8cSJohnny Huang }, { 135a8bd6d8cSJohnny Huang 10, 2, 1, "HCLK ratio AXI:AHB = 2:1" 136a8bd6d8cSJohnny Huang }, { 137a8bd6d8cSJohnny Huang 10, 2, 2, "HCLK ratio AXI:AHB = 3:1" 138a8bd6d8cSJohnny Huang }, { 139a8bd6d8cSJohnny Huang 10, 2, 3, "HCLK ratio AXI:AHB = 4:1" 140a8bd6d8cSJohnny Huang }, { 141a8bd6d8cSJohnny Huang 12, 2, 0, "VGA memory size : 8MB" 142a8bd6d8cSJohnny Huang }, { 143a8bd6d8cSJohnny Huang 12, 2, 1, "VGA memory size : 16MB" 144a8bd6d8cSJohnny Huang }, { 145a8bd6d8cSJohnny Huang 12, 2, 2, "VGA memory size : 32MB" 146a8bd6d8cSJohnny Huang }, { 147a8bd6d8cSJohnny Huang 12, 2, 3, "VGA memory size : 64MB" 148a8bd6d8cSJohnny Huang }, { 149a8bd6d8cSJohnny Huang 14, 3, OTP_REG_RESERVED, "" 150a8bd6d8cSJohnny Huang }, { 151a8bd6d8cSJohnny Huang 17, 1, 0, "VGA class code : Class Code for video device" 152a8bd6d8cSJohnny Huang }, { 153a8bd6d8cSJohnny Huang 17, 1, 1, "VGA class code : Class Code for VGA device" 154a8bd6d8cSJohnny Huang }, { 155a8bd6d8cSJohnny Huang 18, 1, 0, "Enable debug interfaces 0" 156a8bd6d8cSJohnny Huang }, { 157a8bd6d8cSJohnny Huang 18, 1, 1, "Disable debug interfaces 0" 158a8bd6d8cSJohnny Huang }, { 159a8bd6d8cSJohnny Huang 19, 1, 0, "Boot from emmc mode : High eMMC speed" 160a8bd6d8cSJohnny Huang }, { 161a8bd6d8cSJohnny Huang 19, 1, 1, "Boot from emmc mode : Normal eMMC speed" 162a8bd6d8cSJohnny Huang }, { 163a8bd6d8cSJohnny Huang 20, 1, 0, "Enable Pcie EHCI device" 164a8bd6d8cSJohnny Huang }, { 165a8bd6d8cSJohnny Huang 20, 1, 1, "Disable Pcie EHCI device" 166a8bd6d8cSJohnny Huang }, { 167a8bd6d8cSJohnny Huang 21, 1, 0, "Enable VGA XDMA function" 168a8bd6d8cSJohnny Huang }, { 169a8bd6d8cSJohnny Huang 21, 1, 1, "Disable VGA XDMA function" 170a8bd6d8cSJohnny Huang }, { 171a8bd6d8cSJohnny Huang 22, 1, 0, "Normal BMC mode" 172a8bd6d8cSJohnny Huang }, { 173a8bd6d8cSJohnny Huang 22, 1, 1, "Disable dedicated BMC functions for non-BMC application" 174a8bd6d8cSJohnny Huang }, { 175a8bd6d8cSJohnny Huang 23, 1, 0, "SSPRST# pin is for secondary processor dedicated reset pin" 176a8bd6d8cSJohnny Huang }, { 177a8bd6d8cSJohnny Huang 23, 1, 1, "SSPRST# pin is for PCIE root complex dedicated reset pin" 178a8bd6d8cSJohnny Huang }, { 179a8bd6d8cSJohnny Huang 24, 1, 0, "DRAM types : DDR3" 180a8bd6d8cSJohnny Huang }, { 181a8bd6d8cSJohnny Huang 24, 1, 1, "DRAM types : DDR4" 182a8bd6d8cSJohnny Huang }, { 183a8bd6d8cSJohnny Huang 25, 5, OTP_REG_RESERVED, "" 184a8bd6d8cSJohnny Huang }, { 185a8bd6d8cSJohnny Huang 30, 2, OTP_REG_RESERVED, "" 186a8bd6d8cSJohnny Huang }, { 187a8bd6d8cSJohnny Huang 32, 1, 0, "MAC 3 : RMII/NCSI" 188a8bd6d8cSJohnny Huang }, { 189a8bd6d8cSJohnny Huang 32, 1, 1, "MAC 3 : RGMII" 190a8bd6d8cSJohnny Huang }, { 191a8bd6d8cSJohnny Huang 33, 1, 0, "MAC 4 : RMII/NCSI" 192a8bd6d8cSJohnny Huang }, { 193a8bd6d8cSJohnny Huang 33, 1, 1, "MAC 4 : RGMII" 194a8bd6d8cSJohnny Huang }, { 195a8bd6d8cSJohnny Huang 34, 1, 0, "SuperIO configuration address : 0x2E" 196a8bd6d8cSJohnny Huang }, { 197a8bd6d8cSJohnny Huang 34, 1, 1, "SuperIO configuration address : 0x4E" 198a8bd6d8cSJohnny Huang }, { 199a8bd6d8cSJohnny Huang 35, 1, 0, "Enable LPC to decode SuperIO" 200a8bd6d8cSJohnny Huang }, { 201a8bd6d8cSJohnny Huang 35, 1, 1, "Disable LPC to decode SuperIO" 202a8bd6d8cSJohnny Huang }, { 203a8bd6d8cSJohnny Huang 36, 1, 0, "Enable debug interfaces 1" 204a8bd6d8cSJohnny Huang }, { 205a8bd6d8cSJohnny Huang 36, 1, 1, "Disable debug interfaces 1" 206a8bd6d8cSJohnny Huang }, { 207a8bd6d8cSJohnny Huang 37, 1, 0, "Disable ACPI function" 208a8bd6d8cSJohnny Huang }, { 209a8bd6d8cSJohnny Huang 37, 1, 1, "Enable ACPI function" 210a8bd6d8cSJohnny Huang }, { 211a8bd6d8cSJohnny Huang 38, 1, 0, "Enable eSPI mode" 212a8bd6d8cSJohnny Huang }, { 213a8bd6d8cSJohnny Huang 38, 1, 1, "Enable LPC mode" 214a8bd6d8cSJohnny Huang }, { 215a8bd6d8cSJohnny Huang 39, 1, 0, "Enable SAFS mode" 216a8bd6d8cSJohnny Huang }, { 217a8bd6d8cSJohnny Huang 39, 1, 1, "Enable SAFS mode" 218a8bd6d8cSJohnny Huang }, { 219a8bd6d8cSJohnny Huang 40, 2, OTP_REG_RESERVED, "" 220a8bd6d8cSJohnny Huang }, { 221a8bd6d8cSJohnny Huang 42, 1, 0, "Disable boot SPI 3B/4B address mode auto detection" 222a8bd6d8cSJohnny Huang }, { 223a8bd6d8cSJohnny Huang 42, 1, 1, "Enable boot SPI 3B/4B address mode auto detection" 224a8bd6d8cSJohnny Huang }, { 225a8bd6d8cSJohnny Huang 43, 1, 0, "Disable boot SPI ABR" 226a8bd6d8cSJohnny Huang }, { 227a8bd6d8cSJohnny Huang 43, 1, 1, "Enable boot SPI ABR" 228a8bd6d8cSJohnny Huang }, { 229a8bd6d8cSJohnny Huang 44, 1, 0, "Boot SPI ABR mode : dual SPI flash" 230a8bd6d8cSJohnny Huang }, { 231a8bd6d8cSJohnny Huang 44, 1, 1, "Boot SPI ABR mode : single SPI flash" 232a8bd6d8cSJohnny Huang }, { 233a8bd6d8cSJohnny Huang 45, 3, 0, "Boot SPI flash size : no define size" 234a8bd6d8cSJohnny Huang }, { 235a8bd6d8cSJohnny Huang 45, 3, 1, "Boot SPI flash size : 2MB" 236a8bd6d8cSJohnny Huang }, { 237a8bd6d8cSJohnny Huang 45, 3, 2, "Boot SPI flash size : 4MB" 238a8bd6d8cSJohnny Huang }, { 239a8bd6d8cSJohnny Huang 45, 3, 3, "Boot SPI flash size : 8MB" 240a8bd6d8cSJohnny Huang }, { 241a8bd6d8cSJohnny Huang 45, 3, 4, "Boot SPI flash size : 16MB" 242a8bd6d8cSJohnny Huang }, { 243a8bd6d8cSJohnny Huang 45, 3, 5, "Boot SPI flash size : 32MB" 244a8bd6d8cSJohnny Huang }, { 245a8bd6d8cSJohnny Huang 45, 3, 6, "Boot SPI flash size : 64MB" 246a8bd6d8cSJohnny Huang }, { 247a8bd6d8cSJohnny Huang 45, 3, 7, "Boot SPI flash size : 128MB" 248a8bd6d8cSJohnny Huang }, { 249a8bd6d8cSJohnny Huang 48, 1, 0, "Disable host SPI ABR" 250a8bd6d8cSJohnny Huang }, { 251a8bd6d8cSJohnny Huang 48, 1, 1, "Enable host SPI ABR" 252a8bd6d8cSJohnny Huang }, { 253a8bd6d8cSJohnny Huang 49, 1, 0, "Disable host SPI ABR mode select pin" 254a8bd6d8cSJohnny Huang }, { 255a8bd6d8cSJohnny Huang 49, 1, 1, "Enable host SPI ABR mode select pin" 256a8bd6d8cSJohnny Huang }, { 257a8bd6d8cSJohnny Huang 50, 1, 0, "Host SPI ABR mode : dual SPI flash" 258a8bd6d8cSJohnny Huang }, { 259a8bd6d8cSJohnny Huang 50, 1, 1, "Host SPI ABR mode : single SPI flash" 260a8bd6d8cSJohnny Huang }, { 261a8bd6d8cSJohnny Huang 51, 3, 0, "Host SPI flash size : no define size" 262a8bd6d8cSJohnny Huang }, { 263a8bd6d8cSJohnny Huang 51, 3, 1, "Host SPI flash size : 2MB" 264a8bd6d8cSJohnny Huang }, { 265a8bd6d8cSJohnny Huang 51, 3, 2, "Host SPI flash size : 4MB" 266a8bd6d8cSJohnny Huang }, { 267a8bd6d8cSJohnny Huang 51, 3, 3, "Host SPI flash size : 8MB" 268a8bd6d8cSJohnny Huang }, { 269a8bd6d8cSJohnny Huang 51, 3, 4, "Host SPI flash size : 16MB" 270a8bd6d8cSJohnny Huang }, { 271a8bd6d8cSJohnny Huang 51, 3, 5, "Host SPI flash size : 32MB" 272a8bd6d8cSJohnny Huang }, { 273a8bd6d8cSJohnny Huang 51, 3, 6, "Host SPI flash size : 64MB" 274a8bd6d8cSJohnny Huang }, { 275a8bd6d8cSJohnny Huang 51, 3, 7, "Host SPI flash size : 128MB" 276a8bd6d8cSJohnny Huang }, { 277a8bd6d8cSJohnny Huang 54, 1, 0, "Disable boot SPI auxiliary control pins" 278a8bd6d8cSJohnny Huang }, { 279a8bd6d8cSJohnny Huang 54, 1, 1, "Enable boot SPI auxiliary control pins" 280a8bd6d8cSJohnny Huang }, { 281a8bd6d8cSJohnny Huang 55, 2, 0, "Boot SPI CRTM size : disable CRTM" 282a8bd6d8cSJohnny Huang }, { 283a8bd6d8cSJohnny Huang 55, 2, 1, "Boot SPI CRTM size : 256KB" 284a8bd6d8cSJohnny Huang }, { 285a8bd6d8cSJohnny Huang 55, 2, 2, "Boot SPI CRTM size : 512KB" 286a8bd6d8cSJohnny Huang }, { 287a8bd6d8cSJohnny Huang 55, 2, 3, "Boot SPI CRTM size : 1MB" 288a8bd6d8cSJohnny Huang }, { 289a8bd6d8cSJohnny Huang 57, 2, 0, "Host SPI CRTM size : disable CRTM" 290a8bd6d8cSJohnny Huang }, { 291a8bd6d8cSJohnny Huang 57, 2, 1, "Host SPI CRTM size : 256KB" 292a8bd6d8cSJohnny Huang }, { 293a8bd6d8cSJohnny Huang 57, 2, 2, "Host SPI CRTM size : 512KB" 294a8bd6d8cSJohnny Huang }, { 295a8bd6d8cSJohnny Huang 57, 2, 3, "Host SPI CRTM size : 1MB" 296a8bd6d8cSJohnny Huang }, { 297a8bd6d8cSJohnny Huang 59, 1, 0, "Disable host SPI auxiliary control pins" 298a8bd6d8cSJohnny Huang }, { 299a8bd6d8cSJohnny Huang 59, 1, 1, "Enable host SPI auxiliary control pins" 300a8bd6d8cSJohnny Huang }, { 301a8bd6d8cSJohnny Huang 60, 1, 0, "Disable GPIO pass through" 302a8bd6d8cSJohnny Huang }, { 303a8bd6d8cSJohnny Huang 60, 1, 1, "Enable GPIO pass through" 304a8bd6d8cSJohnny Huang }, { 305a8bd6d8cSJohnny Huang 61, 1, 0, "Enable low security secure boot key" 306a8bd6d8cSJohnny Huang }, { 307a8bd6d8cSJohnny Huang 61, 1, 1, "Disable low security secure boot key" 308a8bd6d8cSJohnny Huang }, { 309a8bd6d8cSJohnny Huang 62, 1, 0, "Disable dedicate GPIO strap pins" 310a8bd6d8cSJohnny Huang }, { 311a8bd6d8cSJohnny Huang 62, 1, 1, "Enable dedicate GPIO strap pins" 312b458cd62SJohnny Huang }, { 313b458cd62SJohnny Huang 63, 1, OTP_REG_RESERVED, "" 314a8bd6d8cSJohnny Huang } 31576d13988SJohnny Huang }; 316b458cd62SJohnny Huang struct otpconf_info a0_conf_info[] = { 317b458cd62SJohnny Huang { 318b458cd62SJohnny Huang 0, 0, 1, 0, "Enable Secure Region programming" 319b458cd62SJohnny Huang }, { 320b458cd62SJohnny Huang 0, 0, 1, 1, "Disable Secure Region programming" 321b458cd62SJohnny Huang }, { 322b458cd62SJohnny Huang 0, 1, 1, 0, "Disable Secure Boot" 323b458cd62SJohnny Huang }, { 324b458cd62SJohnny Huang 0, 1, 1, 1, "Enable Secure Boot" 325b458cd62SJohnny Huang }, { 326b458cd62SJohnny Huang 0, 2, 1, 0, "Initialization programming not done" 327b458cd62SJohnny Huang }, { 328b458cd62SJohnny Huang 0, 2, 1, 1, "Initialization programming done" 329b458cd62SJohnny Huang }, { 330b458cd62SJohnny Huang 0, 3, 1, 0, "User region ECC disable" 331b458cd62SJohnny Huang }, { 332b458cd62SJohnny Huang 0, 3, 1, 1, "User region ECC enable" 333b458cd62SJohnny Huang }, { 334b458cd62SJohnny Huang 0, 4, 1, 0, "Secure Region ECC disable" 335b458cd62SJohnny Huang }, { 336b458cd62SJohnny Huang 0, 4, 1, 1, "Secure Region ECC enable" 337b458cd62SJohnny Huang }, { 338b458cd62SJohnny Huang 0, 5, 1, 0, "Enable low security key" 339b458cd62SJohnny Huang }, { 340b458cd62SJohnny Huang 0, 5, 1, 1, "Disable low security key" 341b458cd62SJohnny Huang }, { 342b458cd62SJohnny Huang 0, 6, 1, 0, "Do not ignore Secure Boot hardware strap" 343b458cd62SJohnny Huang }, { 344b458cd62SJohnny Huang 0, 6, 1, 1, "Ignore Secure Boot hardware strap" 345b458cd62SJohnny Huang }, { 346b458cd62SJohnny Huang 0, 7, 1, 0, "Secure Boot Mode: 2" 347b458cd62SJohnny Huang }, { 348b458cd62SJohnny Huang 0, 7, 1, 1, "Secure Boot Mode: 1" 349b458cd62SJohnny Huang }, { 350b458cd62SJohnny Huang 0, 8, 2, 0, "Single cell mode (recommended)" 351b458cd62SJohnny Huang }, { 352b458cd62SJohnny Huang 0, 8, 2, 1, "Differnetial mode" 353b458cd62SJohnny Huang }, { 354b458cd62SJohnny Huang 0, 8, 2, 2, "Differential-redundant mode" 355b458cd62SJohnny Huang }, { 356b458cd62SJohnny Huang 0, 10, 2, 0, "RSA mode : RSA1024" 357b458cd62SJohnny Huang }, { 358b458cd62SJohnny Huang 0, 10, 2, 1, "RSA mode : RSA2048" 359b458cd62SJohnny Huang }, { 360b458cd62SJohnny Huang 0, 10, 2, 2, "RSA mode : RSA3072" 361b458cd62SJohnny Huang }, { 362b458cd62SJohnny Huang 0, 10, 2, 3, "RSA mode : RSA4096" 363b458cd62SJohnny Huang }, { 364b458cd62SJohnny Huang 0, 12, 2, 0, "SHA mode : SHA224" 365b458cd62SJohnny Huang }, { 366b458cd62SJohnny Huang 0, 12, 2, 1, "SHA mode : SHA256" 367b458cd62SJohnny Huang }, { 368b458cd62SJohnny Huang 0, 12, 2, 2, "SHA mode : SHA384" 369b458cd62SJohnny Huang }, { 370b458cd62SJohnny Huang 0, 12, 2, 3, "SHA mode : SHA512" 371b458cd62SJohnny Huang }, { 372b458cd62SJohnny Huang 0, 14, 2, OTP_REG_RESERVED, "" 373b458cd62SJohnny Huang }, { 374b458cd62SJohnny Huang 0, 16, 6, OTP_REG_VALUE, "Secure Region size (DW): 0x%x" 375b458cd62SJohnny Huang }, { 376b458cd62SJohnny Huang 0, 22, 1, 0, "Secure Region : Writable" 377b458cd62SJohnny Huang }, { 378b458cd62SJohnny Huang 0, 22, 1, 1, "Secure Region : Write Protect" 379b458cd62SJohnny Huang }, { 380b458cd62SJohnny Huang 0, 23, 1, 0, "User Region : Writable" 381b458cd62SJohnny Huang }, { 382b458cd62SJohnny Huang 0, 23, 1, 1, "User Region : Write Protect" 383b458cd62SJohnny Huang }, { 384b458cd62SJohnny Huang 0, 24, 1, 0, "Configure Region : Writable" 385b458cd62SJohnny Huang }, { 386b458cd62SJohnny Huang 0, 24, 1, 1, "Configure Region : Write Protect" 387b458cd62SJohnny Huang }, { 388b458cd62SJohnny Huang 0, 25, 1, 0, "OTP strap Region : Writable" 389b458cd62SJohnny Huang }, { 390b458cd62SJohnny Huang 0, 25, 1, 1, "OTP strap Region : Write Protect" 391b458cd62SJohnny Huang }, { 392b458cd62SJohnny Huang 0, 26, 1, 0, "Disable Copy Boot Image to Internal SRAM" 393b458cd62SJohnny Huang }, { 394b458cd62SJohnny Huang 0, 26, 1, 1, "Copy Boot Image to Internal SRAM" 395b458cd62SJohnny Huang }, { 396b458cd62SJohnny Huang 0, 27, 1, 0, "Disable image encryption" 397b458cd62SJohnny Huang }, { 398b458cd62SJohnny Huang 0, 27, 1, 1, "Enable image encryption" 399b458cd62SJohnny Huang }, { 400b458cd62SJohnny Huang 0, 28, 1, OTP_REG_RESERVED, "" 401b458cd62SJohnny Huang }, { 402b458cd62SJohnny Huang 0, 29, 1, 0, "OTP key retire Region : Writable" 403b458cd62SJohnny Huang }, { 404b458cd62SJohnny Huang 0, 29, 1, 1, "OTP key retire Region : Write Protect" 405b458cd62SJohnny Huang }, { 406b458cd62SJohnny Huang 0, 30, 1, 0, "SIPROM RED_EN redundancy repair disable" 407b458cd62SJohnny Huang }, { 408b458cd62SJohnny Huang 0, 30, 1, 1, "SIPROM RED_EN redundancy repair enable" 409b458cd62SJohnny Huang }, { 410b458cd62SJohnny Huang 0, 31, 1, 0, "SIPROM Mlock memory lock disable" 411b458cd62SJohnny Huang }, { 412b458cd62SJohnny Huang 0, 31, 1, 1, "SIPROM Mlock memory lock enable" 413b458cd62SJohnny Huang }, { 414b458cd62SJohnny Huang 2, 0, 16, OTP_REG_VALUE, "Vender ID : 0x%x" 415b458cd62SJohnny Huang }, { 416b458cd62SJohnny Huang 2, 16, 16, OTP_REG_VALUE, "Key Revision : 0x%x" 417b458cd62SJohnny Huang }, { 418b458cd62SJohnny Huang 3, 0, 16, OTP_REG_VALUE, "Secure boot header offset : 0x%x" 419b458cd62SJohnny Huang }, { 420b458cd62SJohnny Huang 4, 0, 8, OTP_REG_VALID_BIT, "Keys valid : %d" 421b458cd62SJohnny Huang }, { 422b458cd62SJohnny Huang 4, 16, 8, OTP_REG_VALID_BIT, "Keys retire : %d" 423b458cd62SJohnny Huang }, { 424b458cd62SJohnny Huang 5, 0, 32, OTP_REG_VALUE, "User define data, random number low : 0x%x" 425b458cd62SJohnny Huang }, { 426b458cd62SJohnny Huang 6, 0, 32, OTP_REG_VALUE, "User define data, random number high : 0x%x" 427b458cd62SJohnny Huang }, { 428*07baa4e8SJohnny Huang 7, 0, 1, 0, "Force enable PCI bus to AHB bus bridge" 429*07baa4e8SJohnny Huang }, { 430*07baa4e8SJohnny Huang 7, 0, 1, 1, "Force disable PCI bus to AHB bus bridge" 431*07baa4e8SJohnny Huang }, { 432*07baa4e8SJohnny Huang 7, 1, 1, 0, "Force enable UART5 debug port function" 433*07baa4e8SJohnny Huang }, { 434*07baa4e8SJohnny Huang 7, 1, 1, 1, "Force disable UART5 debug port function" 435*07baa4e8SJohnny Huang }, { 436*07baa4e8SJohnny Huang 7, 2, 1, 0, "Force enable XDMA function" 437*07baa4e8SJohnny Huang }, { 438*07baa4e8SJohnny Huang 7, 2, 1, 1, "Force disable XDMA function" 439*07baa4e8SJohnny Huang }, { 440*07baa4e8SJohnny Huang 7, 3, 1, 0, "Force enable APB to PCIE device bridge" 441*07baa4e8SJohnny Huang }, { 442*07baa4e8SJohnny Huang 7, 3, 1, 1, "Force disable APB to PCIE device bridge" 443*07baa4e8SJohnny Huang }, { 444*07baa4e8SJohnny Huang 7, 4, 1, 0, "Force enable APB to PCIE bridge config access" 445*07baa4e8SJohnny Huang }, { 446*07baa4e8SJohnny Huang 7, 4, 1, 1, "Force disable APB to PCIE bridge config access" 447*07baa4e8SJohnny Huang }, { 448*07baa4e8SJohnny Huang 7, 5, 1, 0, "Force enable PCIE bus trace buffer" 449*07baa4e8SJohnny Huang }, { 450*07baa4e8SJohnny Huang 7, 5, 1, 1, "Force disable PCIE bus trace buffer" 451*07baa4e8SJohnny Huang }, { 452*07baa4e8SJohnny Huang 7, 6, 1, 0, "Force enable the capability for PCIE device port as a Root Complex" 453*07baa4e8SJohnny Huang }, { 454*07baa4e8SJohnny Huang 7, 6, 1, 1, "Force disable the capability for PCIE device port as a Root Complex" 455*07baa4e8SJohnny Huang }, { 456*07baa4e8SJohnny Huang 7, 16, 1, 0, "Force enable ESPI bus to AHB bus bridge" 457*07baa4e8SJohnny Huang }, { 458*07baa4e8SJohnny Huang 7, 16, 1, 1, "Force disable ESPI bus to AHB bus bridge" 459*07baa4e8SJohnny Huang }, { 460*07baa4e8SJohnny Huang 7, 17, 1, 0, "Force enable LPC bus to AHB bus bridge1" 461*07baa4e8SJohnny Huang }, { 462*07baa4e8SJohnny Huang 7, 17, 1, 1, "Force disable LPC bus to AHB bus bridge1" 463*07baa4e8SJohnny Huang }, { 464*07baa4e8SJohnny Huang 7, 18, 1, 0, "Force enable LPC bus to AHB bus bridge2" 465*07baa4e8SJohnny Huang }, { 466*07baa4e8SJohnny Huang 7, 18, 1, 1, "Force disable LPC bus to AHB bus bridge2" 467*07baa4e8SJohnny Huang }, { 468*07baa4e8SJohnny Huang 7, 19, 1, 0, "Force enable UART1 debug port function" 469*07baa4e8SJohnny Huang }, { 470*07baa4e8SJohnny Huang 7, 19, 1, 1, "Force disable UART1 debug port function" 471*07baa4e8SJohnny Huang }, { 472*07baa4e8SJohnny Huang 7, 31, 1, 0, "Disable chip security setting" 473*07baa4e8SJohnny Huang }, { 474*07baa4e8SJohnny Huang 7, 31, 1, 1, "Enable chip security setting" 475*07baa4e8SJohnny Huang }, { 476b458cd62SJohnny Huang 8, 0, 32, OTP_REG_VALUE, "Redundancy Repair : 0x%x" 477b458cd62SJohnny Huang }, { 478b458cd62SJohnny Huang 10, 0, 32, OTP_REG_VALUE, "Manifest ID low : 0x%x" 479b458cd62SJohnny Huang }, { 480b458cd62SJohnny Huang 11, 0, 32, OTP_REG_VALUE, "Manifest ID high : 0x%x" 481b458cd62SJohnny Huang } 482b458cd62SJohnny Huang }; 4832a856b9aSJohnny Huang static void otp_read_data(uint32_t offset, uint32_t *data) 48469d5fd8fSJohnny Huang { 48569d5fd8fSJohnny Huang writel(offset, 0x1e6f2010); //Read address 48669d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 48769d5fd8fSJohnny Huang udelay(2); 48869d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 48969d5fd8fSJohnny Huang data[1] = readl(0x1e6f2024); 49069d5fd8fSJohnny Huang } 49169d5fd8fSJohnny Huang 4922a856b9aSJohnny Huang static void otp_read_config(uint32_t offset, uint32_t *data) 49369d5fd8fSJohnny Huang { 49469d5fd8fSJohnny Huang int config_offset; 49569d5fd8fSJohnny Huang 49669d5fd8fSJohnny Huang config_offset = 0x800; 49769d5fd8fSJohnny Huang config_offset |= (offset / 8) * 0x200; 49869d5fd8fSJohnny Huang config_offset |= (offset % 8) * 0x2; 49969d5fd8fSJohnny Huang 50069d5fd8fSJohnny Huang writel(config_offset, 0x1e6f2010); //Read address 50169d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 50269d5fd8fSJohnny Huang udelay(2); 50369d5fd8fSJohnny Huang data[0] = readl(0x1e6f2020); 50469d5fd8fSJohnny Huang } 50569d5fd8fSJohnny Huang 50669d5fd8fSJohnny Huang static int otp_print_config(uint32_t offset, int dw_count) 50769d5fd8fSJohnny Huang { 50869d5fd8fSJohnny Huang int i; 50969d5fd8fSJohnny Huang uint32_t ret[1]; 51069d5fd8fSJohnny Huang 51169d5fd8fSJohnny Huang if (offset + dw_count > 32) 5122a856b9aSJohnny Huang return OTP_USAGE; 51369d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i ++) { 51469d5fd8fSJohnny Huang otp_read_config(i, ret); 515a6af4a17SJohnny Huang printf("OTPCFG%X: %08X\n", i, ret[0]); 51669d5fd8fSJohnny Huang } 51769d5fd8fSJohnny Huang printf("\n"); 5182a856b9aSJohnny Huang return OTP_SUCCESS; 51969d5fd8fSJohnny Huang } 52069d5fd8fSJohnny Huang 52169d5fd8fSJohnny Huang static int otp_print_data(uint32_t offset, int dw_count) 52269d5fd8fSJohnny Huang { 52369d5fd8fSJohnny Huang int i; 52469d5fd8fSJohnny Huang uint32_t ret[2]; 52569d5fd8fSJohnny Huang 52669d5fd8fSJohnny Huang if (offset + dw_count > 2048 || offset % 4 != 0) 5272a856b9aSJohnny Huang return OTP_USAGE; 52869d5fd8fSJohnny Huang for (i = offset; i < offset + dw_count; i += 2) { 52969d5fd8fSJohnny Huang otp_read_data(i, ret); 53069d5fd8fSJohnny Huang if (i % 4 == 0) 53169d5fd8fSJohnny Huang printf("%03X: %08X %08X ", i * 4, ret[0], ret[1]); 53269d5fd8fSJohnny Huang else 53369d5fd8fSJohnny Huang printf("%08X %08X\n", ret[0], ret[1]); 53469d5fd8fSJohnny Huang 53569d5fd8fSJohnny Huang } 53669d5fd8fSJohnny Huang printf("\n"); 5372a856b9aSJohnny Huang return OTP_SUCCESS; 53869d5fd8fSJohnny Huang } 53969d5fd8fSJohnny Huang 54069d5fd8fSJohnny Huang static int otp_compare(uint32_t otp_addr, uint32_t addr) 54169d5fd8fSJohnny Huang { 54269d5fd8fSJohnny Huang uint32_t ret; 54369d5fd8fSJohnny Huang uint32_t *buf; 54469d5fd8fSJohnny Huang 54569d5fd8fSJohnny Huang buf = map_physmem(addr, 16, MAP_WRBACK); 54669d5fd8fSJohnny Huang printf("%08X\n", buf[0]); 54769d5fd8fSJohnny Huang printf("%08X\n", buf[1]); 54869d5fd8fSJohnny Huang printf("%08X\n", buf[2]); 54969d5fd8fSJohnny Huang printf("%08X\n", buf[3]); 55069d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Compare address 55169d5fd8fSJohnny Huang writel(buf[0], 0x1e6f2020); //Compare data 1 55269d5fd8fSJohnny Huang writel(buf[1], 0x1e6f2024); //Compare data 2 55369d5fd8fSJohnny Huang writel(buf[2], 0x1e6f2028); //Compare data 3 55469d5fd8fSJohnny Huang writel(buf[3], 0x1e6f202c); //Compare data 4 55569d5fd8fSJohnny Huang writel(0x23b1e363, 0x1e6f2004); //Compare command 55669d5fd8fSJohnny Huang udelay(10); 55769d5fd8fSJohnny Huang ret = readl(0x1e6f2014); //Compare command 55869d5fd8fSJohnny Huang if (ret & 0x1) 55969d5fd8fSJohnny Huang return 0; 56069d5fd8fSJohnny Huang else 56169d5fd8fSJohnny Huang return -1; 56269d5fd8fSJohnny Huang } 56369d5fd8fSJohnny Huang 56469d5fd8fSJohnny Huang static void otp_write(uint32_t otp_addr, uint32_t data) 56569d5fd8fSJohnny Huang { 56669d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 56769d5fd8fSJohnny Huang writel(data, 0x1e6f2020); //write data 56869d5fd8fSJohnny Huang writel(0x23b1e362, 0x1e6f2004); //write command 56969d5fd8fSJohnny Huang udelay(100); 57069d5fd8fSJohnny Huang } 57169d5fd8fSJohnny Huang 57269d5fd8fSJohnny Huang static void otp_prog(uint32_t otp_addr, uint32_t prog_bit) 57369d5fd8fSJohnny Huang { 57469d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //write address 57569d5fd8fSJohnny Huang writel(prog_bit, 0x1e6f2020); //write data 57669d5fd8fSJohnny Huang writel(0x23b1e364, 0x1e6f2004); //write command 57769d5fd8fSJohnny Huang udelay(85); 57869d5fd8fSJohnny Huang } 57969d5fd8fSJohnny Huang 580a6d0d645SJohnny Huang static int verify_bit(uint32_t otp_addr, int bit_offset, int value) 58169d5fd8fSJohnny Huang { 58269d5fd8fSJohnny Huang int ret; 58369d5fd8fSJohnny Huang 58469d5fd8fSJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 58569d5fd8fSJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 58669d5fd8fSJohnny Huang udelay(2); 58769d5fd8fSJohnny Huang ret = readl(0x1e6f2020); 588a6d0d645SJohnny Huang // printf("verify_bit = %x\n", ret); 58969d5fd8fSJohnny Huang if (((ret >> bit_offset) & 1) == value) 59069d5fd8fSJohnny Huang return 0; 59169d5fd8fSJohnny Huang else 59269d5fd8fSJohnny Huang return -1; 59369d5fd8fSJohnny Huang } 59469d5fd8fSJohnny Huang 595d90825e2SJohnny Huang static uint32_t verify_dw(uint32_t otp_addr, uint32_t *value, uint32_t *keep, uint32_t *compare, int size) 5964c1c9b35SJohnny Huang { 5974c1c9b35SJohnny Huang uint32_t ret[2]; 5984c1c9b35SJohnny Huang 5994c1c9b35SJohnny Huang otp_addr &= ~(1 << 15); 6004c1c9b35SJohnny Huang 6014c1c9b35SJohnny Huang if (otp_addr % 2 == 0) 6024c1c9b35SJohnny Huang writel(otp_addr, 0x1e6f2010); //Read address 6034c1c9b35SJohnny Huang else 6044c1c9b35SJohnny Huang writel(otp_addr - 1, 0x1e6f2010); //Read address 6054c1c9b35SJohnny Huang writel(0x23b1e361, 0x1e6f2004); //trigger read 6064c1c9b35SJohnny Huang udelay(2); 6074c1c9b35SJohnny Huang ret[0] = readl(0x1e6f2020); 6084c1c9b35SJohnny Huang ret[1] = readl(0x1e6f2024); 6094c1c9b35SJohnny Huang if (size == 1) { 6104c1c9b35SJohnny Huang if (otp_addr % 2 == 0) { 6114c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[0], value[0]); 612d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0])) { 6134c1c9b35SJohnny Huang compare[0] = 0; 6144c1c9b35SJohnny Huang return 0; 6154c1c9b35SJohnny Huang } else { 6164c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6174c1c9b35SJohnny Huang return -1; 6184c1c9b35SJohnny Huang } 6194c1c9b35SJohnny Huang 6204c1c9b35SJohnny Huang } else { 6214c1c9b35SJohnny Huang // printf("check %x : %x = %x\n", otp_addr, ret[1], value[0]); 622d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[1] & ~keep[0])) { 6234c1c9b35SJohnny Huang compare[0] = ~0; 6244c1c9b35SJohnny Huang return 0; 6254c1c9b35SJohnny Huang } else { 626d90825e2SJohnny Huang compare[0] = ~(value[0] ^ ret[1]); 6274c1c9b35SJohnny Huang return -1; 6284c1c9b35SJohnny Huang } 6294c1c9b35SJohnny Huang } 6304c1c9b35SJohnny Huang } else if (size == 2) { 6314c1c9b35SJohnny Huang // otp_addr should be even 632d90825e2SJohnny Huang if ((value[0] & ~keep[0]) == (ret[0] & ~keep[0]) && (value[1] & ~keep[1]) == (ret[1] & ~keep[1])) { 6334c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 6344c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 6354c1c9b35SJohnny Huang compare[0] = 0; 6364c1c9b35SJohnny Huang compare[1] = ~0; 6374c1c9b35SJohnny Huang return 0; 6384c1c9b35SJohnny Huang } else { 6394c1c9b35SJohnny Huang // printf("check[0] %x : %x = %x\n", otp_addr, ret[0], value[0]); 6404c1c9b35SJohnny Huang // printf("check[1] %x : %x = %x\n", otp_addr, ret[1], value[1]); 6414c1c9b35SJohnny Huang compare[0] = value[0] ^ ret[0]; 6424c1c9b35SJohnny Huang compare[1] = ~(value[1] ^ ret[1]); 6434c1c9b35SJohnny Huang return -1; 6444c1c9b35SJohnny Huang } 6454c1c9b35SJohnny Huang } else { 6464c1c9b35SJohnny Huang return -1; 6474c1c9b35SJohnny Huang } 6484c1c9b35SJohnny Huang } 6494c1c9b35SJohnny Huang 6507e22f42dSJohnny Huang static void otp_soak(int soak) 651d90825e2SJohnny Huang { 652d90825e2SJohnny Huang if (soak) { 653d90825e2SJohnny Huang otp_write(0x3000, 0x4021); // Write MRA 654d90825e2SJohnny Huang otp_write(0x5000, 0x1027); // Write MRB 655d90825e2SJohnny Huang otp_write(0x1000, 0x4820); // Write MR 656d90825e2SJohnny Huang writel(0x041930d4, 0x1e602008); //soak program 657d90825e2SJohnny Huang } else { 658d90825e2SJohnny Huang otp_write(0x3000, 0x4061); // Write MRA 659d90825e2SJohnny Huang otp_write(0x5000, 0x302f); // Write MRB 660d90825e2SJohnny Huang otp_write(0x1000, 0x4020); // Write MR 661d90825e2SJohnny Huang writel(0x04190760, 0x1e602008); //normal program 662d90825e2SJohnny Huang } 663d90825e2SJohnny Huang } 664d90825e2SJohnny Huang 665d90825e2SJohnny Huang static void otp_prog_dw(uint32_t value, uint32_t keep, uint32_t prog_address) 666d90825e2SJohnny Huang { 667d90825e2SJohnny Huang int j, bit_value, prog_bit; 668d90825e2SJohnny Huang 669d90825e2SJohnny Huang for (j = 0; j < 32; j++) { 670d90825e2SJohnny Huang if ((keep >> j) & 0x1) 671d90825e2SJohnny Huang continue; 672d90825e2SJohnny Huang bit_value = (value >> j) & 0x1; 673d90825e2SJohnny Huang if (prog_address % 2 == 0) { 674d90825e2SJohnny Huang if (bit_value) 675d90825e2SJohnny Huang prog_bit = ~(0x1 << j); 676d90825e2SJohnny Huang else 677d90825e2SJohnny Huang continue; 678d90825e2SJohnny Huang } else { 679d90825e2SJohnny Huang prog_address |= 1 << 15; 680d90825e2SJohnny Huang if (bit_value) 681d90825e2SJohnny Huang continue; 682d90825e2SJohnny Huang else 683d90825e2SJohnny Huang prog_bit = 0x1 << j; 684d90825e2SJohnny Huang } 685d90825e2SJohnny Huang otp_prog(prog_address, prog_bit); 686d90825e2SJohnny Huang } 687d90825e2SJohnny Huang } 688d90825e2SJohnny Huang 68976d13988SJohnny Huang 69076d13988SJohnny Huang static void otp_strp_status(struct otpstrap_status *otpstrap) 69176d13988SJohnny Huang { 69276d13988SJohnny Huang uint32_t OTPSTRAP_RAW[2]; 69376d13988SJohnny Huang int i, j; 69476d13988SJohnny Huang 69576d13988SJohnny Huang for (j = 0; j < 64; j++) { 69676d13988SJohnny Huang otpstrap[j].value = 0; 69776d13988SJohnny Huang otpstrap[j].remain_times = 7; 69876d13988SJohnny Huang otpstrap[j].writeable_option = -1; 69976d13988SJohnny Huang otpstrap[j].protected = 0; 70076d13988SJohnny Huang } 70176d13988SJohnny Huang 70276d13988SJohnny Huang for (i = 16; i < 30; i += 2) { 70376d13988SJohnny Huang int option = (i - 16) / 2; 70476d13988SJohnny Huang otp_read_config(i, &OTPSTRAP_RAW[0]); 70576d13988SJohnny Huang otp_read_config(i + 1, &OTPSTRAP_RAW[1]); 70676d13988SJohnny Huang for (j = 0; j < 32; j++) { 70776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[0] >> j) & 0x1); 70876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 70976d13988SJohnny Huang otpstrap[j].writeable_option = option; 71076d13988SJohnny Huang } 71176d13988SJohnny Huang if (bit_value == 1) 71276d13988SJohnny Huang otpstrap[j].remain_times --; 71376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 71476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 71576d13988SJohnny Huang } 71676d13988SJohnny Huang for (j = 32; j < 64; j++) { 71776d13988SJohnny Huang char bit_value = ((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1); 71876d13988SJohnny Huang if ((bit_value == 0) && (otpstrap[j].writeable_option == -1)) { 71976d13988SJohnny Huang otpstrap[j].writeable_option = option; 72076d13988SJohnny Huang } 72176d13988SJohnny Huang if (bit_value == 1) 72276d13988SJohnny Huang otpstrap[j].remain_times --; 72376d13988SJohnny Huang otpstrap[j].value ^= bit_value; 72476d13988SJohnny Huang otpstrap[j].option_array[option] = bit_value; 72576d13988SJohnny Huang } 72676d13988SJohnny Huang } 72776d13988SJohnny Huang otp_read_config(30, &OTPSTRAP_RAW[0]); 72876d13988SJohnny Huang otp_read_config(31, &OTPSTRAP_RAW[1]); 72976d13988SJohnny Huang for (j = 0; j < 32; j++) { 73076d13988SJohnny Huang if (((OTPSTRAP_RAW[0] >> j) & 0x1) == 1) 73176d13988SJohnny Huang otpstrap[j].protected = 1; 73276d13988SJohnny Huang } 73376d13988SJohnny Huang for (j = 32; j < 64; j++) { 73476d13988SJohnny Huang if (((OTPSTRAP_RAW[1] >> (j - 32)) & 0x1) == 1) 73576d13988SJohnny Huang otpstrap[j].protected = 1; 73676d13988SJohnny Huang } 73776d13988SJohnny Huang } 73876d13988SJohnny Huang 739b458cd62SJohnny Huang static int otp_print_conf_image(uint32_t *OTPCFG) 74069d5fd8fSJohnny Huang { 741442839bbSJohnny Huang uint32_t *OTPCFG_KEEP = &OTPCFG[12]; 742b458cd62SJohnny Huang uint32_t mask; 743b458cd62SJohnny Huang uint32_t dw_offset; 744b458cd62SJohnny Huang uint32_t bit_offset; 745b458cd62SJohnny Huang uint32_t otp_value; 746b458cd62SJohnny Huang uint32_t otp_keep; 747b458cd62SJohnny Huang int fail = 0; 748b458cd62SJohnny Huang int valid_bit = 0; 74966f2f8e5SJohnny Huang int i; 75066f2f8e5SJohnny Huang 751737ed20bSJohnny Huang printf("DW BIT Value Description\n"); 75266f2f8e5SJohnny Huang printf("__________________________________________________________________________\n"); 753b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 754b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 755b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 756b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 757b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 758b458cd62SJohnny Huang otp_keep = (OTPCFG_KEEP[dw_offset] >> bit_offset) & mask; 759b458cd62SJohnny Huang 760b458cd62SJohnny Huang if (otp_keep == mask) { 761b458cd62SJohnny Huang continue; 762b458cd62SJohnny Huang } else if (otp_keep != 0) { 763b458cd62SJohnny Huang fail = 1; 764b458cd62SJohnny Huang } 765b458cd62SJohnny Huang 766b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 767b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 768b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 769b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 770b458cd62SJohnny Huang continue; 771b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 772b458cd62SJohnny Huang 773b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 774b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 77566f2f8e5SJohnny Huang } else { 776b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 777b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 778b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 77966f2f8e5SJohnny Huang } 780b458cd62SJohnny Huang printf("0x%-10x", otp_value); 781b458cd62SJohnny Huang 782b458cd62SJohnny Huang if (fail) { 783b458cd62SJohnny Huang printf("Keep mask error\n"); 784b458cd62SJohnny Huang } else { 785b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 786b458cd62SJohnny Huang printf("Reserved\n"); 787b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 788b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 789b458cd62SJohnny Huang printf("\n"); 790b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 791b458cd62SJohnny Huang if (otp_value != 0) { 792b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 793b458cd62SJohnny Huang if (otp_value == (1 << i)) { 794b458cd62SJohnny Huang valid_bit = i + 1; 79566f2f8e5SJohnny Huang } 796b458cd62SJohnny Huang } 797b458cd62SJohnny Huang } else { 798b458cd62SJohnny Huang valid_bit = 0; 799b458cd62SJohnny Huang } 800b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 801b458cd62SJohnny Huang printf("\n"); 802b458cd62SJohnny Huang } else { 803b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 804b458cd62SJohnny Huang } 805b458cd62SJohnny Huang } 806b458cd62SJohnny Huang } 807b458cd62SJohnny Huang 808b458cd62SJohnny Huang if (fail) 809b458cd62SJohnny Huang return OTP_FAILURE; 810b458cd62SJohnny Huang 81166f2f8e5SJohnny Huang return OTP_SUCCESS; 81266f2f8e5SJohnny Huang } 81366f2f8e5SJohnny Huang 8142d4b0742SJohnny Huang static int otp_print_conf_info(int input_offset) 81566f2f8e5SJohnny Huang { 816b458cd62SJohnny Huang uint32_t OTPCFG[12]; 817b458cd62SJohnny Huang uint32_t mask; 818b458cd62SJohnny Huang uint32_t dw_offset; 819b458cd62SJohnny Huang uint32_t bit_offset; 820b458cd62SJohnny Huang uint32_t otp_value; 821b458cd62SJohnny Huang int valid_bit = 0; 82266f2f8e5SJohnny Huang int i; 82366f2f8e5SJohnny Huang 82466f2f8e5SJohnny Huang for (i = 0; i < 12; i++) 82566f2f8e5SJohnny Huang otp_read_config(i, &OTPCFG[i]); 82666f2f8e5SJohnny Huang 82766f2f8e5SJohnny Huang 828b458cd62SJohnny Huang printf("DW BIT Value Description\n"); 829b458cd62SJohnny Huang printf("__________________________________________________________________________\n"); 830b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_conf_info); i++) { 8312d4b0742SJohnny Huang if (input_offset != -1 && input_offset != a0_conf_info[i].dw_offset) 8322d4b0742SJohnny Huang continue; 833b458cd62SJohnny Huang dw_offset = a0_conf_info[i].dw_offset; 834b458cd62SJohnny Huang bit_offset = a0_conf_info[i].bit_offset; 835b458cd62SJohnny Huang mask = BIT(a0_conf_info[i].length) - 1; 836b458cd62SJohnny Huang otp_value = (OTPCFG[dw_offset] >> bit_offset) & mask; 837b458cd62SJohnny Huang 838b458cd62SJohnny Huang if ((otp_value != a0_conf_info[i].value) && 839b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_RESERVED && 840b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALUE && 841b458cd62SJohnny Huang a0_conf_info[i].value != OTP_REG_VALID_BIT) 842b458cd62SJohnny Huang continue; 843b458cd62SJohnny Huang printf("0x%-4X", dw_offset); 844b458cd62SJohnny Huang 845b458cd62SJohnny Huang if (a0_conf_info[i].length == 1) { 846b458cd62SJohnny Huang printf("0x%-9X", a0_conf_info[i].bit_offset); 847b458cd62SJohnny Huang } else { 848b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 849b458cd62SJohnny Huang a0_conf_info[i].bit_offset + a0_conf_info[i].length - 1, 850b458cd62SJohnny Huang a0_conf_info[i].bit_offset); 851b458cd62SJohnny Huang } 852b458cd62SJohnny Huang printf("0x%-10x", otp_value); 853b458cd62SJohnny Huang 854b458cd62SJohnny Huang if (a0_conf_info[i].value == OTP_REG_RESERVED) { 855b458cd62SJohnny Huang printf("Reserved\n"); 856b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALUE) { 857b458cd62SJohnny Huang printf(a0_conf_info[i].information, otp_value); 858b458cd62SJohnny Huang printf("\n"); 859b458cd62SJohnny Huang } else if (a0_conf_info[i].value == OTP_REG_VALID_BIT) { 860b458cd62SJohnny Huang if (otp_value != 0) { 861b458cd62SJohnny Huang for (i = 0; i < 7; i++) { 862b458cd62SJohnny Huang if (otp_value == (1 << i)) { 863b458cd62SJohnny Huang valid_bit = i + 1; 864b458cd62SJohnny Huang } 865b458cd62SJohnny Huang } 866b458cd62SJohnny Huang } else { 867b458cd62SJohnny Huang valid_bit = 0; 868b458cd62SJohnny Huang } 869b458cd62SJohnny Huang printf(a0_conf_info[i].information, valid_bit); 870b458cd62SJohnny Huang printf("\n"); 871b458cd62SJohnny Huang } else { 872b458cd62SJohnny Huang printf("%s\n", a0_conf_info[i].information); 873b458cd62SJohnny Huang } 874b458cd62SJohnny Huang } 875b458cd62SJohnny Huang return OTP_SUCCESS; 87666f2f8e5SJohnny Huang } 87766f2f8e5SJohnny Huang 878b458cd62SJohnny Huang static int otp_print_strap_image(uint32_t *OTPSTRAP) 87976d13988SJohnny Huang { 880a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_PRO = &OTPSTRAP[4]; 881a8bd6d8cSJohnny Huang uint32_t *OTPSTRAP_KEEP = &OTPSTRAP[2]; 88276d13988SJohnny Huang int i; 883a8bd6d8cSJohnny Huang int fail = 0; 884a8bd6d8cSJohnny Huang uint32_t bit_offset; 885a8bd6d8cSJohnny Huang uint32_t dw_offset; 886a8bd6d8cSJohnny Huang uint32_t mask; 887a8bd6d8cSJohnny Huang uint32_t otp_value; 888a8bd6d8cSJohnny Huang uint32_t otp_protect; 889a8bd6d8cSJohnny Huang uint32_t otp_keep; 89076d13988SJohnny Huang 891a8bd6d8cSJohnny Huang printf("BIT(hex) Value Protect Description\n"); 892a8bd6d8cSJohnny Huang printf("__________________________________________________________________________________________\n"); 893b458cd62SJohnny Huang 894a8bd6d8cSJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 895a8bd6d8cSJohnny Huang if (a0_strap_info[i].bit_offset > 32) { 896a8bd6d8cSJohnny Huang dw_offset = 1; 897a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset - 32; 898a8bd6d8cSJohnny Huang } else { 899a8bd6d8cSJohnny Huang dw_offset = 0; 900a8bd6d8cSJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 901a8bd6d8cSJohnny Huang } 90276d13988SJohnny Huang 903a8bd6d8cSJohnny Huang mask = BIT(a0_strap_info[i].length) - 1; 904a8bd6d8cSJohnny Huang otp_value = (OTPSTRAP[dw_offset] >> bit_offset) & mask; 905a8bd6d8cSJohnny Huang otp_protect = (OTPSTRAP_PRO[dw_offset] >> bit_offset) & mask; 906a8bd6d8cSJohnny Huang otp_keep = (OTPSTRAP_KEEP[dw_offset] >> bit_offset) & mask; 907a8bd6d8cSJohnny Huang 908a8bd6d8cSJohnny Huang if (otp_keep == mask) { 909a8bd6d8cSJohnny Huang continue; 910a8bd6d8cSJohnny Huang } else if (otp_keep != 0) { 911a8bd6d8cSJohnny Huang fail = 1; 912a8bd6d8cSJohnny Huang } 913a8bd6d8cSJohnny Huang 914a8bd6d8cSJohnny Huang if ((otp_value != a0_strap_info[i].value) && 915a8bd6d8cSJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 916a8bd6d8cSJohnny Huang continue; 917a8bd6d8cSJohnny Huang 918a8bd6d8cSJohnny Huang if (a0_strap_info[i].length == 1) { 919b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 920a8bd6d8cSJohnny Huang } else { 921b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 922a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset + a0_strap_info[i].length - 1, 923a8bd6d8cSJohnny Huang a0_strap_info[i].bit_offset); 924a8bd6d8cSJohnny Huang } 925a8bd6d8cSJohnny Huang printf("0x%-10x", otp_value); 926a8bd6d8cSJohnny Huang printf("0x%-10x", otp_protect); 927a8bd6d8cSJohnny Huang 928a8bd6d8cSJohnny Huang if (fail) { 929a8bd6d8cSJohnny Huang printf("Keep mask error\n"); 930a8bd6d8cSJohnny Huang } else { 931a8bd6d8cSJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 932a8bd6d8cSJohnny Huang printf("%s\n", a0_strap_info[i].information); 933a8bd6d8cSJohnny Huang else 934a8bd6d8cSJohnny Huang printf("Reserved\n"); 935a8bd6d8cSJohnny Huang } 936a8bd6d8cSJohnny Huang } 937a8bd6d8cSJohnny Huang 938a8bd6d8cSJohnny Huang if (fail) 93976d13988SJohnny Huang return OTP_FAILURE; 94076d13988SJohnny Huang 94176d13988SJohnny Huang return OTP_SUCCESS; 94276d13988SJohnny Huang } 94376d13988SJohnny Huang 944b458cd62SJohnny Huang static int otp_print_strap_info(int view) 94576d13988SJohnny Huang { 94676d13988SJohnny Huang struct otpstrap_status strap_status[64]; 947*07baa4e8SJohnny Huang int i, j; 948b458cd62SJohnny Huang int fail = 0; 949b458cd62SJohnny Huang uint32_t bit_offset; 950b458cd62SJohnny Huang uint32_t length; 951b458cd62SJohnny Huang uint32_t otp_value; 952b458cd62SJohnny Huang uint32_t otp_protect; 95376d13988SJohnny Huang 95476d13988SJohnny Huang otp_strp_status(strap_status); 95576d13988SJohnny Huang 956b458cd62SJohnny Huang if (view) { 957*07baa4e8SJohnny Huang // printf("BIT(hex) Value Option Protect Description\n"); 958*07baa4e8SJohnny Huang // printf(" 0 1 2 3 4 5 6\n"); 959*07baa4e8SJohnny Huang printf("BIT(hex) Value Remains Protect Description\n"); 960*07baa4e8SJohnny Huang printf("___________________________________________________________________________________________________\n"); 961b458cd62SJohnny Huang } else { 962b458cd62SJohnny Huang printf("BIT(hex) Value Description\n"); 963b458cd62SJohnny Huang printf("________________________________________________________________________________\n"); 96476d13988SJohnny Huang } 965b458cd62SJohnny Huang for (i = 0; i < ARRAY_SIZE(a0_strap_info); i++) { 966b458cd62SJohnny Huang otp_value = 0; 967b458cd62SJohnny Huang bit_offset = a0_strap_info[i].bit_offset; 968b458cd62SJohnny Huang length = a0_strap_info[i].length; 969b458cd62SJohnny Huang for (j = 0; j < length; j++) { 970b458cd62SJohnny Huang otp_value |= strap_status[bit_offset].value << j; 971b458cd62SJohnny Huang otp_protect |= strap_status[bit_offset].protected << j; 972b458cd62SJohnny Huang } 973b458cd62SJohnny Huang if ((otp_value != a0_strap_info[i].value) && 974b458cd62SJohnny Huang a0_strap_info[i].value != OTP_REG_RESERVED) 975b458cd62SJohnny Huang continue; 976b458cd62SJohnny Huang if (view) { 977b458cd62SJohnny Huang for (j = 0; j < length; j++) { 978b458cd62SJohnny Huang printf("0x%-7X", a0_strap_info[i].bit_offset + j); 979b458cd62SJohnny Huang printf("0x%-5X", strap_status[bit_offset + j].value); 980*07baa4e8SJohnny Huang printf("%-9d", strap_status[bit_offset + j].remain_times); 981*07baa4e8SJohnny Huang // for (k = 0; k < 7; k++) { 982*07baa4e8SJohnny Huang // printf("%X ", strap_status[bit_offset + j].option_array[k]); 983*07baa4e8SJohnny Huang // } 984b458cd62SJohnny Huang printf("0x%-7X", strap_status[bit_offset].protected); 985b458cd62SJohnny Huang if (a0_strap_info[i].value == OTP_REG_RESERVED) { 986b458cd62SJohnny Huang printf(" Reserved\n"); 987b458cd62SJohnny Huang continue; 988b458cd62SJohnny Huang } 989b458cd62SJohnny Huang if (length == 1) { 990b458cd62SJohnny Huang printf(" %s\n", a0_strap_info[i].information); 991b458cd62SJohnny Huang continue; 99276d13988SJohnny Huang } 99376d13988SJohnny Huang 994b458cd62SJohnny Huang if (j == 0) 995b458cd62SJohnny Huang printf("/%s\n", a0_strap_info[i].information); 996b458cd62SJohnny Huang else if (j == length - 1) 997b458cd62SJohnny Huang printf("\\ \"\n"); 998b458cd62SJohnny Huang else 999b458cd62SJohnny Huang printf("| \"\n"); 100076d13988SJohnny Huang } 1001b458cd62SJohnny Huang } else { 1002b458cd62SJohnny Huang if (a0_strap_info[i].length == 1) { 1003b458cd62SJohnny Huang printf("0x%-9X", a0_strap_info[i].bit_offset); 1004b458cd62SJohnny Huang } else { 1005b458cd62SJohnny Huang printf("0x%-2X:0x%-4X", 1006b458cd62SJohnny Huang bit_offset + length - 1, bit_offset); 1007b458cd62SJohnny Huang } 1008b458cd62SJohnny Huang 1009b458cd62SJohnny Huang printf("0x%-10X", otp_value); 1010b458cd62SJohnny Huang 1011b458cd62SJohnny Huang if (a0_strap_info[i].value != OTP_REG_RESERVED) 1012b458cd62SJohnny Huang printf("%s\n", a0_strap_info[i].information); 1013b458cd62SJohnny Huang else 1014b458cd62SJohnny Huang printf("Reserved\n"); 1015b458cd62SJohnny Huang } 1016b458cd62SJohnny Huang } 1017b458cd62SJohnny Huang 1018b458cd62SJohnny Huang if (fail) 1019b458cd62SJohnny Huang return OTP_FAILURE; 1020b458cd62SJohnny Huang 1021b458cd62SJohnny Huang return OTP_SUCCESS; 1022b458cd62SJohnny Huang } 1023b458cd62SJohnny Huang 1024b458cd62SJohnny Huang // static void otp_info_strap(int view) 1025b458cd62SJohnny Huang // { 1026b458cd62SJohnny Huang // struct otpstrap_status strap_status[64]; 1027b458cd62SJohnny Huang // uint32_t OTPSTRAP[6]; 1028b458cd62SJohnny Huang // int i; 1029b458cd62SJohnny Huang 1030b458cd62SJohnny Huang 1031b458cd62SJohnny Huang // otp_strp_status(strap_status); 1032b458cd62SJohnny Huang 1033b458cd62SJohnny Huang // for (i = 0; i < 6; i++) 1034b458cd62SJohnny Huang // OTPSTRAP[i] = 0; 1035b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 1036b458cd62SJohnny Huang // OTPSTRAP[0] |= (strap_status[i].value & 0x1) << i; 1037b458cd62SJohnny Huang // OTPSTRAP[4] |= (strap_status[i].protected & 0x1) << i; 1038b458cd62SJohnny Huang // } 1039b458cd62SJohnny Huang // for (i = 0; i < 32; i++) { 1040b458cd62SJohnny Huang // OTPSTRAP[1] |= (strap_status[i + 32].value & 0x1) << i; 1041b458cd62SJohnny Huang // OTPSTRAP[5] |= (strap_status[i + 32].protected & 0x1) << i; 1042b458cd62SJohnny Huang // } 1043b458cd62SJohnny Huang 1044b458cd62SJohnny Huang // otp_print_strap_info(OTPSTRAP, view); 1045b458cd62SJohnny Huang // } 104676d13988SJohnny Huang 104769d5fd8fSJohnny Huang static void buf_print(char *buf, int len) 104869d5fd8fSJohnny Huang { 104969d5fd8fSJohnny Huang int i; 105069d5fd8fSJohnny Huang printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); 105169d5fd8fSJohnny Huang for (i = 0; i < len; i++) { 105269d5fd8fSJohnny Huang if (i % 16 == 0) { 105369d5fd8fSJohnny Huang printf("%04X: ", i); 105469d5fd8fSJohnny Huang } 105569d5fd8fSJohnny Huang printf("%02X ", buf[i]); 105669d5fd8fSJohnny Huang if ((i + 1) % 16 == 0) { 105769d5fd8fSJohnny Huang printf("\n"); 105869d5fd8fSJohnny Huang } 105969d5fd8fSJohnny Huang } 106069d5fd8fSJohnny Huang } 106169d5fd8fSJohnny Huang 10627f795e57SJohnny Huang static int otp_print_data_info(uint32_t *buf) 106369d5fd8fSJohnny Huang { 106469d5fd8fSJohnny Huang int key_id, key_offset, last, key_type, key_length, exp_length; 106569d5fd8fSJohnny Huang char *byte_buf; 106669d5fd8fSJohnny Huang int i = 0, len = 0; 106769d5fd8fSJohnny Huang byte_buf = (char *)buf; 106869d5fd8fSJohnny Huang while (1) { 106969d5fd8fSJohnny Huang key_id = buf[i] & 0x7; 107069d5fd8fSJohnny Huang key_offset = buf[i] & 0x1ff8; 107169d5fd8fSJohnny Huang last = (buf[i] >> 13) & 1; 107269d5fd8fSJohnny Huang key_type = (buf[i] >> 14) & 0xf; 107369d5fd8fSJohnny Huang key_length = (buf[i] >> 18) & 0x3; 107469d5fd8fSJohnny Huang exp_length = (buf[i] >> 20) & 0xfff; 10757f795e57SJohnny Huang printf("\nKey[%d]:\n", i); 107669d5fd8fSJohnny Huang printf("Key Type: "); 107769d5fd8fSJohnny Huang switch (key_type) { 107869d5fd8fSJohnny Huang case 0: 107969d5fd8fSJohnny Huang printf("AES-256 as OEM platform key for image encryption/decryption\n"); 108069d5fd8fSJohnny Huang break; 108169d5fd8fSJohnny Huang case 1: 108269d5fd8fSJohnny Huang printf("AES-256 as secret vault key\n"); 108369d5fd8fSJohnny Huang break; 108469d5fd8fSJohnny Huang case 4: 108569d5fd8fSJohnny Huang printf("HMAC as encrypted OEM HMAC keys in Mode 1\n"); 108669d5fd8fSJohnny Huang break; 108769d5fd8fSJohnny Huang case 8: 108869d5fd8fSJohnny Huang printf("RSA-public as OEM DSS public keys in Mode 2\n"); 108969d5fd8fSJohnny Huang break; 109069d5fd8fSJohnny Huang case 9: 109169d5fd8fSJohnny Huang printf("RSA-public as SOC public key\n"); 109269d5fd8fSJohnny Huang break; 109369d5fd8fSJohnny Huang case 10: 109469d5fd8fSJohnny Huang printf("RSA-public as AES key decryption key\n"); 109569d5fd8fSJohnny Huang break; 109669d5fd8fSJohnny Huang case 13: 109769d5fd8fSJohnny Huang printf("RSA-private as SOC private key\n"); 109869d5fd8fSJohnny Huang break; 109969d5fd8fSJohnny Huang case 14: 110069d5fd8fSJohnny Huang printf("RSA-private as AES key decryption key\n"); 110169d5fd8fSJohnny Huang break; 110269d5fd8fSJohnny Huang default: 110369d5fd8fSJohnny Huang printf("key_type error: %x\n", key_type); 110469d5fd8fSJohnny Huang return -1; 110569d5fd8fSJohnny Huang } 110669d5fd8fSJohnny Huang if (key_type == 4) { 110769d5fd8fSJohnny Huang printf("HMAC SHA Type: "); 110869d5fd8fSJohnny Huang switch (key_length) { 110969d5fd8fSJohnny Huang case 0: 111069d5fd8fSJohnny Huang printf("HMAC(SHA224)\n"); 111169d5fd8fSJohnny Huang break; 111269d5fd8fSJohnny Huang case 1: 111369d5fd8fSJohnny Huang printf("HMAC(SHA256)\n"); 111469d5fd8fSJohnny Huang break; 111569d5fd8fSJohnny Huang case 2: 111669d5fd8fSJohnny Huang printf("HMAC(SHA384)\n"); 111769d5fd8fSJohnny Huang break; 111869d5fd8fSJohnny Huang case 3: 111969d5fd8fSJohnny Huang printf("HMAC(SHA512)\n"); 112069d5fd8fSJohnny Huang break; 112169d5fd8fSJohnny Huang } 1122cd1610b4SJohnny Huang } else if (key_type != 0 && key_type != 1) { 112369d5fd8fSJohnny Huang printf("RSA SHA Type: "); 112469d5fd8fSJohnny Huang switch (key_length) { 112569d5fd8fSJohnny Huang case 0: 112669d5fd8fSJohnny Huang printf("RSA1024\n"); 112769d5fd8fSJohnny Huang len = 0x100; 112869d5fd8fSJohnny Huang break; 112969d5fd8fSJohnny Huang case 1: 113069d5fd8fSJohnny Huang printf("RSA2048\n"); 113169d5fd8fSJohnny Huang len = 0x200; 113269d5fd8fSJohnny Huang break; 113369d5fd8fSJohnny Huang case 2: 113469d5fd8fSJohnny Huang printf("RSA3072\n"); 113569d5fd8fSJohnny Huang len = 0x300; 113669d5fd8fSJohnny Huang break; 113769d5fd8fSJohnny Huang case 3: 113869d5fd8fSJohnny Huang printf("RSA4096\n"); 113969d5fd8fSJohnny Huang len = 0x400; 114069d5fd8fSJohnny Huang break; 114169d5fd8fSJohnny Huang } 114269d5fd8fSJohnny Huang printf("RSA exponent bit length: %d\n", exp_length); 114369d5fd8fSJohnny Huang } 114469d5fd8fSJohnny Huang if (key_type == 4 || key_type == 8) 114569d5fd8fSJohnny Huang printf("Key Number ID: %d\n", key_id); 114669d5fd8fSJohnny Huang printf("Key Value:\n"); 114769d5fd8fSJohnny Huang if (key_type == 4) { 114869d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x40); 114969d5fd8fSJohnny Huang } else if (key_type == 0 || key_type == 1) { 115069d5fd8fSJohnny Huang printf("AES Key:\n"); 115169d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], 0x20); 115269d5fd8fSJohnny Huang printf("AES IV:\n"); 115369d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + 0x20], 0x10); 115469d5fd8fSJohnny Huang 115569d5fd8fSJohnny Huang } else { 115669d5fd8fSJohnny Huang printf("RSA mod:\n"); 115769d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset], len / 2); 115869d5fd8fSJohnny Huang printf("RSA exp:\n"); 115969d5fd8fSJohnny Huang buf_print(&byte_buf[key_offset + (len / 2)], len / 2); 116069d5fd8fSJohnny Huang } 116169d5fd8fSJohnny Huang if (last) 116269d5fd8fSJohnny Huang break; 116369d5fd8fSJohnny Huang i++; 116469d5fd8fSJohnny Huang } 116569d5fd8fSJohnny Huang return 0; 116669d5fd8fSJohnny Huang } 116769d5fd8fSJohnny Huang 1168a6d0d645SJohnny Huang static int otp_prog_conf(uint32_t *buf) 116969d5fd8fSJohnny Huang { 1170a6d0d645SJohnny Huang int i, k; 1171d90825e2SJohnny Huang int pass = 0; 1172d90825e2SJohnny Huang int soak = 0; 1173a6d0d645SJohnny Huang uint32_t prog_address; 1174a6d0d645SJohnny Huang uint32_t data[12]; 1175a6d0d645SJohnny Huang uint32_t compare[2]; 1176d90825e2SJohnny Huang uint32_t *buf_keep = &buf[12]; 1177d90825e2SJohnny Huang uint32_t data_masked; 1178d90825e2SJohnny Huang uint32_t buf_masked; 117969d5fd8fSJohnny Huang 1180a6d0d645SJohnny Huang printf("Read OTP Config Region:\n"); 1181a6d0d645SJohnny Huang 1182a6d0d645SJohnny Huang printProgress(0, 12, ""); 1183a6d0d645SJohnny Huang for (i = 0; i < 12 ; i ++) { 1184a6d0d645SJohnny Huang printProgress(i + 1, 12, ""); 118569d5fd8fSJohnny Huang prog_address = 0x800; 1186a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1187a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1188a6d0d645SJohnny Huang otp_read_data(prog_address, &data[i]); 1189a6d0d645SJohnny Huang } 1190a6d0d645SJohnny Huang 1191a6d0d645SJohnny Huang printf("Check writable...\n"); 1192a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1193d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1194d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1195d90825e2SJohnny Huang if (data_masked == buf_masked) 119669d5fd8fSJohnny Huang continue; 1197d90825e2SJohnny Huang if ((data_masked | buf_masked) == buf_masked) { 1198a6d0d645SJohnny Huang continue; 1199a6d0d645SJohnny Huang } else { 1200a6d0d645SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1201a6af4a17SJohnny Huang printf("OTPCFG[%X] = %x\n", i, data[i]); 1202a6af4a17SJohnny Huang printf("Input [%X] = %x\n", i, buf[i]); 1203a6af4a17SJohnny Huang printf("Mask [%X] = %x\n", i, ~buf_keep[i]); 12042a856b9aSJohnny Huang return OTP_FAILURE; 1205a6d0d645SJohnny Huang } 1206a6d0d645SJohnny Huang } 1207a6d0d645SJohnny Huang 1208a6d0d645SJohnny Huang printf("Start Programing...\n"); 1209a6d0d645SJohnny Huang printProgress(0, 12, ""); 1210d90825e2SJohnny Huang otp_soak(0); 1211a6d0d645SJohnny Huang for (i = 0; i < 12; i++) { 1212d90825e2SJohnny Huang data_masked = data[i] & ~buf_keep[i]; 1213d90825e2SJohnny Huang buf_masked = buf[i] & ~buf_keep[i]; 1214a6d0d645SJohnny Huang prog_address = 0x800; 1215a6d0d645SJohnny Huang prog_address |= (i / 8) * 0x200; 1216a6d0d645SJohnny Huang prog_address |= (i % 8) * 0x2; 1217d90825e2SJohnny Huang if (data_masked == buf_masked) { 1218a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X HIT", prog_address, buf[i]); 1219a6d0d645SJohnny Huang continue; 1220a6d0d645SJohnny Huang } 1221d90825e2SJohnny Huang if (soak) { 1222d90825e2SJohnny Huang soak = 0; 1223d90825e2SJohnny Huang otp_soak(0); 1224d90825e2SJohnny Huang } 1225a6d0d645SJohnny Huang printProgress(i + 1, 12, "[%03X]=%08X ", prog_address, buf[i]); 1226a6d0d645SJohnny Huang 1227d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1228a6d0d645SJohnny Huang 122969d5fd8fSJohnny Huang pass = 0; 123069d5fd8fSJohnny Huang for (k = 0; k < RETRY; k++) { 1231d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 1) != 0) { 1232d90825e2SJohnny Huang if (soak == 0) { 1233d90825e2SJohnny Huang soak = 1; 1234d90825e2SJohnny Huang otp_soak(1); 1235d90825e2SJohnny Huang } 1236a6d0d645SJohnny Huang otp_prog_dw(compare[0], prog_address, 1); 1237a6d0d645SJohnny Huang } else { 123869d5fd8fSJohnny Huang pass = 1; 123969d5fd8fSJohnny Huang break; 124069d5fd8fSJohnny Huang } 124169d5fd8fSJohnny Huang } 1242a6d0d645SJohnny Huang } 1243a6d0d645SJohnny Huang 124469d5fd8fSJohnny Huang if (!pass) 12452a856b9aSJohnny Huang return OTP_FAILURE; 1246a6d0d645SJohnny Huang 12472a856b9aSJohnny Huang return OTP_SUCCESS; 1248d90825e2SJohnny Huang 124969d5fd8fSJohnny Huang } 125069d5fd8fSJohnny Huang 125169d5fd8fSJohnny Huang 125276d13988SJohnny Huang static int otp_strap_image_confirm(uint32_t *buf) 125369d5fd8fSJohnny Huang { 125469d5fd8fSJohnny Huang int i; 125569d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 125669d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 125769d5fd8fSJohnny Huang int bit, pbit, kbit; 125869d5fd8fSJohnny Huang int fail = 0; 1259a6af4a17SJohnny Huang int skip = -1; 126066f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 126169d5fd8fSJohnny Huang 126269d5fd8fSJohnny Huang otp_strp_status(otpstrap); 126369d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 126469d5fd8fSJohnny Huang if (i < 32) { 126569d5fd8fSJohnny Huang bit = (buf[0] >> i) & 0x1; 126669d5fd8fSJohnny Huang kbit = (strap_keep[0] >> i) & 0x1; 126769d5fd8fSJohnny Huang pbit = (strap_protect[0] >> i) & 0x1; 126869d5fd8fSJohnny Huang } else { 126969d5fd8fSJohnny Huang bit = (buf[1] >> (i - 32)) & 0x1; 127069d5fd8fSJohnny Huang kbit = (strap_keep[1] >> (i - 32)) & 0x1; 127169d5fd8fSJohnny Huang pbit = (strap_protect[1] >> (i - 32)) & 0x1; 127269d5fd8fSJohnny Huang } 127369d5fd8fSJohnny Huang 127469d5fd8fSJohnny Huang if (kbit == 1) { 127569d5fd8fSJohnny Huang continue; 127669d5fd8fSJohnny Huang } else { 1277a6af4a17SJohnny Huang printf("OTPSTRAP[%X]:\n", i); 127869d5fd8fSJohnny Huang } 127969d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 128069d5fd8fSJohnny Huang printf(" The value is same as before, skip it.\n"); 1281a6af4a17SJohnny Huang if (skip == -1) 1282a6af4a17SJohnny Huang skip = 1; 128369d5fd8fSJohnny Huang continue; 1284a6af4a17SJohnny Huang } else { 1285a6af4a17SJohnny Huang skip = 0; 128669d5fd8fSJohnny Huang } 128769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 128869d5fd8fSJohnny Huang printf(" This bit is protected and is not writable\n"); 128969d5fd8fSJohnny Huang fail = 1; 129069d5fd8fSJohnny Huang continue; 129169d5fd8fSJohnny Huang } 129269d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1293a6af4a17SJohnny Huang printf(" This bit is no remaining times to write.\n"); 129469d5fd8fSJohnny Huang fail = 1; 129569d5fd8fSJohnny Huang continue; 129669d5fd8fSJohnny Huang } 129769d5fd8fSJohnny Huang if (pbit == 1) { 129869d5fd8fSJohnny Huang printf(" This bit will be protected and become non-writable.\n"); 129969d5fd8fSJohnny Huang } 1300a6af4a17SJohnny 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); 130169d5fd8fSJohnny Huang } 130269d5fd8fSJohnny Huang if (fail == 1) 1303a6af4a17SJohnny Huang return OTP_FAILURE; 1304a6af4a17SJohnny Huang else if (skip == 1) 1305a6af4a17SJohnny Huang return OTP_PROG_SKIP; 13067e22f42dSJohnny Huang 13077e22f42dSJohnny Huang return 0; 130869d5fd8fSJohnny Huang } 130969d5fd8fSJohnny Huang 13102a856b9aSJohnny Huang static int otp_print_strap(int start, int count) 131169d5fd8fSJohnny Huang { 131269d5fd8fSJohnny Huang int i, j; 131366f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 131469d5fd8fSJohnny Huang 13152a856b9aSJohnny Huang if (start < 0 || start > 64) 13162a856b9aSJohnny Huang return OTP_USAGE; 13172a856b9aSJohnny Huang 13182a856b9aSJohnny Huang if ((start + count) < 0 || (start + count) > 64) 13192a856b9aSJohnny Huang return OTP_USAGE; 13202a856b9aSJohnny Huang 132169d5fd8fSJohnny Huang otp_strp_status(otpstrap); 132269d5fd8fSJohnny Huang 1323*07baa4e8SJohnny Huang printf("BIT(hex) Value Option Status\n"); 1324a8bd6d8cSJohnny Huang printf("___________________________________________________________________________\n"); 1325737ed20bSJohnny Huang 1326cd1610b4SJohnny Huang for (i = start; i < start + count; i++) { 1327*07baa4e8SJohnny Huang printf("0x%-8X", i); 1328737ed20bSJohnny Huang printf("%-7d", otpstrap[i].value); 1329737ed20bSJohnny Huang for (j = 0; j < 7; j++) 1330737ed20bSJohnny Huang printf("%d ", otpstrap[i].option_array[j]); 1331737ed20bSJohnny Huang printf(" "); 133269d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 1333737ed20bSJohnny Huang printf("protected and not writable"); 133469d5fd8fSJohnny Huang } else { 1335737ed20bSJohnny Huang printf("not protected "); 133669d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 1337737ed20bSJohnny Huang printf("and no remaining times to write."); 133869d5fd8fSJohnny Huang } else { 1339737ed20bSJohnny Huang printf("and still can write %d times", otpstrap[i].remain_times); 134069d5fd8fSJohnny Huang } 134169d5fd8fSJohnny Huang } 1342737ed20bSJohnny Huang printf("\n"); 134369d5fd8fSJohnny Huang } 13442a856b9aSJohnny Huang 13452a856b9aSJohnny Huang return OTP_SUCCESS; 134669d5fd8fSJohnny Huang } 134769d5fd8fSJohnny Huang 134869d5fd8fSJohnny Huang static int otp_prog_strap(uint32_t *buf) 134969d5fd8fSJohnny Huang { 135069d5fd8fSJohnny Huang int i, j; 135169d5fd8fSJohnny Huang uint32_t *strap_keep = buf + 2; 135269d5fd8fSJohnny Huang uint32_t *strap_protect = buf + 4; 135369d5fd8fSJohnny Huang uint32_t prog_bit, prog_address; 135469d5fd8fSJohnny Huang int bit, pbit, kbit, offset; 135569d5fd8fSJohnny Huang int fail = 0; 13567e22f42dSJohnny Huang int pass = 0; 13577e22f42dSJohnny Huang int soak = 0; 135866f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 135969d5fd8fSJohnny Huang 13607f795e57SJohnny Huang printf("Read OTP Strap Region:\n"); 136169d5fd8fSJohnny Huang otp_strp_status(otpstrap); 136269d5fd8fSJohnny Huang 13637f795e57SJohnny Huang printf("Check writable...\n"); 13647f795e57SJohnny Huang if (otp_strap_image_confirm(buf) == OTP_FAILURE) { 13657f795e57SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 13667f795e57SJohnny Huang return OTP_FAILURE; 13677f795e57SJohnny Huang } 13687e22f42dSJohnny Huang 13697f795e57SJohnny Huang otp_soak(0); 137069d5fd8fSJohnny Huang for (i = 0; i < 64; i++) { 13714c1c9b35SJohnny Huang printProgress(i + 1, 64, ""); 137269d5fd8fSJohnny Huang prog_address = 0x800; 137369d5fd8fSJohnny Huang if (i < 32) { 137469d5fd8fSJohnny Huang offset = i; 137569d5fd8fSJohnny Huang bit = (buf[0] >> offset) & 0x1; 137669d5fd8fSJohnny Huang kbit = (strap_keep[0] >> offset) & 0x1; 137769d5fd8fSJohnny Huang pbit = (strap_protect[0] >> offset) & 0x1; 137869d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) / 8) * 0x200; 137969d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 16) % 8) * 0x2; 138069d5fd8fSJohnny Huang 138169d5fd8fSJohnny Huang } else { 138269d5fd8fSJohnny Huang offset = (i - 32); 138369d5fd8fSJohnny Huang bit = (buf[1] >> offset) & 0x1; 138469d5fd8fSJohnny Huang kbit = (strap_keep[1] >> offset) & 0x1; 138569d5fd8fSJohnny Huang pbit = (strap_protect[1] >> offset) & 0x1; 138669d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) / 8) * 0x200; 138769d5fd8fSJohnny Huang prog_address |= ((otpstrap[i].writeable_option * 2 + 17) % 8) * 0x2; 138869d5fd8fSJohnny Huang } 138969d5fd8fSJohnny Huang prog_bit = ~(0x1 << offset); 139069d5fd8fSJohnny Huang 139169d5fd8fSJohnny Huang if (kbit == 1) { 139269d5fd8fSJohnny Huang continue; 139369d5fd8fSJohnny Huang } 139469d5fd8fSJohnny Huang if (bit == otpstrap[i].value) { 139569d5fd8fSJohnny Huang continue; 139669d5fd8fSJohnny Huang } 139769d5fd8fSJohnny Huang if (otpstrap[i].protected == 1) { 139869d5fd8fSJohnny Huang fail = 1; 139969d5fd8fSJohnny Huang continue; 140069d5fd8fSJohnny Huang } 140169d5fd8fSJohnny Huang if (otpstrap[i].remain_times == 0) { 140269d5fd8fSJohnny Huang fail = 1; 140369d5fd8fSJohnny Huang continue; 140469d5fd8fSJohnny Huang } 14057e22f42dSJohnny Huang 14067e22f42dSJohnny Huang if (soak) { 140769d5fd8fSJohnny Huang soak = 0; 14087e22f42dSJohnny Huang otp_soak(0); 14097e22f42dSJohnny Huang } 14107e22f42dSJohnny Huang 14117e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14127e22f42dSJohnny Huang 14137e22f42dSJohnny Huang pass = 0; 14147e22f42dSJohnny Huang 141569d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 1416a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 141769d5fd8fSJohnny Huang pass = 1; 141869d5fd8fSJohnny Huang break; 141969d5fd8fSJohnny Huang } 14207e22f42dSJohnny Huang if (soak == 0) { 142169d5fd8fSJohnny Huang soak = 1; 14227e22f42dSJohnny Huang otp_soak(1); 14234b65a65dSJohnny Huang } 142469d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 142569d5fd8fSJohnny Huang } 142669d5fd8fSJohnny Huang if (!pass) 14272a856b9aSJohnny Huang return OTP_FAILURE; 142869d5fd8fSJohnny Huang 142969d5fd8fSJohnny Huang if (pbit == 0) 143069d5fd8fSJohnny Huang continue; 143169d5fd8fSJohnny Huang prog_address = 0x800; 143269d5fd8fSJohnny Huang if (i < 32) 143369d5fd8fSJohnny Huang prog_address |= 0x60c; 143469d5fd8fSJohnny Huang else 143569d5fd8fSJohnny Huang prog_address |= 0x60e; 143669d5fd8fSJohnny Huang 14377e22f42dSJohnny Huang 14387e22f42dSJohnny Huang if (soak) { 14397e22f42dSJohnny Huang soak = 0; 14407e22f42dSJohnny Huang otp_soak(0); 14417e22f42dSJohnny Huang } 14427e22f42dSJohnny Huang 14437e22f42dSJohnny Huang otp_prog(prog_address, prog_bit); 14447e22f42dSJohnny Huang 14457e22f42dSJohnny Huang pass = 0; 14467e22f42dSJohnny Huang 144769d5fd8fSJohnny Huang for (j = 0; j < RETRY; j++) { 14487e22f42dSJohnny Huang 1449a6d0d645SJohnny Huang if (verify_bit(prog_address, offset, 1) == 0) { 145069d5fd8fSJohnny Huang pass = 1; 145169d5fd8fSJohnny Huang break; 145269d5fd8fSJohnny Huang } 14537e22f42dSJohnny Huang if (soak == 0) { 145469d5fd8fSJohnny Huang soak = 1; 14557e22f42dSJohnny Huang otp_soak(1); 145669d5fd8fSJohnny Huang } 145769d5fd8fSJohnny Huang otp_prog(prog_address, prog_bit); 145869d5fd8fSJohnny Huang } 145969d5fd8fSJohnny Huang if (!pass) 14602a856b9aSJohnny Huang return OTP_FAILURE; 146169d5fd8fSJohnny Huang 146269d5fd8fSJohnny Huang } 146369d5fd8fSJohnny Huang if (fail == 1) 14642a856b9aSJohnny Huang return OTP_FAILURE; 146569d5fd8fSJohnny Huang else 14662a856b9aSJohnny Huang return OTP_SUCCESS; 146769d5fd8fSJohnny Huang 146869d5fd8fSJohnny Huang } 146969d5fd8fSJohnny Huang 1470cd1610b4SJohnny Huang static void otp_prog_bit(uint32_t value, uint32_t prog_address, uint32_t bit_offset, int soak) 1471cd1610b4SJohnny Huang { 1472cd1610b4SJohnny Huang int prog_bit; 1473cd1610b4SJohnny Huang 14747e22f42dSJohnny Huang otp_soak(soak); 14757e22f42dSJohnny Huang 1476cd1610b4SJohnny Huang if (prog_address % 2 == 0) { 1477cd1610b4SJohnny Huang if (value) 1478cd1610b4SJohnny Huang prog_bit = ~(0x1 << bit_offset); 1479cd1610b4SJohnny Huang else 1480cd1610b4SJohnny Huang return; 1481cd1610b4SJohnny Huang } else { 1482cd1610b4SJohnny Huang prog_address |= 1 << 15; 1483cd1610b4SJohnny Huang if (!value) 1484cd1610b4SJohnny Huang prog_bit = 0x1 << bit_offset; 1485cd1610b4SJohnny Huang else 1486cd1610b4SJohnny Huang return; 1487cd1610b4SJohnny Huang } 1488cd1610b4SJohnny Huang otp_prog(prog_address, prog_bit); 1489cd1610b4SJohnny Huang } 1490cd1610b4SJohnny Huang 1491d90825e2SJohnny Huang static int otp_prog_data(uint32_t *buf) 14924c1c9b35SJohnny Huang { 14934c1c9b35SJohnny Huang int i, k; 14944c1c9b35SJohnny Huang int pass; 1495d90825e2SJohnny Huang int soak = 0; 14964c1c9b35SJohnny Huang uint32_t prog_address; 1497d90825e2SJohnny Huang uint32_t data[2048]; 14984c1c9b35SJohnny Huang uint32_t compare[2]; 1499d90825e2SJohnny Huang uint32_t *buf_keep = &buf[2048]; 15004c1c9b35SJohnny Huang 1501d90825e2SJohnny Huang uint32_t data0_masked; 1502d90825e2SJohnny Huang uint32_t data1_masked; 1503d90825e2SJohnny Huang uint32_t buf0_masked; 1504d90825e2SJohnny Huang uint32_t buf1_masked; 15054c1c9b35SJohnny Huang 15064c1c9b35SJohnny Huang printf("Read OTP Data:\n"); 15074c1c9b35SJohnny Huang 1508d90825e2SJohnny Huang printProgress(0, 2048, ""); 1509d90825e2SJohnny Huang for (i = 0; i < 2048 ; i += 2) { 1510d90825e2SJohnny Huang printProgress(i + 2, 2048, ""); 1511d90825e2SJohnny Huang otp_read_data(i, &data[i]); 15124c1c9b35SJohnny Huang } 1513d90825e2SJohnny Huang 15144c1c9b35SJohnny Huang 15154c1c9b35SJohnny Huang printf("Check writable...\n"); 1516d90825e2SJohnny Huang for (i = 0; i < 2048; i++) { 1517d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1518d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1519d90825e2SJohnny Huang if (data0_masked == buf0_masked) 15204c1c9b35SJohnny Huang continue; 1521d90825e2SJohnny Huang if (i % 2 == 0) { 1522d90825e2SJohnny Huang if ((data0_masked | buf0_masked) == buf0_masked) { 15234c1c9b35SJohnny Huang continue; 15244c1c9b35SJohnny Huang } else { 15254c1c9b35SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1526d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 15274c1c9b35SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1528d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15292a856b9aSJohnny Huang return OTP_FAILURE; 153069d5fd8fSJohnny Huang } 1531d90825e2SJohnny Huang } else { 1532d90825e2SJohnny Huang if ((data0_masked & buf0_masked) == buf0_masked) { 1533d90825e2SJohnny Huang continue; 1534d90825e2SJohnny Huang } else { 1535d90825e2SJohnny Huang printf("Input image can't program into OTP, please check.\n"); 1536d90825e2SJohnny Huang printf("OTP_ADDR[%x] = %x\n", i, data[i]); 1537d90825e2SJohnny Huang printf("Input [%x] = %x\n", i, buf[i]); 1538d90825e2SJohnny Huang printf("Mask [%x] = %x\n", i, ~buf_keep[i]); 15392a856b9aSJohnny Huang return OTP_FAILURE; 1540d90825e2SJohnny Huang } 1541d90825e2SJohnny Huang } 1542d90825e2SJohnny Huang } 154369d5fd8fSJohnny Huang 1544d90825e2SJohnny Huang printf("Start Programing...\n"); 1545d90825e2SJohnny Huang printProgress(0, 2048, ""); 1546d90825e2SJohnny Huang 1547d90825e2SJohnny Huang for (i = 0; i < 2048; i += 2) { 1548d90825e2SJohnny Huang prog_address = i; 1549d90825e2SJohnny Huang data0_masked = data[i] & ~buf_keep[i]; 1550d90825e2SJohnny Huang buf0_masked = buf[i] & ~buf_keep[i]; 1551d90825e2SJohnny Huang data1_masked = data[i + 1] & ~buf_keep[i + 1]; 1552d90825e2SJohnny Huang buf1_masked = buf[i + 1] & ~buf_keep[i + 1]; 1553d90825e2SJohnny Huang if ((data0_masked == buf0_masked) && (data1_masked == buf1_masked)) { 1554d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1555d90825e2SJohnny Huang continue; 1556d90825e2SJohnny Huang } 1557d90825e2SJohnny Huang if (soak) { 1558d90825e2SJohnny Huang soak = 0; 1559d90825e2SJohnny Huang otp_soak(0); 1560d90825e2SJohnny Huang } 1561d90825e2SJohnny Huang if (data1_masked == buf1_masked) { 1562d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X HIT", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1563d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1564d90825e2SJohnny Huang } else if (data0_masked == buf0_masked) { 1565d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X HIT;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1566d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1567d90825e2SJohnny Huang } else { 1568d90825e2SJohnny Huang printProgress(i + 2, 2048, "[%03X]=%08X ;[%03X]=%08X ", prog_address, buf[i], prog_address + 1, buf[i + 1]); 1569d90825e2SJohnny Huang otp_prog_dw(buf[i], buf_keep[i], prog_address); 1570d90825e2SJohnny Huang otp_prog_dw(buf[i + 1], buf_keep[i + 1], prog_address + 1); 1571d90825e2SJohnny Huang } 1572d90825e2SJohnny Huang 1573d90825e2SJohnny Huang pass = 0; 1574d90825e2SJohnny Huang for (k = 0; k < RETRY; k++) { 1575d90825e2SJohnny Huang if (verify_dw(prog_address, &buf[i], &buf_keep[i], compare, 2) != 0) { 1576d90825e2SJohnny Huang if (soak == 0) { 1577d90825e2SJohnny Huang soak = 1; 1578d90825e2SJohnny Huang otp_soak(1); 1579d90825e2SJohnny Huang } 1580d90825e2SJohnny Huang if (compare[0] != 0) { 1581d90825e2SJohnny Huang otp_prog_dw(compare[0], buf_keep[i], prog_address); 1582d90825e2SJohnny Huang } 1583d90825e2SJohnny Huang if (compare[1] != ~0) { 1584d90825e2SJohnny Huang otp_prog_dw(compare[1], buf_keep[i], prog_address + 1); 1585d90825e2SJohnny Huang } 1586d90825e2SJohnny Huang } else { 1587d90825e2SJohnny Huang pass = 1; 1588d90825e2SJohnny Huang break; 1589d90825e2SJohnny Huang } 1590d90825e2SJohnny Huang } 1591d90825e2SJohnny Huang 1592d90825e2SJohnny Huang if (!pass) 15932a856b9aSJohnny Huang return OTP_FAILURE; 1594d90825e2SJohnny Huang } 15952a856b9aSJohnny Huang return OTP_SUCCESS; 1596d90825e2SJohnny Huang 1597d90825e2SJohnny Huang } 1598d90825e2SJohnny Huang 1599d90825e2SJohnny Huang static int do_otp_prog(int addr, int byte_size, int nconfirm) 160069d5fd8fSJohnny Huang { 160169d5fd8fSJohnny Huang int ret; 1602d90825e2SJohnny Huang int mode; 160369d5fd8fSJohnny Huang uint32_t *buf; 1604d90825e2SJohnny Huang uint32_t *data_region = NULL; 1605d90825e2SJohnny Huang uint32_t *conf_region = NULL; 1606d90825e2SJohnny Huang uint32_t *strap_region = NULL; 160769d5fd8fSJohnny Huang 1608d90825e2SJohnny Huang buf = map_physmem(addr, byte_size, MAP_WRBACK); 160969d5fd8fSJohnny Huang if (!buf) { 161069d5fd8fSJohnny Huang puts("Failed to map physical memory\n"); 16112a856b9aSJohnny Huang return OTP_FAILURE; 161269d5fd8fSJohnny Huang } 1613d90825e2SJohnny Huang 1614d90825e2SJohnny Huang if (((buf[0] >> 29) & 0x7) == 0x7) { 1615d90825e2SJohnny Huang mode = OTP_REGION_ALL; 1616d90825e2SJohnny Huang conf_region = &buf[1]; 1617d90825e2SJohnny Huang strap_region = &buf[25]; 1618d90825e2SJohnny Huang data_region = &buf[31]; 1619d90825e2SJohnny Huang } else { 1620d90825e2SJohnny Huang if (buf[0] & BIT(29)) { 1621d90825e2SJohnny Huang mode = OTP_REGION_DATA; 1622d90825e2SJohnny Huang data_region = &buf[31]; 1623d90825e2SJohnny Huang } 1624d90825e2SJohnny Huang if (buf[0] & BIT(30)) { 1625d90825e2SJohnny Huang mode = OTP_REGION_CONF; 1626d90825e2SJohnny Huang strap_region = &buf[25]; 1627d90825e2SJohnny Huang } 1628d90825e2SJohnny Huang if (buf[0] & BIT(31)) { 1629d90825e2SJohnny Huang mode = OTP_REGION_STRAP; 1630d90825e2SJohnny Huang conf_region = &buf[1]; 1631d90825e2SJohnny Huang } 1632d90825e2SJohnny Huang } 163369d5fd8fSJohnny Huang if (!nconfirm) { 1634a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 16357f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1636b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 163769d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 16382a856b9aSJohnny Huang return OTP_FAILURE; 163969d5fd8fSJohnny Huang } 1640a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 16417f795e57SJohnny Huang printf("\nOTP data region :\n"); 16427f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 164369d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16442a856b9aSJohnny Huang return OTP_FAILURE; 164569d5fd8fSJohnny Huang } 1646a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 16477f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1648b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 164969d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 16502a856b9aSJohnny Huang return OTP_FAILURE; 165169d5fd8fSJohnny Huang } 1652a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 16537f795e57SJohnny Huang printf("\nOTP configuration region :\n"); 1654b458cd62SJohnny Huang if (otp_print_conf_image(conf_region) < 0) { 165569d5fd8fSJohnny Huang printf("OTP config error, please check.\n"); 16562a856b9aSJohnny Huang return OTP_FAILURE; 165769d5fd8fSJohnny Huang } 16587f795e57SJohnny Huang printf("\nOTP strap region :\n"); 1659b458cd62SJohnny Huang if (otp_print_strap_image(strap_region) < 0) { 166069d5fd8fSJohnny Huang printf("OTP strap error, please check.\n"); 16612a856b9aSJohnny Huang return OTP_FAILURE; 166269d5fd8fSJohnny Huang } 16637f795e57SJohnny Huang printf("\nOTP data region :\n"); 16647f795e57SJohnny Huang if (otp_print_data_info(data_region) < 0) { 166569d5fd8fSJohnny Huang printf("OTP data error, please check.\n"); 16662a856b9aSJohnny Huang return OTP_FAILURE; 166769d5fd8fSJohnny Huang } 166869d5fd8fSJohnny Huang } 166969d5fd8fSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 167069d5fd8fSJohnny Huang if (!confirm_yesno()) { 167169d5fd8fSJohnny Huang printf(" Aborting\n"); 16722a856b9aSJohnny Huang return OTP_FAILURE; 167369d5fd8fSJohnny Huang } 167469d5fd8fSJohnny Huang } 1675a6d0d645SJohnny Huang if (mode == OTP_REGION_CONF) { 1676d90825e2SJohnny Huang return otp_prog_conf(conf_region); 1677a6d0d645SJohnny Huang } else if (mode == OTP_REGION_STRAP) { 1678d90825e2SJohnny Huang return otp_prog_strap(strap_region); 1679a6d0d645SJohnny Huang } else if (mode == OTP_REGION_DATA) { 1680d90825e2SJohnny Huang return otp_prog_data(data_region); 1681a6d0d645SJohnny Huang } else if (mode == OTP_REGION_ALL) { 168269d5fd8fSJohnny Huang printf("programing data region ... "); 1683d90825e2SJohnny Huang ret = otp_prog_data(data_region); 16842a856b9aSJohnny Huang if (ret != 0) { 168569d5fd8fSJohnny Huang printf("Error\n"); 168669d5fd8fSJohnny Huang return ret; 168769d5fd8fSJohnny Huang } else { 168869d5fd8fSJohnny Huang printf("Done\n"); 168969d5fd8fSJohnny Huang } 169069d5fd8fSJohnny Huang printf("programing strap region ... "); 1691d90825e2SJohnny Huang ret = otp_prog_strap(strap_region); 16922a856b9aSJohnny Huang if (ret != 0) { 169369d5fd8fSJohnny Huang printf("Error\n"); 169469d5fd8fSJohnny Huang return ret; 169569d5fd8fSJohnny Huang } else { 169669d5fd8fSJohnny Huang printf("Done\n"); 169769d5fd8fSJohnny Huang } 169869d5fd8fSJohnny Huang printf("programing configuration region ... "); 1699d90825e2SJohnny Huang ret = otp_prog_conf(conf_region); 17002a856b9aSJohnny Huang if (ret != 0) { 170169d5fd8fSJohnny Huang printf("Error\n"); 170269d5fd8fSJohnny Huang return ret; 170369d5fd8fSJohnny Huang } 170469d5fd8fSJohnny Huang printf("Done\n"); 17052a856b9aSJohnny Huang return OTP_SUCCESS; 170669d5fd8fSJohnny Huang } 1707cd1610b4SJohnny Huang 17082a856b9aSJohnny Huang return OTP_USAGE; 17092a856b9aSJohnny Huang } 17102a856b9aSJohnny Huang 17112a856b9aSJohnny Huang static int do_otp_prog_bit(int mode, int otp_dw_offset, int bit_offset, int value, int nconfirm) 1712cd1610b4SJohnny Huang { 1713a6af4a17SJohnny Huang uint32_t read[2]; 1714cd1610b4SJohnny Huang uint32_t strap_buf[6]; 1715d90825e2SJohnny Huang uint32_t prog_address = 0; 171666f2f8e5SJohnny Huang struct otpstrap_status otpstrap[64]; 1717cd1610b4SJohnny Huang int otp_bit; 1718cd1610b4SJohnny Huang int i; 1719cd1610b4SJohnny Huang int pass; 1720a6af4a17SJohnny Huang int ret; 1721cd1610b4SJohnny Huang 1722cd1610b4SJohnny Huang switch (mode) { 1723a6d0d645SJohnny Huang case OTP_REGION_CONF: 1724a6af4a17SJohnny Huang otp_read_config(otp_dw_offset, read); 1725cd1610b4SJohnny Huang prog_address = 0x800; 1726cd1610b4SJohnny Huang prog_address |= (otp_dw_offset / 8) * 0x200; 1727cd1610b4SJohnny Huang prog_address |= (otp_dw_offset % 8) * 0x2; 1728a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1729cd1610b4SJohnny Huang if (otp_bit == value) { 1730a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1731cd1610b4SJohnny Huang printf("No need to program\n"); 17322a856b9aSJohnny Huang return OTP_SUCCESS; 1733cd1610b4SJohnny Huang } 1734cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1735a6af4a17SJohnny Huang printf("OTPCFG%X[%X] = 1\n", otp_dw_offset, bit_offset); 1736cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17372a856b9aSJohnny Huang return OTP_FAILURE; 1738cd1610b4SJohnny Huang } 1739a6af4a17SJohnny Huang printf("Program OTPCFG%X[%X] to 1\n", otp_dw_offset, bit_offset); 1740cd1610b4SJohnny Huang break; 1741a6d0d645SJohnny Huang case OTP_REGION_DATA: 1742cd1610b4SJohnny Huang prog_address = otp_dw_offset; 1743cd1610b4SJohnny Huang 1744cd1610b4SJohnny Huang if (otp_dw_offset % 2 == 0) { 1745a6af4a17SJohnny Huang otp_read_data(otp_dw_offset, read); 1746a6af4a17SJohnny Huang otp_bit = (read[0] >> bit_offset) & 0x1; 1747cd1610b4SJohnny Huang } else { 1748a6af4a17SJohnny Huang otp_read_data(otp_dw_offset - 1, read); 1749a6af4a17SJohnny Huang otp_bit = (read[1] >> bit_offset) & 0x1; 1750cd1610b4SJohnny Huang } 1751cd1610b4SJohnny Huang if (otp_bit == value) { 1752a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = %d\n", otp_dw_offset, bit_offset, value); 1753cd1610b4SJohnny Huang printf("No need to program\n"); 17542a856b9aSJohnny Huang return OTP_SUCCESS; 1755cd1610b4SJohnny Huang } 1756cd1610b4SJohnny Huang if (otp_bit == 1 && value == 0) { 1757a6af4a17SJohnny Huang printf("OTPDATA%X[%X] = 1\n", otp_dw_offset, bit_offset); 1758cd1610b4SJohnny Huang printf("OTP is programed, which can't be clean\n"); 17592a856b9aSJohnny Huang return OTP_FAILURE; 1760cd1610b4SJohnny Huang } 1761a6af4a17SJohnny Huang printf("Program OTPDATA%X[%X] to 1\n", otp_dw_offset, bit_offset); 1762cd1610b4SJohnny Huang break; 1763a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1764cd1610b4SJohnny Huang otp_strp_status(otpstrap); 1765cd1610b4SJohnny Huang otp_print_strap(bit_offset, 1); 1766cd1610b4SJohnny Huang if (bit_offset < 32) { 1767cd1610b4SJohnny Huang strap_buf[0] = value << bit_offset; 1768cd1610b4SJohnny Huang strap_buf[2] = ~BIT(bit_offset); 1769cd1610b4SJohnny Huang strap_buf[3] = ~0; 1770cd1610b4SJohnny Huang strap_buf[5] = 0; 17712a856b9aSJohnny Huang // if (protect) 17722a856b9aSJohnny Huang // strap_buf[4] = BIT(bit_offset); 17732a856b9aSJohnny Huang // else 17742a856b9aSJohnny Huang // strap_buf[4] = 0; 1775cd1610b4SJohnny Huang } else { 1776cd1610b4SJohnny Huang strap_buf[1] = value << (bit_offset - 32); 1777cd1610b4SJohnny Huang strap_buf[2] = ~0; 1778cd1610b4SJohnny Huang strap_buf[3] = ~BIT(bit_offset - 32); 1779cd1610b4SJohnny Huang strap_buf[4] = 0; 17802a856b9aSJohnny Huang // if (protect) 17812a856b9aSJohnny Huang // strap_buf[5] = BIT(bit_offset - 32); 17822a856b9aSJohnny Huang // else 17832a856b9aSJohnny Huang // strap_buf[5] = 0; 1784cd1610b4SJohnny Huang } 178576d13988SJohnny Huang ret = otp_strap_image_confirm(strap_buf); 1786a6af4a17SJohnny Huang if (ret == OTP_FAILURE) 17872a856b9aSJohnny Huang return OTP_FAILURE; 1788a6af4a17SJohnny Huang else if (ret == OTP_PROG_SKIP) 1789a6af4a17SJohnny Huang return OTP_SUCCESS; 1790a6af4a17SJohnny Huang 1791cd1610b4SJohnny Huang break; 1792cd1610b4SJohnny Huang } 1793cd1610b4SJohnny Huang 1794cd1610b4SJohnny Huang if (!nconfirm) { 1795cd1610b4SJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 1796cd1610b4SJohnny Huang if (!confirm_yesno()) { 1797cd1610b4SJohnny Huang printf(" Aborting\n"); 17982a856b9aSJohnny Huang return OTP_FAILURE; 1799cd1610b4SJohnny Huang } 1800cd1610b4SJohnny Huang } 1801cd1610b4SJohnny Huang 1802cd1610b4SJohnny Huang switch (mode) { 1803a6d0d645SJohnny Huang case OTP_REGION_STRAP: 1804cd1610b4SJohnny Huang return otp_prog_strap(strap_buf); 1805a6d0d645SJohnny Huang case OTP_REGION_CONF: 1806a6d0d645SJohnny Huang case OTP_REGION_DATA: 1807cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 0); 1808cd1610b4SJohnny Huang pass = -1; 1809cd1610b4SJohnny Huang for (i = 0; i < RETRY; i++) { 1810a6d0d645SJohnny Huang if (verify_bit(prog_address, bit_offset, value) != 0) { 1811cd1610b4SJohnny Huang otp_prog_bit(value, prog_address, bit_offset, 1); 1812cd1610b4SJohnny Huang } else { 1813cd1610b4SJohnny Huang pass = 0; 1814cd1610b4SJohnny Huang break; 1815cd1610b4SJohnny Huang } 1816cd1610b4SJohnny Huang } 18172a856b9aSJohnny Huang if (pass == 0) 18182a856b9aSJohnny Huang return OTP_SUCCESS; 1819cd1610b4SJohnny Huang } 1820cd1610b4SJohnny Huang 18212a856b9aSJohnny Huang return OTP_USAGE; 1822cd1610b4SJohnny Huang } 1823cd1610b4SJohnny Huang 18242a856b9aSJohnny Huang static int do_otpread(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 182569d5fd8fSJohnny Huang { 18262a856b9aSJohnny Huang uint32_t offset, count; 18272a856b9aSJohnny Huang int ret; 182869d5fd8fSJohnny Huang 18292a856b9aSJohnny Huang if (argc == 4) { 18302a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 18312a856b9aSJohnny Huang count = simple_strtoul(argv[3], NULL, 16); 18322a856b9aSJohnny Huang } else if (argc == 3) { 18332a856b9aSJohnny Huang offset = simple_strtoul(argv[2], NULL, 16); 18342a856b9aSJohnny Huang count = 1; 18352a856b9aSJohnny Huang } else { 183669d5fd8fSJohnny Huang return CMD_RET_USAGE; 183769d5fd8fSJohnny Huang } 183869d5fd8fSJohnny Huang 183969d5fd8fSJohnny Huang 18402a856b9aSJohnny Huang if (!strcmp(argv[1], "conf")) { 184169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18422a856b9aSJohnny Huang ret = otp_print_config(offset, count); 18432a856b9aSJohnny Huang } else if (!strcmp(argv[1], "data")) { 18442a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18452a856b9aSJohnny Huang ret = otp_print_data(offset, count); 18462a856b9aSJohnny Huang } else if (!strcmp(argv[1], "strap")) { 18472a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18482a856b9aSJohnny Huang ret = otp_print_strap(offset, count); 18492a856b9aSJohnny Huang } else { 18502a856b9aSJohnny Huang return CMD_RET_USAGE; 185169d5fd8fSJohnny Huang } 185269d5fd8fSJohnny Huang 18532a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18542a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18552a856b9aSJohnny Huang else 18562a856b9aSJohnny Huang return CMD_RET_USAGE; 18572a856b9aSJohnny Huang 18582a856b9aSJohnny Huang } 18592a856b9aSJohnny Huang 18602a856b9aSJohnny Huang static int do_otpprog(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18612a856b9aSJohnny Huang { 18622a856b9aSJohnny Huang phys_addr_t addr; 18632a856b9aSJohnny Huang uint32_t byte_size; 18642a856b9aSJohnny Huang int ret; 18652a856b9aSJohnny Huang 18662a856b9aSJohnny Huang if (argc == 4) { 18672a856b9aSJohnny Huang if (strcmp(argv[1], "f")) 18682a856b9aSJohnny Huang return CMD_RET_USAGE; 18692a856b9aSJohnny Huang addr = simple_strtoul(argv[2], NULL, 16); 18702a856b9aSJohnny Huang byte_size = simple_strtoul(argv[3], NULL, 16); 187169d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18722a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 1); 18732a856b9aSJohnny Huang } else if (argc == 3) { 18742a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 18752a856b9aSJohnny Huang byte_size = simple_strtoul(argv[2], NULL, 16); 18762a856b9aSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 18772a856b9aSJohnny Huang ret = do_otp_prog(addr, byte_size, 0); 18782a856b9aSJohnny Huang } else { 18792a856b9aSJohnny Huang return CMD_RET_USAGE; 18802a856b9aSJohnny Huang } 18812a856b9aSJohnny Huang 18822a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 18832a856b9aSJohnny Huang return CMD_RET_SUCCESS; 18842a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 18852a856b9aSJohnny Huang return CMD_RET_FAILURE; 18862a856b9aSJohnny Huang else 18872a856b9aSJohnny Huang return CMD_RET_USAGE; 18882a856b9aSJohnny Huang } 18892a856b9aSJohnny Huang 18902a856b9aSJohnny Huang static int do_otppb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 18912a856b9aSJohnny Huang { 18922a856b9aSJohnny Huang int mode = 0; 18932a856b9aSJohnny Huang int nconfirm = 0; 18942a856b9aSJohnny Huang int otp_addr = 0; 18952a856b9aSJohnny Huang int bit_offset; 18962a856b9aSJohnny Huang int value; 18972a856b9aSJohnny Huang int ret; 18982a856b9aSJohnny Huang 18992a856b9aSJohnny Huang if (argc != 4 && argc != 5 && argc != 6) 19002a856b9aSJohnny Huang return CMD_RET_USAGE; 19012a856b9aSJohnny Huang 19022a856b9aSJohnny Huang /* Drop the pb cmd */ 19032a856b9aSJohnny Huang argc--; 19042a856b9aSJohnny Huang argv++; 19052a856b9aSJohnny Huang 19062a856b9aSJohnny Huang if (!strcmp(argv[0], "conf")) 1907a6d0d645SJohnny Huang mode = OTP_REGION_CONF; 19082a856b9aSJohnny Huang else if (!strcmp(argv[0], "strap")) 1909a6d0d645SJohnny Huang mode = OTP_REGION_STRAP; 19102a856b9aSJohnny Huang else if (!strcmp(argv[0], "data")) 1911a6d0d645SJohnny Huang mode = OTP_REGION_DATA; 1912cd1610b4SJohnny Huang else 19132a856b9aSJohnny Huang return CMD_RET_USAGE; 19142a856b9aSJohnny Huang 19152a856b9aSJohnny Huang /* Drop the region cmd */ 19162a856b9aSJohnny Huang argc--; 19172a856b9aSJohnny Huang argv++; 19182a856b9aSJohnny Huang 19192a856b9aSJohnny Huang if (!strcmp(argv[0], "f")) { 1920cd1610b4SJohnny Huang nconfirm = 1; 19212a856b9aSJohnny Huang /* Drop the force option */ 19222a856b9aSJohnny Huang argc--; 19232a856b9aSJohnny Huang argv++; 19242a856b9aSJohnny Huang } 1925cd1610b4SJohnny Huang 1926a6d0d645SJohnny Huang if (mode == OTP_REGION_STRAP) { 19272a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[0], NULL, 16); 19282a856b9aSJohnny Huang value = simple_strtoul(argv[1], NULL, 16); 1929cd1610b4SJohnny Huang if (bit_offset >= 64) 19302a856b9aSJohnny Huang return CMD_RET_USAGE; 1931cd1610b4SJohnny Huang } else { 19322a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[0], NULL, 16); 19332a856b9aSJohnny Huang bit_offset = simple_strtoul(argv[1], NULL, 16); 19342a856b9aSJohnny Huang value = simple_strtoul(argv[2], NULL, 16); 1935cd1610b4SJohnny Huang if (bit_offset >= 32) 19362a856b9aSJohnny Huang return CMD_RET_USAGE; 1937cd1610b4SJohnny Huang } 1938cd1610b4SJohnny Huang if (value != 0 && value != 1) 19392a856b9aSJohnny Huang return CMD_RET_USAGE; 1940cd1610b4SJohnny Huang 1941cd1610b4SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19422a856b9aSJohnny Huang ret = do_otp_prog_bit(mode, otp_addr, bit_offset, value, nconfirm); 19432a856b9aSJohnny Huang 19442a856b9aSJohnny Huang if (ret == OTP_SUCCESS) 19452a856b9aSJohnny Huang return CMD_RET_SUCCESS; 19462a856b9aSJohnny Huang else if (ret == OTP_FAILURE) 19472a856b9aSJohnny Huang return CMD_RET_FAILURE; 19482a856b9aSJohnny Huang else 19492a856b9aSJohnny Huang return CMD_RET_USAGE; 19502a856b9aSJohnny Huang } 19512a856b9aSJohnny Huang 19522a856b9aSJohnny Huang static int do_otpcmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 19532a856b9aSJohnny Huang { 19542a856b9aSJohnny Huang phys_addr_t addr; 19552a856b9aSJohnny Huang int otp_addr = 0; 19562a856b9aSJohnny Huang 19572a856b9aSJohnny Huang if (argc != 3) 19582a856b9aSJohnny Huang return CMD_RET_USAGE; 19592a856b9aSJohnny Huang 196069d5fd8fSJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19612a856b9aSJohnny Huang addr = simple_strtoul(argv[1], NULL, 16); 19622a856b9aSJohnny Huang otp_addr = simple_strtoul(argv[2], NULL, 16); 19632a856b9aSJohnny Huang if (otp_compare(otp_addr, addr) == 0) { 196469d5fd8fSJohnny Huang printf("Compare pass\n"); 19652a856b9aSJohnny Huang return CMD_RET_SUCCESS; 196669d5fd8fSJohnny Huang } else { 196769d5fd8fSJohnny Huang printf("Compare fail\n"); 19682a856b9aSJohnny Huang return CMD_RET_FAILURE; 196969d5fd8fSJohnny Huang } 197069d5fd8fSJohnny Huang } 197169d5fd8fSJohnny Huang 197266f2f8e5SJohnny Huang static int do_otpinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 197366f2f8e5SJohnny Huang { 1974a8bd6d8cSJohnny Huang int view = 0; 19752d4b0742SJohnny Huang int input; 1976a8bd6d8cSJohnny Huang 1977a8bd6d8cSJohnny Huang if (argc != 2 && argc != 3) 197866f2f8e5SJohnny Huang return CMD_RET_USAGE; 197966f2f8e5SJohnny Huang 19802d4b0742SJohnny Huang if (!strcmp(argv[1], "conf")) { 198166f2f8e5SJohnny Huang 19822d4b0742SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 19832d4b0742SJohnny Huang if (argc == 3) { 19842d4b0742SJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 19852d4b0742SJohnny Huang otp_print_conf_info(input); 19862d4b0742SJohnny Huang } else { 19872d4b0742SJohnny Huang otp_print_conf_info(-1); 19882d4b0742SJohnny Huang } 19892d4b0742SJohnny Huang } else if (!strcmp(argv[1], "strap")) { 19902d4b0742SJohnny Huang if (!strcmp(argv[2], "v")) { 1991a8bd6d8cSJohnny Huang view = 1; 1992a8bd6d8cSJohnny Huang /* Drop the view option */ 1993a8bd6d8cSJohnny Huang argc--; 1994a8bd6d8cSJohnny Huang argv++; 1995a8bd6d8cSJohnny Huang } 199666f2f8e5SJohnny Huang writel(OTP_PASSWD, 0x1e6f2000); //password 1997b458cd62SJohnny Huang otp_print_strap_info(view); 199866f2f8e5SJohnny Huang } else { 199966f2f8e5SJohnny Huang return CMD_RET_USAGE; 200066f2f8e5SJohnny Huang } 20012d4b0742SJohnny Huang 200266f2f8e5SJohnny Huang return CMD_RET_SUCCESS; 200366f2f8e5SJohnny Huang } 200466f2f8e5SJohnny Huang 2005737ed20bSJohnny Huang static int do_otpprotect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 2006737ed20bSJohnny Huang { 2007737ed20bSJohnny Huang int input; 2008737ed20bSJohnny Huang int bit_offset; 2009737ed20bSJohnny Huang int prog_address; 2010737ed20bSJohnny Huang int pass; 2011737ed20bSJohnny Huang int i; 2012737ed20bSJohnny Huang if (argc != 3 && argc != 2) 2013737ed20bSJohnny Huang return CMD_RET_USAGE; 2014737ed20bSJohnny Huang 2015737ed20bSJohnny Huang if (!strcmp(argv[0], "f")) { 2016737ed20bSJohnny Huang input = simple_strtoul(argv[2], NULL, 16); 2017737ed20bSJohnny Huang } else { 2018737ed20bSJohnny Huang input = simple_strtoul(argv[1], NULL, 16); 2019737ed20bSJohnny Huang printf("OTPSTRAP[%d] will be protected\n", input); 2020737ed20bSJohnny Huang printf("type \"YES\" (no quotes) to continue:\n"); 2021737ed20bSJohnny Huang if (!confirm_yesno()) { 2022737ed20bSJohnny Huang printf(" Aborting\n"); 2023737ed20bSJohnny Huang return CMD_RET_FAILURE; 2024737ed20bSJohnny Huang } 2025737ed20bSJohnny Huang } 2026737ed20bSJohnny Huang 2027737ed20bSJohnny Huang prog_address = 0x800; 2028737ed20bSJohnny Huang if (input < 32) { 2029737ed20bSJohnny Huang bit_offset = input; 2030737ed20bSJohnny Huang prog_address |= 0x60c; 2031737ed20bSJohnny Huang } else if (input < 64) { 2032737ed20bSJohnny Huang bit_offset = input - 32; 2033737ed20bSJohnny Huang prog_address |= 0x60e; 2034737ed20bSJohnny Huang } else { 2035737ed20bSJohnny Huang return CMD_RET_USAGE; 2036737ed20bSJohnny Huang } 2037737ed20bSJohnny Huang 2038737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) == 0) { 2039737ed20bSJohnny Huang printf("OTPSTRAP[%d] already protected\n", input); 2040737ed20bSJohnny Huang } 2041737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 0); 2042737ed20bSJohnny Huang pass = -1; 2043737ed20bSJohnny Huang for (i = 0; i < RETRY; i++) { 2044737ed20bSJohnny Huang if (verify_bit(prog_address, bit_offset, 1) != 0) { 2045737ed20bSJohnny Huang otp_prog_bit(1, prog_address, bit_offset, 1); 2046737ed20bSJohnny Huang } else { 2047737ed20bSJohnny Huang pass = 0; 2048737ed20bSJohnny Huang break; 2049737ed20bSJohnny Huang } 2050737ed20bSJohnny Huang } 2051737ed20bSJohnny Huang if (pass == 0) { 2052737ed20bSJohnny Huang printf("OTPSTRAP[%d] is protected\n", input); 2053737ed20bSJohnny Huang return CMD_RET_SUCCESS; 2054737ed20bSJohnny Huang } 2055737ed20bSJohnny Huang 2056737ed20bSJohnny Huang printf("Protect OTPSTRAP[%d] fail\n", input); 2057737ed20bSJohnny Huang return CMD_RET_FAILURE; 2058737ed20bSJohnny Huang 2059737ed20bSJohnny Huang } 20602a856b9aSJohnny Huang static cmd_tbl_t cmd_otp[] = { 20612a856b9aSJohnny Huang U_BOOT_CMD_MKENT(read, 4, 0, do_otpread, "", ""), 2062a8bd6d8cSJohnny Huang U_BOOT_CMD_MKENT(info, 3, 0, do_otpinfo, "", ""), 20632a856b9aSJohnny Huang U_BOOT_CMD_MKENT(prog, 4, 0, do_otpprog, "", ""), 20642a856b9aSJohnny Huang U_BOOT_CMD_MKENT(pb, 6, 0, do_otppb, "", ""), 2065737ed20bSJohnny Huang U_BOOT_CMD_MKENT(protect, 3, 0, do_otpprotect, "", ""), 20662a856b9aSJohnny Huang U_BOOT_CMD_MKENT(cmp, 3, 0, do_otpcmp, "", ""), 20672a856b9aSJohnny Huang }; 20682a856b9aSJohnny Huang 20692a856b9aSJohnny Huang static int do_ast_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 20702a856b9aSJohnny Huang { 20712a856b9aSJohnny Huang cmd_tbl_t *cp; 20722a856b9aSJohnny Huang 20732a856b9aSJohnny Huang cp = find_cmd_tbl(argv[1], cmd_otp, ARRAY_SIZE(cmd_otp)); 20742a856b9aSJohnny Huang 2075737ed20bSJohnny Huang /* Drop the otp command */ 20762a856b9aSJohnny Huang argc--; 20772a856b9aSJohnny Huang argv++; 20782a856b9aSJohnny Huang 20792a856b9aSJohnny Huang if (cp == NULL || argc > cp->maxargs) 20802a856b9aSJohnny Huang return CMD_RET_USAGE; 20812a856b9aSJohnny Huang if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) 20822a856b9aSJohnny Huang return CMD_RET_SUCCESS; 20832a856b9aSJohnny Huang 20842a856b9aSJohnny Huang return cp->cmd(cmdtp, flag, argc, argv); 208569d5fd8fSJohnny Huang } 208669d5fd8fSJohnny Huang 208769d5fd8fSJohnny Huang U_BOOT_CMD( 208869d5fd8fSJohnny Huang otp, 7, 0, do_ast_otp, 208969d5fd8fSJohnny Huang "ASPEED One-Time-Programmable sub-system", 20902a856b9aSJohnny Huang "read conf|data <otp_dw_offset> <dw_count>\n" 20912a856b9aSJohnny Huang "otp read strap <strap_bit_offset> <bit_count>\n" 20922d4b0742SJohnny Huang "otp info strap [v]\n" 20932d4b0742SJohnny Huang "otp info conf [otp_dw_offset]\n" 2094d90825e2SJohnny Huang "otp prog [f] <addr> <byte_size>\n" 2095cd1610b4SJohnny Huang "otp pb conf|data [f] <otp_dw_offset> <bit_offset> <value>\n" 2096737ed20bSJohnny Huang "otp pb strap [f] <bit_offset> <value>\n" 2097737ed20bSJohnny Huang "otp protect [f] <bit_offset>\n" 20982a856b9aSJohnny Huang "otp cmp <addr> <otp_dw_offset>\n" 209969d5fd8fSJohnny Huang ); 2100