1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2a02d517bSMax Krummenacher /*
3a02d517bSMax Krummenacher * Copyright (C) 2014-2016, Toradex AG
4a02d517bSMax Krummenacher */
5a02d517bSMax Krummenacher
6a02d517bSMax Krummenacher /*
7a02d517bSMax Krummenacher * Helpers for i.MX OTP fusing during module production
8a02d517bSMax Krummenacher */
9a02d517bSMax Krummenacher
10a02d517bSMax Krummenacher #include <common.h>
11a02d517bSMax Krummenacher #ifndef CONFIG_SPL_BUILD
12a02d517bSMax Krummenacher #include <console.h>
13a02d517bSMax Krummenacher #include <fuse.h>
14a02d517bSMax Krummenacher
mfgr_fuse(void)15a02d517bSMax Krummenacher static int mfgr_fuse(void)
16a02d517bSMax Krummenacher {
17a02d517bSMax Krummenacher unsigned val, val6;
18a02d517bSMax Krummenacher
19a02d517bSMax Krummenacher fuse_sense(0, 5, &val);
20a02d517bSMax Krummenacher printf("Fuse 0, 5: %8x\n", val);
21a02d517bSMax Krummenacher fuse_sense(0, 6, &val6);
22a02d517bSMax Krummenacher printf("Fuse 0, 6: %8x\n", val6);
23a02d517bSMax Krummenacher fuse_sense(4, 3, &val);
24a02d517bSMax Krummenacher printf("Fuse 4, 3: %8x\n", val);
25a02d517bSMax Krummenacher fuse_sense(4, 2, &val);
26a02d517bSMax Krummenacher printf("Fuse 4, 2: %8x\n", val);
27a02d517bSMax Krummenacher if (val6 & 0x10) {
28a02d517bSMax Krummenacher puts("BT_FUSE_SEL already fused, will do nothing\n");
29a02d517bSMax Krummenacher return CMD_RET_FAILURE;
30a02d517bSMax Krummenacher }
31a02d517bSMax Krummenacher /* boot cfg */
32a02d517bSMax Krummenacher fuse_prog(0, 5, 0x00005072);
33a02d517bSMax Krummenacher /* BT_FUSE_SEL */
34a02d517bSMax Krummenacher fuse_prog(0, 6, 0x00000010);
35a02d517bSMax Krummenacher return CMD_RET_SUCCESS;
36a02d517bSMax Krummenacher }
37a02d517bSMax Krummenacher
do_mfgr_fuse(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])38a02d517bSMax Krummenacher int do_mfgr_fuse(cmd_tbl_t *cmdtp, int flag, int argc,
39a02d517bSMax Krummenacher char * const argv[])
40a02d517bSMax Krummenacher {
41a02d517bSMax Krummenacher int ret;
42a02d517bSMax Krummenacher puts("Fusing...\n");
43a02d517bSMax Krummenacher ret = mfgr_fuse();
44a02d517bSMax Krummenacher if (ret == CMD_RET_SUCCESS)
45a02d517bSMax Krummenacher puts("done.\n");
46a02d517bSMax Krummenacher else
47a02d517bSMax Krummenacher puts("failed.\n");
48a02d517bSMax Krummenacher return ret;
49a02d517bSMax Krummenacher }
50a02d517bSMax Krummenacher
do_updt_fuse(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])51a02d517bSMax Krummenacher int do_updt_fuse(cmd_tbl_t *cmdtp, int flag, int argc,
52a02d517bSMax Krummenacher char * const argv[])
53a02d517bSMax Krummenacher {
54a02d517bSMax Krummenacher unsigned val;
55a02d517bSMax Krummenacher int ret;
56a02d517bSMax Krummenacher int confirmed = argc >= 1 && !strcmp(argv[1], "-y");
57a02d517bSMax Krummenacher
58a02d517bSMax Krummenacher /* can be used in scripts for command availability check */
59a02d517bSMax Krummenacher if (argc >= 1 && !strcmp(argv[1], "-n"))
60a02d517bSMax Krummenacher return CMD_RET_SUCCESS;
61a02d517bSMax Krummenacher
62a02d517bSMax Krummenacher /* boot cfg */
63a02d517bSMax Krummenacher fuse_sense(0, 5, &val);
64a02d517bSMax Krummenacher printf("Fuse 0, 5: %8x\n", val);
65a02d517bSMax Krummenacher if (val & 0x10) {
66a02d517bSMax Krummenacher puts("Fast boot mode already fused, no need to fuse\n");
67a02d517bSMax Krummenacher return CMD_RET_SUCCESS;
68a02d517bSMax Krummenacher }
69a02d517bSMax Krummenacher if (!confirmed) {
70a02d517bSMax Krummenacher puts("Warning: Programming fuses is an irreversible operation!\n"
71a02d517bSMax Krummenacher " Updating to fast boot mode prevents easy\n"
72a02d517bSMax Krummenacher " downgrading to previous BSP versions.\n"
73a02d517bSMax Krummenacher "\nReally perform this fuse programming? <y/N>\n");
74a02d517bSMax Krummenacher if (!confirm_yesno())
75a02d517bSMax Krummenacher return CMD_RET_FAILURE;
76a02d517bSMax Krummenacher }
77a02d517bSMax Krummenacher puts("Fusing fast boot mode...\n");
78a02d517bSMax Krummenacher ret = fuse_prog(0, 5, 0x00005072);
79a02d517bSMax Krummenacher if (ret == CMD_RET_SUCCESS)
80a02d517bSMax Krummenacher puts("done.\n");
81a02d517bSMax Krummenacher else
82a02d517bSMax Krummenacher puts("failed.\n");
83a02d517bSMax Krummenacher return ret;
84a02d517bSMax Krummenacher }
85a02d517bSMax Krummenacher
86a02d517bSMax Krummenacher U_BOOT_CMD(
87a02d517bSMax Krummenacher mfgr_fuse, 1, 0, do_mfgr_fuse,
88a02d517bSMax Krummenacher "OTP fusing during module production",
89a02d517bSMax Krummenacher ""
90a02d517bSMax Krummenacher );
91a02d517bSMax Krummenacher
92a02d517bSMax Krummenacher U_BOOT_CMD(
93a02d517bSMax Krummenacher updt_fuse, 2, 0, do_updt_fuse,
94a02d517bSMax Krummenacher "OTP fusing during module update",
95a02d517bSMax Krummenacher "updt_fuse [-n] [-y] - boot cfg fast boot mode fusing"
96a02d517bSMax Krummenacher );
97a02d517bSMax Krummenacher #endif /* CONFIG_SPL_BUILD */
98