blob: 0df57dbc8071f123fedf009a1e440b20839aec1a [file] [log] [blame]
Benoît Thébaudeauccca7df2013-04-23 10:17:40 +00001/*
2 * (C) Copyright 2009-2013 ADVANSEE
3 * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
4 *
5 * Based on the mpc512x iim code:
6 * Copyright 2008 Silicon Turnkey Express, Inc.
7 * Martha Marx <mmarx@silicontkx.com>
8 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02009 * SPDX-License-Identifier: GPL-2.0+
Benoît Thébaudeauccca7df2013-04-23 10:17:40 +000010 */
11
12#include <common.h>
13#include <command.h>
14#include <fuse.h>
15#include <asm/errno.h>
16
17static int strtou32(const char *str, unsigned int base, u32 *result)
18{
19 char *ep;
20
21 *result = simple_strtoul(str, &ep, base);
22 if (ep == str || *ep != '\0')
23 return -EINVAL;
24
25 return 0;
26}
27
28static int confirm_prog(void)
29{
30 puts("Warning: Programming fuses is an irreversible operation!\n"
31 " This may brick your system.\n"
32 " Use this command only if you are sure of "
33 "what you are doing!\n"
34 "\nReally perform this fuse programming? <y/N>\n");
35
36 if (getc() == 'y') {
37 int c;
38
39 putc('y');
40 c = getc();
41 putc('\n');
42 if (c == '\r')
43 return 1;
44 }
45
46 puts("Fuse programming aborted\n");
47 return 0;
48}
49
50static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
51{
52 const char *op = argc >= 2 ? argv[1] : NULL;
53 int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
54 u32 bank, word, cnt, val;
55 int ret, i;
56
57 argc -= 2 + confirmed;
58 argv += 2 + confirmed;
59
60 if (argc < 2 || strtou32(argv[0], 0, &bank) ||
61 strtou32(argv[1], 0, &word))
62 return CMD_RET_USAGE;
63
64 if (!strcmp(op, "read")) {
65 if (argc == 2)
66 cnt = 1;
67 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
68 return CMD_RET_USAGE;
69
70 printf("Reading bank %u:\n", bank);
71 for (i = 0; i < cnt; i++, word++) {
72 if (!(i % 4))
73 printf("\nWord 0x%.8x:", word);
74
75 ret = fuse_read(bank, word, &val);
76 if (ret)
77 goto err;
78
79 printf(" %.8x", val);
80 }
81 putc('\n');
82 } else if (!strcmp(op, "sense")) {
83 if (argc == 2)
84 cnt = 1;
85 else if (argc != 3 || strtou32(argv[2], 0, &cnt))
86 return CMD_RET_USAGE;
87
88 printf("Sensing bank %u:\n", bank);
89 for (i = 0; i < cnt; i++, word++) {
90 if (!(i % 4))
91 printf("\nWord 0x%.8x:", word);
92
93 ret = fuse_sense(bank, word, &val);
94 if (ret)
95 goto err;
96
97 printf(" %.8x", val);
98 }
99 putc('\n');
100 } else if (!strcmp(op, "prog")) {
101 if (argc < 3)
102 return CMD_RET_USAGE;
103
104 for (i = 2; i < argc; i++, word++) {
105 if (strtou32(argv[i], 16, &val))
106 return CMD_RET_USAGE;
107
108 printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
109 bank, word, val);
110 if (!confirmed && !confirm_prog())
111 return CMD_RET_FAILURE;
112 ret = fuse_prog(bank, word, val);
113 if (ret)
114 goto err;
115 }
116 } else if (!strcmp(op, "override")) {
117 if (argc < 3)
118 return CMD_RET_USAGE;
119
120 for (i = 2; i < argc; i++, word++) {
121 if (strtou32(argv[i], 16, &val))
122 return CMD_RET_USAGE;
123
124 printf("Overriding bank %u word 0x%.8x with "
125 "0x%.8x...\n", bank, word, val);
126 ret = fuse_override(bank, word, val);
127 if (ret)
128 goto err;
129 }
130 } else {
131 return CMD_RET_USAGE;
132 }
133
134 return 0;
135
136err:
137 puts("ERROR\n");
138 return ret;
139}
140
141U_BOOT_CMD(
142 fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
143 "Fuse sub-system",
144 "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
145 " starting at 'word'\n"
146 "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
147 " starting at 'word'\n"
148 "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
149 " several fuse words, starting at 'word' (PERMANENT)\n"
150 "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
151 " several fuse words, starting at 'word'"
152);