]>
Commit | Line | Data |
---|---|---|
afb0840f PD |
1 | // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause |
2 | /* | |
3 | * Copyright (C) 2019, STMicroelectronics - All Rights Reserved | |
888dc681 PD |
4 | * |
5 | * the st command stboard supports the STMicroelectronics board identification | |
6 | * saved in OTP 59. | |
7 | * | |
8 | * The ST product codification have several element | |
9 | * - "Commercial Product Name" (CPN): type of product board (DKX, EVX) | |
10 | * associated to the board ID "MBxxxx" | |
11 | * - "Finished Good" or "Finish Good" (FG): | |
12 | * effective content of the product without chip STM32MP1xx (LCD, Wifi,…) | |
13 | * - BOM: cost variant for same FG (for example, several provider of the same | |
14 | * component) | |
15 | * | |
16 | * For example | |
17 | * - commercial product = STM32MP157C-EV1 for board MB1263 | |
18 | * - Finished Good = EVA32MP157A1$AU1 | |
19 | * | |
20 | * Both information are written on board and these information are also saved | |
21 | * in OTP59, with: | |
22 | * bit [31:16] (hex) => Board id, MBxxxx | |
23 | * bit [15:12] (dec) => Variant CPN (1....15) | |
24 | * bit [11:8] (dec) => Revision board (index with A = 1, Z = 26) | |
25 | * bit [7:4] (dec) => Variant FG : finished good index | |
26 | * bit [3:0] (dec) => BOM (01, .... 255) | |
27 | * | |
28 | * and displayed with the format: | |
29 | * Board: MB<Board> Var<VarCPN>.<VarFG> Rev.<Revision>-<BOM> | |
afb0840f PD |
30 | */ |
31 | ||
ba2c20ce | 32 | #ifndef CONFIG_SPL_BUILD |
afb0840f | 33 | #include <common.h> |
09140113 | 34 | #include <command.h> |
afb0840f PD |
35 | #include <console.h> |
36 | #include <misc.h> | |
37 | #include <dm/device.h> | |
38 | #include <dm/uclass.h> | |
39 | ||
40 | static bool check_stboard(u16 board) | |
41 | { | |
42 | unsigned int i; | |
888dc681 | 43 | /* list of supported ST boards */ |
afb0840f PD |
44 | const u16 st_board_id[] = { |
45 | 0x1272, | |
46 | 0x1263, | |
47 | 0x1264, | |
48 | 0x1298, | |
49 | 0x1341, | |
50 | 0x1497, | |
51 | }; | |
52 | ||
53 | for (i = 0; i < ARRAY_SIZE(st_board_id); i++) | |
54 | if (board == st_board_id[i]) | |
55 | return true; | |
56 | ||
57 | return false; | |
58 | } | |
59 | ||
60 | static void display_stboard(u32 otp) | |
61 | { | |
888dc681 PD |
62 | /* display board indentification with OPT coding */ |
63 | printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", | |
afb0840f PD |
64 | otp >> 16, |
65 | (otp >> 12) & 0xF, | |
888dc681 | 66 | (otp >> 4) & 0xF, |
afb0840f PD |
67 | ((otp >> 8) & 0xF) - 1 + 'A', |
68 | otp & 0xF); | |
69 | } | |
70 | ||
09140113 SG |
71 | static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc, |
72 | char *const argv[]) | |
afb0840f PD |
73 | { |
74 | int ret; | |
658fde8a | 75 | u32 otp, lock; |
afb0840f | 76 | u8 revision; |
888dc681 | 77 | unsigned long board, var_cpn, var_fg, bom; |
afb0840f | 78 | struct udevice *dev; |
888dc681 | 79 | int confirmed = argc == 7 && !strcmp(argv[1], "-y"); |
afb0840f PD |
80 | |
81 | argc -= 1 + confirmed; | |
82 | argv += 1 + confirmed; | |
83 | ||
888dc681 | 84 | if (argc != 0 && argc != 5) |
afb0840f PD |
85 | return CMD_RET_USAGE; |
86 | ||
87 | ret = uclass_get_device_by_driver(UCLASS_MISC, | |
88 | DM_GET_DRIVER(stm32mp_bsec), | |
89 | &dev); | |
90 | ||
fdabacec | 91 | ret = misc_read(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), |
afb0840f PD |
92 | &otp, sizeof(otp)); |
93 | ||
781a9177 | 94 | if (ret < 0) { |
afb0840f PD |
95 | puts("OTP read error"); |
96 | return CMD_RET_FAILURE; | |
97 | } | |
98 | ||
658fde8a PD |
99 | ret = misc_read(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), |
100 | &lock, sizeof(lock)); | |
101 | if (ret < 0) { | |
102 | puts("LOCK read error"); | |
103 | return CMD_RET_FAILURE; | |
104 | } | |
105 | ||
afb0840f PD |
106 | if (argc == 0) { |
107 | if (!otp) | |
108 | puts("Board : OTP board FREE\n"); | |
109 | else | |
110 | display_stboard(otp); | |
658fde8a PD |
111 | printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD, |
112 | lock == 1 ? "" : "NOT"); | |
afb0840f PD |
113 | return CMD_RET_SUCCESS; |
114 | } | |
115 | ||
116 | if (otp) { | |
117 | display_stboard(otp); | |
118 | printf("ERROR: OTP board not FREE\n"); | |
119 | return CMD_RET_FAILURE; | |
120 | } | |
121 | ||
122 | if (strict_strtoul(argv[0], 16, &board) < 0 || | |
123 | board == 0 || board > 0xFFFF) { | |
124 | printf("argument %d invalid: %s\n", 1, argv[0]); | |
125 | return CMD_RET_USAGE; | |
126 | } | |
127 | ||
888dc681 PD |
128 | if (strict_strtoul(argv[1], 10, &var_cpn) < 0 || |
129 | var_cpn == 0 || var_cpn > 15) { | |
afb0840f PD |
130 | printf("argument %d invalid: %s\n", 2, argv[1]); |
131 | return CMD_RET_USAGE; | |
132 | } | |
133 | ||
134 | revision = argv[2][0] - 'A' + 1; | |
135 | if (strlen(argv[2]) > 1 || revision == 0 || revision > 15) { | |
136 | printf("argument %d invalid: %s\n", 3, argv[2]); | |
137 | return CMD_RET_USAGE; | |
138 | } | |
139 | ||
888dc681 PD |
140 | if (strict_strtoul(argv[3], 10, &var_fg) < 0 || |
141 | var_fg > 15) { | |
142 | printf("argument %d invalid: %s\n", 4, argv[3]); | |
143 | return CMD_RET_USAGE; | |
144 | } | |
145 | ||
146 | if (strict_strtoul(argv[4], 10, &bom) < 0 || | |
afb0840f PD |
147 | bom == 0 || bom > 15) { |
148 | printf("argument %d invalid: %s\n", 4, argv[3]); | |
149 | return CMD_RET_USAGE; | |
150 | } | |
151 | ||
888dc681 PD |
152 | /* st board indentification value */ |
153 | otp = (board << 16) | (var_cpn << 12) | (revision << 8) | | |
154 | (var_fg << 4) | bom; | |
afb0840f PD |
155 | display_stboard(otp); |
156 | printf("=> OTP[%d] = %08X\n", BSEC_OTP_BOARD, otp); | |
157 | ||
158 | if (!check_stboard((u16)board)) { | |
159 | printf("Unknown board MB%04x\n", (u16)board); | |
160 | return CMD_RET_FAILURE; | |
161 | } | |
162 | if (!confirmed) { | |
163 | printf("Warning: Programming BOARD in OTP is irreversible!\n"); | |
164 | printf("Really perform this OTP programming? <y/N>\n"); | |
165 | ||
166 | if (!confirm_yesno()) { | |
167 | puts("BOARD programming aborted\n"); | |
168 | return CMD_RET_FAILURE; | |
169 | } | |
170 | } | |
171 | ||
172 | ret = misc_write(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), | |
173 | &otp, sizeof(otp)); | |
174 | ||
16aa3e3f | 175 | if (ret < 0) { |
afb0840f PD |
176 | puts("BOARD programming error\n"); |
177 | return CMD_RET_FAILURE; | |
178 | } | |
658fde8a PD |
179 | |
180 | /* write persistent lock */ | |
181 | otp = 1; | |
182 | ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), | |
183 | &otp, sizeof(otp)); | |
184 | if (ret < 0) { | |
185 | puts("BOARD lock error\n"); | |
186 | return CMD_RET_FAILURE; | |
187 | } | |
188 | ||
afb0840f PD |
189 | puts("BOARD programming done\n"); |
190 | ||
191 | return CMD_RET_SUCCESS; | |
192 | } | |
193 | ||
888dc681 | 194 | U_BOOT_CMD(stboard, 7, 0, do_stboard, |
afb0840f PD |
195 | "read/write board reference in OTP", |
196 | "\n" | |
197 | " Print current board information\n" | |
888dc681 | 198 | "stboard [-y] <Board> <VarCPN> <Revision> <VarFG> <BOM>\n" |
afb0840f PD |
199 | " Write board information\n" |
200 | " - Board: xxxx, example 1264 for MB1264\n" | |
888dc681 | 201 | " - VarCPN: 1...15\n" |
afb0840f | 202 | " - Revision: A...O\n" |
888dc681 | 203 | " - VarFG: 0...15\n" |
afb0840f | 204 | " - BOM: 1...15\n"); |
ba2c20ce PD |
205 | |
206 | #endif |