1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2592f4aedSMax Krummenacher /* 3592f4aedSMax Krummenacher * Copyright (C) 2014-2016, Toradex AG 4592f4aedSMax Krummenacher */ 5592f4aedSMax Krummenacher 6592f4aedSMax Krummenacher /* 7592f4aedSMax Krummenacher * Helpers for i.MX OTP fusing during module production 8592f4aedSMax Krummenacher */ 9592f4aedSMax Krummenacher 10592f4aedSMax Krummenacher #include <common.h> 11592f4aedSMax Krummenacher #ifndef CONFIG_SPL_BUILD 12592f4aedSMax Krummenacher #include <console.h> 13592f4aedSMax Krummenacher #include <fuse.h> 14592f4aedSMax Krummenacher 15592f4aedSMax Krummenacher static int mfgr_fuse(void) 16592f4aedSMax Krummenacher { 17592f4aedSMax Krummenacher unsigned val, val6; 18592f4aedSMax Krummenacher 19592f4aedSMax Krummenacher fuse_sense(0, 5, &val); 20592f4aedSMax Krummenacher printf("Fuse 0, 5: %8x\n", val); 21592f4aedSMax Krummenacher fuse_sense(0, 6, &val6); 22592f4aedSMax Krummenacher printf("Fuse 0, 6: %8x\n", val6); 23592f4aedSMax Krummenacher fuse_sense(4, 3, &val); 24592f4aedSMax Krummenacher printf("Fuse 4, 3: %8x\n", val); 25592f4aedSMax Krummenacher fuse_sense(4, 2, &val); 26592f4aedSMax Krummenacher printf("Fuse 4, 2: %8x\n", val); 27592f4aedSMax Krummenacher if (val6 & 0x10) { 28592f4aedSMax Krummenacher puts("BT_FUSE_SEL already fused, will do nothing\n"); 29592f4aedSMax Krummenacher return CMD_RET_FAILURE; 30592f4aedSMax Krummenacher } 31592f4aedSMax Krummenacher /* boot cfg */ 32592f4aedSMax Krummenacher fuse_prog(0, 5, 0x00005072); 33592f4aedSMax Krummenacher /* BT_FUSE_SEL */ 34592f4aedSMax Krummenacher fuse_prog(0, 6, 0x00000010); 35592f4aedSMax Krummenacher return CMD_RET_SUCCESS; 36592f4aedSMax Krummenacher } 37592f4aedSMax Krummenacher 38592f4aedSMax Krummenacher int do_mfgr_fuse(cmd_tbl_t *cmdtp, int flag, int argc, 39592f4aedSMax Krummenacher char * const argv[]) 40592f4aedSMax Krummenacher { 41592f4aedSMax Krummenacher int ret; 42592f4aedSMax Krummenacher puts("Fusing...\n"); 43592f4aedSMax Krummenacher ret = mfgr_fuse(); 44592f4aedSMax Krummenacher if (ret == CMD_RET_SUCCESS) 45592f4aedSMax Krummenacher puts("done.\n"); 46592f4aedSMax Krummenacher else 47592f4aedSMax Krummenacher puts("failed.\n"); 48592f4aedSMax Krummenacher return ret; 49592f4aedSMax Krummenacher } 50592f4aedSMax Krummenacher 51592f4aedSMax Krummenacher int do_updt_fuse(cmd_tbl_t *cmdtp, int flag, int argc, 52592f4aedSMax Krummenacher char * const argv[]) 53592f4aedSMax Krummenacher { 54592f4aedSMax Krummenacher unsigned val; 55592f4aedSMax Krummenacher int ret; 56592f4aedSMax Krummenacher int confirmed = argc >= 1 && !strcmp(argv[1], "-y"); 57592f4aedSMax Krummenacher 58592f4aedSMax Krummenacher /* can be used in scripts for command availability check */ 59592f4aedSMax Krummenacher if (argc >= 1 && !strcmp(argv[1], "-n")) 60592f4aedSMax Krummenacher return CMD_RET_SUCCESS; 61592f4aedSMax Krummenacher 62592f4aedSMax Krummenacher /* boot cfg */ 63592f4aedSMax Krummenacher fuse_sense(0, 5, &val); 64592f4aedSMax Krummenacher printf("Fuse 0, 5: %8x\n", val); 65592f4aedSMax Krummenacher if (val & 0x10) { 66592f4aedSMax Krummenacher puts("Fast boot mode already fused, no need to fuse\n"); 67592f4aedSMax Krummenacher return CMD_RET_SUCCESS; 68592f4aedSMax Krummenacher } 69592f4aedSMax Krummenacher if (!confirmed) { 70592f4aedSMax Krummenacher puts("Warning: Programming fuses is an irreversible operation!\n" 71592f4aedSMax Krummenacher " Updating to fast boot mode prevents easy\n" 72592f4aedSMax Krummenacher " downgrading to previous BSP versions.\n" 73592f4aedSMax Krummenacher "\nReally perform this fuse programming? <y/N>\n"); 74592f4aedSMax Krummenacher if (!confirm_yesno()) 75592f4aedSMax Krummenacher return CMD_RET_FAILURE; 76592f4aedSMax Krummenacher } 77592f4aedSMax Krummenacher puts("Fusing fast boot mode...\n"); 78592f4aedSMax Krummenacher ret = fuse_prog(0, 5, 0x00005072); 79592f4aedSMax Krummenacher if (ret == CMD_RET_SUCCESS) 80592f4aedSMax Krummenacher puts("done.\n"); 81592f4aedSMax Krummenacher else 82592f4aedSMax Krummenacher puts("failed.\n"); 83592f4aedSMax Krummenacher return ret; 84592f4aedSMax Krummenacher } 85592f4aedSMax Krummenacher 86592f4aedSMax Krummenacher U_BOOT_CMD( 87592f4aedSMax Krummenacher mfgr_fuse, 1, 0, do_mfgr_fuse, 88592f4aedSMax Krummenacher "OTP fusing during module production", 89592f4aedSMax Krummenacher "" 90592f4aedSMax Krummenacher ); 91592f4aedSMax Krummenacher 92592f4aedSMax Krummenacher U_BOOT_CMD( 93592f4aedSMax Krummenacher updt_fuse, 2, 0, do_updt_fuse, 94592f4aedSMax Krummenacher "OTP fusing during module update", 95592f4aedSMax Krummenacher "updt_fuse [-n] [-y] - boot cfg fast boot mode fusing" 96592f4aedSMax Krummenacher ); 97592f4aedSMax Krummenacher #endif /* CONFIG_SPL_BUILD */ 98