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
mfgr_fuse(void)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
do_mfgr_fuse(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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
do_updt_fuse(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])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