1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2/* 3 * Copyright (C) 2019, STMicroelectronics - All Rights Reserved 4 * 5 * the command stboard supports the STMicroelectronics board identification 6 * saved in OTP_BOARD. 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 OTP_BOARD (59 for STM32MP15x or 60 for STM32MP13x), 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> 30 */ 31 32#ifndef CONFIG_SPL_BUILD 33#include <common.h> 34#include <command.h> 35#include <console.h> 36#include <misc.h> 37#include <asm/arch/bsec.h> 38#include <dm/device.h> 39#include <dm/uclass.h> 40 41static bool check_stboard(u16 board) 42{ 43 unsigned int i; 44 /* list of supported ST boards */ 45 const u16 st_board_id[] = { 46 0x1272, 47 0x1263, 48 0x1264, 49 0x1298, 50 0x1341, 51 0x1497, 52 0x1605, /* stm32mp25xx-dk */ 53 0x1635, 54 0x1936, /* stm32mp25xx-ev1 */ 55 }; 56 57 for (i = 0; i < ARRAY_SIZE(st_board_id); i++) 58 if (board == st_board_id[i]) 59 return true; 60 61 return false; 62} 63 64static void display_stboard(u32 otp) 65{ 66 /* display board indentification with OPT coding */ 67 printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n", 68 otp >> 16, 69 (otp >> 12) & 0xF, 70 (otp >> 4) & 0xF, 71 ((otp >> 8) & 0xF) - 1 + 'A', 72 otp & 0xF); 73} 74 75static int do_stboard(struct cmd_tbl *cmdtp, int flag, int argc, 76 char *const argv[]) 77{ 78 int ret; 79 u32 otp, lock; 80 u8 revision; 81 unsigned long board, var_cpn, var_fg, bom; 82 struct udevice *dev; 83 int confirmed = argc == 7 && !strcmp(argv[1], "-y"); 84 85 argc -= 1 + confirmed; 86 argv += 1 + confirmed; 87 88 if (argc != 0 && argc != 5) 89 return CMD_RET_USAGE; 90 91 ret = uclass_get_device_by_driver(UCLASS_MISC, 92 DM_DRIVER_GET(stm32mp_bsec), 93 &dev); 94 95 ret = misc_read(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), 96 &otp, sizeof(otp)); 97 98 if (ret != sizeof(otp)) { 99 puts("OTP read error\n"); 100 return CMD_RET_FAILURE; 101 } 102 103 ret = misc_read(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), 104 &lock, sizeof(lock)); 105 if (ret != sizeof(lock)) { 106 puts("LOCK read error\n"); 107 return CMD_RET_FAILURE; 108 } 109 110 if (argc == 0) { 111 if (!otp) 112 puts("Board : OTP board FREE\n"); 113 else 114 display_stboard(otp); 115 printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD, 116 lock & BSEC_LOCK_PERM ? "" : "NOT"); 117 return CMD_RET_SUCCESS; 118 } 119 120 if (otp) { 121 display_stboard(otp); 122 printf("ERROR: OTP board not FREE\n"); 123 return CMD_RET_FAILURE; 124 } 125 126 if (strict_strtoul(argv[0], 16, &board) < 0 || 127 board == 0 || board > 0xFFFF) { 128 printf("argument %d invalid: %s\n", 1, argv[0]); 129 return CMD_RET_USAGE; 130 } 131 132 if (strict_strtoul(argv[1], 10, &var_cpn) < 0 || 133 var_cpn == 0 || var_cpn > 15) { 134 printf("argument %d invalid: %s\n", 2, argv[1]); 135 return CMD_RET_USAGE; 136 } 137 138 revision = argv[2][0] - 'A' + 1; 139 if (strlen(argv[2]) > 1 || revision == 0 || revision > 15) { 140 printf("argument %d invalid: %s\n", 3, argv[2]); 141 return CMD_RET_USAGE; 142 } 143 144 if (strict_strtoul(argv[3], 10, &var_fg) < 0 || 145 var_fg > 15) { 146 printf("argument %d invalid: %s\n", 4, argv[3]); 147 return CMD_RET_USAGE; 148 } 149 150 if (strict_strtoul(argv[4], 10, &bom) < 0 || 151 bom == 0 || bom > 15) { 152 printf("argument %d invalid: %s\n", 4, argv[3]); 153 return CMD_RET_USAGE; 154 } 155 156 /* st board indentification value */ 157 otp = (board << 16) | (var_cpn << 12) | (revision << 8) | 158 (var_fg << 4) | bom; 159 display_stboard(otp); 160 printf("=> OTP[%d] = %08X\n", BSEC_OTP_BOARD, otp); 161 162 if (!check_stboard((u16)board)) { 163 printf("Unknown board MB%04x\n", (u16)board); 164 return CMD_RET_FAILURE; 165 } 166 if (!confirmed) { 167 printf("Warning: Programming BOARD in OTP is irreversible!\n"); 168 printf("Really perform this OTP programming? <y/N>\n"); 169 170 if (!confirm_yesno()) { 171 puts("BOARD programming aborted\n"); 172 return CMD_RET_FAILURE; 173 } 174 } 175 176 ret = misc_write(dev, STM32_BSEC_OTP(BSEC_OTP_BOARD), 177 &otp, sizeof(otp)); 178 179 if (ret != sizeof(otp)) { 180 puts("BOARD programming error\n"); 181 return CMD_RET_FAILURE; 182 } 183 184 /* write persistent lock */ 185 otp = BSEC_LOCK_PERM; 186 ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD), 187 &otp, sizeof(otp)); 188 if (ret != sizeof(otp)) { 189 puts("BOARD lock error\n"); 190 return CMD_RET_FAILURE; 191 } 192 193 puts("BOARD programming done\n"); 194 195 return CMD_RET_SUCCESS; 196} 197 198U_BOOT_CMD(stboard, 7, 0, do_stboard, 199 "read/write board reference in OTP", 200 "\n" 201 " Print current board information\n" 202 "stboard [-y] <Board> <VarCPN> <Revision> <VarFG> <BOM>\n" 203 " Write board information\n" 204 " - Board: xxxx, example 1264 for MB1264\n" 205 " - VarCPN: 1...15\n" 206 " - Revision: A...O\n" 207 " - VarFG: 0...15\n" 208 " - BOM: 1...15\n"); 209 210#endif 211